Skip to content

Commit

Permalink
Discourage fee sniping with nLockTime
Browse files Browse the repository at this point in the history
  • Loading branch information
petertodd committed Sep 14, 2013
1 parent 08ed7a2 commit e9124c0
Showing 1 changed file with 43 additions and 1 deletion.
44 changes: 43 additions & 1 deletion src/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1164,6 +1164,44 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend,

wtxNew.BindWallet(this);

// Only allow this transaction to be mined by the next block, rather than a

This comment has been minimized.

Copy link
@wtogami

wtogami Sep 14, 2013

Probably be a stupid question ... how does your wallet know what the "next block" is? Isn't there a tiny race window?

This comment has been minimized.

Copy link
@petertodd

petertodd Sep 15, 2013

Author Owner

Huh? All it does is sets the nLockTime so the transaction can only be included in a block with height one greater than the current best block height.

// block orphaning the current best block. There are two reasons to do
// this, the first is the minor benefit that using nLockTime ensures
// related bugs get caught immediately, so protocols that need that feature
// don't become "unusual" transactions with flaky behavior.
//
// The more important reason is to discourage "fee sniping" by deliberately
// mining blocks that orphan the current best block. Basically for a large
// miner the value of the transactions in the best block and the mempool
// can exceed the cost of deliberately attempting to mine two blocks to
// orphan the best block. However with nLockTime you'll soon run out of
// transactions you can put in the first block, which means they now need
// to go in the second. With limited block sizes you're run out of room,
// and additionally another miner now only needs to orphan one block to
// in-turn snipe the high-fee transactions you had to place in the second
// block, wrecking all your hard work.
//
// Of course, the subsidy is high enough, and transaction volume low
// enough, that fee sniping isn't a problem yet, but by implementing a fix
// now we ensure code won't be written that makes assumptions about
// nLockTime that preclude a fix later. Transaction propagation is not
// impacted; even with non-final is non-standard the best block height
// implies we have at least one peer, and very soon more peers, that will
// accept and rebroadcast the transaction immediately.
//
// It is possible (if very unlikely) for a re-org near a retarget to result
// in nBestHeight decreasing, however transactions already accepted to a
// node's mempool will not be evicted by the non-final is non-standard rule
// and thus will confirm once more blocks are mined.
//
// However, CreateNewBlock() in <=0.8.0 has an off-by-one error and won't

This comment has been minimized.

Copy link
@wtogami

wtogami Sep 14, 2013

Litecoin has pretty much zero <=0.8 miners anymore, so do we need -1?

This comment has been minimized.

Copy link
@petertodd

petertodd Sep 15, 2013

Author Owner

No released Bitcoin or Litecoin version fixes that problem yet; see bitcoin#2342

// mine transactions until one block *after* their nLockTime expires, so
// for now we take that into account. This doesn't really offer any
// protection, but it does at least serve to shake out bugs for when the
// network is upgraded and the -1 can be removed so the protection actually
// works.
wtxNew.nLockTime = nBestHeight-1;

{
LOCK2(cs_main, cs_wallet);
{
Expand Down Expand Up @@ -1255,8 +1293,12 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend,
reservekey.ReturnKey();

// Fill vin
//
// Note how the sequence number is set to max()-1 so the
// nLockTime set above actually works.
BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
wtxNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second));
wtxNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second,CScript(),
std::numeric_limits<unsigned int>::max()-1));

// Sign
int nIn = 0;
Expand Down

0 comments on commit e9124c0

Please sign in to comment.