diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.cpp | 19 | ||||
| -rw-r--r-- | src/main.h | 15 | ||||
| -rw-r--r-- | src/rpc.cpp | 13 |
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 | } |
| @@ -43,15 +43,24 @@ static const unsigned int MAX_BLOCK_SIZE = 1000000; | |||
| 43 | static const unsigned int MAX_BLOCK_SIZE_GEN = MAX_BLOCK_SIZE / 2; | 43 | static 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. |
| 52 | inline 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. | ||
| 59 | inline 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 | } |
| 56 | static const int64 COIN = 100000000; | 65 | static 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 | } |