diff --git a/src/validation.cpp b/src/validation.cpp --- a/src/validation.cpp +++ b/src/validation.cpp @@ -719,11 +719,10 @@ } if (IsGreatWallEnabledForCurrentBlock(config)) { - if (fRequireStandard) { - extraFlags |= SCRIPT_DISALLOW_SEGWIT_RECOVERY; - } extraFlags |= SCRIPT_ENABLE_SCHNORR; - } else { + } + + if (fRequireStandard) { extraFlags |= SCRIPT_DISALLOW_SEGWIT_RECOVERY; } @@ -1622,15 +1621,12 @@ flags |= SCRIPT_VERIFY_CLEANSTACK; } - // If the Great Wall fork is enabled, we start accepting transactions - // recovering coins sent to segwit addresses. We also start accepting + // If the Great Wall fork is enabled, we start accepting // 65/64-byte Schnorr signatures in CHECKSIG and CHECKDATASIG respectively, // and their verify variants. We also stop accepting 65 byte signatures in // CHECKMULTISIG and its verify variant. if (IsGreatWallEnabled(config, pChainTip)) { flags |= SCRIPT_ENABLE_SCHNORR; - } else { - flags |= SCRIPT_DISALLOW_SEGWIT_RECOVERY; } // We make sure this node will have replay protection during the next hard diff --git a/test/functional/abc-segwit-recovery-activation.py b/test/functional/abc-segwit-recovery.py rename from test/functional/abc-segwit-recovery-activation.py rename to test/functional/abc-segwit-recovery.py --- a/test/functional/abc-segwit-recovery-activation.py +++ b/test/functional/abc-segwit-recovery.py @@ -4,15 +4,19 @@ # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """ -This test checks activation of the Segwit Recovery feature. +This test checks that blocks containing segwit recovery transactions will be accepted, +that segwit recovery transactions are rejected from mempool acceptance (even with +-acceptnonstdtxn=1), and that segwit recovery transactions don't result in bans. """ +import time + from test_framework.blocktools import ( create_block, create_coinbase, make_conform_to_ctor, ) -from test_framework.comptool import RejectResult, TestInstance, TestManager +from test_framework.comptool import TestInstance, TestManager from test_framework.messages import ( COIN, COutPoint, @@ -36,16 +40,11 @@ ) from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( - assert_equal, assert_raises_rpc_error, sync_blocks, ) -# far into the future -GREAT_WALL_START_TIME = 2000000000 - -# First blocks (initial coinbases, pre-fork test blocks) happen 1 day before. -FIRST_BLOCK_TIME = GREAT_WALL_START_TIME - 86400 +TEST_TIME = int(time.time()) # Error due to non clean stack CLEANSTACK_ERROR = b'non-mandatory-script-verify-flag (Script did not clean its stack)' @@ -63,7 +62,7 @@ self.n = n -class SegwitRecoveryActivationTest(BitcoinTestFramework): +class SegwitRecoveryTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 2 @@ -72,35 +71,26 @@ self.tip = None self.blocks = {} # We have 2 nodes: - # 1) node_nonstd (nodes[0]) accepts non-standard txns. It's used to - # test the activation itself via TestManager. + # 1) node_nonstd (nodes[0]) accepts non-standard txns. We check it + # accepts segwit spending txns. # 2) node_std (nodes[1]) doesn't accept non-standard txns and # doesn't have us whitelisted. It's used to test for bans, as we # connect directly to it via mininode and send a segwit spending - # txn. This transaction is non-standard and, before activation, - # also invalid. We check, before and after activation, that - # sending this transaction doesn't result in a ban. + # txn. This transaction is non-standard. We check that sending + # this transaction doesn't result in a ban. # Nodes are connected to each other, so node_std receives blocks and # transactions that node_nonstd has accepted. Since we are checking # that segwit spending txn are not resulting in bans, node_nonstd # doesn't get banned when forwarding this kind of transactions to # node_std. self.extra_args = [['-whitelist=127.0.0.1', - "-acceptnonstdtxn", - "-greatwallactivationtime={}".format( - GREAT_WALL_START_TIME), - "-replayprotectionactivationtime={}".format( - 2 * GREAT_WALL_START_TIME)], - ["-acceptnonstdtxn=0", - "-greatwallactivationtime={}".format( - GREAT_WALL_START_TIME), - "-replayprotectionactivationtime={}".format( - 2 * GREAT_WALL_START_TIME)]] + "-acceptnonstdtxn"], + ["-acceptnonstdtxn=0"]] def run_test(self): # Move the mocktime up to activation for node in self.nodes: - node.setmocktime(GREAT_WALL_START_TIME) + node.setmocktime(TEST_TIME) test = TestManager(self, self.options.tmpdir) # TestManager only connects to node_nonstd (nodes[0]) test.add_all_connections([self.nodes[0]]) @@ -112,7 +102,7 @@ def next_block(self, number): if self.tip == None: base_block_hash = self.genesis_hash - block_time = FIRST_BLOCK_TIME + block_time = TEST_TIME else: base_block_hash = self.tip.sha256 block_time = self.tip.nTime + 1 @@ -189,8 +179,6 @@ # 2) txspend: spends outputs from segwit addresses def create_segwit_fund_and_spend_tx(spend, case0=False): if not case0: - # To make sure we'll be able to recover coins sent to segwit addresses, - # we test using historical recoveries from btc.com: # Spending from a P2SH-P2WPKH coin, # txhash:a45698363249312f8d3d93676aa714be59b0bd758e62fa054fb1ea6218480691 redeem_script0 = bytearray.fromhex( @@ -281,63 +269,16 @@ txfund_case0, txspend_case0 = create_segwit_fund_and_spend_tx( out[1], True) - # Create blocks to get closer to activate the fork. # Mine txfund, as it can't go into node_std mempool because it's # nonstandard. b = block(5555) - b.nTime = GREAT_WALL_START_TIME - 1 update_block(5555, [txfund, txfund_case0]) yield accepted() - for i in range(5): - block(5100 + i) - test.blocks_and_transactions.append([self.tip, True]) - yield test - # Since the TestManager is not connected to node_std, we must check # both nodes are synchronized before continuing. sync_blocks(self.nodes) - # Check we are just before the activation time - assert_equal(node_nonstd.getblockheader( - node_nonstd.getbestblockhash())['mediantime'], GREAT_WALL_START_TIME - 1) - assert_equal(node_std.getblockheader( - node_std.getbestblockhash())['mediantime'], GREAT_WALL_START_TIME - 1) - - # Before the fork, segwit spending txns are rejected. - assert_raises_rpc_error(-26, RPC_CLEANSTACK_ERROR, - node_nonstd.sendrawtransaction, ToHex(txspend)) - assert_raises_rpc_error(-26, RPC_CLEANSTACK_ERROR, - node_std.sendrawtransaction, ToHex(txspend)) - assert_raises_rpc_error(-26, RPC_EVAL_FALSE_ERROR, - node_nonstd.sendrawtransaction, ToHex(txspend_case0)) - assert_raises_rpc_error(-26, RPC_EVAL_FALSE_ERROR, - node_std.sendrawtransaction, ToHex(txspend_case0)) - - # Blocks containing segwit spending txns are rejected as well. - block(2) - update_block(2, [txspend, txspend_case0]) - yield rejected(RejectResult(16, b'blk-bad-inputs')) - - # Rewind bad block - tip(5104) - - # Check that non-upgraded nodes checking for standardness are not - # banning nodes sending segwit spending txns. - check_for_no_ban_on_rejected_tx(txspend, 64, CLEANSTACK_ERROR) - check_for_no_ban_on_rejected_tx(txspend_case0, 64, EVAL_FALSE_ERROR) - - # Activate the fork in both nodes! - forkblock = block(5556) - yield accepted() - sync_blocks(self.nodes) - - # Check we just activated the fork - assert_equal(node_nonstd.getblockheader( - node_nonstd.getbestblockhash())['mediantime'], GREAT_WALL_START_TIME) - assert_equal(node_std.getblockheader( - node_std.getbestblockhash())['mediantime'], GREAT_WALL_START_TIME) - # Check that upgraded nodes checking for standardness are not banning # nodes sending segwit spending txns. check_for_no_ban_on_rejected_tx(txspend, 64, CLEANSTACK_ERROR) @@ -353,27 +294,12 @@ assert_raises_rpc_error(-26, RPC_EVAL_FALSE_ERROR, node_std.sendrawtransaction, ToHex(txspend_case0)) - # Blocks containing segwit spending txns are now accepted in both - # nodes. + # Blocks containing segwit spending txns are accepted in both nodes. block(5) postforkblock = update_block(5, [txspend, txspend_case0]) yield accepted() sync_blocks(self.nodes) - # Ok, now we check if a reorg work properly accross the activation. - node_nonstd.invalidateblock(postforkblock.hash) - check_mempool_equal(node_nonstd, [txspend, txspend_case0]) - - # Also check that nodes checking for standardness don't return a segwit - # spending txn into the mempool when disconnecting a block. - node_std.invalidateblock(postforkblock.hash) - assert(len(node_std.getrawmempool()) == 0) - - # Deactivate the fork. The spending tx has been evicted from the - # mempool - node_nonstd.invalidateblock(forkblock.hash) - assert(len(node_nonstd.getrawmempool()) == 0) - if __name__ == '__main__': - SegwitRecoveryActivationTest().main() + SegwitRecoveryTest().main()