Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Do not allow overwriting unspent transactions (BIP 30)

Introduce the following network rule:
 * a block is not valid if it contains a transaction whose hash
   already exists in the block chain, unless all that transaction's
   outputs were already spent before said block.

Warning: this is effectively a network rule change, with potential
risk for forking the block chain. Leaving this unfixed carries the
same risk however, for attackers that can cause a reorganisation
in part of the network.

Thanks to Russell O'Connor and Ben Reeves.
  • Loading branch information...
commit a206b0ea12eb4606b93323268fc81a4f1f952531 1 parent 50abb55
@sipa sipa authored
Showing with 24 additions and 2 deletions.
  1. +24 −2 src/main.cpp
View
26 src/main.cpp
@@ -976,8 +976,10 @@ bool CTransaction::DisconnectInputs(CTxDB& txdb)
}
// Remove transaction from index
- if (!txdb.EraseTxIndex(*this))
- return error("DisconnectInputs() : EraseTxPos failed");
+ // This can fail if a duplicate of this transaction was in a chain that got
+ // reorganized away. This is only possible if this transaction was completely
+ // spent, so erasing it would be a no-op anway.
+ txdb.EraseTxIndex(*this);
return true;
}
@@ -1256,6 +1258,26 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex)
if (!CheckBlock())
return false;
+ // Do not allow blocks that contain transactions which 'overwrite' older transactions,
+ // unless those are already completely spent.
+ // If such overwrites are allowed, coinbases and transactions depending upon those
+ // can be duplicated to remove the ability to spend the first instance -- even after
+ // being sent to another address.
+ // See BIP30 and http://r6.ca/blog/20120206T005236Z.html for more information.
+ // This logic is not necessary for memory pool transactions, as AcceptToMemoryPool
+ // already refuses previously-known transaction id's entirely.
+ // This rule applies to all blocks whose timestamp is after March 15, 2012, 0:00 UTC.
+ // On testnet it is enabled as of februari 20, 2012, 0:00 UTC.
+ if (pindex->nTime > 1331769600 || (fTestNet && pindex->nTime > 1329696000))
+ BOOST_FOREACH(CTransaction& tx, vtx)
+ {
+ CTxIndex txindexOld;
+ if (txdb.ReadTxIndex(tx.GetHash(), txindexOld))
+ BOOST_FOREACH(CDiskTxPos &pos, txindexOld.vSpent)
+ if (pos.IsNull())
+ return false;
+ }
+
// To avoid being on the short end of a block-chain split,
// don't do secondary validation of pay-to-script-hash transactions
// until blocks with timestamps after paytoscripthashtime (see init.cpp for default).
Please sign in to comment.
Something went wrong with that request. Please try again.