diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -1236,10 +1236,6 @@ } break; case OP_REVERSEBYTES: { - if (!(flags & SCRIPT_ENABLE_OP_REVERSEBYTES)) { - return set_error(serror, ScriptError::BAD_OPCODE); - } - // (in -- out) if (stack.size() < 1) { return set_error( diff --git a/src/script/script_flags.h b/src/script/script_flags.h --- a/src/script/script_flags.h +++ b/src/script/script_flags.h @@ -107,9 +107,6 @@ // VERIFY_INPUT_SIGCHECKS SCRIPT_VERIFY_INPUT_SIGCHECKS = (1U << 22), - // Whether the new OP_REVERSEBYTES opcode can be used. - SCRIPT_ENABLE_OP_REVERSEBYTES = (1U << 23), - // A utility flag to decide whether VerifyScript should output the correct // sigchecks value or to report zero. // This has no effect on script success / failure, and will be removed diff --git a/src/test/data/script_tests.json b/src/test/data/script_tests.json --- a/src/test/data/script_tests.json +++ b/src/test/data/script_tests.json @@ -962,39 +962,37 @@ ], ["REVERSEBYTES"], -["0", "REVERSEBYTES 0 EQUAL", "P2SH", "BAD_OPCODE", "REVERSEBYTES, not yet activated in executed branch"], -["0x02 0xbeef", "REVERSEBYTES 0x02 0xefbe EQUAL", "P2SH", "BAD_OPCODE", "REVERSEBYTES, not yet activated in executed branch"], -["", "REVERSEBYTES 0 EQUAL", "P2SH,REVERSEBYTES", "INVALID_STACK_OPERATION", "REVERSEBYTES, empty stack"], -["0", "REVERSEBYTES 0 EQUAL", "P2SH,REVERSEBYTES", "OK", "REVERSEBYTES, empty data"], -["0x01 0x99", "REVERSEBYTES 0x01 0x99 EQUAL", "P2SH,REVERSEBYTES", "OK", "REVERSEBYTES, 1 byte"], -["0x02 0xbeef", "REVERSEBYTES 0x02 0xefbe EQUAL", "P2SH,REVERSEBYTES", "OK", "REVERSEBYTES, 2 bytes"], -["0x03 0xdeada1", "REVERSEBYTES 0x03 0xa1adde EQUAL", "P2SH,REVERSEBYTES", "OK", "REVERSEBYTES, 3 bytes"], -["0x04 0xdeadbeef", "REVERSEBYTES 0x04 0xefbeadde EQUAL", "P2SH,REVERSEBYTES", "OK", "REVERSEBYTES, 4 bytes"], -["0x41 0x1052a02f76cf6c3bc43e4671af4c6065f6d918c79f58ad7f90a49c4e2603a4728fc6d81d49087dd97bc43ae184da55dc5195553526ce076df092be27a398b68f41", "0x21 0xa8f459fbe84e0568ff03454d438183b0464e0c18ff73658ec0d2619b20ff29e502 REVERSEBYTES CHECKSIG", "NULLFAIL,STRICTENC,REVERSEBYTES,SIGHASH_FORKID", "OK", "REVERSEBYTES, reversed pubkey"], -["'Bitcoin:_A_peer-to-peer_electronic_cash_system'", "REVERSEBYTES 'metsys_hsac_cinortcele_reep-ot-reep_A_:nioctiB' EQUAL", "P2SH,REVERSEBYTES", "OK", "REVERSEBYTES, whitepaper title"], +["", "REVERSEBYTES 0 EQUAL", "P2SH", "INVALID_STACK_OPERATION", "REVERSEBYTES, empty stack"], +["0", "REVERSEBYTES 0 EQUAL", "P2SH", "OK", "REVERSEBYTES, empty data"], +["0x01 0x99", "REVERSEBYTES 0x01 0x99 EQUAL", "P2SH", "OK", "REVERSEBYTES, 1 byte"], +["0x02 0xbeef", "REVERSEBYTES 0x02 0xefbe EQUAL", "P2SH", "OK", "REVERSEBYTES, 2 bytes"], +["0x03 0xdeada1", "REVERSEBYTES 0x03 0xa1adde EQUAL", "P2SH", "OK", "REVERSEBYTES, 3 bytes"], +["0x04 0xdeadbeef", "REVERSEBYTES 0x04 0xefbeadde EQUAL", "P2SH", "OK", "REVERSEBYTES, 4 bytes"], +["0x41 0x1052a02f76cf6c3bc43e4671af4c6065f6d918c79f58ad7f90a49c4e2603a4728fc6d81d49087dd97bc43ae184da55dc5195553526ce076df092be27a398b68f41", "0x21 0xa8f459fbe84e0568ff03454d438183b0464e0c18ff73658ec0d2619b20ff29e502 REVERSEBYTES CHECKSIG", "NULLFAIL,STRICTENC,SIGHASH_FORKID", "OK", "REVERSEBYTES, reversed pubkey"], +["'Bitcoin:_A_peer-to-peer_electronic_cash_system'", "REVERSEBYTES 'metsys_hsac_cinortcele_reep-ot-reep_A_:nioctiB' EQUAL", "P2SH", "OK", "REVERSEBYTES, whitepaper title"], [ "'zngyivniryrgefgnvqwfwqplmramujzilzyrsdvinxfkfmuowdpuzycnzbupwwpzrfxsbyrhdlsyixyzysodseayvvrtbsfxtikrjwkbduulrjyjlwlaigomhyohsukawdwbrpuacdijzzgxhataguajvuopuktvtklwhsxqvzzfttpdgnxtnbpsiqecxurlczqmoxznlsuejvneiyejetcxlblzrydscnrbydnqytorstjtuzlbbtbyzfiniuehbisqnqhvexylhohjiyiknzgjowvobsrwcxyfowqcvakgdolwpltfcxtrhuysrrvtprzpsucgogsjapdkrbobpxccqgkdumskaleycwsbkabdkuukqiyizceduplmauszwjdzptvmthxocwrignxjogxsvrsjrrlecvdmazlpfkgmskiqqitrevuwiisvpxvkeypzaqjwwiozvmahmtvtjpbolwrymvzfstopzcexalirwbbcqgjvfjfuirrcnlgcfyqnafhh'", "REVERSEBYTES 'hhfanqyfcglncrriufjfvjgqcbbwrilaxeczpotsfzvmyrwlobpjtvtmhamvzoiwwjqazpyekvxpvsiiwuvertiqqiksmgkfplzamdvcelrrjsrvsxgojxngirwcoxhtmvtpzdjwzsuamlpudecziyiqkuukdbakbswcyelaksmudkgqccxpbobrkdpajsgogcuspzrptvrrsyuhrtxcftlpwlodgkavcqwofyxcwrsbovwojgznkiyijhohlyxevhqnqsibheuinifzybtbblzutjtsrotyqndybrncsdyrzlblxctejeyienvjeuslnzxomqzclruxceqispbntxngdpttfzzvqxshwlktvtkupouvjaugatahxgzzjidcauprbwdwakushoyhmogialwljyjrluudbkwjrkitxfsbtrvvyaesdosyzyxiysldhrybsxfrzpwwpubzncyzupdwoumfkfxnivdsryzlizjumarmlpqwfwqvngfegryrinviygnz' EQUAL", - "P2SH,REVERSEBYTES", "OK", "REVERSEBYTES, 520 bytes" + "P2SH", "OK", "REVERSEBYTES, 520 bytes" ], -["0x03 0x123456", "REVERSEBYTES 0x03 0x563412 OP_EQUAL", "P2SH,REVERSEBYTES", "OK", "REVERSEBYTES, 3 bytes equal"], -["0x06 0x020406080a0c", "DUP REVERSEBYTES REVERSEBYTES OP_EQUAL", "P2SH,REVERSEBYTES", "OK", "REVERSEBYTES, 3 bytes double reverse equal"], -["'Bitcoin:_A_peer-to-peer_electronic_cash_system'", "DUP REVERSEBYTES REVERSEBYTES OP_EQUAL", "P2SH,REVERSEBYTES", "OK", "REVERSEBYTES, whitepaper title double reverse equal"], +["0x03 0x123456", "REVERSEBYTES 0x03 0x563412 OP_EQUAL", "P2SH", "OK", "REVERSEBYTES, 3 bytes equal"], +["0x06 0x020406080a0c", "DUP REVERSEBYTES REVERSEBYTES OP_EQUAL", "P2SH", "OK", "REVERSEBYTES, 3 bytes double reverse equal"], +["'Bitcoin:_A_peer-to-peer_electronic_cash_system'", "DUP REVERSEBYTES REVERSEBYTES OP_EQUAL", "P2SH", "OK", "REVERSEBYTES, whitepaper title double reverse equal"], [ "'zngyivniryrgefgnvqwfwqplmramujzilzyrsdvinxfkfmuowdpuzycnzbupwwpzrfxsbyrhdlsyixyzysodseayvvrtbsfxtikrjwkbduulrjyjlwlaigomhyohsukawdwbrpuacdijzzgxhataguajvuopuktvtklwhsxqvzzfttpdgnxtnbpsiqecxurlczqmoxznlsuejvneiyejetcxlblzrydscnrbydnqytorstjtuzlbbtbyzfiniuehbisqnqhvexylhohjiyiknzgjowvobsrwcxyfowqcvakgdolwpltfcxtrhuysrrvtprzpsucgogsjapdkrbobpxccqgkdumskaleycwsbkabdkuukqiyizceduplmauszwjdzptvmthxocwrignxjogxsvrsjrrlecvdmazlpfkgmskiqqitrevuwiisvpxvkeypzaqjwwiozvmahmtvtjpbolwrymvzfstopzcexalirwbbcqgjvfjfuirrcnlgcfyqnafhh'", "DUP REVERSEBYTES REVERSEBYTES OP_EQUAL", - "P2SH,REVERSEBYTES", + "P2SH", "OK", "REVERSEBYTES, 520 bytes double reverse equal" ], -["0x05 0x0102030201", "DUP REVERSEBYTES OP_EQUAL", "P2SH,REVERSEBYTES", "OK", "REVERSEBYTES, palindrome 1"], -["0x08 0x7766554444556677", "DUP REVERSEBYTES OP_EQUAL", "P2SH,REVERSEBYTES", "OK", "REVERSEBYTES, palindrome 2"], -["'madam'", "DUP REVERSEBYTES OP_EQUAL", "P2SH,REVERSEBYTES", "OK", "REVERSEBYTES, palindrome 3"], -["'racecar'", "DUP REVERSEBYTES OP_EQUAL", "P2SH,REVERSEBYTES", "OK", "REVERSEBYTES, palindrome 4"], -["'redrum_siris_murder'", "DUP REVERSEBYTES OP_EQUAL", "P2SH,REVERSEBYTES", "OK", "REVERSEBYTES, palindrome 5"], -["'step_on_no_pets'", "DUP REVERSEBYTES OP_EQUAL", "P2SH,REVERSEBYTES", "OK", "REVERSEBYTES, palindrome 6"], -["'Bitcoin:_A_peer-to-peer_electronic_cash_system'", "DUP REVERSEBYTES OP_EQUAL", "P2SH,REVERSEBYTES", "EVAL_FALSE", "REVERSEBYTES, non-palindrome 1"], -["0x02 0x1234", "DUP REVERSEBYTES OP_EQUAL", "P2SH,REVERSEBYTES", "EVAL_FALSE", "REVERSEBYTES, non-palindrome 2"], +["0x05 0x0102030201", "DUP REVERSEBYTES OP_EQUAL", "P2SH", "OK", "REVERSEBYTES, palindrome 1"], +["0x08 0x7766554444556677", "DUP REVERSEBYTES OP_EQUAL", "P2SH", "OK", "REVERSEBYTES, palindrome 2"], +["'madam'", "DUP REVERSEBYTES OP_EQUAL", "P2SH", "OK", "REVERSEBYTES, palindrome 3"], +["'racecar'", "DUP REVERSEBYTES OP_EQUAL", "P2SH", "OK", "REVERSEBYTES, palindrome 4"], +["'redrum_siris_murder'", "DUP REVERSEBYTES OP_EQUAL", "P2SH", "OK", "REVERSEBYTES, palindrome 5"], +["'step_on_no_pets'", "DUP REVERSEBYTES OP_EQUAL", "P2SH", "OK", "REVERSEBYTES, palindrome 6"], +["'Bitcoin:_A_peer-to-peer_electronic_cash_system'", "DUP REVERSEBYTES OP_EQUAL", "P2SH", "EVAL_FALSE", "REVERSEBYTES, non-palindrome 1"], +["0x02 0x1234", "DUP REVERSEBYTES OP_EQUAL", "P2SH", "EVAL_FALSE", "REVERSEBYTES, non-palindrome 2"], ["NUM2BIN"], ["", "NUM2BIN 0 EQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "NUM2BIN, empty stack"], @@ -1276,7 +1274,6 @@ "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS", "Discouraged NOP10 in redeemScript"], ["0x50","1", "P2SH,STRICTENC", "BAD_OPCODE", "opcode 0x50 is reserved"], -["1", "IF REVERSEBYTES ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "opcode OP_REVERSEBYTES invalid if executed normally"], ["1", "IF 0xbd ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "opcodes >= FIRST_UNDEFINED_OP_VALUE invalid if executed"], ["1", "IF 0xbe ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xbf ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], diff --git a/src/test/op_reversebytes_tests.cpp b/src/test/op_reversebytes_tests.cpp --- a/src/test/op_reversebytes_tests.cpp +++ b/src/test/op_reversebytes_tests.cpp @@ -41,34 +41,6 @@ BOOST_CHECK(stack == expected); } -/** - * Verifies that the given error occurs with OP_REVERSEBYTES enabled - * and that BAD_OPCODE occurs if disabled. - */ -static void CheckErrorIfEnabled(const uint32_t flags, - const stacktype &original_stack, - const CScript &script, - const ScriptError expected) { - CheckErrorWithFlags(flags | SCRIPT_ENABLE_OP_REVERSEBYTES, original_stack, - script, expected); - CheckErrorWithFlags(flags & ~SCRIPT_ENABLE_OP_REVERSEBYTES, original_stack, - script, ScriptError::BAD_OPCODE); -} - -/** - * Verifies that the given stack results with OP_REVERSEBYTES enabled - * and that BAD_OPCODE occurs if disabled. - */ -static void CheckPassIfEnabled(const uint32_t flags, - const stacktype &original_stack, - const CScript &script, - const stacktype &expected) { - CheckPassWithFlags(flags | SCRIPT_ENABLE_OP_REVERSEBYTES, original_stack, - script, expected); - CheckErrorWithFlags(flags & ~SCRIPT_ENABLE_OP_REVERSEBYTES, original_stack, - script, ScriptError::BAD_OPCODE); -} - /** * Verifies the different combinations of a given test case. * Checks if @@ -79,13 +51,13 @@ */ static void CheckPassForCombinations(const uint32_t flags, const valtype &item, const valtype &reversed_item) { - CheckPassIfEnabled(flags, {item}, CScript() << OP_REVERSEBYTES, + CheckPassWithFlags(flags, {item}, CScript() << OP_REVERSEBYTES, {reversed_item}); - CheckPassIfEnabled(flags, {reversed_item}, CScript() << OP_REVERSEBYTES, + CheckPassWithFlags(flags, {reversed_item}, CScript() << OP_REVERSEBYTES, {item}); - CheckPassIfEnabled(flags, {item}, + CheckPassWithFlags(flags, {item}, CScript() << OP_REVERSEBYTES << OP_REVERSEBYTES, {item}); - CheckPassIfEnabled(flags, {reversed_item}, + CheckPassWithFlags(flags, {reversed_item}, CScript() << OP_REVERSEBYTES << OP_REVERSEBYTES, {reversed_item}); } @@ -162,7 +134,7 @@ // Verify random data passes. CheckPassForCombinations(flags, random_data, random_data_reversed); // Verify palindrome check passes. - CheckPassIfEnabled(flags, {palindrome}, + CheckPassWithFlags(flags, {palindrome}, CScript() << OP_REVERSEBYTES, {palindrome}); } } @@ -175,13 +147,13 @@ uint32_t flags = lcg.next(); // Verify non-palindrome fails. - CheckErrorIfEnabled(flags, {{0x01, 0x02, 0x03, 0x02, 0x02}}, + CheckErrorWithFlags(flags, {{0x01, 0x02, 0x03, 0x02, 0x02}}, CScript() << OP_DUP << OP_REVERSEBYTES << OP_EQUALVERIFY, ScriptError::EQUALVERIFY); // Test empty stack results in INVALID_STACK_OPERATION. - CheckErrorIfEnabled(flags, {}, CScript() << OP_REVERSEBYTES, + CheckErrorWithFlags(flags, {}, CScript() << OP_REVERSEBYTES, ScriptError::INVALID_STACK_OPERATION); } } diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -151,7 +151,7 @@ // anything about what happens when they are flipped. Keep them as-is. extra_flags &= ~(SCRIPT_ENABLE_SIGHASH_FORKID | SCRIPT_ENABLE_REPLAY_PROTECTION | - SCRIPT_ENABLE_SCHNORR_MULTISIG | SCRIPT_ENABLE_OP_REVERSEBYTES); + SCRIPT_ENABLE_SCHNORR_MULTISIG); uint32_t combined_flags = expect ? (flags & ~extra_flags) : (flags | extra_flags); // Weed out invalid flag combinations. diff --git a/src/test/scriptflags.cpp b/src/test/scriptflags.cpp --- a/src/test/scriptflags.cpp +++ b/src/test/scriptflags.cpp @@ -33,7 +33,6 @@ {"DISALLOW_SEGWIT_RECOVERY", SCRIPT_DISALLOW_SEGWIT_RECOVERY}, {"SCHNORR_MULTISIG", SCRIPT_ENABLE_SCHNORR_MULTISIG}, {"INPUT_SIGCHECKS", SCRIPT_VERIFY_INPUT_SIGCHECKS}, - {"REVERSEBYTES", SCRIPT_ENABLE_OP_REVERSEBYTES}, }; uint32_t ParseScriptFlags(std::string strFlags) { diff --git a/src/validation.cpp b/src/validation.cpp --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1119,22 +1119,6 @@ scriptError = check2.GetScriptError(); } - // Before banning, we need to check whether the transaction would - // be valid on the other side of the upgrade, so as to avoid - // splitting the network between upgraded and non-upgraded nodes. - // Note that this will create strange error messages like - // "upgrade-conditional-script-failure (Opcode missing or not - // understood)". - CScriptCheck check3(scriptPubKey, amount, tx, i, - mandatoryFlags ^ SCRIPT_ENABLE_OP_REVERSEBYTES, - sigCacheStore, txdata); - if (check3()) { - return state.Invalid( - false, REJECT_INVALID, - strprintf("upgrade-conditional-script-failure (%s)", - ScriptErrorString(check.GetScriptError()))); - } - // Failures of other flags indicate a transaction that is invalid in // new blocks, e.g. a invalid P2SH. We DoS ban such nodes as they // are not following the protocol. That said during an upgrade @@ -1492,7 +1476,6 @@ } if (IsPhononEnabled(params, pindex)) { - flags |= SCRIPT_ENABLE_OP_REVERSEBYTES; flags |= SCRIPT_REPORT_SIGCHECKS; } diff --git a/test/functional/abc-op-reversebytes-activation.py b/test/functional/abc-op-reversebytes-activation.py deleted file mode 100755 --- a/test/functional/abc-op-reversebytes-activation.py +++ /dev/null @@ -1,291 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2020 The Bitcoin developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. -""" -This test checks the activation logic of OP_REVERSEBYTES. -Derived from both abc-schnorrmultisig-activation.py (see https://reviews.bitcoinabc.org/D3736) and -abc-schnorrmultisig.py -""" - -from test_framework.blocktools import ( - create_block, - create_coinbase, - create_tx_with_script, - make_conform_to_ctor, -) -from test_framework.messages import ( - CBlock, - COutPoint, - CTransaction, - CTxIn, - CTxOut, - FromHex, - ToHex, -) -from test_framework.mininode import ( - P2PDataStore, -) -from test_framework.script import ( - CScript, - OP_EQUAL, - OP_REVERSEBYTES, - OP_RETURN, -) -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. -PHONON_START_TIME = 2000000000 - - -# Blocks with invalid scripts give this error: -BAD_INPUTS_ERROR = 'blk-bad-inputs' - -# Pre-upgrade, we get a BAD_OPCODE error -PRE_UPGRADE_BAD_OPCODE_ERROR = \ - 'upgrade-conditional-script-failure (Opcode missing or not understood)' - - -class OpReversebytesActivationTest(BitcoinTestFramework): - def set_test_params(self): - self.num_nodes = 1 - self.block_heights = {} - self.extra_args = [ - ["-phononactivationtime={}".format(PHONON_START_TIME), - "-acceptnonstdtxn=1"]] - - def bootstrap_p2p(self, *, num_connections=1): - """Add a P2P connection to the node. - - Helper to connect and wait for version handshake.""" - for _ in range(num_connections): - self.nodes[0].add_p2p_connection(P2PDataStore()) - self.nodes[0].p2p.wait_for_verack() - - def reconnect_p2p(self, **kwargs): - """Tear down and bootstrap the P2P connection to the node. - - The node gets disconnected several times in this test. This helper - method reconnects the p2p and restarts the network thread.""" - self.nodes[0].disconnect_p2ps() - self.bootstrap_p2p(**kwargs) - - def get_best_block(self, node): - """Get the best block. Register its height so we can use build_block.""" - block_height = node.getblockcount() - blockhash = node.getblockhash(block_height) - block = FromHex(CBlock(), node.getblock(blockhash, 0)) - block.calc_sha256() - self.block_heights[block.sha256] = block_height - return block - - def build_block(self, parent, transactions=(), n_time=None): - """Make a new block with an OP_1 coinbase output. - - Requires parent to have its height registered.""" - parent.calc_sha256() - block_height = self.block_heights[parent.sha256] + 1 - block_time = (parent.nTime + 1) if n_time is None else n_time - - block = create_block( - parent.sha256, create_coinbase(block_height), block_time) - block.vtx.extend(transactions) - make_conform_to_ctor(block) - block.hashMerkleRoot = block.calc_merkle_root() - block.solve() - self.block_heights[block.sha256] = block_height - return block - - 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_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_ban_on_rejected_block(self, block, reject_reason=None): - """Check we are disconnected when sending a block that the node rejects. - - (Can't actually get banned, since bitcoind won't ban local peers.)""" - self.nodes[0].p2p.send_blocks_and_test([block], self.nodes[0], success=False, - reject_reason=reject_reason, expect_disconnect=True) - self.reconnect_p2p() - - def run_test(self): - node, = self.nodes - - self.bootstrap_p2p() - - tip = self.get_best_block(node) - - self.log.info("Create some blocks with OP_1 coinbase for spending.") - blocks = [] - for _ in range(10): - tip = self.build_block(tip) - blocks.append(tip) - node.p2p.send_blocks_and_test(blocks, node, success=True) - spendable_outputs = [block.vtx[0] for block in blocks] - - self.log.info("Mature the blocks and get out of IBD.") - node.generatetoaddress(100, node.get_deterministic_priv_key().address) - - tip = self.get_best_block(node) - - self.log.info( - "Set up spending transactions to test and mine the funding transactions.") - - def create_fund_and_spend_tx(): - spend_from = spendable_outputs.pop() - value = spend_from.vout[0].nValue - - # Reversed data - data = bytes.fromhex('0123456789abcdef') - rev_data = bytes(reversed(data)) - - # Lockscript: provide a bytestring that reverses to X - script = CScript([OP_REVERSEBYTES, rev_data, OP_EQUAL]) - - # Fund transaction: REVERSEBYTES EQUAL - tx_fund = create_tx_with_script(spend_from, 0, b'', value, script) - tx_fund.rehash() - - # Spend transaction: - tx_spend = CTransaction() - tx_spend.vout.append( - CTxOut(value - 1000, CScript([b'x' * 100, OP_RETURN]))) - tx_spend.vin.append( - CTxIn(COutPoint(tx_fund.sha256, 0), b'')) - tx_spend.vin[0].scriptSig = CScript([data]) - tx_spend.rehash() - - return tx_spend, tx_fund - - # Create funding/spending transaction pair - tx_reversebytes_spend, tx_reversebytes_fund = create_fund_and_spend_tx() - - # Mine funding transaction into block. Pre-upgrade output scripts can have - # OP_REVERSEBYTES and still be fully valid, but they cannot spend it. - tip = self.build_block(tip, [tx_reversebytes_fund]) - node.p2p.send_blocks_and_test([tip], node) - - self.log.info("Start pre-upgrade tests") - - self.log.info( - "Sending rejected transaction (bad opcode) via RPC (doesn't ban)") - assert_raises_rpc_error(-26, PRE_UPGRADE_BAD_OPCODE_ERROR, - node.sendrawtransaction, ToHex(tx_reversebytes_spend)) - - self.log.info( - "Sending rejected transaction (bad opcode) via net (no banning)") - self.check_for_no_ban_on_rejected_tx( - tx_reversebytes_spend, PRE_UPGRADE_BAD_OPCODE_ERROR) - - self.log.info( - "Sending invalid transactions in blocks (bad inputs, and get banned)") - self.check_for_ban_on_rejected_block(self.build_block(tip, [tx_reversebytes_spend]), - BAD_INPUTS_ERROR) - - self.log.info("Start activation tests") - - self.log.info("Approach to just before upgrade activation") - # Move our clock to the upgrade time so we will accept such - # future-timestamped blocks. - node.setmocktime(PHONON_START_TIME) - - # Mine six blocks with timestamp starting at PHONON_START_TIME-1 - blocks = [] - for i in range(-1, 5): - tip = self.build_block(tip, n_time=PHONON_START_TIME + i) - blocks.append(tip) - node.p2p.send_blocks_and_test(blocks, node) - - # Ensure our MTP is PHONON_START_TIME-1, just before activation - assert_equal(node.getblockchaininfo()['mediantime'], - PHONON_START_TIME - 1) - - self.log.info( - "The next block will activate, but the activation block itself must follow old rules") - self.check_for_ban_on_rejected_block( - self.build_block(tip, [tx_reversebytes_spend]), BAD_INPUTS_ERROR) - - # Save pre-upgrade block, we will reorg based on this block later - pre_upgrade_block = tip - - self.log.info("Mine the activation block itself") - tip = self.build_block(tip, []) - node.p2p.send_blocks_and_test([tip], node) - - self.log.info("We have activated!") - # Ensure our MTP is PHONON_START_TIME, exactly at activation - assert_equal(node.getblockchaininfo()['mediantime'], PHONON_START_TIME) - # Ensure empty mempool - assert_equal(node.getrawmempool(), []) - - # Save upgrade block, will invalidate and reconsider this later - upgrade_block = tip - - self.log.info( - "Submitting a new OP_REVERSEBYTES tx via net, and mining it in a block") - # Send OP_REVERSEBYTES tx - node.p2p.send_txs_and_test([tx_reversebytes_spend], node) - - # Verify OP_REVERSEBYTES tx is in mempool - assert_equal(set(node.getrawmempool()), {tx_reversebytes_spend.hash}) - - # Mine OP_REVERSEBYTES tx into block - tip = self.build_block(tip, [tx_reversebytes_spend]) - node.p2p.send_blocks_and_test([tip], node) - - # Save post-upgrade block, will invalidate and reconsider this later - post_upgrade_block = tip - - self.log.info("Start deactivation tests") - - self.log.info( - "Invalidating the post-upgrade blocks returns OP_REVERSEBYTES transaction to mempool") - node.invalidateblock(post_upgrade_block.hash) - assert_equal(set(node.getrawmempool()), { - tx_reversebytes_spend.hash}) - - self.log.info( - "Invalidating the upgrade block evicts the OP_REVERSEBYTES transaction") - node.invalidateblock(upgrade_block.hash) - assert_equal(set(node.getrawmempool()), set()) - - self.log.info("Return to our tip") - node.reconsiderblock(upgrade_block.hash) - node.reconsiderblock(post_upgrade_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 = pre_upgrade_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()), - {tx_reversebytes_spend.hash}) - node.generatetoaddress(1, node.get_deterministic_priv_key().address) - tip = self.get_best_block(node) - assert (set(tx.rehash() for tx in tip.vtx) >= - {tx_reversebytes_spend.hash}) - - -if __name__ == '__main__': - OpReversebytesActivationTest().main()