Skip to content

Commit 962c302

Browse files
author
MarcoFalke
committed
Merge #13983: rpc: Return more specific reject reason for submitblock
fa6ab8a rpc: Return more specific reject reason for submitblock (MarcoFalke) Pull request description: The second commit in #13439 made the `TODO` in the first commit impossible to solve. The meaning of `fNewBlock` changed from "This is the first time we process this block" to "We are about to write the new *valid* block". So whenever `fNewBlock` is true, the block was valid. And whenever the `fNewBlock` is false, the block is either valid or invalid. If it was valid and not new, we know it is a `"duplicate"`. In all other cases, the `BIP22ValidationResult()` will return the reason why it is invalid. Tree-SHA512: 4b6edf7a912339c3acb0fccfabbdd6d812a0321fb1639c244c2714e58dc119aa2b8c6bf8f7d61ea609a1b861bbc23f920370fcf989c48452721e259a8ce93d24
2 parents b9ed2fd + fa6ab8a commit 962c302

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
@@ -44,6 +44,12 @@ def skip_test_if_missing_module(self):
4444
def run_test(self):
4545
node = self.nodes[0]
4646

47+
def assert_submitblock(block, result_str_1, result_str_2=None):
48+
block.solve()
49+
result_str_2 = result_str_2 or 'duplicate-invalid'
50+
assert_equal(result_str_1, node.submitblock(hexdata=b2x(block.serialize())))
51+
assert_equal(result_str_2, node.submitblock(hexdata=b2x(block.serialize())))
52+
4753
self.log.info('getmininginfo')
4854
mining_info = node.getmininginfo()
4955
assert_equal(mining_info['blocks'], 200)
@@ -96,6 +102,7 @@ def run_test(self):
96102
bad_block = copy.deepcopy(block)
97103
bad_block.vtx.append(bad_block.vtx[0])
98104
assert_template(node, bad_block, 'bad-txns-duplicate')
105+
assert_submitblock(bad_block, 'bad-txns-duplicate', 'bad-txns-duplicate')
99106

100107
self.log.info("getblocktemplate: Test invalid transaction")
101108
bad_block = copy.deepcopy(block)
@@ -104,12 +111,14 @@ def run_test(self):
104111
bad_tx.rehash()
105112
bad_block.vtx.append(bad_tx)
106113
assert_template(node, bad_block, 'bad-txns-inputs-missingorspent')
114+
assert_submitblock(bad_block, 'bad-txns-inputs-missingorspent')
107115

108116
self.log.info("getblocktemplate: Test nonfinal transaction")
109117
bad_block = copy.deepcopy(block)
110118
bad_block.vtx[0].nLockTime = 2 ** 32 - 1
111119
bad_block.vtx[0].rehash()
112120
assert_template(node, bad_block, 'bad-txns-nonfinal')
121+
assert_submitblock(bad_block, 'bad-txns-nonfinal')
113122

114123
self.log.info("getblocktemplate: Test bad tx count")
115124
# The tx count is immediately after the block header
@@ -128,24 +137,29 @@ def run_test(self):
128137
bad_block = copy.deepcopy(block)
129138
bad_block.hashMerkleRoot += 1
130139
assert_template(node, bad_block, 'bad-txnmrklroot', False)
140+
assert_submitblock(bad_block, 'bad-txnmrklroot', 'bad-txnmrklroot')
131141

132142
self.log.info("getblocktemplate: Test bad timestamps")
133143
bad_block = copy.deepcopy(block)
134144
bad_block.nTime = 2 ** 31 - 1
135145
assert_template(node, bad_block, 'time-too-new')
146+
assert_submitblock(bad_block, 'time-too-new', 'time-too-new')
136147
bad_block.nTime = 0
137148
assert_template(node, bad_block, 'time-too-old')
149+
assert_submitblock(bad_block, 'time-too-old', 'time-too-old')
138150

139151
self.log.info("getblocktemplate: Test not best block")
140152
bad_block = copy.deepcopy(block)
141153
bad_block.hashPrevBlock = 123
142154
assert_template(node, bad_block, 'inconclusive-not-best-prevblk')
155+
assert_submitblock(bad_block, 'prev-blk-not-found', 'prev-blk-not-found')
143156

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

162+
block.nTime += 1
149163
block.solve()
150164

151165
def chain_tip(b_hash, *, status='headers-only', branchlen=1):
@@ -164,7 +178,8 @@ def chain_tip(b_hash, *, status='headers-only', branchlen=1):
164178
node.submitheader(hexdata=b2x(CBlockHeader(bad_block_root).serialize()))
165179
assert chain_tip(bad_block_root.hash) in node.getchaintips()
166180
# Should still reject invalid blocks, even if we have the header:
167-
assert_equal(node.submitblock(hexdata=b2x(bad_block_root.serialize())), 'invalid')
181+
assert_equal(node.submitblock(hexdata=b2x(bad_block_root.serialize())), 'bad-txnmrklroot')
182+
assert_equal(node.submitblock(hexdata=b2x(bad_block_root.serialize())), 'bad-txnmrklroot')
168183
assert chain_tip(bad_block_root.hash) in node.getchaintips()
169184
# We know the header for this invalid block, so should just return early without error:
170185
node.submitheader(hexdata=b2x(CBlockHeader(bad_block_root).serialize()))
@@ -175,7 +190,8 @@ def chain_tip(b_hash, *, status='headers-only', branchlen=1):
175190
bad_block_lock.vtx[0].rehash()
176191
bad_block_lock.hashMerkleRoot = bad_block_lock.calc_merkle_root()
177192
bad_block_lock.solve()
178-
assert_equal(node.submitblock(hexdata=b2x(bad_block_lock.serialize())), 'invalid')
193+
assert_equal(node.submitblock(hexdata=b2x(bad_block_lock.serialize())), 'bad-txns-nonfinal')
194+
assert_equal(node.submitblock(hexdata=b2x(bad_block_lock.serialize())), 'duplicate-invalid')
179195
# Build a "good" block on top of the submitted bad block
180196
bad_block2 = copy.deepcopy(block)
181197
bad_block2.hashPrevBlock = bad_block_lock.sha256
@@ -201,6 +217,7 @@ def chain_tip(b_hash, *, status='headers-only', branchlen=1):
201217
assert_raises_rpc_error(-25, 'bad-prevblk', lambda: node.submitheader(hexdata=b2x(CBlockHeader(bad_block2).serialize())))
202218
node.submitheader(hexdata=b2x(CBlockHeader(block).serialize()))
203219
node.submitheader(hexdata=b2x(CBlockHeader(bad_block_root).serialize()))
220+
assert_equal(node.submitblock(hexdata=b2x(block.serialize())), 'duplicate') # valid
204221

205222

206223
if __name__ == '__main__':

0 commit comments

Comments
 (0)