Changeset View
Changeset View
Standalone View
Standalone View
test/functional/rpc_txoutproof.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 merkleblock fetch/validation | # Test merkleblock fetch/validation | ||||
# | # | ||||
from test_framework.test_framework import BitcoinTestFramework | from test_framework.test_framework import BitcoinTestFramework | ||||
from test_framework.util import ( | from test_framework.util import ( | ||||
assert_equal, | assert_equal, | ||||
assert_raises_rpc_error, | assert_raises_rpc_error, | ||||
connect_nodes, | connect_nodes, | ||||
) | ) | ||||
from test_framework.messages import CMerkleBlock, FromHex, ToHex | |||||
class MerkleBlockTest(BitcoinTestFramework): | class MerkleBlockTest(BitcoinTestFramework): | ||||
def set_test_params(self): | def set_test_params(self): | ||||
self.num_nodes = 4 | self.num_nodes = 4 | ||||
self.setup_clean_chain = True | self.setup_clean_chain = True | ||||
# Nodes 0/1 are "wallet" nodes, Nodes 2/3 are used for testing | # Nodes 0/1 are "wallet" nodes, Nodes 2/3 are used for testing | ||||
self.extra_args = [[], [], [], ["-txindex"]] | self.extra_args = [[], [], [], ["-txindex"]] | ||||
▲ Show 20 Lines • Show All 75 Lines • ▼ Show 20 Lines | def run_test(self): | ||||
self.nodes[2].gettxoutproof([txid2, txid1]))), sorted(txlist)) | self.nodes[2].gettxoutproof([txid2, txid1]))), sorted(txlist)) | ||||
# We can always get a proof if we have a -txindex | # We can always get a proof if we have a -txindex | ||||
assert_equal(self.nodes[2].verifytxoutproof( | assert_equal(self.nodes[2].verifytxoutproof( | ||||
self.nodes[3].gettxoutproof([txid_spent])), [txid_spent]) | self.nodes[3].gettxoutproof([txid_spent])), [txid_spent]) | ||||
# We can't get a proof if we specify transactions from different blocks | # We can't get a proof if we specify transactions from different blocks | ||||
assert_raises_rpc_error(-5, "Not all transactions found in specified or retrieved block", | assert_raises_rpc_error(-5, "Not all transactions found in specified or retrieved block", | ||||
self.nodes[2].gettxoutproof, [txid1, txid3]) | self.nodes[2].gettxoutproof, [txid1, txid3]) | ||||
# Now we'll try tweaking a proof. | |||||
proof = self.nodes[3].gettxoutproof([txid1, txid2]) | |||||
assert txid1 in self.nodes[0].verifytxoutproof(proof) | |||||
assert txid2 in self.nodes[1].verifytxoutproof(proof) | |||||
tweaked_proof = FromHex(CMerkleBlock(), proof) | |||||
# Make sure that our serialization/deserialization is working | |||||
assert txid1 in self.nodes[2].verifytxoutproof(ToHex(tweaked_proof)) | |||||
# Check to see if we can go up the merkle tree and pass this off as a | |||||
# single-transaction block | |||||
tweaked_proof.txn.nTransactions = 1 | |||||
tweaked_proof.txn.vHash = [tweaked_proof.header.hashMerkleRoot] | |||||
tweaked_proof.txn.vBits = [True] + [False]*7 | |||||
for n in self.nodes: | |||||
assert not n.verifytxoutproof(ToHex(tweaked_proof)) | |||||
# TODO: try more variants, eg transactions at different depths, and | |||||
# verify that the proofs are invalid | |||||
if __name__ == '__main__': | if __name__ == '__main__': | ||||
MerkleBlockTest().main() | MerkleBlockTest().main() |