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.cpp41
-rw-r--r--src/main.h20
-rw-r--r--src/rpc.cpp34
3 files changed, 81 insertions, 14 deletions
diff --git a/src/main.cpp b/src/main.cpp
index 7b3e555..64eb290 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -4470,7 +4470,6 @@ bool BitcoinMiner(int nThreadId)
4470 map<uint256, CTxIndex> mapTestPool; 4470 map<uint256, CTxIndex> mapTestPool;
4471 vector<char> vfAlreadyAdded(mapTransactions.size()); 4471 vector<char> vfAlreadyAdded(mapTransactions.size());
4472 bool fFoundSomething = true; 4472 bool fFoundSomething = true;
4473 unsigned int nBlockSize = 0;
4474 // Assembly must stop below the consensus cap that CheckBlock() 4473 // Assembly must stop below the consensus cap that CheckBlock()
4475 // enforces, or we mine a block our own node then rejects. 4474 // enforces, or we mine a block our own node then rejects.
4476 // 4475 //
@@ -4481,9 +4480,19 @@ bool BitcoinMiner(int nThreadId)
4481 // meant solving a block and throwing it away -- with this pool at 4480 // meant solving a block and throwing it away -- with this pool at
4482 // ~90% of hashrate, that is the network stalling, not just us. 4481 // ~90% of hashrate, that is the network stalling, not just us.
4483 // 4482 //
4484 // Half the cap, keeping the original margin: the test runs before 4483 // The budget test then sat only on this outer while, and the
4485 // a transaction is added, so the loop can overshoot by one tx. 4484 // comment claimed that bounded the overshoot to a single
4486 while (fFoundSomething && nBlockSize < MAX_BLOCK_SIZE/2) 4485 // transaction. It did not. The inner for walks all of
4486 // mapTransactions with no test of its own, so one pass could append
4487 // the entire mempool: the overshoot was bounded by mempool size,
4488 // which is to say not bounded at all. Ask per transaction, before
4489 // appending, and the overshoot is zero rather than small.
4490 //
4491 // Seeded with what the block already weighs -- header, tx count,
4492 // coinbase -- because CheckBlock() weighs the whole serialized
4493 // block and not just the transactions we chose to add to it.
4494 unsigned int nBlockSize = ::GetSerializeSize(*pblock, SER_DISK);
4495 while (fFoundSomething && nBlockSize < MAX_BLOCK_SIZE_GEN)
4487 { 4496 {
4488 fFoundSomething = false; 4497 fFoundSomething = false;
4489 unsigned int n = 0; 4498 unsigned int n = 0;
@@ -4495,6 +4504,28 @@ bool BitcoinMiner(int nThreadId)
4495 if (tx.IsCoinBase() || !tx.IsFinal()) 4504 if (tx.IsCoinBase() || !tx.IsFinal())
4496 continue; 4505 continue;
4497 4506
4507 // Skip, not break: a transaction too big for the room left
4508 // says nothing about the next one, which may still fit.
4509 //
4510 // This is also the only ceiling on a single transaction's
4511 // size anywhere on the path into a block. CheckTransaction
4512 // does not cap it and neither does AcceptTransaction, so
4513 // the mempool will hold one of any size the wire allows;
4514 // without this test a lone 1.5 MB transaction offering a
4515 // fat fee is selected, and every template built from that
4516 // mempool is one CheckBlock() throws away. The fee is never
4517 // paid, because the block never confirms.
4518 //
4519 // Deliberately before ConnectInputs and not after:
4520 // ConnectInputs adds this transaction's fee to nFees by
4521 // reference on success. Passing it and then declining the
4522 // transaction would credit the coinbase for a fee no
4523 // transaction in the block pays, and the block would be
4524 // rejected for a wholly different reason.
4525 unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK);
4526 if (!BlockTemplateFits(nBlockSize, nTxSize))
4527 continue;
4528
4498 // Transaction fee requirements, mainly only needed for flood control 4529 // Transaction fee requirements, mainly only needed for flood control
4499 // Under 10K (about 80 inputs) is free for first 100 transactions 4530 // Under 10K (about 80 inputs) is free for first 100 transactions
4500 // Base rate is 0.01 per KB 4531 // Base rate is 0.01 per KB
@@ -4506,7 +4537,7 @@ bool BitcoinMiner(int nThreadId)
4506 swap(mapTestPool, mapTestPoolTmp); 4537 swap(mapTestPool, mapTestPoolTmp);
4507 4538
4508 pblock->vtx.push_back(tx); 4539 pblock->vtx.push_back(tx);
4509 nBlockSize += ::GetSerializeSize(tx, SER_NETWORK); 4540 nBlockSize += nTxSize;
4510 vfAlreadyAdded[n] = true; 4541 vfAlreadyAdded[n] = true;
4511 fFoundSomething = true; 4542 fFoundSomething = true;
4512 } 4543 }
diff --git a/src/main.h b/src/main.h
index 382dd9c..1f452b5 100644
--- a/src/main.h
+++ b/src/main.h
@@ -33,6 +33,26 @@ static const unsigned int MAX_BLOCK_SIGOPS = 20000;
33// limit (32 MB), not a block rule. Bitcoin 0.1.0 predated the later 1 MB block 33// limit (32 MB), not a block rule. Bitcoin 0.1.0 predated the later 1 MB block
34// cap, so this tree inherited no real block-size consensus limit. 34// cap, so this tree inherited no real block-size consensus limit.
35static const unsigned int MAX_BLOCK_SIZE = 1000000; 35static const unsigned int MAX_BLOCK_SIZE = 1000000;
36// How much of that cap a template we build may fill. Half, which is what both
37// assemblers already aimed at -- this only gives the number a name and one
38// place to live. They had already drifted on how it was enforced, which is the
39// bug this exists to stop repeating.
40//
41// NOT a consensus rule. CheckBlock() decides what the network accepts; this
42// decides what we are willing to produce, and it has to stay under that.
43static const unsigned int MAX_BLOCK_SIZE_GEN = MAX_BLOCK_SIZE / 2;
44
45// Room for one more transaction in a template that currently weighs
46// nBlockSize bytes?
47//
48// Asked BEFORE the transaction is appended, never after. A template that has
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
51// different idea of what fits.
52inline bool BlockTemplateFits(unsigned int nBlockSize, unsigned int nTxSize)
53{
54 return (nBlockSize + nTxSize <= MAX_BLOCK_SIZE_GEN);
55}
36static const int64 COIN = 100000000; 56static const int64 COIN = 100000000;
37// Total Bitflash emission: identical to Bitcoin (21 million). 57// Total Bitflash emission: identical to Bitcoin (21 million).
38// MAX_MONEY guards against the value overflow bug (CVE-2010-5139), which in 58// MAX_MONEY guards against the value overflow bug (CVE-2010-5139), which in
diff --git a/src/rpc.cpp b/src/rpc.cpp
index a4b53ca..7c5ef6c 100644
--- a/src/rpc.cpp
+++ b/src/rpc.cpp
@@ -267,16 +267,24 @@ static bool RebuildJob()
267 map<uint256, CTxIndex> pool; 267 map<uint256, CTxIndex> pool;
268 vector<char> vfAlreadyAdded(mapTransactions.size()); 268 vector<char> vfAlreadyAdded(mapTransactions.size());
269 bool fFoundSomething = true; 269 bool fFoundSomething = true;
270 unsigned int sz = 0; 270 // The cap is MAX_BLOCK_SIZE_GEN, not MAX_SIZE/2. MAX_SIZE is
271 // The cap is MAX_BLOCK_SIZE/2, not MAX_SIZE/2. MAX_SIZE is the 271 // the 32 MB serialisation ceiling, so half of it is 16 MB --
272 // 32 MB serialisation ceiling, so half of it is 16 MB -- this 272 // this builder would happily assemble a template that its own
273 // builder would happily assemble a template that its own
274 // CheckBlock() rejects at the 1 MB consensus cap. This is the 273 // CheckBlock() rejects at the 1 MB consensus cap. This is the
275 // pool's job builder, so a block over the cap is not one 274 // pool's job builder, so a block over the cap is not one
276 // wasted solve, it is every miner on the pool working a 275 // wasted solve, it is every miner on the pool working a
277 // template the network will reject. The inner break bounds the 276 // template the network will reject.
278 // overshoot to a single transaction within a pass. 277 //
279 while (fFoundSomething && sz < MAX_BLOCK_SIZE / 2) 278 // The inner break used to bound the overshoot to one
279 // transaction per pass. One transaction is still too many:
280 // nothing caps how big a single transaction may be, so that
281 // bound was worth up to MAX_SIZE. Asking whether each one fits
282 // before appending it bounds the overshoot at zero instead.
283 //
284 // Seeded with the header, tx count and coinbase, because
285 // CheckBlock() weighs the whole serialized block.
286 unsigned int sz = ::GetSerializeSize(block, SER_DISK);
287 while (fFoundSomething && sz < MAX_BLOCK_SIZE_GEN)
280 { 288 {
281 fFoundSomething = false; 289 fFoundSomething = false;
282 unsigned int n = 0; 290 unsigned int n = 0;
@@ -287,16 +295,24 @@ static bool RebuildJob()
287 continue; 295 continue;
288 CTransaction& tx = (*mi).second; 296 CTransaction& tx = (*mi).second;
289 if (tx.IsCoinBase() || !tx.IsFinal()) continue; 297 if (tx.IsCoinBase() || !tx.IsFinal()) continue;
298 // Skip rather than stop: one transaction too big for
299 // the room left does not mean the next is. Ordered
300 // before ConnectInputs because ConnectInputs credits
301 // nFees by reference on success, and a transaction we
302 // then decline would leave the coinbase claiming a fee
303 // this block does not collect.
304 unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK);
305 if (!BlockTemplateFits(sz, nTxSize))
306 continue;
290 map<uint256, CTxIndex> tmp(pool); 307 map<uint256, CTxIndex> tmp(pool);
291 if (!tx.ConnectInputs(txdb, tmp, CDiskTxPos(1,1,1), 0, nFees, 308 if (!tx.ConnectInputs(txdb, tmp, CDiskTxPos(1,1,1), 0, nFees,
292 false, true, tx.GetMinFee(block.vtx.size() < 100))) 309 false, true, tx.GetMinFee(block.vtx.size() < 100)))
293 continue; 310 continue;
294 swap(pool, tmp); 311 swap(pool, tmp);
295 block.vtx.push_back(tx); 312 block.vtx.push_back(tx);
296 sz += ::GetSerializeSize(tx, SER_NETWORK); 313 sz += nTxSize;
297 vfAlreadyAdded[n] = true; 314 vfAlreadyAdded[n] = true;
298 fFoundSomething = true; 315 fFoundSomething = true;
299 if (sz > MAX_BLOCK_SIZE / 2) break;
300 } 316 }
301 } 317 }
302 } 318 }