diff --git a/test/functional/abc-minimaldata-activation.py b/test/functional/abc-minimaldata.py rename from test/functional/abc-minimaldata-activation.py rename to test/functional/abc-minimaldata.py --- a/test/functional/abc-minimaldata-activation.py +++ b/test/functional/abc-minimaldata.py @@ -3,7 +3,7 @@ # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """ -This tests the activation of MINIMALDATA rule to consensus (from standard). +This tests the MINIMALDATA consensus rule. - test rejection in mempool, with error changing before/after activation. - test acceptance in blocks before activation, and rejection after. - check non-banning for peers who send invalid txns that would have been valid @@ -37,34 +37,20 @@ ) from test_framework.test_framework import BitcoinTestFramework from test_framework.txtools import pad_tx -from test_framework.util import assert_equal, assert_raises_rpc_error +from test_framework.util import assert_raises_rpc_error -# the upgrade activation time, which we artificially set far into the future -GRAVITON_START_TIME = 2000000000 - -# If we don't do this, autoreplay protection will activate before graviton and -# all our sigs will mysteriously fail. -REPLAY_PROTECTION_START_TIME = GRAVITON_START_TIME * 2 - - -# Both before and after the upgrade, minimal push violations are rejected as -# nonstandard. After the upgrade they are actually invalid, but we get the -# same error since MINIMALDATA is internally marked as a "standardness" flag. MINIMALPUSH_ERROR = 'non-mandatory-script-verify-flag (Data push larger than necessary)' # Blocks with invalid scripts give this error: BADINPUTS_ERROR = 'blk-bad-inputs' -class SchnorrTest(BitcoinTestFramework): +class MinimaldataTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 1 self.block_heights = {} - self.extra_args = [["-gravitonactivationtime={}".format( - GRAVITON_START_TIME), - "-replayprotectionactivationtime={}".format( - REPLAY_PROTECTION_START_TIME)]] + self.extra_args = [[]] def bootstrap_p2p(self, *, num_connections=1): """Add a P2P connection to the node. @@ -107,14 +93,6 @@ self.block_heights[block.sha256] = block_height return block - def check_for_ban_on_rejected_tx(self, tx, reject_reason=None): - """Check we are disconnected when sending a txn that the node rejects. - - (Can't actually get banned, since bitcoind won't ban local peers.)""" - self.nodes[0].p2p.send_txs_and_test( - [tx], self.nodes[0], success=False, expect_disconnect=True, reject_reason=reject_reason) - self.reconnect_p2p() - def check_for_no_ban_on_rejected_tx(self, tx, reject_reason): """Check we are not disconnected when sending a txn that the node rejects.""" self.nodes[0].p2p.send_txs_and_test( @@ -178,72 +156,21 @@ return txspend - # make a few of these, which are nonstandard before upgrade and invalid after. + # Non minimal tx are invalid. nonminimaltx = create_fund_and_spend_tx() - nonminimaltx_2 = create_fund_and_spend_tx() - nonminimaltx_3 = create_fund_and_spend_tx() tip = self.build_block(tip, fundings) node.p2p.send_blocks_and_test([tip], node) - self.log.info("Start preupgrade tests") - - self.log.info("Sending rejected transactions via RPC") - assert_raises_rpc_error(-26, MINIMALPUSH_ERROR, - node.sendrawtransaction, ToHex(nonminimaltx)) - assert_raises_rpc_error(-26, MINIMALPUSH_ERROR, - node.sendrawtransaction, ToHex(nonminimaltx_2)) - assert_raises_rpc_error(-26, MINIMALPUSH_ERROR, - node.sendrawtransaction, ToHex(nonminimaltx_3)) - - self.log.info( - "Sending rejected transactions via net (no banning)") - self.check_for_no_ban_on_rejected_tx( - nonminimaltx, MINIMALPUSH_ERROR) - self.check_for_no_ban_on_rejected_tx( - nonminimaltx_2, MINIMALPUSH_ERROR) - self.check_for_no_ban_on_rejected_tx( - nonminimaltx_3, MINIMALPUSH_ERROR) - - assert_equal(node.getrawmempool(), []) - - self.log.info("Successfully mine nonstandard transaction") - tip = self.build_block(tip, [nonminimaltx]) - node.p2p.send_blocks_and_test([tip], node) - - # Activation tests - - self.log.info("Approach to just before upgrade activation") - # Move our clock to the uprade time so we will accept such future-timestamped blocks. - node.setmocktime(GRAVITON_START_TIME) - # Mine six blocks with timestamp starting at GRAVITON_START_TIME-1 - blocks = [] - for i in range(-1, 5): - tip = self.build_block(tip, nTime=GRAVITON_START_TIME + i) - blocks.append(tip) - node.p2p.send_blocks_and_test(blocks, node) - assert_equal(node.getblockchaininfo()[ - 'mediantime'], GRAVITON_START_TIME - 1) - - self.log.info( - "Mine the activation block itself, including a minimaldata violation at the last possible moment") - tip = self.build_block(tip, [nonminimaltx_2]) - node.p2p.send_blocks_and_test([tip], node) - - self.log.info("We have activated!") - assert_equal(node.getblockchaininfo()[ - 'mediantime'], GRAVITON_START_TIME) - - self.log.info( - "Trying to mine a minimaldata violation, but we are just barely too late") + self.log.info("Trying to mine a minimaldata violation.") self.check_for_ban_on_rejected_block( - self.build_block(tip, [nonminimaltx_3]), BADINPUTS_ERROR) + self.build_block(tip, [nonminimaltx]), BADINPUTS_ERROR) self.log.info( - "If we try to submit it by mempool or RPC we still aren't banned") + "If we try to submit it by mempool or RPC we aren't banned") assert_raises_rpc_error(-26, MINIMALPUSH_ERROR, - node.sendrawtransaction, ToHex(nonminimaltx_3)) + node.sendrawtransaction, ToHex(nonminimaltx)) self.check_for_no_ban_on_rejected_tx( - nonminimaltx_3, MINIMALPUSH_ERROR) + nonminimaltx, MINIMALPUSH_ERROR) self.log.info("Mine a normal block") tip = self.build_block(tip) @@ -251,4 +178,4 @@ if __name__ == '__main__': - SchnorrTest().main() + MinimaldataTest().main() diff --git a/test/functional/abc-schnorrmultisig-activation.py b/test/functional/abc-schnorrmultisig.py rename from test/functional/abc-schnorrmultisig-activation.py rename to test/functional/abc-schnorrmultisig.py --- a/test/functional/abc-schnorrmultisig-activation.py +++ b/test/functional/abc-schnorrmultisig.py @@ -3,9 +3,8 @@ # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """ -This tests the activation of the upgraded CHECKMULTISIG mode that uses -Schnorr transaction signatures and repurposes the dummy element to indicate -which signatures are being checked. +This tests the CHECKMULTISIG mode that uses Schnorr transaction signatures and +repurposes the dummy element to indicate which signatures are being checked. - acceptance both in mempool and blocks. - check non-banning for peers who send invalid txns that would have been valid on the other side of the upgrade. @@ -47,23 +46,13 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import assert_equal, assert_raises_rpc_error -# the upgrade activation time, which we artificially set far into the future -GRAVITON_START_TIME = 2000000000 -# If we don't do this, autoreplay protection will activate before graviton and -# all our sigs will mysteriously fail. -REPLAY_PROTECTION_START_TIME = GRAVITON_START_TIME * 2 - - -# Before the upgrade, Schnorr checkmultisig is rejected. -PREUPGRADE_SCHNORR_MULTISIG_ERROR = 'mandatory-script-verify-flag-failed (Signature cannot be 65 bytes in CHECKMULTISIG)' - -# After the upgrade, ECDSA checkmultisig with non-null dummy are invalid since -# the new mode refuses ECDSA. -POSTUPGRADE_ECDSA_NULLDUMMY_ERROR = 'mandatory-script-verify-flag-failed (Only Schnorr signatures allowed in this operation)' +# ECDSA checkmultisig with non-null dummy are invalid since the new mode +# refuses ECDSA. +ECDSA_NULLDUMMY_ERROR = 'mandatory-script-verify-flag-failed (Only Schnorr signatures allowed in this operation)' # A mandatory (bannable) error occurs when people pass Schnorr signatures into -# legacy OP_CHECKMULTISIG; this is the case on both sides of the upgrade. +# legacy OP_CHECKMULTISIG. SCHNORR_LEGACY_MULTISIG_ERROR = 'mandatory-script-verify-flag-failed (Signature cannot be 65 bytes in CHECKMULTISIG)' # Blocks with invalid scripts give this error: @@ -76,15 +65,11 @@ sig64 = b'\0'*64 -class SchnorrTest(BitcoinTestFramework): +class SchnorrMultisigTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 1 self.block_heights = {} - self.extra_args = [["-gravitonactivationtime={}".format( - GRAVITON_START_TIME), - "-replayprotectionactivationtime={}".format( - REPLAY_PROTECTION_START_TIME)]] def bootstrap_p2p(self, *, num_connections=1): """Add a P2P connection to the node. @@ -135,11 +120,6 @@ [tx], self.nodes[0], success=False, expect_disconnect=True, reject_reason=reject_reason) self.reconnect_p2p() - def check_for_no_ban_on_rejected_tx(self, tx, reject_reason): - """Check we are not disconnected when sending a txn that the node rejects.""" - self.nodes[0].p2p.send_txs_and_test( - [tx], self.nodes[0], success=False, reject_reason=reject_reason) - def check_for_ban_on_rejected_block(self, block, reject_reason=None): """Check we are disconnected when sending a block that the node rejects. @@ -211,165 +191,57 @@ return txspend - # two of these transactions, which are valid both before and after upgrade. + # This is valid. ecdsa0tx = create_fund_and_spend_tx(OP_0, 'ecdsa') - ecdsa0tx_2 = create_fund_and_spend_tx(OP_0, 'ecdsa') - # two of these, which are valid before upgrade and invalid after. + # This is invalid. ecdsa1tx = create_fund_and_spend_tx(OP_1, 'ecdsa') - ecdsa1tx_2 = create_fund_and_spend_tx(OP_1, 'ecdsa') - # this one is always invalid. + # This is invalid. schnorr0tx = create_fund_and_spend_tx(OP_0, 'schnorr') - # this one is only going to be valid after the upgrade. + # This is valid. schnorr1tx = create_fund_and_spend_tx(OP_1, 'schnorr') tip = self.build_block(tip, fundings) node.p2p.send_blocks_and_test([tip], node) - self.log.info("Start preupgrade tests") - - self.log.info("Sending rejected transactions via RPC") - assert_raises_rpc_error(-26, SCHNORR_LEGACY_MULTISIG_ERROR, - node.sendrawtransaction, ToHex(schnorr0tx)) - assert_raises_rpc_error(-26, PREUPGRADE_SCHNORR_MULTISIG_ERROR, - node.sendrawtransaction, ToHex(schnorr1tx)) - - self.log.info( - "Sending rejected transactions via net (bannable)") - self.check_for_ban_on_rejected_tx( - schnorr0tx, SCHNORR_LEGACY_MULTISIG_ERROR) - self.check_for_ban_on_rejected_tx( - schnorr1tx, PREUPGRADE_SCHNORR_MULTISIG_ERROR) - - self.log.info( - "Sending invalid transactions in blocks (and get banned!)") - self.check_for_ban_on_rejected_block( - self.build_block(tip, [schnorr0tx]), BADINPUTS_ERROR) - self.check_for_ban_on_rejected_block( - self.build_block(tip, [schnorr1tx]), BADINPUTS_ERROR) - - self.log.info("Sending valid transaction via net, then mining it") + self.log.info("Send a legacy ECDSA multisig into mempool.") node.p2p.send_txs_and_test([ecdsa0tx], node) assert_equal(node.getrawmempool(), [ecdsa0tx.hash]) - tip = self.build_block(tip, [ecdsa0tx]) - node.p2p.send_blocks_and_test([tip], node) - assert_equal(node.getrawmempool(), []) - - # Activation tests - - self.log.info("Approach to just before upgrade activation") - # Move our clock to the uprade time so we will accept such future-timestamped blocks. - node.setmocktime(GRAVITON_START_TIME) - # Mine six blocks with timestamp starting at GRAVITON_START_TIME-1 - blocks = [] - for i in range(-1, 5): - tip = self.build_block(tip, nTime=GRAVITON_START_TIME + i) - blocks.append(tip) - node.p2p.send_blocks_and_test(blocks, node) - assert_equal(node.getblockchaininfo()[ - 'mediantime'], GRAVITON_START_TIME - 1) - self.log.info( - "The next block will activate, but the activation block itself must follow old rules") + self.log.info("Trying to mine a non-null-dummy ECDSA.") self.check_for_ban_on_rejected_block( - self.build_block(tip, [schnorr0tx]), BADINPUTS_ERROR) - - self.log.info( - "Send a lecacy ECDSA multisig into mempool, we will check after upgrade to make sure it didn't get cleaned out unnecessarily.") - node.p2p.send_txs_and_test([ecdsa0tx_2], node) - assert_equal(node.getrawmempool(), [ecdsa0tx_2.hash]) - - # save this tip for later - preupgrade_block = tip - - self.log.info( - "Mine the activation block itself, including a non-null-dummy ECDSA at the last possible moment") - node.p2p.send_txs_and_test([ecdsa1tx], node) - tip = self.build_block(tip, [ecdsa1tx]) - node.p2p.send_blocks_and_test([tip], node) - - self.log.info("We have activated!") - assert_equal(node.getblockchaininfo()[ - 'mediantime'], GRAVITON_START_TIME) - assert_equal(node.getrawmempool(), [ecdsa0tx_2.hash]) - - # save this tip for later - upgrade_block = tip - - self.log.info( - "Trying to mine a non-null-dummy ECDSA, but we are just barely too late") - self.check_for_ban_on_rejected_block( - self.build_block(tip, [ecdsa1tx_2]), BADINPUTS_ERROR) + self.build_block(tip, [ecdsa1tx]), BADINPUTS_ERROR) self.log.info( "If we try to submit it by mempool or RPC, it is rejected and we are banned") - assert_raises_rpc_error(-26, POSTUPGRADE_ECDSA_NULLDUMMY_ERROR, - node.sendrawtransaction, ToHex(ecdsa1tx_2)) + assert_raises_rpc_error(-26, ECDSA_NULLDUMMY_ERROR, + node.sendrawtransaction, ToHex(ecdsa1tx)) self.check_for_ban_on_rejected_tx( - ecdsa1tx_2, POSTUPGRADE_ECDSA_NULLDUMMY_ERROR) + ecdsa1tx, ECDSA_NULLDUMMY_ERROR) self.log.info( - "Submitting a new Schnorr-multisig via net, and mining it in a block") + "Submitting a Schnorr-multisig via net, and mining it in a block") node.p2p.send_txs_and_test([schnorr1tx], node) assert_equal(set(node.getrawmempool()), { - ecdsa0tx_2.hash, schnorr1tx.hash}) + ecdsa0tx.hash, schnorr1tx.hash}) tip = self.build_block(tip, [schnorr1tx]) node.p2p.send_blocks_and_test([tip], node) - # save this tip for later - postupgrade_block = tip - self.log.info( "That legacy ECDSA multisig is still in mempool, let's mine it") - assert_equal(node.getrawmempool(), [ecdsa0tx_2.hash]) - tip = self.build_block(tip, [ecdsa0tx_2]) + assert_equal(node.getrawmempool(), [ecdsa0tx.hash]) + tip = self.build_block(tip, [ecdsa0tx]) node.p2p.send_blocks_and_test([tip], node) assert_equal(node.getrawmempool(), []) self.log.info( - "Trying Schnorr in legacy multisig remains invalid and banworthy as ever") + "Trying Schnorr in legacy multisig is invalid and banworthy.") self.check_for_ban_on_rejected_tx( schnorr0tx, SCHNORR_LEGACY_MULTISIG_ERROR) self.check_for_ban_on_rejected_block( self.build_block(tip, [schnorr0tx]), BADINPUTS_ERROR) - # Deactivation tests - - self.log.info( - "Invalidating the post-upgrade blocks returns the transactions to mempool") - node.invalidateblock(postupgrade_block.hash) - assert_equal(set(node.getrawmempool()), { - ecdsa0tx_2.hash, schnorr1tx.hash}) - self.log.info( - "Invalidating the upgrade block evicts the transactions valid only after upgrade") - node.invalidateblock(upgrade_block.hash) - assert_equal(set(node.getrawmempool()), { - ecdsa0tx_2.hash, ecdsa1tx.hash}) - - self.log.info("Return to our tip") - node.reconsiderblock(upgrade_block.hash) - node.reconsiderblock(postupgrade_block.hash) - assert_equal(node.getbestblockhash(), tip.hash) - assert_equal(node.getrawmempool(), []) - - self.log.info( - "Create an empty-block reorg that forks from pre-upgrade") - tip = preupgrade_block - blocks = [] - for _ in range(10): - tip = self.build_block(tip) - blocks.append(tip) - node.p2p.send_blocks_and_test(blocks, node) - - self.log.info("Transactions from orphaned blocks are sent into mempool ready to be mined again, including upgrade-dependent ones even though the fork deactivated and reactivated the upgrade.") - assert_equal(set(node.getrawmempool()), { - ecdsa0tx_2.hash, schnorr1tx.hash}) - node.generate(1) - tip = self.getbestblock(node) - assert set(tx.rehash() for tx in tip.vtx).issuperset( - {ecdsa0tx_2.hash, schnorr1tx.hash}) - if __name__ == '__main__': - SchnorrTest().main() + SchnorrMultisigTest().main() diff --git a/test/functional/timing.json b/test/functional/timing.json --- a/test/functional/timing.json +++ b/test/functional/timing.json @@ -36,7 +36,7 @@ "time": 2 }, { - "name": "abc-minimaldata-activation.py", + "name": "abc-minimaldata.py", "time": 2 }, { @@ -64,7 +64,7 @@ "time": 2 }, { - "name": "abc-schnorrmultisig-activation.py", + "name": "abc-schnorrmultisig.py", "time": 3 }, {