184 Billion Coins From Nowhere — JavaScript Bug Hunt
Modelled on the Bitcoin value overflow incident (CVE-2010-5139, 15 August 2010): a transaction with two enormous outputs made their sum overflow a signed…
- Language: JavaScript
- Layer: Backend
- Difficulty: Medium
- Concepts: Overflow, Validation
- Modelled on: Bitcoin · CVE-2010-5139
- Visible tests: an ordinary spend is accepted; an overflowing pair of outputs is rejected
- Reward: 50 XP for a complete fix
Briefing
Modelled on the Bitcoin value overflow incident (CVE-2010-5139, 15 August 2010): a transaction with two enormous outputs made their sum overflow a signed 64-bit integer and wrap to a small number, so the "outputs must not exceed inputs" check passed. Block 74638 created 184.467 billion BTC out of nothing, and the chain had to be forked.
ledger.js validates a transaction the same way — by summing outputs and comparing.
Fix validate so a wrapped or absurd total cannot pass.
Bug report
BUG-VALUEOVERFLOW · Priority: Critical · Reported by: consensus
validate(inputTotal, outputs) returns true only if the outputs are a legitimate spend:
- every output must be strictly positive and at most MAX_MONEY
- the sum of the outputs must be at most inputTotal
Observed: two outputs just under the wrap point sum to a small positive number and the transaction is accepted, minting money from nothing.
Logs
[consensus] accepted tx outputs=[9223372036854775806, 9223372036854775806] inputTotal=50
[consensus] supply increased by 1.844e+11The code as shipped
src/chain/ledger.js (editable)
var MAX_MONEY = 2100000000000000;
exports.MAX_MONEY = MAX_MONEY;
// Wraps like a fixed-width signed integer would.
function addWrapping(a, b) {
var sum = a + b;
if (sum > MAX_MONEY * 4) sum = sum - MAX_MONEY * 8;
return sum;
}
exports.validate = function (inputTotal, outputs) {
var total = 0;
for (var i = 0; i < outputs.length; i++) {
total = addWrapping(total, outputs[i]);
}
return total <= inputTotal;
};
Read-only context: src/chain/CONSENSUS.js.
Open the hunt to edit the files, run the visible tests and submit against the hidden ones. More JavaScript bug hunts.