diff options
author | Gavin Andresen <gavinandresen@gmail.com> | 2012-05-16 11:26:56 -0400 |
---|---|---|
committer | Luke Dashjr <luke-jr+git@utopios.org> | 2012-06-20 17:39:24 +0000 |
commit | ce1a071f6d6d1548974796c4327399659415b489 (patch) | |
tree | 40dc41309b192872251dd2706df07088edc51162 /src/main.cpp | |
parent | c3def40293a89307d296ff66653b5927165c3c18 (diff) | |
download | bitcoin-ce1a071f6d6d1548974796c4327399659415b489.tar.xz |
Further DoS prevention: Verify signatures last
Loop over all inputs doing inexpensive validity checks first,
and then loop over them a second time doing expensive signature
checks. This helps prevent possible CPU exhaustion attacks
where an attacker tries to make a victim waste time checking
signatures for invalid transactions.
Diffstat (limited to 'src/main.cpp')
-rw-r--r-- | src/main.cpp | 19 |
1 files changed, 15 insertions, 4 deletions
diff --git a/src/main.cpp b/src/main.cpp index b7067b2092..00f0633431 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1033,15 +1033,26 @@ bool CTransaction::ConnectInputs(MapPrevTx inputs, if (pindex->nBlockPos == txindex.pos.nBlockPos && pindex->nFile == txindex.pos.nFile) return error("ConnectInputs() : tried to spend coinbase at depth %d", pindexBlock->nHeight - pindex->nHeight); - // Check for conflicts (double-spend) - if (!txindex.vSpent[prevout.n].IsNull()) - return fMiner ? false : error("ConnectInputs() : %s prev tx already used at %s", GetHash().ToString().substr(0,10).c_str(), txindex.vSpent[prevout.n].ToString().c_str()); - // Check for negative or overflow input values nValueIn += txPrev.vout[prevout.n].nValue; if (!MoneyRange(txPrev.vout[prevout.n].nValue) || !MoneyRange(nValueIn)) return error("ConnectInputs() : txin values out of range"); + } + // The first loop above does all the inexpensive checks. + // Only if ALL inputs pass do we perform expensive ECDSA signature checks. + // Helps prevent CPU exhaustion attacks. + for (unsigned int i = 0; i < vin.size(); i++) + { + COutPoint prevout = vin[i].prevout; + assert(inputs.count(prevout.hash) > 0); + CTxIndex& txindex = inputs[prevout.hash].first; + CTransaction& txPrev = inputs[prevout.hash].second; + + // Check for conflicts (double-spend) + if (!txindex.vSpent[prevout.n].IsNull()) + return fMiner ? false : error("ConnectInputs() : %s prev tx already used at %s", GetHash().ToString().substr(0,10).c_str(), txindex.vSpent[prevout.n].ToString().c_str()); + // Verify signature if (!VerifySignature(txPrev, *this, i, fStrictPayToScriptHash, 0)) { |