diff options
Diffstat (limited to 'src/wallet.cpp')
-rw-r--r-- | src/wallet.cpp | 132 |
1 files changed, 63 insertions, 69 deletions
diff --git a/src/wallet.cpp b/src/wallet.cpp index 353010ae07..6c5af3bdc7 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; @@ -35,7 +36,7 @@ bool fPayAtLeastCustomFee = true; * Fees smaller than this (in satoshi) are considered zero fee (for transaction creation) * Override with -mintxfee */ -CFeeRate CWallet::minTxFee = CFeeRate(10000); +CFeeRate CWallet::minTxFee = CFeeRate(1000); /** @defgroup mapWallet * @@ -70,7 +71,6 @@ CPubKey CWallet::GenerateNewKey() AssertLockHeld(cs_wallet); // mapKeyMetadata bool fCompressed = CanSupportFeature(FEATURE_COMPRPUBKEY); // default to compressed public keys if we want 0.6.0 wallets - RandAddSeedPerfmon(); CKey secret; secret.MakeNewKey(fCompressed); @@ -579,7 +579,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet) wtx.nOrderPos = IncOrderPosNext(); wtx.nTimeSmart = wtx.nTimeReceived; - if (wtxIn.hashBlock != 0) + if (!wtxIn.hashBlock.IsNull()) { if (mapBlockIndex.count(wtxIn.hashBlock)) { @@ -630,7 +630,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet) if (!fInsertedNew) { // Merge - if (wtxIn.hashBlock != 0 && wtxIn.hashBlock != wtx.hashBlock) + if (!wtxIn.hashBlock.IsNull() && wtxIn.hashBlock != wtx.hashBlock) { wtx.hashBlock = wtxIn.hashBlock; fUpdated = true; @@ -795,7 +795,7 @@ int CWalletTx::GetRequestCount() const if (IsCoinBase()) { // Generated block - if (hashBlock != 0) + if (!hashBlock.IsNull()) { map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock); if (mi != pwallet->mapRequestCount.end()) @@ -811,7 +811,7 @@ int CWalletTx::GetRequestCount() const nRequests = (*mi).second; // How about the block it's in? - if (nRequests == 0 && hashBlock != 0) + if (nRequests == 0 && !hashBlock.IsNull()) { map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock); if (mi != pwallet->mapRequestCount.end()) @@ -1382,6 +1382,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 +1497,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 +1525,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; @@ -1587,53 +1618,10 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey) return true; } - - - -string CWallet::SendMoney(const CTxDestination &address, CAmount nValue, CWalletTx& wtxNew) -{ - // Check amount - if (nValue <= 0) - return _("Invalid amount"); - if (nValue > GetBalance()) - return _("Insufficient funds"); - - string strError; - if (IsLocked()) - { - strError = _("Error: Wallet locked, unable to create transaction!"); - LogPrintf("SendMoney() : %s", strError); - return strError; - } - - // Parse Bitcoin address - CScript scriptPubKey = GetScriptForDestination(address); - - // Create and send the transaction - CReserveKey reservekey(this); - CAmount nFeeRequired; - if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired, strError)) - { - if (nValue + nFeeRequired > GetBalance()) - strError = strprintf(_("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds!"), FormatMoney(nFeeRequired)); - LogPrintf("SendMoney() : %s\n", strError); - return strError; - } - if (!CommitTransaction(wtxNew, reservekey)) - return _("Error: The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."); - - return ""; -} - - - CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool) { // 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(); @@ -1644,6 +1632,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; } @@ -2030,7 +2024,7 @@ set< set<CTxDestination> > CWallet::GetAddressGroupings() set<CTxDestination> CWallet::GetAccountAddresses(string strAccount) const { - AssertLockHeld(cs_wallet); // mapWallet + LOCK(cs_wallet); set<CTxDestination> result; BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& item, mapAddressBook) { @@ -2323,7 +2317,7 @@ int CMerkleTx::SetMerkleBranch(const CBlock& block) int CMerkleTx::GetDepthInMainChainINTERNAL(const CBlockIndex* &pindexRet) const { - if (hashBlock == 0 || nIndex == -1) + if (hashBlock.IsNull() || nIndex == -1) return 0; AssertLockHeld(cs_main); |