diff --git a/src/validation.cpp b/src/validation.cpp --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1916,6 +1916,10 @@ flags |= SCRIPT_VERIFY_NULLFAIL; } + if (IsMagneticAnomalyEnabled(config, pChainTip)) { + flags |= SCRIPT_VERIFY_SIGPUSHONLY; + } + // We make sure this node will have replay protection during the next hard // fork. if (IsReplayProtectionEnabled(config, pChainTip)) { diff --git a/test/functional/abc-magnetic-anomaly-activation.py b/test/functional/abc-magnetic-anomaly-activation.py --- a/test/functional/abc-magnetic-anomaly-activation.py +++ b/test/functional/abc-magnetic-anomaly-activation.py @@ -10,7 +10,9 @@ from test_framework.test_framework import ComparisonTestFramework from test_framework.util import assert_equal, assert_raises_rpc_error from test_framework.comptool import TestManager, TestInstance, RejectResult -from test_framework.blocktools import * +from test_framework.blocktools import create_coinbase, create_block +from test_framework.mininode import * +from test_framework.script import * from test_framework.cdefs import MIN_TX_SIZE from collections import deque @@ -50,9 +52,10 @@ [tx.rehash() for tx in tx_list] block.vtx.extend(tx_list) - def next_block(self, number, spend=None, tx_size=0): + def next_block(self, number, spend=None, tx_size=0, pushonly=True): if self.tip == None: base_block_hash = self.genesis_hash + import time block_time = int(time.time()) + 1 else: base_block_hash = self.tip.sha256 @@ -78,6 +81,8 @@ # Spend from one of the spendable outputs spend = spendable_outputs.popleft() tx.vin.append(CTxIn(COutPoint(spend.tx.sha256, spend.n))) + if pushonly == False: + tx.vin[0].scriptSig = CScript([OP_TRUE, OP_DROP]) # Add spendable outputs for i in range(2): tx.vout.append(CTxOut(0, CScript([OP_TRUE]))) @@ -87,8 +92,19 @@ tx.vout.append( CTxOut(0, CScript([random.getrandbits(8), OP_RETURN]))) else: - tx.vout.append( - CTxOut(0, CScript([random.getrandbits(8 * (tx_size - 82) - 1), OP_RETURN]))) + # Create an input to pad the transaction. + tx.vout.append(CTxOut(0, CScript([OP_RETURN]))) + + # Estimate the size of the padding. + push_size = tx_size - len(tx.serialize()) - 1 + + # Because several field are of variable size, we grow the push slowly + # up to the requested size. + while len(tx.serialize()) < tx_size: + tx.vout[2] = CTxOut(0, CScript( + [random.getrandbits(8 * push_size - 1), OP_RETURN])) + push_size += 1 + assert_equal(len(tx.serialize()), tx_size) # Make it the same format as transaction added for padding and save the size. @@ -197,8 +213,9 @@ assert_equal(node.getblockheader(node.getbestblockhash())['mediantime'], MAGNETIC_ANOMALY_START_TIME - 1) - # Check that block with small transactions are still accepted. - small_tx_block = block(4444, out[0], MIN_TX_SIZE - 1) + # Check that block with small transactions and non push only signatures + # are still accepted. + small_tx_block = block(4444, out[0], MIN_TX_SIZE - 1, False) assert_equal(len(small_tx_block.vtx[1].serialize()), MIN_TX_SIZE - 1) yield accepted() @@ -215,8 +232,17 @@ # Rewind bad block. tip(4444) + # Now that the for activated, it is not possible to have + # non push only transactions. + non_pushonly_tx_block = block(4446, out[1], MIN_TX_SIZE, False) + assert_equal(len(small_tx_block.vtx[1].serialize()), MIN_TX_SIZE - 1) + yield rejected(RejectResult(16, b'blk-bad-inputs')) + + # Rewind bad block. + tip(4444) + # But large transactions are still ok. - large_tx_block = block(4446, out[1], MIN_TX_SIZE) + large_tx_block = block(3333, out[1], MIN_TX_SIZE) assert_equal(len(large_tx_block.vtx[1].serialize()), MIN_TX_SIZE) yield accepted()