diff options
author | Wladimir J. van der Laan <laanwj@gmail.com> | 2018-08-15 17:12:14 +0200 |
---|---|---|
committer | Wladimir J. van der Laan <laanwj@gmail.com> | 2018-08-15 17:52:06 +0200 |
commit | b5591ca0b053623f0d96423b05ad809115a0bdef (patch) | |
tree | 4c85ec5c953376386685805a079d2b2e5be0f435 /test | |
parent | ef98e122ca39f1d6dca998b546d69a60dae65ae7 (diff) | |
parent | fa091b001605c4481fb4eca415929a98d3478549 (diff) | |
download | bitcoin-b5591ca0b053623f0d96423b05ad809115a0bdef.tar.xz |
Merge #13399: rpc: Add submitheader
fa091b001605c4481fb4eca415929a98d3478549 qa: Add tests for submitheader (MarcoFalke)
36b1b63f20cc718084971d2cadd04497a9b72634 rpc: Expose ProcessNewBlockHeaders (MarcoFalke)
Pull request description:
This exposes `ProcessNewBlockHeaders` as an rpc called `submitheader`. This can be used to check for invalid block headers and submission of valid block headers via the rpc.
Tree-SHA512: a61e850470f15465f88e450609116df0a98d5d9afadf36b2033d820933d8b6a4012f9f2b3246319c08a0e511bef517f5d808cd0f44ffca91d10895a938004f0b
Diffstat (limited to 'test')
-rwxr-xr-x | test/functional/mining_basic.py | 79 |
1 files changed, 74 insertions, 5 deletions
diff --git a/test/functional/mining_basic.py b/test/functional/mining_basic.py index fa20a2d2f4..15b2d7f757 100755 --- a/test/functional/mining_basic.py +++ b/test/functional/mining_basic.py @@ -9,16 +9,23 @@ - submitblock""" import copy -from binascii import b2a_hex from decimal import Decimal from test_framework.blocktools import create_coinbase -from test_framework.messages import CBlock +from test_framework.messages import ( + CBlock, + CBlockHeader, +) +from test_framework.mininode import ( + P2PDataStore, +) from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import assert_equal, assert_raises_rpc_error +from test_framework.util import ( + assert_equal, + assert_raises_rpc_error, + bytes_to_hex_str as b2x, +) -def b2x(b): - return b2a_hex(b).decode('ascii') def assert_template(node, block, expect, rehash=True): if rehash: @@ -131,5 +138,67 @@ class MiningTest(BitcoinTestFramework): bad_block.hashPrevBlock = 123 assert_template(node, bad_block, 'inconclusive-not-best-prevblk') + self.log.info('submitheader tests') + assert_raises_rpc_error(-22, 'Block header decode failed', lambda: node.submitheader(hexdata='xx' * 80)) + assert_raises_rpc_error(-22, 'Block header decode failed', lambda: node.submitheader(hexdata='ff' * 78)) + assert_raises_rpc_error(-25, 'Must submit previous header', lambda: node.submitheader(hexdata='ff' * 80)) + + block.solve() + + def chain_tip(b_hash, *, status='headers-only', branchlen=1): + return {'hash': b_hash, 'height': 202, 'branchlen': branchlen, 'status': status} + + assert chain_tip(block.hash) not in node.getchaintips() + node.submitheader(hexdata=b2x(block.serialize())) + assert chain_tip(block.hash) in node.getchaintips() + node.submitheader(hexdata=b2x(CBlockHeader(block).serialize())) # Noop + assert chain_tip(block.hash) in node.getchaintips() + + bad_block_root = copy.deepcopy(block) + bad_block_root.hashMerkleRoot += 2 + bad_block_root.solve() + assert chain_tip(bad_block_root.hash) not in node.getchaintips() + node.submitheader(hexdata=b2x(CBlockHeader(bad_block_root).serialize())) + assert chain_tip(bad_block_root.hash) in node.getchaintips() + # Should still reject invalid blocks, even if we have the header: + assert_equal(node.submitblock(hexdata=b2x(bad_block_root.serialize())), 'invalid') + assert chain_tip(bad_block_root.hash) in node.getchaintips() + # We know the header for this invalid block, so should just return early without error: + node.submitheader(hexdata=b2x(CBlockHeader(bad_block_root).serialize())) + assert chain_tip(bad_block_root.hash) in node.getchaintips() + + bad_block_lock = copy.deepcopy(block) + bad_block_lock.vtx[0].nLockTime = 2**32 - 1 + bad_block_lock.vtx[0].rehash() + bad_block_lock.hashMerkleRoot = bad_block_lock.calc_merkle_root() + bad_block_lock.solve() + assert_equal(node.submitblock(hexdata=b2x(bad_block_lock.serialize())), 'invalid') + # Build a "good" block on top of the submitted bad block + bad_block2 = copy.deepcopy(block) + bad_block2.hashPrevBlock = bad_block_lock.sha256 + bad_block2.solve() + assert_raises_rpc_error(-25, 'bad-prevblk', lambda: node.submitheader(hexdata=b2x(CBlockHeader(bad_block2).serialize()))) + + # Should reject invalid header right away + bad_block_time = copy.deepcopy(block) + bad_block_time.nTime = 1 + bad_block_time.solve() + assert_raises_rpc_error(-25, 'time-too-old', lambda: node.submitheader(hexdata=b2x(CBlockHeader(bad_block_time).serialize()))) + + # Should ask for the block from a p2p node, if they announce the header as well: + node.add_p2p_connection(P2PDataStore()) + node.p2p.wait_for_getheaders(timeout=5) # Drop the first getheaders + node.p2p.send_blocks_and_test(blocks=[block], rpc=node) + # Must be active now: + assert chain_tip(block.hash, status='active', branchlen=0) in node.getchaintips() + + # Building a few blocks should give the same results + node.generate(10) + assert_raises_rpc_error(-25, 'time-too-old', lambda: node.submitheader(hexdata=b2x(CBlockHeader(bad_block_time).serialize()))) + assert_raises_rpc_error(-25, 'bad-prevblk', lambda: node.submitheader(hexdata=b2x(CBlockHeader(bad_block2).serialize()))) + node.submitheader(hexdata=b2x(CBlockHeader(block).serialize())) + node.submitheader(hexdata=b2x(CBlockHeader(bad_block_root).serialize())) + + if __name__ == '__main__': MiningTest().main() |