upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/rpc.cpp
diff options
context:
space:
mode:
authorbitflash-maintainer <noreply@bitflash.invalid>2026-09-02 14:16:48 +0000
committerbitflash-maintainer <noreply@bitflash.invalid>2026-09-02 14:16:48 +0000
commit2ed8fae6088c99f1a5dfcfd760c1a24c2b2706db (patch)
treef23023e737fc73cdb384e4840c033cfc5ac08e10 /src/rpc.cpp
parent74c068829967bbff60da3506613844df4da1ae80 (diff)
mine: count sigops while selecting, not only when validating
CheckBlock() caps a block at MAX_BLOCK_SIGOPS and neither assembler counted against it. Bytes do not bound what a block costs to verify: every OP_CHECKSIG is an elliptic-curve verification, so a template comfortably inside the size budget can still be one the network refuses for demanding more work than a block is allowed to. Counted with CTransaction::GetSigOpCount -- the same function CheckBlock() sums, not a second implementation of it -- and seeded from the coinbase, because CheckBlock() sums over all of vtx. The comparison matches too: CheckBlock() fails on `> MAX_BLOCK_SIGOPS`, so a block exactly on the limit is valid and selection accepts it. Assembly and validation differing by one is the shape of the bug this series started with. Unlike the size budget this takes no margin. There is no use for headroom in a sigop count, so assembly holds itself to the consensus number exactly. Assembly only; MAX_BLOCK_SIGOPS and the CheckBlock() test are unchanged.
Diffstat (limited to 'src/rpc.cpp')
-rw-r--r--src/rpc.cpp13
1 files changed, 10 insertions, 3 deletions
diff --git a/src/rpc.cpp b/src/rpc.cpp
index 7c5ef6c..62eec7a 100644
--- a/src/rpc.cpp
+++ b/src/rpc.cpp
@@ -284,6 +284,11 @@ static bool RebuildJob()
284 // Seeded with the header, tx count and coinbase, because 284 // Seeded with the header, tx count and coinbase, because
285 // CheckBlock() weighs the whole serialized block. 285 // CheckBlock() weighs the whole serialized block.
286 unsigned int sz = ::GetSerializeSize(block, SER_DISK); 286 unsigned int sz = ::GetSerializeSize(block, SER_DISK);
287 // And the sigop budget, which CheckBlock() enforces and this
288 // builder never counted against. Same counting function
289 // CheckBlock() sums, seeded from the coinbase because it sums
290 // over all of vtx.
291 unsigned int nSigOps = block.vtx[0].GetSigOpCount();
287 while (fFoundSomething && sz < MAX_BLOCK_SIZE_GEN) 292 while (fFoundSomething && sz < MAX_BLOCK_SIZE_GEN)
288 { 293 {
289 fFoundSomething = false; 294 fFoundSomething = false;
@@ -301,8 +306,9 @@ static bool RebuildJob()
301 // nFees by reference on success, and a transaction we 306 // nFees by reference on success, and a transaction we
302 // then decline would leave the coinbase claiming a fee 307 // then decline would leave the coinbase claiming a fee
303 // this block does not collect. 308 // this block does not collect.
304 unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK); 309 unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK);
305 if (!BlockTemplateFits(sz, nTxSize)) 310 unsigned int nTxSigOps = tx.GetSigOpCount();
311 if (!BlockTemplateFits(sz, nSigOps, nTxSize, nTxSigOps))
306 continue; 312 continue;
307 map<uint256, CTxIndex> tmp(pool); 313 map<uint256, CTxIndex> tmp(pool);
308 if (!tx.ConnectInputs(txdb, tmp, CDiskTxPos(1,1,1), 0, nFees, 314 if (!tx.ConnectInputs(txdb, tmp, CDiskTxPos(1,1,1), 0, nFees,
@@ -310,7 +316,8 @@ static bool RebuildJob()
310 continue; 316 continue;
311 swap(pool, tmp); 317 swap(pool, tmp);
312 block.vtx.push_back(tx); 318 block.vtx.push_back(tx);
313 sz += nTxSize; 319 sz += nTxSize;
320 nSigOps += nTxSigOps;
314 vfAlreadyAdded[n] = true; 321 vfAlreadyAdded[n] = true;
315 fFoundSomething = true; 322 fFoundSomething = true;
316 } 323 }