Changeset View
Changeset View
Standalone View
Standalone View
test/functional/abc-transaction-ordering.py
Show First 20 Lines • Show All 109 Lines • ▼ Show 20 Lines | def next_block(self, number, spend=None, tx_count=0): | ||||
# Do PoW, which is cheap on regnet | # Do PoW, which is cheap on regnet | ||||
block.solve() | block.solve() | ||||
self.tip = block | self.tip = block | ||||
self.block_heights[block.sha256] = height | self.block_heights[block.sha256] = height | ||||
assert number not in self.blocks | assert number not in self.blocks | ||||
self.blocks[number] = block | self.blocks[number] = block | ||||
return block | return block | ||||
def set_tip(self, number: int): | |||||
""" | |||||
Move the tip back to a previous block. | |||||
""" | |||||
self.tip = self.blocks[number] | |||||
def run_test(self): | def run_test(self): | ||||
node = self.nodes[0] | node = self.nodes[0] | ||||
node.add_p2p_connection(P2PDataStore()) | node.add_p2p_connection(P2PDataStore()) | ||||
self.genesis_hash = int(node.getbestblockhash(), 16) | self.genesis_hash = int(node.getbestblockhash(), 16) | ||||
self.block_heights[self.genesis_hash] = 0 | self.block_heights[self.genesis_hash] = 0 | ||||
spendable_outputs = [] | spendable_outputs = [] | ||||
# save the current tip so it can be spent by a later block | # save the current tip so it can be spent by a later block | ||||
def save_spendable_output(): | def save_spendable_output(): | ||||
spendable_outputs.append(self.tip) | spendable_outputs.append(self.tip) | ||||
# get an output that we previously marked as spendable | # get an output that we previously marked as spendable | ||||
def get_spendable_output(): | def get_spendable_output(): | ||||
return PreviousSpendableOutput(spendable_outputs.pop(0).vtx[0], 0) | return PreviousSpendableOutput(spendable_outputs.pop(0).vtx[0], 0) | ||||
# move the tip back to a previous block | |||||
def tip(number): | |||||
self.tip = self.blocks[number] | |||||
# update block state | # update block state | ||||
def update_block(block_number): | def update_block(block_number): | ||||
block = self.blocks[block_number] | block = self.blocks[block_number] | ||||
old_sha256 = block.sha256 | old_sha256 = block.sha256 | ||||
block.hashMerkleRoot = block.calc_merkle_root() | block.hashMerkleRoot = block.calc_merkle_root() | ||||
block.solve() | block.solve() | ||||
# Update the internal state just like in next_block | # Update the internal state just like in next_block | ||||
self.tip = block | self.tip = block | ||||
Show All 31 Lines | def run_test(self): | ||||
node.p2p.send_blocks_and_test([block(5556)], node) | node.p2p.send_blocks_and_test([block(5556)], node) | ||||
# Block with regular ordering are now rejected. | # Block with regular ordering are now rejected. | ||||
node.p2p.send_blocks_and_test([block( | node.p2p.send_blocks_and_test([block( | ||||
5557, out[17], tx_count=16)], node, success=False, reject_reason='tx-ordering') | 5557, out[17], tx_count=16)], node, success=False, reject_reason='tx-ordering') | ||||
# Rewind bad block. | # Rewind bad block. | ||||
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. | ||||
node.p2p.send_blocks_and_test([ordered_block(4445, out[17])], node) | node.p2p.send_blocks_and_test([ordered_block(4445, out[17])], node) | ||||
node.p2p.send_blocks_and_test([ordered_block(4446, out[18])], node) | node.p2p.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) | ||||
node.p2p.send_blocks_and_test( | node.p2p.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. | ||||
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]) | ||||
node.p2p.send_blocks_and_test([self.tip], node) | node.p2p.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]) | ||||
Show All 9 Lines |