diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.cpp | 41 | ||||
| -rw-r--r-- | src/main.h | 20 | ||||
| -rw-r--r-- | src/rpc.cpp | 34 |
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 | } |
| @@ -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. |
| 35 | static const unsigned int MAX_BLOCK_SIZE = 1000000; | 35 | static 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. | ||
| 43 | static 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. | ||
| 52 | inline bool BlockTemplateFits(unsigned int nBlockSize, unsigned int nTxSize) | ||
| 53 | { | ||
| 54 | return (nBlockSize + nTxSize <= MAX_BLOCK_SIZE_GEN); | ||
| 55 | } | ||
| 36 | static const int64 COIN = 100000000; | 56 | static 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 | } |