diff --git a/src/chainparams.cpp b/src/chainparams.cpp --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -123,8 +123,8 @@ // November 15, 2018 hard fork consensus.magneticAnomalyHeight = 556766; - // Nov 15, 2019 12:00:00 UTC protocol upgrade - consensus.gravitonActivationTime = 1573819200; + // November 15, 2019 protocol upgrade + consensus.gravitonHeight = 609135; // May 15, 2020 12:00:00 UTC protocol upgrade consensus.phononActivationTime = 1589544000; @@ -294,8 +294,8 @@ // November 15, 2018 hard fork consensus.magneticAnomalyHeight = 1267996; - // Nov 15, 2019 12:00:00 UTC protocol upgrade - consensus.gravitonActivationTime = 1573819200; + // November 15, 2019 protocol upgrade + consensus.gravitonHeight = 1341711; // May 15, 2020 12:00:00 UTC protocol upgrade consensus.phononActivationTime = 1589544000; @@ -421,8 +421,8 @@ // November 15, 2018 hard fork is always on on regtest. consensus.magneticAnomalyHeight = 0; - // Nov 15, 2019 12:00:00 UTC protocol upgrade - consensus.gravitonActivationTime = 1573819200; + // November 15, 2019 protocol upgrade + consensus.gravitonHeight = 0; // May 15, 2020 12:00:00 UTC protocol upgrade consensus.phononActivationTime = 1589544000; diff --git a/src/consensus/activation.cpp b/src/consensus/activation.cpp --- a/src/consensus/activation.cpp +++ b/src/consensus/activation.cpp @@ -48,15 +48,18 @@ return IsMagneticAnomalyEnabled(params, pindexPrev->nHeight); } +static bool IsGravitonEnabled(const Consensus::Params ¶ms, + int32_t nHeight) { + return nHeight >= params.gravitonHeight; +} + bool IsGravitonEnabled(const Consensus::Params ¶ms, const CBlockIndex *pindexPrev) { if (pindexPrev == nullptr) { return false; } - return pindexPrev->GetMedianTimePast() >= - gArgs.GetArg("-gravitonactivationtime", - params.gravitonActivationTime); + return IsGravitonEnabled(params, pindexPrev->nHeight); } bool IsPhononEnabled(const Consensus::Params ¶ms, diff --git a/src/consensus/params.h b/src/consensus/params.h --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -34,8 +34,8 @@ int daaHeight; /** Block height at which the magnetic anomaly activation becomes active */ int magneticAnomalyHeight; - /** Unix time used for MTP activation of Nov 15 2019 12:00:00 UTC upgrade */ - int gravitonActivationTime; + /** Block height at which the graviton activation becomes active */ + int gravitonHeight; /** Unix time used for MTP activation of 15 May 2020 12:00:00 UTC upgrade */ int phononActivationTime; /** Proof of work parameters */ diff --git a/src/init.cpp b/src/init.cpp --- a/src/init.cpp +++ b/src/init.cpp @@ -986,9 +986,6 @@ gArgs.AddArg("-replayprotectionactivationtime", "", false, OptionsCategory::HIDDEN); - // TODO remove after the Nov 2019 upgrade - gArgs.AddArg("-gravitonactivationtime", "", false, OptionsCategory::HIDDEN); - // TODO remove after the May 2020 upgrade gArgs.AddArg("-phononactivationtime", "", false, OptionsCategory::HIDDEN); } diff --git a/src/test/activation_tests.cpp b/src/test/activation_tests.cpp --- a/src/test/activation_tests.cpp +++ b/src/test/activation_tests.cpp @@ -24,29 +24,21 @@ } BOOST_AUTO_TEST_CASE(isgravitonenabled) { - CBlockIndex prev; - - const Consensus::Params ¶ms = Params().GetConsensus(); - const auto activation = - gArgs.GetArg("-gravitonactivationtime", params.gravitonActivationTime); - SetMockTime(activation - 1000000); + const auto ¶ms = + CreateChainParams(CBaseChainParams::MAIN)->GetConsensus(); BOOST_CHECK(!IsGravitonEnabled(params, nullptr)); - std::array blocks; + std::array blocks; + blocks[0].nHeight = params.gravitonHeight - 2; for (size_t i = 1; i < blocks.size(); ++i) { blocks[i].pprev = &blocks[i - 1]; + blocks[i].nHeight = blocks[i - 1].nHeight + 1; } - BOOST_CHECK(!IsGravitonEnabled(params, &blocks.back())); - - SetMTP(blocks, activation - 1); - BOOST_CHECK(!IsGravitonEnabled(params, &blocks.back())); - - SetMTP(blocks, activation); - BOOST_CHECK(IsGravitonEnabled(params, &blocks.back())); - - SetMTP(blocks, activation + 1); - BOOST_CHECK(IsGravitonEnabled(params, &blocks.back())); + BOOST_CHECK(!IsGravitonEnabled(params, &blocks[0])); + BOOST_CHECK(!IsGravitonEnabled(params, &blocks[1])); + BOOST_CHECK(IsGravitonEnabled(params, &blocks[2])); + BOOST_CHECK(IsGravitonEnabled(params, &blocks[3])); } BOOST_AUTO_TEST_CASE(isphononenabled) { diff --git a/src/test/test_bitcoin_main.cpp b/src/test/test_bitcoin_main.cpp --- a/src/test/test_bitcoin_main.cpp +++ b/src/test/test_bitcoin_main.cpp @@ -28,13 +28,12 @@ return false; } -std::set testArgs = { - "-gravitonactivationtime", - "-phononactivationtime", -}; - int main(int argc, char *argv[]) { // Additional CLI params supported by test_bitcoin: + std::set testArgs = { + "-phononactivationtime", + }; + // Note: gArgs.ParseParameters() cannot be called here or it will fail to // parse BOOST runtime params. for (int i = 1; i < argc; i++) { diff --git a/src/validation.cpp b/src/validation.cpp --- a/src/validation.cpp +++ b/src/validation.cpp @@ -461,12 +461,6 @@ return IsMagneticAnomalyEnabled(params, chainActive.Tip()); } -static bool IsGravitonEnabledForCurrentBlock(const Consensus::Params ¶ms) - EXCLUSIVE_LOCKS_REQUIRED(cs_main) { - AssertLockHeld(cs_main); - return IsGravitonEnabled(params, chainActive.Tip()); -} - // Command-line argument "-replayprotectionactivationtime=" will // cause the node to switch to replay protected SigHash ForkID value when the // median timestamp of the previous 11 blocks is greater than or equal to @@ -795,6 +789,9 @@ if (!CheckInputsFromMempoolAndCache(tx, state, view, pool, nextBlockScriptVerifyFlags, true, txdata)) { + // This can occur under some circumstances, if the node receives an + // unrequested tx which is invalid due to new consensus rules not + // being activated yet (during IBD). return error("%s: BUG! PLEASE REPORT THIS! CheckInputs failed " "against next-block but not STANDARD flags %s, %s", __func__, txid.ToString(), FormatStateMessage(state)); diff --git a/test/functional/abc-minimaldata-activation.py b/test/functional/abc-minimaldata-activation.py --- a/test/functional/abc-minimaldata-activation.py +++ b/test/functional/abc-minimaldata-activation.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,33 +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 in mempool are -# rejected with a bannable error. +# Minimal push violations in mempool are rejected with a bannable error. MINIMALPUSH_ERROR = 'mandatory-script-verify-flag-failed (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)]] def bootstrap_p2p(self, *, num_connections=1): """Add a P2P connection to the node. @@ -114,11 +101,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. @@ -177,72 +159,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 (banning)") - self.check_for_ban_on_rejected_tx( - nonminimaltx, MINIMALPUSH_ERROR) - self.check_for_ban_on_rejected_tx( - nonminimaltx_2, MINIMALPUSH_ERROR) - self.check_for_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 are banned") assert_raises_rpc_error(-26, MINIMALPUSH_ERROR, - node.sendrawtransaction, ToHex(nonminimaltx_3)) + node.sendrawtransaction, ToHex(nonminimaltx)) self.check_for_ban_on_rejected_tx( - nonminimaltx_3, MINIMALPUSH_ERROR) + nonminimaltx, MINIMALPUSH_ERROR) self.log.info("Mine a normal block") tip = self.build_block(tip) @@ -250,4 +181,4 @@ if __name__ == '__main__': - SchnorrTest().main() + MinimaldataTest().main() diff --git a/test/functional/abc-schnorrmultisig-activation.py b/test/functional/abc-schnorrmultisig-activation.py --- a/test/functional/abc-schnorrmultisig-activation.py +++ b/test/functional/abc-schnorrmultisig-activation.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,188 +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 nonstandard 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)) - # Since MULTISIG_SCHNORR is in mandatory flags, we are not accepting - # non-null-dummy ECDSA transactions before the upgrade. We get a - # post-upgrade error since the mempool is using post-upgrade flags. - assert_raises_rpc_error(-26, POSTUPGRADE_ECDSA_NULLDUMMY_ERROR, - node.sendrawtransaction, ToHex(ecdsa1tx)) - - # The Schnorr multisig almost gets accepted here but it finally gets - # caught in the block flags check. Note that "BUG! PLEASE REPORT - # THIS!" will appear in the log, since AcceptToMemoryPoolWorker expects - # that scriptVerifyFlags is more strict than nextBlockScriptVerifyFlags. - # For strictly subtractive ('soft forking') flags, it is fine if they - # are always part of scriptVerifyFlags and only sometimes appear in - # nextBlockScriptVerifyFlags, but for additive flags this kind of - # strange situation can be created. - # In practice, only new nodes will ever be in a pre-upgrade state, - # and they will also be in initial block download mode and hence - # not request transactions from peers. So, this weird log message - # could only be triggered by unsolicited submission of a tx, and - # it would be benign since the node is behaving correctly by rejecting - # the transaction (as tested here). - 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( - ecdsa1tx, POSTUPGRADE_ECDSA_NULLDUMMY_ERROR) - # If we are sent unsolicited post-upgrade transactions while before - # the upgrade block, the tx is to be rejected. - 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") - 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}) - - 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()