Changeset View
Changeset View
Standalone View
Standalone View
test/functional/mempool_reorg.py
#!/usr/bin/env python3 | #!/usr/bin/env python3 | ||||
# Copyright (c) 2014-2016 The Bitcoin Core developers | # Copyright (c) 2014-2016 The Bitcoin Core developers | ||||
# Distributed under the MIT software license, see the accompanying | # Distributed under the MIT software license, see the accompanying | ||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php. | # file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
"""Test mempool re-org scenarios. | """Test mempool re-org scenarios. | ||||
Test re-org scenarios with a mempool that contains transactions | Test re-org scenarios with a mempool that contains transactions | ||||
that spend (directly or indirectly) coinbase transactions. | that spend (directly or indirectly) coinbase transactions. | ||||
""" | """ | ||||
from test_framework.test_framework import BitcoinTestFramework | from test_framework.test_framework import BitcoinTestFramework | ||||
from test_framework.util import assert_equal, assert_raises_rpc_error, create_tx | from test_framework.blocktools import create_raw_transaction | ||||
from test_framework.util import assert_equal, assert_raises_rpc_error | |||||
# Create one-input, one-output, no-fee transaction: | # Create one-input, one-output, no-fee transaction: | ||||
class MempoolCoinbaseTest(BitcoinTestFramework): | class MempoolCoinbaseTest(BitcoinTestFramework): | ||||
def set_test_params(self): | def set_test_params(self): | ||||
self.num_nodes = 2 | self.num_nodes = 2 | ||||
self.extra_args = [["-checkmempool"]] * 2 | self.extra_args = [["-checkmempool"]] * 2 | ||||
Show All 15 Lines | def run_test(self): | ||||
# Three scenarios for re-orging coinbase spends in the memory pool: | # Three scenarios for re-orging coinbase spends in the memory pool: | ||||
# 1. Direct coinbase spend : spend_101 | # 1. Direct coinbase spend : spend_101 | ||||
# 2. Indirect (coinbase spend in chain, child in mempool) : spend_102 and spend_102_1 | # 2. Indirect (coinbase spend in chain, child in mempool) : spend_102 and spend_102_1 | ||||
# 3. Indirect (coinbase and child both in chain) : spend_103 and spend_103_1 | # 3. Indirect (coinbase and child both in chain) : spend_103 and spend_103_1 | ||||
# Use invalidatblock to make all of the above coinbase spends invalid (immature coinbase), | # Use invalidatblock to make all of the above coinbase spends invalid (immature coinbase), | ||||
# and make sure the mempool code behaves correctly. | # and make sure the mempool code behaves correctly. | ||||
b = [self.nodes[0].getblockhash(n) for n in range(101, 105)] | b = [self.nodes[0].getblockhash(n) for n in range(101, 105)] | ||||
coinbase_txids = [self.nodes[0].getblock(h)['tx'][0] for h in b] | coinbase_txids = [self.nodes[0].getblock(h)['tx'][0] for h in b] | ||||
spend_101_raw = create_tx( | spend_101_raw = create_raw_transaction( | ||||
self.nodes[0], coinbase_txids[1], node1_address, 49.99) | self.nodes[0], coinbase_txids[1], node1_address, 49.99) | ||||
spend_102_raw = create_tx( | spend_102_raw = create_raw_transaction( | ||||
self.nodes[0], coinbase_txids[2], node0_address, 49.99) | self.nodes[0], coinbase_txids[2], node0_address, 49.99) | ||||
spend_103_raw = create_tx( | spend_103_raw = create_raw_transaction( | ||||
self.nodes[0], coinbase_txids[3], node0_address, 49.99) | self.nodes[0], coinbase_txids[3], node0_address, 49.99) | ||||
# Create a transaction which is time-locked to two blocks in the future | # Create a transaction which is time-locked to two blocks in the future | ||||
timelock_tx = self.nodes[0].createrawtransaction( | timelock_tx = self.nodes[0].createrawtransaction( | ||||
[{"txid": coinbase_txids[0], "vout": 0}], {node0_address: 49.99}) | [{"txid": coinbase_txids[0], "vout": 0}], {node0_address: 49.99}) | ||||
# Set the time lock | # Set the time lock | ||||
timelock_tx = timelock_tx.replace("ffffffff", "11111191", 1) | timelock_tx = timelock_tx.replace("ffffffff", "11111191", 1) | ||||
timelock_tx = timelock_tx[:-8] + \ | timelock_tx = timelock_tx[:-8] + \ | ||||
hex(self.nodes[0].getblockcount() + 2)[2:] + "000000" | hex(self.nodes[0].getblockcount() + 2)[2:] + "000000" | ||||
timelock_tx = self.nodes[0].signrawtransactionwithwallet(timelock_tx)[ | timelock_tx = self.nodes[0].signrawtransactionwithwallet(timelock_tx)[ | ||||
"hex"] | "hex"] | ||||
# This will raise an exception because the timelock transaction is too immature to spend | # This will raise an exception because the timelock transaction is too immature to spend | ||||
assert_raises_rpc_error(-26, "bad-txns-nonfinal", | assert_raises_rpc_error(-26, "bad-txns-nonfinal", | ||||
self.nodes[0].sendrawtransaction, timelock_tx) | self.nodes[0].sendrawtransaction, timelock_tx) | ||||
# Broadcast and mine spend_102 and 103: | # Broadcast and mine spend_102 and 103: | ||||
spend_102_id = self.nodes[0].sendrawtransaction(spend_102_raw) | spend_102_id = self.nodes[0].sendrawtransaction(spend_102_raw) | ||||
spend_103_id = self.nodes[0].sendrawtransaction(spend_103_raw) | spend_103_id = self.nodes[0].sendrawtransaction(spend_103_raw) | ||||
self.nodes[0].generate(1) | self.nodes[0].generate(1) | ||||
# Time-locked transaction is still too immature to spend | # Time-locked transaction is still too immature to spend | ||||
assert_raises_rpc_error(-26, 'bad-txns-nonfinal', | assert_raises_rpc_error(-26, 'bad-txns-nonfinal', | ||||
self.nodes[0].sendrawtransaction, timelock_tx) | self.nodes[0].sendrawtransaction, timelock_tx) | ||||
# Create 102_1 and 103_1: | # Create 102_1 and 103_1: | ||||
spend_102_1_raw = create_tx( | spend_102_1_raw = create_raw_transaction( | ||||
self.nodes[0], spend_102_id, node1_address, 49.98) | self.nodes[0], spend_102_id, node1_address, 49.98) | ||||
spend_103_1_raw = create_tx( | spend_103_1_raw = create_raw_transaction( | ||||
self.nodes[0], spend_103_id, node1_address, 49.98) | self.nodes[0], spend_103_id, node1_address, 49.98) | ||||
# Broadcast and mine 103_1: | # Broadcast and mine 103_1: | ||||
spend_103_1_id = self.nodes[0].sendrawtransaction(spend_103_1_raw) | spend_103_1_id = self.nodes[0].sendrawtransaction(spend_103_1_raw) | ||||
last_block = self.nodes[0].generate(1) | last_block = self.nodes[0].generate(1) | ||||
# Time-locked transaction can now be spent | # Time-locked transaction can now be spent | ||||
timelock_tx_id = self.nodes[0].sendrawtransaction(timelock_tx) | timelock_tx_id = self.nodes[0].sendrawtransaction(timelock_tx) | ||||
Show All 29 Lines |