Changeset View
Changeset View
Standalone View
Standalone View
test/functional/feature_dersig.py
Show All 22 Lines | |||||
def unDERify(tx): | def unDERify(tx): | ||||
""" | """ | ||||
Make the signature in vin 0 of a tx non-DER-compliant, | Make the signature in vin 0 of a tx non-DER-compliant, | ||||
by adding padding after the S-value. | by adding padding after the S-value. | ||||
""" | """ | ||||
scriptSig = CScript(tx.vin[0].scriptSig) | scriptSig = CScript(tx.vin[0].scriptSig) | ||||
newscript = [] | newscript = [] | ||||
for i in scriptSig: | for i in scriptSig: | ||||
if (len(newscript) == 0): | if len(newscript) == 0: | ||||
newscript.append(i[0:-1] + b'\0' + i[-1:]) | newscript.append(i[0:-1] + b"\0" + i[-1:]) | ||||
else: | else: | ||||
newscript.append(i) | newscript.append(i) | ||||
tx.vin[0].scriptSig = CScript(newscript) | tx.vin[0].scriptSig = CScript(newscript) | ||||
class BIP66Test(BitcoinTestFramework): | class BIP66Test(BitcoinTestFramework): | ||||
def set_test_params(self): | def set_test_params(self): | ||||
self.num_nodes = 1 | self.num_nodes = 1 | ||||
self.extra_args = [['-whitelist=noban@127.0.0.1']] | self.extra_args = [["-whitelist=noban@127.0.0.1"]] | ||||
self.setup_clean_chain = True | self.setup_clean_chain = True | ||||
self.rpc_timeout = 240 | self.rpc_timeout = 240 | ||||
def skip_test_if_missing_module(self): | def skip_test_if_missing_module(self): | ||||
self.skip_if_no_wallet() | self.skip_if_no_wallet() | ||||
def run_test(self): | def run_test(self): | ||||
peer = self.nodes[0].add_p2p_connection(P2PInterface()) | peer = self.nodes[0].add_p2p_connection(P2PInterface()) | ||||
self.log.info(f"Mining {DERSIG_HEIGHT - 1} blocks") | self.log.info(f"Mining {DERSIG_HEIGHT - 1} blocks") | ||||
self.coinbase_txids = [self.nodes[0].getblock( | self.coinbase_txids = [ | ||||
b)['tx'][0] for b in self.generate(self.nodes[0], DERSIG_HEIGHT - 1)] | self.nodes[0].getblock(b)["tx"][0] | ||||
for b in self.generate(self.nodes[0], DERSIG_HEIGHT - 1) | |||||
] | |||||
self.nodeaddress = self.nodes[0].getnewaddress() | self.nodeaddress = self.nodes[0].getnewaddress() | ||||
self.log.info("Test that blocks must now be at least version 3") | self.log.info("Test that blocks must now be at least version 3") | ||||
tip = self.nodes[0].getbestblockhash() | tip = self.nodes[0].getbestblockhash() | ||||
block_time = self.nodes[0].getblockheader(tip)['mediantime'] + 1 | block_time = self.nodes[0].getblockheader(tip)["mediantime"] + 1 | ||||
block = create_block( | block = create_block(int(tip, 16), create_coinbase(DERSIG_HEIGHT), block_time) | ||||
int(tip, 16), create_coinbase(DERSIG_HEIGHT), block_time) | |||||
block.nVersion = 2 | block.nVersion = 2 | ||||
block.rehash() | block.rehash() | ||||
block.solve() | block.solve() | ||||
with self.nodes[0].assert_debug_log(expected_msgs=[f'{block.hash}, bad-version(0x00000002)']): | with self.nodes[0].assert_debug_log( | ||||
expected_msgs=[f"{block.hash}, bad-version(0x00000002)"] | |||||
): | |||||
peer.send_and_ping(msg_block(block)) | peer.send_and_ping(msg_block(block)) | ||||
assert_equal(self.nodes[0].getbestblockhash(), tip) | assert_equal(self.nodes[0].getbestblockhash(), tip) | ||||
peer.sync_with_ping() | peer.sync_with_ping() | ||||
self.log.info( | self.log.info( | ||||
"Test that transactions with non-DER signatures cannot appear in a block") | "Test that transactions with non-DER signatures cannot appear in a block" | ||||
) | |||||
block.nVersion = 3 | block.nVersion = 3 | ||||
spendtx = create_transaction(self.nodes[0], self.coinbase_txids[1], | spendtx = create_transaction( | ||||
self.nodeaddress, amount=1000000) | self.nodes[0], self.coinbase_txids[1], self.nodeaddress, amount=1000000 | ||||
) | |||||
unDERify(spendtx) | unDERify(spendtx) | ||||
spendtx.rehash() | spendtx.rehash() | ||||
# First we show that this tx is valid except for DERSIG by getting it | # First we show that this tx is valid except for DERSIG by getting it | ||||
# rejected from the mempool for exactly that reason. | # rejected from the mempool for exactly that reason. | ||||
assert_equal( | assert_equal( | ||||
[{'txid': spendtx.hash, 'allowed': False, | [ | ||||
'reject-reason': 'mandatory-script-verify-flag-failed (Non-canonical DER signature)'}], | { | ||||
"txid": spendtx.hash, | |||||
"allowed": False, | |||||
"reject-reason": ( | |||||
"mandatory-script-verify-flag-failed (Non-canonical DER" | |||||
" signature)" | |||||
), | |||||
} | |||||
], | |||||
self.nodes[0].testmempoolaccept( | self.nodes[0].testmempoolaccept( | ||||
rawtxs=[spendtx.serialize().hex()], maxfeerate=0) | rawtxs=[spendtx.serialize().hex()], maxfeerate=0 | ||||
), | |||||
) | ) | ||||
# Now we verify that a block with this transaction is also invalid. | # Now we verify that a block with this transaction is also invalid. | ||||
block.vtx.append(spendtx) | block.vtx.append(spendtx) | ||||
block.hashMerkleRoot = block.calc_merkle_root() | block.hashMerkleRoot = block.calc_merkle_root() | ||||
block.rehash() | block.rehash() | ||||
block.solve() | block.solve() | ||||
with self.nodes[0].assert_debug_log(expected_msgs=[f'ConnectBlock {block.hash} failed, blk-bad-inputs']): | with self.nodes[0].assert_debug_log( | ||||
expected_msgs=[f"ConnectBlock {block.hash} failed, blk-bad-inputs"] | |||||
): | |||||
peer.send_and_ping(msg_block(block)) | peer.send_and_ping(msg_block(block)) | ||||
assert_equal(self.nodes[0].getbestblockhash(), tip) | assert_equal(self.nodes[0].getbestblockhash(), tip) | ||||
peer.sync_with_ping() | peer.sync_with_ping() | ||||
self.log.info( | self.log.info( | ||||
"Test that a version 3 block with a DERSIG-compliant transaction is accepted") | "Test that a version 3 block with a DERSIG-compliant transaction is" | ||||
block.vtx[1] = create_transaction(self.nodes[0], | " accepted" | ||||
self.coinbase_txids[1], self.nodeaddress, amount=1.0) | ) | ||||
block.vtx[1] = create_transaction( | |||||
self.nodes[0], self.coinbase_txids[1], self.nodeaddress, amount=1.0 | |||||
) | |||||
block.hashMerkleRoot = block.calc_merkle_root() | block.hashMerkleRoot = block.calc_merkle_root() | ||||
block.rehash() | block.rehash() | ||||
block.solve() | block.solve() | ||||
peer.send_and_ping(msg_block(block)) | peer.send_and_ping(msg_block(block)) | ||||
assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.sha256) | assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.sha256) | ||||
if __name__ == '__main__': | if __name__ == "__main__": | ||||
BIP66Test().main() | BIP66Test().main() |