Changeset View
Changeset View
Standalone View
Standalone View
test/functional/feature_utxo_set_hash.py
Show All 21 Lines | def skip_test_if_missing_module(self): | ||||
self.skip_if_no_wallet() | self.skip_if_no_wallet() | ||||
def test_deterministic_hash_results(self): | def test_deterministic_hash_results(self): | ||||
self.log.info("Test deterministic UTXO set hash results") | self.log.info("Test deterministic UTXO set hash results") | ||||
# These depend on the setup_clean_chain option, the chain loaded from | # These depend on the setup_clean_chain option, the chain loaded from | ||||
# the cache | # the cache | ||||
assert_equal( | assert_equal( | ||||
self.nodes[0].gettxoutsetinfo()['hash_serialized'], | self.nodes[0].gettxoutsetinfo()["hash_serialized"], | ||||
"b32ec1dda5a53cd025b95387aad344a801825fe46a60ff952ce26528f01d3be8") | "b32ec1dda5a53cd025b95387aad344a801825fe46a60ff952ce26528f01d3be8", | ||||
) | |||||
assert_equal( | assert_equal( | ||||
self.nodes[0].gettxoutsetinfo("muhash")['muhash'], | self.nodes[0].gettxoutsetinfo("muhash")["muhash"], | ||||
"dd5ad2a105c2d29495f577245c357409002329b9f4d6182c0af3dc2f462555c8") | "dd5ad2a105c2d29495f577245c357409002329b9f4d6182c0af3dc2f462555c8", | ||||
) | |||||
def test_muhash_implementation(self): | def test_muhash_implementation(self): | ||||
self.log.info("Test MuHash implementation consistency") | self.log.info("Test MuHash implementation consistency") | ||||
node = self.nodes[0] | node = self.nodes[0] | ||||
# Generate 100 blocks and remove the first since we plan to spend its | # Generate 100 blocks and remove the first since we plan to spend its | ||||
# coinbase | # coinbase | ||||
block_hashes = self.generate(node, 100) | block_hashes = self.generate(node, 100) | ||||
blocks = [ | blocks = [ | ||||
FromHex(CBlock(), node.getblock(block, False)) for block in block_hashes] | FromHex(CBlock(), node.getblock(block, False)) for block in block_hashes | ||||
] | |||||
spending = blocks.pop(0) | spending = blocks.pop(0) | ||||
# Create a spending transaction and mine a block which includes it | # Create a spending transaction and mine a block which includes it | ||||
tx = create_transaction( | tx = create_transaction( | ||||
node, spending.vtx[0].rehash(), node.getnewaddress(), | node, spending.vtx[0].rehash(), node.getnewaddress(), amount=49_000_000 | ||||
amount=49_000_000) | ) | ||||
txid = node.sendrawtransaction( | txid = node.sendrawtransaction(hexstring=tx.serialize().hex(), maxfeerate=0) | ||||
hexstring=tx.serialize().hex(), maxfeerate=0) | |||||
tx_block = self.generateblock( | |||||
tx_block = self.generateblock(node, | node, output=node.getnewaddress(), transactions=[txid] | ||||
output=node.getnewaddress(), | ) | ||||
transactions=[txid]) | blocks.append(FromHex(CBlock(), node.getblock(tx_block["hash"], False))) | ||||
blocks.append( | |||||
FromHex(CBlock(), node.getblock(tx_block['hash'], False))) | |||||
# Serialize the outputs that should be in the UTXO set and add them to | # Serialize the outputs that should be in the UTXO set and add them to | ||||
# a MuHash object | # a MuHash object | ||||
muhash = MuHash3072() | muhash = MuHash3072() | ||||
for height, block in enumerate(blocks): | for height, block in enumerate(blocks): | ||||
# The Genesis block coinbase is not part of the UTXO set and we | # The Genesis block coinbase is not part of the UTXO set and we | ||||
# spent the first mined block | # spent the first mined block | ||||
height += 2 | height += 2 | ||||
for tx in block.vtx: | for tx in block.vtx: | ||||
for n, tx_out in enumerate(tx.vout): | for n, tx_out in enumerate(tx.vout): | ||||
coinbase = 1 if not tx.vin[0].prevout.txid else 0 | coinbase = 1 if not tx.vin[0].prevout.txid else 0 | ||||
data = COutPoint(int(tx.rehash(), 16), n).serialize() | data = COutPoint(int(tx.rehash(), 16), n).serialize() | ||||
data += struct.pack("<i", height * 2 + coinbase) | data += struct.pack("<i", height * 2 + coinbase) | ||||
data += tx_out.serialize() | data += tx_out.serialize() | ||||
muhash.insert(data) | muhash.insert(data) | ||||
finalized = muhash.digest() | finalized = muhash.digest() | ||||
node_muhash = node.gettxoutsetinfo("muhash")['muhash'] | node_muhash = node.gettxoutsetinfo("muhash")["muhash"] | ||||
assert_equal(finalized[::-1].hex(), node_muhash) | assert_equal(finalized[::-1].hex(), node_muhash) | ||||
def run_test(self): | def run_test(self): | ||||
self.test_deterministic_hash_results() | self.test_deterministic_hash_results() | ||||
self.test_muhash_implementation() | self.test_muhash_implementation() | ||||
if __name__ == '__main__': | if __name__ == "__main__": | ||||
UTXOSetHashTest().main() | UTXOSetHashTest().main() |