diff options
Diffstat (limited to 'src/wallet.cpp')
-rw-r--r-- | src/wallet.cpp | 77 |
1 files changed, 56 insertions, 21 deletions
diff --git a/src/wallet.cpp b/src/wallet.cpp index 32a64daac0..8504c0a287 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2014 The Bitcoin developers +// Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -26,6 +26,7 @@ using namespace std; * Settings */ CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE); +CAmount maxTxFee = DEFAULT_TRANSACTION_MAXFEE; unsigned int nTxConfirmTarget = 1; bool bSpendZeroConfChange = true; bool fSendFreeTransactions = false; @@ -1382,6 +1383,28 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, CAmount> >& vecSend, wtxNew.BindWallet(this); CMutableTransaction txNew; + // Discourage fee sniping. + // + // However because of a off-by-one-error in previous versions we need to + // neuter it by setting nLockTime to at least one less than nBestHeight. + // Secondly currently propagation of transactions created for block heights + // corresponding to blocks that were just mined may be iffy - transactions + // aren't re-accepted into the mempool - we additionally neuter the code by + // going ten blocks back. Doesn't yet do anything for sniping, but does act + // to shake out wallet bugs like not showing nLockTime'd transactions at + // all. + txNew.nLockTime = std::max(0, chainActive.Height() - 10); + + // Secondly occasionally randomly pick a nLockTime even further back, so + // that transactions that are delayed after signing for whatever reason, + // e.g. high-latency mix networks and some CoinJoin implementations, have + // better privacy. + if (GetRandInt(10) == 0) + txNew.nLockTime = std::max(0, (int)txNew.nLockTime - GetRandInt(100)); + + assert(txNew.nLockTime <= (unsigned int)chainActive.Height()); + assert(txNew.nLockTime < LOCKTIME_THRESHOLD); + { LOCK2(cs_main, cs_wallet); { @@ -1475,8 +1498,12 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, CAmount> >& vecSend, reservekey.ReturnKey(); // Fill vin + // + // Note how the sequence number is set to max()-1 so that the + // nLockTime set above actually works. BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins) - txNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second)); + txNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second,CScript(), + std::numeric_limits<unsigned int>::max()-1)); // Sign int nIn = 0; @@ -1499,27 +1526,32 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, CAmount> >& vecSend, } dPriority = wtxNew.ComputePriority(dPriority, nBytes); - CAmount nFeeNeeded = GetMinimumFee(nBytes, nTxConfirmTarget, mempool); + // Can we complete this as a free transaction? + if (fSendFreeTransactions && nBytes <= MAX_FREE_TRANSACTION_CREATE_SIZE) + { + // Not enough fee: enough priority? + double dPriorityNeeded = mempool.estimatePriority(nTxConfirmTarget); + // Not enough mempool history to estimate: use hard-coded AllowFree. + if (dPriorityNeeded <= 0 && AllowFree(dPriority)) + break; + + // Small enough, and priority high enough, to send for free + if (dPriorityNeeded > 0 && dPriority >= dPriorityNeeded) + break; + } - if (nFeeRet >= nFeeNeeded) - break; // Done, enough fee included. + CAmount nFeeNeeded = GetMinimumFee(nBytes, nTxConfirmTarget, mempool); - // Too big to send for free? Include more fee and try again: - if (!fSendFreeTransactions || nBytes > MAX_FREE_TRANSACTION_CREATE_SIZE) + // If we made it here and we aren't even able to meet the relay fee on the next pass, give up + // because we must be at the maximum allowed fee. + if (nFeeNeeded < ::minRelayTxFee.GetFee(nBytes)) { - nFeeRet = nFeeNeeded; - continue; + strFailReason = _("Transaction too large for fee policy"); + return false; } - // Not enough fee: enough priority? - double dPriorityNeeded = mempool.estimatePriority(nTxConfirmTarget); - // Not enough mempool history to estimate: use hard-coded AllowFree. - if (dPriorityNeeded <= 0 && AllowFree(dPriority)) - break; - - // Small enough, and priority high enough, to send for free - if (dPriorityNeeded > 0 && dPriority >= dPriorityNeeded) - break; + if (nFeeRet >= nFeeNeeded) + break; // Done, enough fee included. // Include more fee and try again. nFeeRet = nFeeNeeded; @@ -1591,9 +1623,6 @@ CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarge { // payTxFee is user-set "I want to pay this much" CAmount nFeeNeeded = payTxFee.GetFee(nTxBytes); - // prevent user from paying a non-sense fee (like 1 satoshi): 0 < fee < minRelayFee - if (nFeeNeeded > 0 && nFeeNeeded < ::minRelayTxFee.GetFee(nTxBytes)) - nFeeNeeded = ::minRelayTxFee.GetFee(nTxBytes); // user selected total at least (default=true) if (fPayAtLeastCustomFee && nFeeNeeded > 0 && nFeeNeeded < payTxFee.GetFeePerK()) nFeeNeeded = payTxFee.GetFeePerK(); @@ -1604,6 +1633,12 @@ CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarge // back to a hard-coded fee if (nFeeNeeded == 0) nFeeNeeded = minTxFee.GetFee(nTxBytes); + // prevent user from paying a non-sense fee (like 1 satoshi): 0 < fee < minRelayFee + if (nFeeNeeded < ::minRelayTxFee.GetFee(nTxBytes)) + nFeeNeeded = ::minRelayTxFee.GetFee(nTxBytes); + // But always obey the maximum + if (nFeeNeeded > maxTxFee) + nFeeNeeded = maxTxFee; return nFeeNeeded; } |