rpc: Return more specific reject reason for submitblock
This commit is contained in:
parent
b5591ca0b0
commit
fa6ab8ada1
2 changed files with 20 additions and 7 deletions
|
@ -750,11 +750,7 @@ static UniValue submitblock(const JSONRPCRequest& request)
|
|||
RegisterValidationInterface(&sc);
|
||||
bool accepted = ProcessNewBlock(Params(), blockptr, /* fForceProcessing */ true, /* fNewBlock */ &new_block);
|
||||
UnregisterValidationInterface(&sc);
|
||||
if (!new_block) {
|
||||
if (!accepted) {
|
||||
// TODO Maybe pass down fNewBlock to AcceptBlockHeader, so it is properly set to true in this case?
|
||||
return "invalid";
|
||||
}
|
||||
if (!new_block && accepted) {
|
||||
return "duplicate";
|
||||
}
|
||||
if (!sc.found) {
|
||||
|
|
|
@ -41,6 +41,12 @@ class MiningTest(BitcoinTestFramework):
|
|||
def run_test(self):
|
||||
node = self.nodes[0]
|
||||
|
||||
def assert_submitblock(block, result_str_1, result_str_2=None):
|
||||
block.solve()
|
||||
result_str_2 = result_str_2 or 'duplicate-invalid'
|
||||
assert_equal(result_str_1, node.submitblock(hexdata=b2x(block.serialize())))
|
||||
assert_equal(result_str_2, node.submitblock(hexdata=b2x(block.serialize())))
|
||||
|
||||
self.log.info('getmininginfo')
|
||||
mining_info = node.getmininginfo()
|
||||
assert_equal(mining_info['blocks'], 200)
|
||||
|
@ -93,6 +99,7 @@ class MiningTest(BitcoinTestFramework):
|
|||
bad_block = copy.deepcopy(block)
|
||||
bad_block.vtx.append(bad_block.vtx[0])
|
||||
assert_template(node, bad_block, 'bad-txns-duplicate')
|
||||
assert_submitblock(bad_block, 'bad-txns-duplicate', 'bad-txns-duplicate')
|
||||
|
||||
self.log.info("getblocktemplate: Test invalid transaction")
|
||||
bad_block = copy.deepcopy(block)
|
||||
|
@ -101,12 +108,14 @@ class MiningTest(BitcoinTestFramework):
|
|||
bad_tx.rehash()
|
||||
bad_block.vtx.append(bad_tx)
|
||||
assert_template(node, bad_block, 'bad-txns-inputs-missingorspent')
|
||||
assert_submitblock(bad_block, 'bad-txns-inputs-missingorspent')
|
||||
|
||||
self.log.info("getblocktemplate: Test nonfinal transaction")
|
||||
bad_block = copy.deepcopy(block)
|
||||
bad_block.vtx[0].nLockTime = 2 ** 32 - 1
|
||||
bad_block.vtx[0].rehash()
|
||||
assert_template(node, bad_block, 'bad-txns-nonfinal')
|
||||
assert_submitblock(bad_block, 'bad-txns-nonfinal')
|
||||
|
||||
self.log.info("getblocktemplate: Test bad tx count")
|
||||
# The tx count is immediately after the block header
|
||||
|
@ -125,24 +134,29 @@ class MiningTest(BitcoinTestFramework):
|
|||
bad_block = copy.deepcopy(block)
|
||||
bad_block.hashMerkleRoot += 1
|
||||
assert_template(node, bad_block, 'bad-txnmrklroot', False)
|
||||
assert_submitblock(bad_block, 'bad-txnmrklroot', 'bad-txnmrklroot')
|
||||
|
||||
self.log.info("getblocktemplate: Test bad timestamps")
|
||||
bad_block = copy.deepcopy(block)
|
||||
bad_block.nTime = 2 ** 31 - 1
|
||||
assert_template(node, bad_block, 'time-too-new')
|
||||
assert_submitblock(bad_block, 'time-too-new', 'time-too-new')
|
||||
bad_block.nTime = 0
|
||||
assert_template(node, bad_block, 'time-too-old')
|
||||
assert_submitblock(bad_block, 'time-too-old', 'time-too-old')
|
||||
|
||||
self.log.info("getblocktemplate: Test not best block")
|
||||
bad_block = copy.deepcopy(block)
|
||||
bad_block.hashPrevBlock = 123
|
||||
assert_template(node, bad_block, 'inconclusive-not-best-prevblk')
|
||||
assert_submitblock(bad_block, 'prev-blk-not-found', 'prev-blk-not-found')
|
||||
|
||||
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.nTime += 1
|
||||
block.solve()
|
||||
|
||||
def chain_tip(b_hash, *, status='headers-only', branchlen=1):
|
||||
|
@ -161,7 +175,8 @@ class MiningTest(BitcoinTestFramework):
|
|||
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_equal(node.submitblock(hexdata=b2x(bad_block_root.serialize())), 'bad-txnmrklroot')
|
||||
assert_equal(node.submitblock(hexdata=b2x(bad_block_root.serialize())), 'bad-txnmrklroot')
|
||||
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()))
|
||||
|
@ -172,7 +187,8 @@ class MiningTest(BitcoinTestFramework):
|
|||
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')
|
||||
assert_equal(node.submitblock(hexdata=b2x(bad_block_lock.serialize())), 'bad-txns-nonfinal')
|
||||
assert_equal(node.submitblock(hexdata=b2x(bad_block_lock.serialize())), 'duplicate-invalid')
|
||||
# Build a "good" block on top of the submitted bad block
|
||||
bad_block2 = copy.deepcopy(block)
|
||||
bad_block2.hashPrevBlock = bad_block_lock.sha256
|
||||
|
@ -198,6 +214,7 @@ class MiningTest(BitcoinTestFramework):
|
|||
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()))
|
||||
assert_equal(node.submitblock(hexdata=b2x(block.serialize())), 'duplicate') # valid
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
Loading…
Reference in a new issue