diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.cpp | 30 | ||||
| -rw-r--r-- | src/main.h | 2 | ||||
| -rw-r--r-- | src/rpc.cpp | 2 | ||||
| -rw-r--r-- | src/script.cpp | 31 | ||||
| -rw-r--r-- | src/script.h | 4 |
5 files changed, 60 insertions, 9 deletions
diff --git a/src/main.cpp b/src/main.cpp index aff7bab..a7298ea 100644 --- a/src/main.cpp +++ b/src/main.cpp | |||
| @@ -729,12 +729,16 @@ uint256 GetOrphanRoot(const CBlock* pblock) | |||
| 729 | return pblock->GetHash(); | 729 | return pblock->GetHash(); |
| 730 | } | 730 | } |
| 731 | 731 | ||
| 732 | int64 CBlock::GetBlockValue(int64 nFees) const | 732 | int64 CBlock::GetBlockValue(int nHeight, int64 nFees) const |
| 733 | { | 733 | { |
| 734 | int64 nSubsidy = 50 * COIN; | 734 | int64 nSubsidy = 50 * COIN; |
| 735 | 735 | ||
| 736 | // Subsidy is cut in half every 4 years | 736 | // Halve on the height of this block, never on nBestHeight. The subsidy a |
| 737 | nSubsidy >>= (nBestHeight / 210000); | 737 | // block is allowed to pay is a property of that block; deriving it from |
| 738 | // the validating node's own tip makes the answer depend on how far that | ||
| 739 | // node happens to have synced, so two nodes at different heights would | ||
| 740 | // disagree about the same block across a halving boundary. | ||
| 741 | nSubsidy >>= (nHeight / 210000); | ||
| 738 | 742 | ||
| 739 | return nSubsidy + nFees; | 743 | return nSubsidy + nFees; |
| 740 | } | 744 | } |
| @@ -1011,7 +1015,7 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex) | |||
| 1011 | return false; | 1015 | return false; |
| 1012 | } | 1016 | } |
| 1013 | 1017 | ||
| 1014 | if (vtx[0].GetValueOut() > GetBlockValue(nFees)) | 1018 | if (vtx[0].GetValueOut() > GetBlockValue(pindex->nHeight, nFees)) |
| 1015 | return false; | 1019 | return false; |
| 1016 | 1020 | ||
| 1017 | // Update block index on disk without changing it in memory. | 1021 | // Update block index on disk without changing it in memory. |
| @@ -1237,6 +1241,22 @@ bool CBlock::CheckBlock() const | |||
| 1237 | if (!tx.CheckTransaction()) | 1241 | if (!tx.CheckTransaction()) |
| 1238 | return error("CheckBlock() : CheckTransaction failed"); | 1242 | return error("CheckBlock() : CheckTransaction failed"); |
| 1239 | 1243 | ||
| 1244 | // Reject blocks carrying the same transaction twice (CVE-2012-2459). | ||
| 1245 | // | ||
| 1246 | // BuildMerkleTree duplicates the last hash when a level has an odd width, | ||
| 1247 | // so appending a copy of the trailing transaction(s) yields a block with | ||
| 1248 | // an identical merkle root -- and therefore an identical block hash -- to | ||
| 1249 | // a legitimate one. The forgery fails validation, the hash gets recorded | ||
| 1250 | // as bad, and the real block is then refused because it hashes the same. | ||
| 1251 | set<uint256> setTxHashes; | ||
| 1252 | foreach(const CTransaction& tx, vtx) | ||
| 1253 | { | ||
| 1254 | uint256 hashTx = tx.GetHash(); | ||
| 1255 | if (setTxHashes.count(hashTx)) | ||
| 1256 | return error("CheckBlock() : duplicate transaction in block"); | ||
| 1257 | setTxHashes.insert(hashTx); | ||
| 1258 | } | ||
| 1259 | |||
| 1240 | // Check proof of work matches claimed amount (memory-hard RandomX PoW) | 1260 | // Check proof of work matches claimed amount (memory-hard RandomX PoW) |
| 1241 | if (CBigNum().SetCompact(nBits) > bnProofOfWorkLimit) | 1261 | if (CBigNum().SetCompact(nBits) > bnProofOfWorkLimit) |
| 1242 | return error("CheckBlock() : nBits below minimum work"); | 1262 | return error("CheckBlock() : nBits below minimum work"); |
| @@ -2803,7 +2823,7 @@ bool BitcoinMiner() | |||
| 2803 | } | 2823 | } |
| 2804 | } | 2824 | } |
| 2805 | pblock->nBits = nBits; | 2825 | pblock->nBits = nBits; |
| 2806 | pblock->vtx[0].vout[0].nValue = pblock->GetBlockValue(nFees); | 2826 | pblock->vtx[0].vout[0].nValue = pblock->GetBlockValue(nBestHeight + 1, nFees); |
| 2807 | if (LogAcceptsCategory("net")) printf("\n\nRunning BitcoinMiner with %d transactions in block\n", pblock->vtx.size()); | 2827 | if (LogAcceptsCategory("net")) printf("\n\nRunning BitcoinMiner with %d transactions in block\n", pblock->vtx.size()); |
| 2808 | 2828 | ||
| 2809 | 2829 | ||
| @@ -1073,7 +1073,7 @@ public: | |||
| 1073 | } | 1073 | } |
| 1074 | 1074 | ||
| 1075 | 1075 | ||
| 1076 | int64 GetBlockValue(int64 nFees) const; | 1076 | int64 GetBlockValue(int nHeight, int64 nFees) const; |
| 1077 | bool DisconnectBlock(CTxDB& txdb, CBlockIndex* pindex); | 1077 | bool DisconnectBlock(CTxDB& txdb, CBlockIndex* pindex); |
| 1078 | bool ConnectBlock(CTxDB& txdb, CBlockIndex* pindex); | 1078 | bool ConnectBlock(CTxDB& txdb, CBlockIndex* pindex); |
| 1079 | bool ReadFromDisk(const CBlockIndex* blockindex, bool fReadTransactions); | 1079 | bool ReadFromDisk(const CBlockIndex* blockindex, bool fReadTransactions); |
diff --git a/src/rpc.cpp b/src/rpc.cpp index 1b529e8..3b2dae9 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp | |||
| @@ -182,7 +182,7 @@ static bool RebuildJob() | |||
| 182 | } | 182 | } |
| 183 | } | 183 | } |
| 184 | 184 | ||
| 185 | block.vtx[0].vout[0].nValue = block.GetBlockValue(0); | 185 | block.vtx[0].vout[0].nValue = block.GetBlockValue(pindexPrev->nHeight + 1, 0); |
| 186 | block.hashPrevBlock = pindexPrev->GetBlockHash(); | 186 | block.hashPrevBlock = pindexPrev->GetBlockHash(); |
| 187 | block.hashMerkleRoot = block.BuildMerkleTree(); | 187 | block.hashMerkleRoot = block.BuildMerkleTree(); |
| 188 | block.nTime = max((unsigned int)(pindexPrev->GetMedianTimePast() + 1), | 188 | block.nTime = max((unsigned int)(pindexPrev->GetMedianTimePast() + 1), |
diff --git a/src/script.cpp b/src/script.cpp index d2111ed..44eed93 100644 --- a/src/script.cpp +++ b/src/script.cpp | |||
| @@ -67,6 +67,24 @@ bool EvalScript(const CScript& script, const CTransaction& txTo, unsigned int nI | |||
| 67 | if (!script.GetOp(pc, opcode, vchPushValue)) | 67 | if (!script.GetOp(pc, opcode, vchPushValue)) |
| 68 | return false; | 68 | return false; |
| 69 | 69 | ||
| 70 | if (vchPushValue.size() > MAX_SCRIPT_ELEMENT_SIZE) | ||
| 71 | return false; | ||
| 72 | |||
| 73 | // Disabled opcodes. Checked before the fExec test, so they invalidate | ||
| 74 | // the script even inside a branch that is never taken. | ||
| 75 | // | ||
| 76 | // These are unbounded: OP_CAT grows a stack element without limit | ||
| 77 | // (<x> OP_DUP OP_CAT repeated doubles it each time, so a tiny script | ||
| 78 | // exhausts memory), and OP_LSHIFT shifts by an attacker-supplied | ||
| 79 | // amount with no ceiling. Both let any transaction take down every | ||
| 80 | // node that validates it. Bitcoin removed the whole group for this. | ||
| 81 | if (opcode == OP_CAT || opcode == OP_SUBSTR || opcode == OP_LEFT || | ||
| 82 | opcode == OP_RIGHT || opcode == OP_INVERT || opcode == OP_AND || | ||
| 83 | opcode == OP_OR || opcode == OP_XOR || opcode == OP_2MUL || | ||
| 84 | opcode == OP_2DIV || opcode == OP_MUL || opcode == OP_DIV || | ||
| 85 | opcode == OP_MOD || opcode == OP_LSHIFT || opcode == OP_RSHIFT) | ||
| 86 | return false; | ||
| 87 | |||
| 70 | if (fExec && opcode <= OP_PUSHDATA4) | 88 | if (fExec && opcode <= OP_PUSHDATA4) |
| 71 | stack.push_back(vchPushValue); | 89 | stack.push_back(vchPushValue); |
| 72 | else if (fExec || (OP_IF <= opcode && opcode <= OP_ENDIF)) | 90 | else if (fExec || (OP_IF <= opcode && opcode <= OP_ENDIF)) |
| @@ -169,9 +187,18 @@ bool EvalScript(const CScript& script, const CTransaction& txTo, unsigned int nI | |||
| 169 | 187 | ||
| 170 | case OP_RETURN: | 188 | case OP_RETURN: |
| 171 | { | 189 | { |
| 172 | pc = pend; | 190 | // Must fail the script outright, never just stop executing it. |
| 191 | // | ||
| 192 | // scriptSig and scriptPubKey are evaluated as one concatenated | ||
| 193 | // script (see VerifySignature). The 0.1.0 behaviour here was | ||
| 194 | // "pc = pend", which jumps past everything that follows — so a | ||
| 195 | // scriptSig of <OP_TRUE OP_RETURN> skipped the entire | ||
| 196 | // scriptPubKey, including OP_CHECKSIG, and the final | ||
| 197 | // CastToBool(stack.back()) saw the attacker's own OP_TRUE. | ||
| 198 | // That let anyone spend anyone else's outputs without a | ||
| 199 | // signature. Bitcoin closed this in 0.3.5. | ||
| 200 | return false; | ||
| 173 | } | 201 | } |
| 174 | break; | ||
| 175 | 202 | ||
| 176 | 203 | ||
| 177 | // | 204 | // |
diff --git a/src/script.h b/src/script.h index d52d06b..27c1b13 100644 --- a/src/script.h +++ b/src/script.h | |||
| @@ -4,6 +4,10 @@ | |||
| 4 | 4 | ||
| 5 | class CTransaction; | 5 | class CTransaction; |
| 6 | 6 | ||
| 7 | // Largest byte vector a script may push onto the stack. Without a ceiling, | ||
| 8 | // script evaluation allocates whatever the transaction asks it to. | ||
| 9 | static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520; | ||
| 10 | |||
| 7 | enum | 11 | enum |
| 8 | { | 12 | { |
| 9 | SIGHASH_ALL = 1, | 13 | SIGHASH_ALL = 1, |