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.
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.
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.
233@@ -234,7 +234,6 @@ static const uint64_t MIN_DISK_SPACE_FOR_BLOCK_FILES = 550 * 1024 * 1024;
234 * (and possibly also) BlockChecked will have been called.
235 *
236 *
237- *
Commit “rpc: Expose ProcessNewBlockHeaders”
This should be in commit “doc: Rewrite some validation doc to be machine-readable:”.
243@@ -245,8 +244,6 @@ bool ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr<cons
244 /**
245 * Process incoming block headers.
246 *
247- *
Commit “rpc: Expose ProcessNewBlockHeaders”
This should be in commit “doc: Rewrite some validation doc to be machine-readable:”.
231@@ -232,28 +232,25 @@ static const uint64_t MIN_DISK_SPACE_FOR_BLOCK_FILES = 550 * 1024 * 1024;
232 *
233 * Note that we guarantee that either the proof-of-work is valid on pblock, or
234 * (and possibly also) BlockChecked will have been called.
235- *
236- * Call without cs_main held.
237+ *
140@@ -131,5 +141,61 @@ def run_test(self):
141 bad_block.hashPrevBlock = 123
142 assert_template(node, bad_block, 'inconclusive-not-best-prevblk')
143
144+ self.log.info('submitheader tests')
145+ assert_raises_rpc_error(-22, 'Block header decode failed', lambda: node.submitheader(hexdata='xx' * 80))
146+ assert_raises_rpc_error(-22, 'Block header decode failed', lambda: node.submitheader(hexdata='ff' * 78))
147+ assert_raises_rpc_error(-25, 'Must submit previous header', lambda: node.submitheader(hexdata='ff' * 80))
783+ if (!DecodeHexBlockHeader(h, request.params[0].get_str())) {
784+ throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block header decode failed");
785+ }
786+ {
787+ LOCK(cs_main);
788+ if (LookupBlockIndex(h.GetHash())) return NullUniValue;
ProcessNewBlockHeaders
-> CChainState::AcceptBlockHeader
. Could use ProcessNewBlockHeaders
return value.
None
and not the return value of PNBH
790+ throw JSONRPCError(RPC_VERIFY_ERROR, "Must submit previous header (" + h.hashPrevBlock.GetHex() + ") first");
791+ }
792+ }
793+
794+ CValidationState state;
795+ ProcessNewBlockHeaders({h}, state, Params(), /* ppindex */ nullptr, /* first_invalid */ nullptr);
231@@ -232,28 +232,24 @@ static const uint64_t MIN_DISK_SPACE_FOR_BLOCK_FILES = 550 * 1024 * 1024;
232 *
233 * Note that we guarantee that either the proof-of-work is valid on pblock, or
234 * (and possibly also) BlockChecked will have been called.
235- *
supernit: you remove this text in commit doc: Rewrite some validation doc to be machine-readable, and then remove the lines in commit rpc: Expose ProcessNewBlockHeaders. Just remove the lines in the first commit.
Same for ProcessNewBlockHeaders
comment below.
28+ assert_equal,
29+ assert_raises_rpc_error,
30+ bytes_to_hex_str,
31+)
32+
33+b2x = bytes_to_hex_str
Can just use:
0from test_framework.util import (
1 assert_equal,
2 assert_raises_rpc_error,
3 bytes_to_hex_str as b2x,
4+)
178+ assert_equal(node.submitblock(hexdata=b2x(bad_block.serialize())), 'bad-txns-nonfinal')
179+ # Build a "good" block on top of the submitted bad block
180+ bad_block2 = copy.deepcopy(block)
181+ bad_block2.hashPrevBlock = bad_block.sha256
182+ bad_block2.solve()
183+ assert_raises_rpc_error(-25, 'bad-prevblk', lambda: node.submitheader(hexdata=b2x(CBlockHeader(bad_block2).serialize())))
Normal way we do this is:
0 assert_raises_rpc_error(-25, 'bad-prevblk', node.submitheader, b2x(CBlockHeader(bad_block2).serialize()))
Any reason you’ve chosen to use a lambda?
This should work:
0assert_raises_rpc_error(-25, 'bad-prevblk', node.submitheader, hexdata=b2x(CBlockHeader(bad_block2).serialize()))
154+ assert chain_tip(block.hash) not in node.getchaintips()
155+ node.submitheader(hexdata=b2x(block.serialize()))
156+ assert chain_tip(block.hash) in node.getchaintips()
157+ node.submitheader(hexdata=b2x(CBlockHeader(block).serialize())) # Noop
158+ assert chain_tip(block.hash) in node.getchaintips()
159+
Looks great. utACK 2595028d97fc08ea0d27c3133c44d63f3e8bbc0f
A few nits inline. Feel free to ignore.
utACK fa7d7dd34cbd180ec9587c640078dfb7bf2ead04.
Having this functionality can’t hurt, as it available with identical semantics via P2P anyway.
I have no opinion about the test code style.
170+ bad_block_lock = copy.deepcopy(block)
171+ bad_block_lock.vtx[0].nLockTime = 2**32 - 1
172+ bad_block_lock.vtx[0].rehash()
173+ bad_block_lock.hashMerkleRoot = bad_block_lock.calc_merkle_root()
174+ bad_block_lock.solve()
175+ assert_equal(node.submitblock(hexdata=b2x(bad_block_lock.serialize())), 'invalid')
MarcoFalke
DrahtBot
laanwj
TheBlueMatt
promag
jnewbery
sipa
luke-jr
Labels
Feature
RPC/REST/ZMQ
Milestone
0.18.0