Changeset View
Changeset View
Standalone View
Standalone View
test/functional/abc-transaction-ordering.py
Show All 18 Lines | |||||
from test_framework.messages import COutPoint, CTransaction, CTxIn, CTxOut | from test_framework.messages import COutPoint, CTransaction, CTxIn, CTxOut | ||||
from test_framework.p2p import P2PDataStore | from test_framework.p2p import P2PDataStore | ||||
from test_framework.script import OP_RETURN, OP_TRUE, CScript | from test_framework.script import OP_RETURN, OP_TRUE, CScript | ||||
from test_framework.test_framework import BitcoinTestFramework | from test_framework.test_framework import BitcoinTestFramework | ||||
from test_framework.util import assert_equal | from test_framework.util import assert_equal | ||||
class PreviousSpendableOutput: | class PreviousSpendableOutput: | ||||
def __init__(self, tx=CTransaction(), n=-1): | def __init__(self, tx=CTransaction(), n=-1): | ||||
self.tx = tx | self.tx = tx | ||||
self.n = n # the output we're spending | self.n = n # the output we're spending | ||||
class TransactionOrderingTest(BitcoinTestFramework): | class TransactionOrderingTest(BitcoinTestFramework): | ||||
def set_test_params(self): | def set_test_params(self): | ||||
self.num_nodes = 1 | self.num_nodes = 1 | ||||
self.setup_clean_chain = True | self.setup_clean_chain = True | ||||
self.block_heights = {} | self.block_heights = {} | ||||
self.tip = None | self.tip = None | ||||
self.blocks = {} | self.blocks = {} | ||||
self.extra_args = [['-whitelist=noban@127.0.0.1']] | self.extra_args = [["-whitelist=noban@127.0.0.1"]] | ||||
def add_transactions_to_block(self, block, tx_list): | def add_transactions_to_block(self, block, tx_list): | ||||
[tx.rehash() for tx in tx_list] | [tx.rehash() for tx in tx_list] | ||||
block.vtx.extend(tx_list) | block.vtx.extend(tx_list) | ||||
def next_block(self, number, spend=None, tx_count=0): | def next_block(self, number, spend=None, tx_count=0): | ||||
if self.tip is None: | if self.tip is None: | ||||
base_block_hash = self.genesis_hash | base_block_hash = self.genesis_hash | ||||
▲ Show 20 Lines • Show All 124 Lines • ▼ Show 20 Lines | def run_test(self): | ||||
# Let's build some blocks and test them. | # Let's build some blocks and test them. | ||||
for i in range(17): | for i in range(17): | ||||
n = i + 1 | n = i + 1 | ||||
peer.send_blocks_and_test([block(n)], node) | peer.send_blocks_and_test([block(n)], node) | ||||
peer.send_blocks_and_test([block(5556)], node) | peer.send_blocks_and_test([block(5556)], node) | ||||
# Block with regular ordering are now rejected. | # Block with regular ordering are now rejected. | ||||
peer.send_blocks_and_test([block( | peer.send_blocks_and_test( | ||||
5557, out[17], tx_count=16)], node, success=False, reject_reason='tx-ordering') | [block(5557, out[17], tx_count=16)], | ||||
node, | |||||
success=False, | |||||
reject_reason="tx-ordering", | |||||
) | |||||
# Rewind bad block. | # Rewind bad block. | ||||
self.set_tip(5556) | self.set_tip(5556) | ||||
# After we activate the Nov 15, 2018 HF, transaction order is enforced. | # After we activate the Nov 15, 2018 HF, transaction order is enforced. | ||||
def ordered_block(block_number, spend): | def ordered_block(block_number, spend): | ||||
b = block(block_number, spend=spend, tx_count=16) | b = block(block_number, spend=spend, tx_count=16) | ||||
make_conform_to_ctor(b) | make_conform_to_ctor(b) | ||||
update_block(block_number) | update_block(block_number) | ||||
return b | return b | ||||
# Now that the fork activated, we need to order transaction per txid. | # Now that the fork activated, we need to order transaction per txid. | ||||
peer.send_blocks_and_test([ordered_block(4445, out[17])], node) | peer.send_blocks_and_test([ordered_block(4445, out[17])], node) | ||||
peer.send_blocks_and_test([ordered_block(4446, out[18])], node) | peer.send_blocks_and_test([ordered_block(4446, out[18])], node) | ||||
# Generate a block with a duplicated transaction. | # Generate a block with a duplicated transaction. | ||||
double_tx_block = ordered_block(4447, out[19]) | double_tx_block = ordered_block(4447, out[19]) | ||||
assert_equal(len(double_tx_block.vtx), 16) | assert_equal(len(double_tx_block.vtx), 16) | ||||
double_tx_block.vtx = double_tx_block.vtx[:8] + \ | double_tx_block.vtx = ( | ||||
[double_tx_block.vtx[8]] + double_tx_block.vtx[8:] | double_tx_block.vtx[:8] + [double_tx_block.vtx[8]] + double_tx_block.vtx[8:] | ||||
) | |||||
update_block(4447) | update_block(4447) | ||||
peer.send_blocks_and_test( | peer.send_blocks_and_test( | ||||
[self.tip], node, success=False, reject_reason='bad-txns-duplicate') | [self.tip], node, success=False, reject_reason="bad-txns-duplicate" | ||||
) | |||||
# Rewind bad block. | # Rewind bad block. | ||||
self.set_tip(4446) | self.set_tip(4446) | ||||
# Check over two blocks. | # Check over two blocks. | ||||
proper_block = ordered_block(4448, out[20]) | proper_block = ordered_block(4448, out[20]) | ||||
peer.send_blocks_and_test([self.tip], node) | peer.send_blocks_and_test([self.tip], node) | ||||
replay_tx_block = ordered_block(4449, out[21]) | replay_tx_block = ordered_block(4449, out[21]) | ||||
assert_equal(len(replay_tx_block.vtx), 16) | assert_equal(len(replay_tx_block.vtx), 16) | ||||
replay_tx_block.vtx.append(proper_block.vtx[5]) | replay_tx_block.vtx.append(proper_block.vtx[5]) | ||||
replay_tx_block.vtx = [replay_tx_block.vtx[0]] + \ | replay_tx_block.vtx = [replay_tx_block.vtx[0]] + sorted( | ||||
sorted(replay_tx_block.vtx[1:], key=lambda tx: tx.get_id()) | replay_tx_block.vtx[1:], key=lambda tx: tx.get_id() | ||||
) | |||||
update_block(4449) | update_block(4449) | ||||
peer.send_blocks_and_test( | peer.send_blocks_and_test( | ||||
[self.tip], node, success=False, reject_reason='bad-txns-BIP30') | [self.tip], node, success=False, reject_reason="bad-txns-BIP30" | ||||
) | |||||
if __name__ == '__main__': | if __name__ == "__main__": | ||||
TransactionOrderingTest().main() | TransactionOrderingTest().main() |