upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.cpp19
-rw-r--r--src/main.h15
-rw-r--r--src/rpc.cpp13
3 files changed, 38 insertions, 9 deletions
diff --git a/src/main.cpp b/src/main.cpp
index 64eb290..4d8031d 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -4492,6 +4492,17 @@ bool BitcoinMiner(int nThreadId)
4492 // coinbase -- because CheckBlock() weighs the whole serialized 4492 // coinbase -- because CheckBlock() weighs the whole serialized
4493 // block and not just the transactions we chose to add to it. 4493 // block and not just the transactions we chose to add to it.
4494 unsigned int nBlockSize = ::GetSerializeSize(*pblock, SER_DISK); 4494 unsigned int nBlockSize = ::GetSerializeSize(*pblock, SER_DISK);
4495 // Sigops are a budget too, and CheckBlock() enforces one that no
4496 // assembler here counted against. Bytes do not bound validation
4497 // cost: every OP_CHECKSIG is an elliptic-curve verification, so a
4498 // template well inside the size limit can still be refused for
4499 // demanding more work than a block is allowed to. Counted with
4500 // CTransaction::GetSigOpCount, the function CheckBlock() itself
4501 // sums, so the two cannot disagree about what a transaction costs.
4502 //
4503 // Seeded from the coinbase because CheckBlock() sums over all of
4504 // vtx, coinbase included.
4505 unsigned int nBlockSigOps = pblock->vtx[0].GetSigOpCount();
4495 while (fFoundSomething && nBlockSize < MAX_BLOCK_SIZE_GEN) 4506 while (fFoundSomething && nBlockSize < MAX_BLOCK_SIZE_GEN)
4496 { 4507 {
4497 fFoundSomething = false; 4508 fFoundSomething = false;
@@ -4522,8 +4533,9 @@ bool BitcoinMiner(int nThreadId)
4522 // transaction would credit the coinbase for a fee no 4533 // transaction would credit the coinbase for a fee no
4523 // transaction in the block pays, and the block would be 4534 // transaction in the block pays, and the block would be
4524 // rejected for a wholly different reason. 4535 // rejected for a wholly different reason.
4525 unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK); 4536 unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK);
4526 if (!BlockTemplateFits(nBlockSize, nTxSize)) 4537 unsigned int nTxSigOps = tx.GetSigOpCount();
4538 if (!BlockTemplateFits(nBlockSize, nBlockSigOps, nTxSize, nTxSigOps))
4527 continue; 4539 continue;
4528 4540
4529 // Transaction fee requirements, mainly only needed for flood control 4541 // Transaction fee requirements, mainly only needed for flood control
@@ -4537,7 +4549,8 @@ bool BitcoinMiner(int nThreadId)
4537 swap(mapTestPool, mapTestPoolTmp); 4549 swap(mapTestPool, mapTestPoolTmp);
4538 4550
4539 pblock->vtx.push_back(tx); 4551 pblock->vtx.push_back(tx);
4540 nBlockSize += nTxSize; 4552 nBlockSize += nTxSize;
4553 nBlockSigOps += nTxSigOps;
4541 vfAlreadyAdded[n] = true; 4554 vfAlreadyAdded[n] = true;
4542 fFoundSomething = true; 4555 fFoundSomething = true;
4543 } 4556 }
diff --git a/src/main.h b/src/main.h
index 1f452b5..30e25ef 100644
--- a/src/main.h
+++ b/src/main.h
@@ -43,15 +43,24 @@ static const unsigned int MAX_BLOCK_SIZE = 1000000;
43static const unsigned int MAX_BLOCK_SIZE_GEN = MAX_BLOCK_SIZE / 2; 43static const unsigned int MAX_BLOCK_SIZE_GEN = MAX_BLOCK_SIZE / 2;
44 44
45// Room for one more transaction in a template that currently weighs 45// Room for one more transaction in a template that currently weighs
46// nBlockSize bytes? 46// nBlockSize bytes and spends nBlockSigOps signature operations?
47// 47//
48// Asked BEFORE the transaction is appended, never after. A template that has 48// Asked BEFORE the transaction is appended, never after. A template that has
49// already overshot is one CheckBlock() rejects, and asking afterwards only 49// already overshot is one CheckBlock() rejects, and asking afterwards only
50// measures the waste. Both assemblers call this, so neither can drift into a 50// measures the waste. Both assemblers call this, so neither can drift into a
51// different idea of what fits. 51// different idea of what fits.
52inline bool BlockTemplateFits(unsigned int nBlockSize, unsigned int nTxSize) 52//
53// Size gets a margin (half the cap); sigops do not. There is no cheap way to
54// spend the sigop budget usefully and no reason to reserve headroom in it, so
55// assembly holds itself to the same number CheckBlock() enforces -- and to the
56// same comparison. CheckBlock() fails on `> MAX_BLOCK_SIGOPS`, so a block
57// sitting exactly on the limit is valid and this has to accept it too.
58// Assembly and validation disagreeing by one is how the size bug started.
59inline bool BlockTemplateFits(unsigned int nBlockSize, unsigned int nBlockSigOps,
60 unsigned int nTxSize, unsigned int nTxSigOps)
53{ 61{
54 return (nBlockSize + nTxSize <= MAX_BLOCK_SIZE_GEN); 62 return (nBlockSize + nTxSize <= MAX_BLOCK_SIZE_GEN &&
63 nBlockSigOps + nTxSigOps <= MAX_BLOCK_SIGOPS);
55} 64}
56static const int64 COIN = 100000000; 65static const int64 COIN = 100000000;
57// Total Bitflash emission: identical to Bitcoin (21 million). 66// Total Bitflash emission: identical to Bitcoin (21 million).
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 }