aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGavin Andresen <gavinandresen@gmail.com>2012-05-16 11:26:56 -0400
committerLuke Dashjr <luke-jr+git@utopios.org>2012-06-20 17:39:24 +0000
commitce1a071f6d6d1548974796c4327399659415b489 (patch)
tree40dc41309b192872251dd2706df07088edc51162 /src
parentc3def40293a89307d296ff66653b5927165c3c18 (diff)
downloadbitcoin-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')
-rw-r--r--src/main.cpp19
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))
{