Skip to content

Commit fa6ab8a

Browse files
author
MarcoFalke
committed
rpc: Return more specific reject reason for submitblock
1 parent b5591ca commit fa6ab8a

File tree

2 files changed

+20
-7
lines changed

2 files changed

+20
-7
lines changed

src/rpc/mining.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -750,11 +750,7 @@ static UniValue submitblock(const JSONRPCRequest& request)
750750
RegisterValidationInterface(&sc);
751751
bool accepted = ProcessNewBlock(Params(), blockptr, /* fForceProcessing */ true, /* fNewBlock */ &new_block);
752752
UnregisterValidationInterface(&sc);
753-
if (!new_block) {
754-
if (!accepted) {
755-
// TODO Maybe pass down fNewBlock to AcceptBlockHeader, so it is properly set to true in this case?
756-
return "invalid";
757-
}
753+
if (!new_block && accepted) {
758754
return "duplicate";
759755
}
760756
if (!sc.found) {

test/functional/mining_basic.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@ def set_test_params(self):
4141
def run_test(self):
4242
node = self.nodes[0]
4343

44+
def assert_submitblock(block, result_str_1, result_str_2=None):
45+
block.solve()
46+
result_str_2 = result_str_2 or 'duplicate-invalid'
47+
assert_equal(result_str_1, node.submitblock(hexdata=b2x(block.serialize())))
48+
assert_equal(result_str_2, node.submitblock(hexdata=b2x(block.serialize())))
49+
4450
self.log.info('getmininginfo')
4551
mining_info = node.getmininginfo()
4652
assert_equal(mining_info['blocks'], 200)
@@ -93,6 +99,7 @@ def run_test(self):
9399
bad_block = copy.deepcopy(block)
94100
bad_block.vtx.append(bad_block.vtx[0])
95101
assert_template(node, bad_block, 'bad-txns-duplicate')
102+
assert_submitblock(bad_block, 'bad-txns-duplicate', 'bad-txns-duplicate')
96103

97104
self.log.info("getblocktemplate: Test invalid transaction")
98105
bad_block = copy.deepcopy(block)
@@ -101,12 +108,14 @@ def run_test(self):
101108
bad_tx.rehash()
102109
bad_block.vtx.append(bad_tx)
103110
assert_template(node, bad_block, 'bad-txns-inputs-missingorspent')
111+
assert_submitblock(bad_block, 'bad-txns-inputs-missingorspent')
104112

105113
self.log.info("getblocktemplate: Test nonfinal transaction")
106114
bad_block = copy.deepcopy(block)
107115
bad_block.vtx[0].nLockTime = 2 ** 32 - 1
108116
bad_block.vtx[0].rehash()
109117
assert_template(node, bad_block, 'bad-txns-nonfinal')
118+
assert_submitblock(bad_block, 'bad-txns-nonfinal')
110119

111120
self.log.info("getblocktemplate: Test bad tx count")
112121
# The tx count is immediately after the block header
@@ -125,24 +134,29 @@ def run_test(self):
125134
bad_block = copy.deepcopy(block)
126135
bad_block.hashMerkleRoot += 1
127136
assert_template(node, bad_block, 'bad-txnmrklroot', False)
137+
assert_submitblock(bad_block, 'bad-txnmrklroot', 'bad-txnmrklroot')
128138

129139
self.log.info("getblocktemplate: Test bad timestamps")
130140
bad_block = copy.deepcopy(block)
131141
bad_block.nTime = 2 ** 31 - 1
132142
assert_template(node, bad_block, 'time-too-new')
143+
assert_submitblock(bad_block, 'time-too-new', 'time-too-new')
133144
bad_block.nTime = 0
134145
assert_template(node, bad_block, 'time-too-old')
146+
assert_submitblock(bad_block, 'time-too-old', 'time-too-old')
135147

136148
self.log.info("getblocktemplate: Test not best block")
137149
bad_block = copy.deepcopy(block)
138150
bad_block.hashPrevBlock = 123
139151
assert_template(node, bad_block, 'inconclusive-not-best-prevblk')
152+
assert_submitblock(bad_block, 'prev-blk-not-found', 'prev-blk-not-found')
140153

141154
self.log.info('submitheader tests')
142155
assert_raises_rpc_error(-22, 'Block header decode failed', lambda: node.submitheader(hexdata='xx' * 80))
143156
assert_raises_rpc_error(-22, 'Block header decode failed', lambda: node.submitheader(hexdata='ff' * 78))
144157
assert_raises_rpc_error(-25, 'Must submit previous header', lambda: node.submitheader(hexdata='ff' * 80))
145158

159+
block.nTime += 1
146160
block.solve()
147161

148162
def chain_tip(b_hash, *, status='headers-only', branchlen=1):
@@ -161,7 +175,8 @@ def chain_tip(b_hash, *, status='headers-only', branchlen=1):
161175
node.submitheader(hexdata=b2x(CBlockHeader(bad_block_root).serialize()))
162176
assert chain_tip(bad_block_root.hash) in node.getchaintips()
163177
# Should still reject invalid blocks, even if we have the header:
164-
assert_equal(node.submitblock(hexdata=b2x(bad_block_root.serialize())), 'invalid')
178+
assert_equal(node.submitblock(hexdata=b2x(bad_block_root.serialize())), 'bad-txnmrklroot')
179+
assert_equal(node.submitblock(hexdata=b2x(bad_block_root.serialize())), 'bad-txnmrklroot')
165180
assert chain_tip(bad_block_root.hash) in node.getchaintips()
166181
# We know the header for this invalid block, so should just return early without error:
167182
node.submitheader(hexdata=b2x(CBlockHeader(bad_block_root).serialize()))
@@ -172,7 +187,8 @@ def chain_tip(b_hash, *, status='headers-only', branchlen=1):
172187
bad_block_lock.vtx[0].rehash()
173188
bad_block_lock.hashMerkleRoot = bad_block_lock.calc_merkle_root()
174189
bad_block_lock.solve()
175-
assert_equal(node.submitblock(hexdata=b2x(bad_block_lock.serialize())), 'invalid')
190+
assert_equal(node.submitblock(hexdata=b2x(bad_block_lock.serialize())), 'bad-txns-nonfinal')
191+
assert_equal(node.submitblock(hexdata=b2x(bad_block_lock.serialize())), 'duplicate-invalid')
176192
# Build a "good" block on top of the submitted bad block
177193
bad_block2 = copy.deepcopy(block)
178194
bad_block2.hashPrevBlock = bad_block_lock.sha256
@@ -198,6 +214,7 @@ def chain_tip(b_hash, *, status='headers-only', branchlen=1):
198214
assert_raises_rpc_error(-25, 'bad-prevblk', lambda: node.submitheader(hexdata=b2x(CBlockHeader(bad_block2).serialize())))
199215
node.submitheader(hexdata=b2x(CBlockHeader(block).serialize()))
200216
node.submitheader(hexdata=b2x(CBlockHeader(bad_block_root).serialize()))
217+
assert_equal(node.submitblock(hexdata=b2x(block.serialize())), 'duplicate') # valid
201218

202219

203220
if __name__ == '__main__':

0 commit comments

Comments
 (0)