aboutsummaryrefslogtreecommitdiff
path: root/src/wallet.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/wallet.cpp')
-rw-r--r--src/wallet.cpp205
1 files changed, 113 insertions, 92 deletions
diff --git a/src/wallet.cpp b/src/wallet.cpp
index 6bfaec3681..19e43f6ec2 100644
--- a/src/wallet.cpp
+++ b/src/wallet.cpp
@@ -15,6 +15,8 @@
#include "util.h"
#include "utilmoneystr.h"
+#include <assert.h>
+
#include <boost/algorithm/string/replace.hpp>
#include <boost/thread.hpp>
@@ -35,8 +37,8 @@ CFeeRate CWallet::minTxFee = CFeeRate(10000); // Override with -mintxfee
struct CompareValueOnly
{
- bool operator()(const pair<int64_t, pair<const CWalletTx*, unsigned int> >& t1,
- const pair<int64_t, pair<const CWalletTx*, unsigned int> >& t2) const
+ bool operator()(const pair<CAmount, pair<const CWalletTx*, unsigned int> >& t1,
+ const pair<CAmount, pair<const CWalletTx*, unsigned int> >& t2) const
{
return t1.first < t2.first;
}
@@ -87,6 +89,13 @@ bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey)
AssertLockHeld(cs_wallet); // mapKeyMetadata
if (!CCryptoKeyStore::AddKeyPubKey(secret, pubkey))
return false;
+
+ // check if we need to remove from watch-only
+ CScript script;
+ script = GetScriptForDestination(pubkey.GetID());
+ if (HaveWatchOnly(script))
+ RemoveWatchOnly(script);
+
if (!fFileBacked)
return true;
if (!IsCrypted()) {
@@ -169,6 +178,20 @@ bool CWallet::AddWatchOnly(const CScript &dest)
return CWalletDB(strWalletFile).WriteWatchOnly(dest);
}
+bool CWallet::RemoveWatchOnly(const CScript &dest)
+{
+ AssertLockHeld(cs_wallet);
+ if (!CCryptoKeyStore::RemoveWatchOnly(dest))
+ return false;
+ if (!HaveWatchOnly())
+ NotifyWatchonlyChanged(false);
+ if (fFileBacked)
+ if (!CWalletDB(strWalletFile).EraseWatchOnly(dest))
+ return false;
+
+ return true;
+}
+
bool CWallet::LoadWatchOnly(const CScript &dest)
{
return CCryptoKeyStore::AddWatchOnly(dest);
@@ -426,17 +449,25 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
if (fFileBacked)
{
+ assert(!pwalletdbEncryption);
pwalletdbEncryption = new CWalletDB(strWalletFile);
- if (!pwalletdbEncryption->TxnBegin())
+ if (!pwalletdbEncryption->TxnBegin()) {
+ delete pwalletdbEncryption;
+ pwalletdbEncryption = NULL;
return false;
+ }
pwalletdbEncryption->WriteMasterKey(nMasterKeyMaxID, kMasterKey);
}
if (!EncryptKeys(vMasterKey))
{
- if (fFileBacked)
+ if (fFileBacked) {
pwalletdbEncryption->TxnAbort();
- exit(1); //We now probably have half of our keys encrypted in memory, and half not...die and let the user reload their unencrypted wallet.
+ delete pwalletdbEncryption;
+ }
+ // We now probably have half of our keys encrypted in memory, and half not...
+ // die and let the user reload their unencrypted wallet.
+ assert(false);
}
// Encryption was introduced in version 0.4.0
@@ -444,8 +475,12 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
if (fFileBacked)
{
- if (!pwalletdbEncryption->TxnCommit())
- exit(1); //We now have keys encrypted in memory, but no on disk...die to avoid confusion and let the user reload their unencrypted wallet.
+ if (!pwalletdbEncryption->TxnCommit()) {
+ delete pwalletdbEncryption;
+ // We now have keys encrypted in memory, but no on disk...
+ // die to avoid confusion and let the user reload their unencrypted wallet.
+ assert(false);
+ }
delete pwalletdbEncryption;
pwalletdbEncryption = NULL;
@@ -646,7 +681,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl
CWalletTx wtx(this,tx);
// Get merkle branch if transaction was found in a block
if (pblock)
- wtx.SetMerkleBranch(pblock);
+ wtx.SetMerkleBranch(*pblock);
return AddToWallet(wtx);
}
}
@@ -697,7 +732,7 @@ isminetype CWallet::IsMine(const CTxIn &txin) const
return ISMINE_NO;
}
-int64_t CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const
+CAmount CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const
{
{
LOCK(cs_wallet);
@@ -781,7 +816,7 @@ int CWalletTx::GetRequestCount() const
}
void CWalletTx::GetAmounts(list<COutputEntry>& listReceived,
- list<COutputEntry>& listSent, int64_t& nFee, string& strSentAccount, const isminefilter& filter) const
+ list<COutputEntry>& listSent, CAmount& nFee, string& strSentAccount, const isminefilter& filter) const
{
nFee = 0;
listReceived.clear();
@@ -789,10 +824,10 @@ void CWalletTx::GetAmounts(list<COutputEntry>& listReceived,
strSentAccount = strFromAccount;
// Compute fee:
- int64_t nDebit = GetDebit(filter);
+ CAmount nDebit = GetDebit(filter);
if (nDebit > 0) // debit>0 means we signed/sent this transaction
{
- int64_t nValueOut = GetValueOut();
+ CAmount nValueOut = GetValueOut();
nFee = nDebit - nValueOut;
}
@@ -835,12 +870,12 @@ void CWalletTx::GetAmounts(list<COutputEntry>& listReceived,
}
-void CWalletTx::GetAccountAmounts(const string& strAccount, int64_t& nReceived,
- int64_t& nSent, int64_t& nFee, const isminefilter& filter) const
+void CWalletTx::GetAccountAmounts(const string& strAccount, CAmount& nReceived,
+ CAmount& nSent, CAmount& nFee, const isminefilter& filter) const
{
nReceived = nSent = nFee = 0;
- int64_t allFee;
+ CAmount allFee;
string strSentAccount;
list<COutputEntry> listReceived;
list<COutputEntry> listSent;
@@ -1011,9 +1046,9 @@ void CWallet::ResendWalletTransactions()
//
-int64_t CWallet::GetBalance() const
+CAmount CWallet::GetBalance() const
{
- int64_t nTotal = 0;
+ CAmount nTotal = 0;
{
LOCK2(cs_main, cs_wallet);
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
@@ -1027,9 +1062,9 @@ int64_t CWallet::GetBalance() const
return nTotal;
}
-int64_t CWallet::GetUnconfirmedBalance() const
+CAmount CWallet::GetUnconfirmedBalance() const
{
- int64_t nTotal = 0;
+ CAmount nTotal = 0;
{
LOCK2(cs_main, cs_wallet);
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
@@ -1042,9 +1077,9 @@ int64_t CWallet::GetUnconfirmedBalance() const
return nTotal;
}
-int64_t CWallet::GetImmatureBalance() const
+CAmount CWallet::GetImmatureBalance() const
{
- int64_t nTotal = 0;
+ CAmount nTotal = 0;
{
LOCK2(cs_main, cs_wallet);
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
@@ -1056,9 +1091,9 @@ int64_t CWallet::GetImmatureBalance() const
return nTotal;
}
-int64_t CWallet::GetWatchOnlyBalance() const
+CAmount CWallet::GetWatchOnlyBalance() const
{
- int64_t nTotal = 0;
+ CAmount nTotal = 0;
{
LOCK2(cs_main, cs_wallet);
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
@@ -1068,13 +1103,13 @@ int64_t CWallet::GetWatchOnlyBalance() const
nTotal += pcoin->GetAvailableWatchOnlyCredit();
}
}
-
+
return nTotal;
}
-int64_t CWallet::GetUnconfirmedWatchOnlyBalance() const
+CAmount CWallet::GetUnconfirmedWatchOnlyBalance() const
{
- int64_t nTotal = 0;
+ CAmount nTotal = 0;
{
LOCK2(cs_main, cs_wallet);
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
@@ -1087,9 +1122,9 @@ int64_t CWallet::GetUnconfirmedWatchOnlyBalance() const
return nTotal;
}
-int64_t CWallet::GetImmatureWatchOnlyBalance() const
+CAmount CWallet::GetImmatureWatchOnlyBalance() const
{
- int64_t nTotal = 0;
+ CAmount nTotal = 0;
{
LOCK2(cs_main, cs_wallet);
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
@@ -1137,8 +1172,8 @@ void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed, const
}
}
-static void ApproximateBestSubset(vector<pair<int64_t, pair<const CWalletTx*,unsigned int> > >vValue, int64_t nTotalLower, int64_t nTargetValue,
- vector<char>& vfBest, int64_t& nBest, int iterations = 1000)
+static void ApproximateBestSubset(vector<pair<CAmount, pair<const CWalletTx*,unsigned int> > >vValue, const CAmount& nTotalLower, const CAmount& nTargetValue,
+ vector<char>& vfBest, CAmount& nBest, int iterations = 1000)
{
vector<char> vfIncluded;
@@ -1150,7 +1185,7 @@ static void ApproximateBestSubset(vector<pair<int64_t, pair<const CWalletTx*,uns
for (int nRep = 0; nRep < iterations && nBest != nTargetValue; nRep++)
{
vfIncluded.assign(vValue.size(), false);
- int64_t nTotal = 0;
+ CAmount nTotal = 0;
bool fReachedTarget = false;
for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++)
{
@@ -1183,18 +1218,18 @@ static void ApproximateBestSubset(vector<pair<int64_t, pair<const CWalletTx*,uns
}
}
-bool CWallet::SelectCoinsMinConf(int64_t nTargetValue, int nConfMine, int nConfTheirs, vector<COutput> vCoins,
- set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64_t& nValueRet) const
+bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, vector<COutput> vCoins,
+ set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet) const
{
setCoinsRet.clear();
nValueRet = 0;
// List of values less than target
- pair<int64_t, pair<const CWalletTx*,unsigned int> > coinLowestLarger;
- coinLowestLarger.first = std::numeric_limits<int64_t>::max();
+ pair<CAmount, pair<const CWalletTx*,unsigned int> > coinLowestLarger;
+ coinLowestLarger.first = std::numeric_limits<CAmount>::max();
coinLowestLarger.second.first = NULL;
- vector<pair<int64_t, pair<const CWalletTx*,unsigned int> > > vValue;
- int64_t nTotalLower = 0;
+ vector<pair<CAmount, pair<const CWalletTx*,unsigned int> > > vValue;
+ CAmount nTotalLower = 0;
random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);
@@ -1209,9 +1244,9 @@ bool CWallet::SelectCoinsMinConf(int64_t nTargetValue, int nConfMine, int nConfT
continue;
int i = output.i;
- int64_t n = pcoin->vout[i].nValue;
+ CAmount n = pcoin->vout[i].nValue;
- pair<int64_t,pair<const CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin, i));
+ pair<CAmount,pair<const CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin, i));
if (n == nTargetValue)
{
@@ -1252,7 +1287,7 @@ bool CWallet::SelectCoinsMinConf(int64_t nTargetValue, int nConfMine, int nConfT
// Solve subset sum by stochastic approximation
sort(vValue.rbegin(), vValue.rend(), CompareValueOnly());
vector<char> vfBest;
- int64_t nBest;
+ CAmount nBest;
ApproximateBestSubset(vValue, nTotalLower, nTargetValue, vfBest, nBest, 1000);
if (nBest != nTargetValue && nTotalLower >= nTargetValue + CENT)
@@ -1284,7 +1319,7 @@ bool CWallet::SelectCoinsMinConf(int64_t nTargetValue, int nConfMine, int nConfT
return true;
}
-bool CWallet::SelectCoins(int64_t nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64_t& nValueRet, const CCoinControl* coinControl) const
+bool CWallet::SelectCoins(const CAmount& nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet, const CCoinControl* coinControl) const
{
vector<COutput> vCoins;
AvailableCoins(vCoins, true, coinControl);
@@ -1310,11 +1345,11 @@ bool CWallet::SelectCoins(int64_t nTargetValue, set<pair<const CWalletTx*,unsign
-bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend,
- CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl)
+bool CWallet::CreateTransaction(const vector<pair<CScript, CAmount> >& vecSend,
+ CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl)
{
- int64_t nValue = 0;
- BOOST_FOREACH (const PAIRTYPE(CScript, int64_t)& s, vecSend)
+ CAmount nValue = 0;
+ BOOST_FOREACH (const PAIRTYPE(CScript, CAmount)& s, vecSend)
{
if (nValue < 0)
{
@@ -1343,10 +1378,10 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend,
txNew.vout.clear();
wtxNew.fFromMe = true;
- int64_t nTotalValue = nValue + nFeeRet;
+ CAmount nTotalValue = nValue + nFeeRet;
double dPriority = 0;
// vouts to the payees
- BOOST_FOREACH (const PAIRTYPE(CScript, int64_t)& s, vecSend)
+ BOOST_FOREACH (const PAIRTYPE(CScript, CAmount)& s, vecSend)
{
CTxOut txout(s.second, s.first);
if (txout.IsDust(::minRelayTxFee))
@@ -1359,7 +1394,7 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend,
// Choose coins to use
set<pair<const CWalletTx*,unsigned int> > setCoins;
- int64_t nValueIn = 0;
+ CAmount nValueIn = 0;
if (!SelectCoins(nTotalValue, setCoins, nValueIn, coinControl))
{
strFailReason = _("Insufficient funds");
@@ -1367,14 +1402,14 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend,
}
BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
{
- int64_t nCredit = pcoin.first->vout[pcoin.second].nValue;
+ CAmount nCredit = pcoin.first->vout[pcoin.second].nValue;
//The priority after the next block (depth+1) is used instead of the current,
//reflecting an assumption the user would accept a bit more delay for
//a chance at a free transaction.
dPriority += (double)nCredit * (pcoin.first->GetDepthInMainChain()+1);
}
- int64_t nChange = nValueIn - nValue - nFeeRet;
+ CAmount nChange = nValueIn - nValue - nFeeRet;
if (nChange > 0)
{
@@ -1450,7 +1485,7 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend,
}
dPriority = wtxNew.ComputePriority(dPriority, nBytes);
- int64_t nFeeNeeded = GetMinimumFee(nBytes, nTxConfirmTarget, mempool);
+ CAmount nFeeNeeded = GetMinimumFee(nBytes, nTxConfirmTarget, mempool);
if (nFeeRet >= nFeeNeeded)
break; // Done, enough fee included.
@@ -1481,10 +1516,10 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend,
return true;
}
-bool CWallet::CreateTransaction(CScript scriptPubKey, int64_t nValue,
- CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl)
+bool CWallet::CreateTransaction(CScript scriptPubKey, const CAmount& nValue,
+ CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl)
{
- vector< pair<CScript, int64_t> > vecSend;
+ vector< pair<CScript, CAmount> > vecSend;
vecSend.push_back(make_pair(scriptPubKey, nValue));
return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet, strFailReason, coinControl);
}
@@ -1539,7 +1574,7 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
-string CWallet::SendMoney(const CTxDestination &address, int64_t nValue, CWalletTx& wtxNew)
+string CWallet::SendMoney(const CTxDestination &address, CAmount nValue, CWalletTx& wtxNew)
{
// Check amount
if (nValue <= 0)
@@ -1560,7 +1595,7 @@ string CWallet::SendMoney(const CTxDestination &address, int64_t nValue, CWallet
// Create and send the transaction
CReserveKey reservekey(this);
- int64_t nFeeRequired;
+ CAmount nFeeRequired;
if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired, strError))
{
if (nValue + nFeeRequired > GetBalance())
@@ -1576,10 +1611,10 @@ string CWallet::SendMoney(const CTxDestination &address, int64_t nValue, CWallet
-int64_t CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool)
+CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool)
{
// payTxFee is user-set "I want to pay this much"
- int64_t nFeeNeeded = payTxFee.GetFee(nTxBytes);
+ CAmount nFeeNeeded = payTxFee.GetFee(nTxBytes);
// User didn't set: use -txconfirmtarget to estimate...
if (nFeeNeeded == 0)
nFeeNeeded = pool.estimateFee(nConfirmTarget).GetFee(nTxBytes);
@@ -1838,9 +1873,9 @@ int64_t CWallet::GetOldestKeyPoolTime()
return keypool.nTime;
}
-std::map<CTxDestination, int64_t> CWallet::GetAddressBalances()
+std::map<CTxDestination, CAmount> CWallet::GetAddressBalances()
{
- map<CTxDestination, int64_t> balances;
+ map<CTxDestination, CAmount> balances;
{
LOCK(cs_wallet);
@@ -1866,7 +1901,7 @@ std::map<CTxDestination, int64_t> CWallet::GetAddressBalances()
if(!ExtractDestination(pcoin->vout[i].scriptPubKey, addr))
continue;
- int64_t n = IsSpent(walletEntry.first, i) ? 0 : pcoin->vout[i].nValue;
+ CAmount n = IsSpent(walletEntry.first, i) ? 0 : pcoin->vout[i].nValue;
if (!balances.count(addr))
balances[addr] = 0;
@@ -2229,48 +2264,34 @@ CWalletKey::CWalletKey(int64_t nExpires)
nTimeExpires = nExpires;
}
-int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
+int CMerkleTx::SetMerkleBranch(const CBlock& block)
{
AssertLockHeld(cs_main);
CBlock blockTmp;
- if (pblock == NULL) {
- CCoins coins;
- if (pcoinsTip->GetCoins(GetHash(), coins)) {
- CBlockIndex *pindex = chainActive[coins.nHeight];
- if (pindex) {
- if (!ReadBlockFromDisk(blockTmp, pindex))
- return 0;
- pblock = &blockTmp;
- }
- }
- }
-
- if (pblock) {
- // Update the tx's hashBlock
- hashBlock = pblock->GetHash();
-
- // Locate the transaction
- for (nIndex = 0; nIndex < (int)pblock->vtx.size(); nIndex++)
- if (pblock->vtx[nIndex] == *(CTransaction*)this)
- break;
- if (nIndex == (int)pblock->vtx.size())
- {
- vMerkleBranch.clear();
- nIndex = -1;
- LogPrintf("ERROR: SetMerkleBranch() : couldn't find tx in block\n");
- return 0;
- }
+ // Update the tx's hashBlock
+ hashBlock = block.GetHash();
- // Fill in merkle branch
- vMerkleBranch = pblock->GetMerkleBranch(nIndex);
+ // Locate the transaction
+ for (nIndex = 0; nIndex < (int)block.vtx.size(); nIndex++)
+ if (block.vtx[nIndex] == *(CTransaction*)this)
+ break;
+ if (nIndex == (int)block.vtx.size())
+ {
+ vMerkleBranch.clear();
+ nIndex = -1;
+ LogPrintf("ERROR: SetMerkleBranch() : couldn't find tx in block\n");
+ return 0;
}
+ // Fill in merkle branch
+ vMerkleBranch = block.GetMerkleBranch(nIndex);
+
// Is the tx in a block that's in the main chain
BlockMap::iterator mi = mapBlockIndex.find(hashBlock);
if (mi == mapBlockIndex.end())
return 0;
- CBlockIndex* pindex = (*mi).second;
+ const CBlockIndex* pindex = (*mi).second;
if (!pindex || !chainActive.Contains(pindex))
return 0;