aboutsummaryrefslogtreecommitdiff
path: root/src/wallet.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/wallet.cpp')
-rw-r--r--src/wallet.cpp172
1 files changed, 89 insertions, 83 deletions
diff --git a/src/wallet.cpp b/src/wallet.cpp
index 76f3df602a..a7a2992bb9 100644
--- a/src/wallet.cpp
+++ b/src/wallet.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -159,7 +159,7 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase,
if (pMasterKey.second.nDeriveIterations < 25000)
pMasterKey.second.nDeriveIterations = 25000;
- printf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
+ LogPrintf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
if (!crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
return false;
@@ -267,7 +267,7 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
if (kMasterKey.nDeriveIterations < 25000)
kMasterKey.nDeriveIterations = 25000;
- printf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations);
+ LogPrintf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations);
if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod))
return false;
@@ -368,10 +368,10 @@ void CWallet::WalletUpdateSpent(const CTransaction &tx)
{
CWalletTx& wtx = (*mi).second;
if (txin.prevout.n >= wtx.vout.size())
- printf("WalletUpdateSpent: bad wtx %s\n", wtx.GetHash().ToString().c_str());
+ LogPrintf("WalletUpdateSpent: bad wtx %s\n", wtx.GetHash().ToString().c_str());
else if (!wtx.IsSpent(txin.prevout.n) && IsMine(wtx.vout[txin.prevout.n]))
{
- printf("WalletUpdateSpent found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
+ LogPrintf("WalletUpdateSpent found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
wtx.MarkSpent(txin.prevout.n);
wtx.WriteToDisk();
NotifyTransactionChanged(this, txin.prevout.hash, CT_UPDATED);
@@ -446,9 +446,9 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn)
wtx.nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
}
else
- printf("AddToWallet() : found %s in block %s not in index\n",
- wtxIn.GetHash().ToString().c_str(),
- wtxIn.hashBlock.ToString().c_str());
+ LogPrintf("AddToWallet() : found %s in block %s not in index\n",
+ wtxIn.GetHash().ToString().c_str(),
+ wtxIn.hashBlock.ToString().c_str());
}
}
@@ -476,32 +476,13 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn)
}
//// debug print
- printf("AddToWallet %s %s%s\n", wtxIn.GetHash().ToString().c_str(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
+ LogPrintf("AddToWallet %s %s%s\n", wtxIn.GetHash().ToString().c_str(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
// Write to disk
if (fInsertedNew || fUpdated)
if (!wtx.WriteToDisk())
return false;
- if (!fHaveGUI) {
- // If default receiving address gets used, replace it with a new one
- if (vchDefaultKey.IsValid()) {
- CScript scriptDefaultKey;
- scriptDefaultKey.SetDestination(vchDefaultKey.GetID());
- BOOST_FOREACH(const CTxOut& txout, wtx.vout)
- {
- if (txout.scriptPubKey == scriptDefaultKey)
- {
- CPubKey newDefaultKey;
- if (GetKeyFromPool(newDefaultKey, false))
- {
- SetDefaultKey(newDefaultKey);
- SetAddressBookName(vchDefaultKey.GetID(), "");
- }
- }
- }
- }
- }
// since AddToWallet is called directly for self-originating transactions, check for consumption of own coins
WalletUpdateSpent(wtx);
@@ -691,8 +672,8 @@ void CWalletTx::GetAmounts(list<pair<CTxDestination, int64> >& listReceived,
CTxDestination address;
if (!ExtractDestination(txout.scriptPubKey, address))
{
- printf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n",
- this->GetHash().ToString().c_str());
+ LogPrintf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n",
+ this->GetHash().ToString().c_str());
address = CNoDestination();
}
@@ -730,8 +711,8 @@ void CWalletTx::GetAccountAmounts(const string& strAccount, int64& nReceived,
{
if (pwallet->mapAddressBook.count(r.first))
{
- map<CTxDestination, string>::const_iterator mi = pwallet->mapAddressBook.find(r.first);
- if (mi != pwallet->mapAddressBook.end() && (*mi).second == strAccount)
+ map<CTxDestination, CAddressBookData>::const_iterator mi = pwallet->mapAddressBook.find(r.first);
+ if (mi != pwallet->mapAddressBook.end() && (*mi).second.name == strAccount)
nReceived += r.second;
}
else if (strAccount.empty())
@@ -812,7 +793,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
// no need to read and scan block, if block was created before
// our wallet birthday (as adjusted for block time variability)
if (nTimeFirstKey && (pindex->nTime < (nTimeFirstKey - 7200))) {
- pindex = pindex->GetNextInMainChain();
+ pindex = chainActive.Next(pindex);
continue;
}
@@ -823,7 +804,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
if (AddToWalletIfInvolvingMe(tx.GetHash(), tx, &block, fUpdate))
ret++;
}
- pindex = pindex->GetNextInMainChain();
+ pindex = chainActive.Next(pindex);
}
}
return ret;
@@ -862,7 +843,7 @@ void CWallet::ReacceptWalletTransactions()
}
if (fUpdated)
{
- printf("ReacceptWalletTransactions found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
+ LogPrintf("ReacceptWalletTransactions found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
wtx.MarkDirty();
wtx.WriteToDisk();
}
@@ -877,7 +858,7 @@ void CWallet::ReacceptWalletTransactions()
if (fMissing)
{
// TODO: optimize this to scan just part of the block chain?
- if (ScanForWalletTransactions(pindexGenesisBlock))
+ if (ScanForWalletTransactions(chainActive.Genesis()))
fRepeat = true; // Found missing transactions: re-do re-accept.
}
}
@@ -895,7 +876,7 @@ void CWalletTx::RelayWalletTransaction()
{
if (GetDepthInMainChain() == 0) {
uint256 hash = GetHash();
- printf("Relaying wtx %s\n", hash.ToString().c_str());
+ LogPrintf("Relaying wtx %s\n", hash.ToString().c_str());
RelayTransaction((CTransaction)*this, hash);
}
}
@@ -905,22 +886,20 @@ void CWallet::ResendWalletTransactions()
{
// Do this infrequently and randomly to avoid giving away
// that these are our transactions.
- static int64 nNextTime;
- if (GetTime() < nNextTime)
+ if (GetTime() < nNextResend)
return;
- bool fFirst = (nNextTime == 0);
- nNextTime = GetTime() + GetRand(30 * 60);
+ bool fFirst = (nNextResend == 0);
+ nNextResend = GetTime() + GetRand(30 * 60);
if (fFirst)
return;
// Only do it if there's been a new block since last time
- static int64 nLastTime;
- if (nTimeBestReceived < nLastTime)
+ if (nTimeBestReceived < nLastResend)
return;
- nLastTime = GetTime();
+ nLastResend = GetTime();
// Rebroadcast any of our txes that aren't in a block yet
- printf("ResendWalletTransactions()\n");
+ LogPrintf("ResendWalletTransactions()\n");
{
LOCK(cs_wallet);
// Sort them in chronological order
@@ -1160,12 +1139,11 @@ bool CWallet::SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfThe
nValueRet += vValue[i].first;
}
- //// debug print
- printf("SelectCoins() best subset: ");
+ LogPrint("selectcoins", "SelectCoins() best subset: ");
for (unsigned int i = 0; i < vValue.size(); i++)
if (vfBest[i])
- printf("%s ", FormatMoney(vValue[i].first).c_str());
- printf("total %s\n", FormatMoney(nBest).c_str());
+ LogPrint("selectcoins", "%s ", FormatMoney(vValue[i].first).c_str());
+ LogPrint("selectcoins", "total %s\n", FormatMoney(nBest).c_str());
}
return true;
@@ -1209,7 +1187,7 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend,
LOCK2(cs_main, cs_wallet);
{
nFeeRet = nTransactionFee;
- loop
+ while (true)
{
wtxNew.vin.clear();
wtxNew.vout.clear();
@@ -1247,9 +1225,10 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend,
}
int64 nChange = nValueIn - nValue - nFeeRet;
- // if sub-cent change is required, the fee must be raised to at least nMinTxFee
- // or until nChange becomes zero
- // NOTE: this depends on the exact behaviour of GetMinFee
+ // The following if statement should be removed once enough miners
+ // have upgraded to the 0.9 GetMinFee() rules. Until then, this avoids
+ // creating free transactions that have change outputs less than
+ // CENT bitcoins.
if (nFeeRet < CTransaction::nMinTxFee && nChange > 0 && nChange < CENT)
{
int64 nMoveToFee = min(nChange, CTransaction::nMinTxFee - nFeeRet);
@@ -1315,7 +1294,15 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend,
strFailReason = _("Transaction too large");
return false;
}
- dPriority /= nBytes;
+ unsigned int nTxSizeMod = nBytes;
+ // See miner.c's dPriority logic for the matching network-node side code.
+ BOOST_FOREACH(const CTxIn& txin, (*(CTransaction*)&wtxNew).vin)
+ {
+ unsigned int offset = 41U + min(110U, (unsigned int)txin.scriptSig.size());
+ if (nTxSizeMod > offset)
+ nTxSizeMod -= offset;
+ }
+ dPriority /= nTxSizeMod;
// Check that enough fee is included
int64 nPayFee = nTransactionFee * (1 + (int64)nBytes / 1000);
@@ -1351,7 +1338,7 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
{
{
LOCK2(cs_main, cs_wallet);
- printf("CommitTransaction:\n%s", wtxNew.ToString().c_str());
+ LogPrintf("CommitTransaction:\n%s", wtxNew.ToString().c_str());
{
// This is only to keep the database open to defeat the auto-flush for the
// duration of this scope. This is the only place where this optimization
@@ -1387,7 +1374,7 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
if (!wtxNew.AcceptToMemoryPool(false))
{
// This must not fail. The transaction has already been signed and recorded.
- printf("CommitTransaction() : Error: Transaction not valid");
+ LogPrintf("CommitTransaction() : Error: Transaction not valid");
return false;
}
wtxNew.RelayWalletTransaction();
@@ -1406,7 +1393,7 @@ string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew,
if (IsLocked())
{
string strError = _("Error: Wallet locked, unable to create transaction!");
- printf("SendMoney() : %s", strError.c_str());
+ LogPrintf("SendMoney() : %s", strError.c_str());
return strError;
}
string strError;
@@ -1414,7 +1401,7 @@ string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew,
{
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).c_str());
- printf("SendMoney() : %s\n", strError.c_str());
+ LogPrintf("SendMoney() : %s\n", strError.c_str());
return strError;
}
@@ -1472,26 +1459,32 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
}
-bool CWallet::SetAddressBookName(const CTxDestination& address, const string& strName)
+bool CWallet::SetAddressBook(const CTxDestination& address, const string& strName, const string& strPurpose)
{
- std::map<CTxDestination, std::string>::iterator mi = mapAddressBook.find(address);
- mapAddressBook[address] = strName;
- NotifyAddressBookChanged(this, address, strName, ::IsMine(*this, address), (mi == mapAddressBook.end()) ? CT_NEW : CT_UPDATED);
+ std::map<CTxDestination, CAddressBookData>::iterator mi = mapAddressBook.find(address);
+ mapAddressBook[address].name = strName;
+ if (!strPurpose.empty()) /* update purpose only if requested */
+ mapAddressBook[address].purpose = strPurpose;
+ NotifyAddressBookChanged(this, address, strName, ::IsMine(*this, address),
+ mapAddressBook[address].purpose,
+ (mi == mapAddressBook.end()) ? CT_NEW : CT_UPDATED);
if (!fFileBacked)
return false;
+ if (!strPurpose.empty() && !CWalletDB(strWalletFile).WritePurpose(CBitcoinAddress(address).ToString(), strPurpose))
+ return false;
return CWalletDB(strWalletFile).WriteName(CBitcoinAddress(address).ToString(), strName);
}
-bool CWallet::DelAddressBookName(const CTxDestination& address)
+bool CWallet::DelAddressBook(const CTxDestination& address)
{
mapAddressBook.erase(address);
- NotifyAddressBookChanged(this, address, "", ::IsMine(*this, address), CT_DELETED);
+ NotifyAddressBookChanged(this, address, "", ::IsMine(*this, address), "", CT_DELETED);
if (!fFileBacked)
return false;
+ CWalletDB(strWalletFile).ErasePurpose(CBitcoinAddress(address).ToString());
return CWalletDB(strWalletFile).EraseName(CBitcoinAddress(address).ToString());
}
-
void CWallet::PrintWallet(const CBlock& block)
{
{
@@ -1499,10 +1492,10 @@ void CWallet::PrintWallet(const CBlock& block)
if (mapWallet.count(block.vtx[0].GetHash()))
{
CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()];
- printf(" mine: %d %d %"PRI64d"", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
+ LogPrintf(" mine: %d %d %"PRI64d"", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
}
}
- printf("\n");
+ LogPrintf("\n");
}
bool CWallet::GetTransaction(const uint256 &hashTx, CWalletTx& wtx)
@@ -1561,12 +1554,12 @@ bool CWallet::NewKeyPool()
walletdb.WritePool(nIndex, CKeyPool(GenerateNewKey()));
setKeyPool.insert(nIndex);
}
- printf("CWallet::NewKeyPool wrote %"PRI64d" new keys\n", nKeys);
+ LogPrintf("CWallet::NewKeyPool wrote %"PRI64d" new keys\n", nKeys);
}
return true;
}
-bool CWallet::TopUpKeyPool()
+bool CWallet::TopUpKeyPool(unsigned int kpSize)
{
{
LOCK(cs_wallet);
@@ -1577,7 +1570,12 @@ bool CWallet::TopUpKeyPool()
CWalletDB walletdb(strWalletFile);
// Top up key pool
- unsigned int nTargetSize = max(GetArg("-keypool", 100), 0LL);
+ unsigned int nTargetSize;
+ if (kpSize > 0)
+ nTargetSize = kpSize;
+ else
+ nTargetSize = max(GetArg("-keypool", 100), 0LL);
+
while (setKeyPool.size() < (nTargetSize + 1))
{
int64 nEnd = 1;
@@ -1586,7 +1584,7 @@ bool CWallet::TopUpKeyPool()
if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey())))
throw runtime_error("TopUpKeyPool() : writing generated key failed");
setKeyPool.insert(nEnd);
- printf("keypool added key %"PRI64d", size=%"PRIszu"\n", nEnd, setKeyPool.size());
+ LogPrintf("keypool added key %"PRI64d", size=%"PRIszu"\n", nEnd, setKeyPool.size());
}
}
return true;
@@ -1615,7 +1613,7 @@ void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
if (!HaveKey(keypool.vchPubKey.GetID()))
throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool");
assert(keypool.vchPubKey.IsValid());
- printf("keypool reserve %"PRI64d"\n", nIndex);
+ LogPrintf("keypool reserve %"PRI64d"\n", nIndex);
}
}
@@ -1642,7 +1640,7 @@ void CWallet::KeepKey(int64 nIndex)
CWalletDB walletdb(strWalletFile);
walletdb.ErasePool(nIndex);
}
- printf("keypool keep %"PRI64d"\n", nIndex);
+ LogPrintf("keypool keep %"PRI64d"\n", nIndex);
}
void CWallet::ReturnKey(int64 nIndex)
@@ -1652,10 +1650,10 @@ void CWallet::ReturnKey(int64 nIndex)
LOCK(cs_wallet);
setKeyPool.insert(nIndex);
}
- printf("keypool return %"PRI64d"\n", nIndex);
+ LogPrintf("keypool return %"PRI64d"\n", nIndex);
}
-bool CWallet::GetKeyFromPool(CPubKey& result, bool fAllowReuse)
+bool CWallet::GetKeyFromPool(CPubKey& result)
{
int64 nIndex = 0;
CKeyPool keypool;
@@ -1664,11 +1662,6 @@ bool CWallet::GetKeyFromPool(CPubKey& result, bool fAllowReuse)
ReserveKeyFromKeyPool(nIndex, keypool);
if (nIndex == -1)
{
- if (fAllowReuse && vchDefaultKey.IsValid())
- {
- result = vchDefaultKey;
- return true;
- }
if (IsLocked()) return false;
result = GenerateNewKey();
return true;
@@ -1822,6 +1815,19 @@ set< set<CTxDestination> > CWallet::GetAddressGroupings()
return ret;
}
+set<CTxDestination> CWallet::GetAccountAddresses(string strAccount) const
+{
+ set<CTxDestination> result;
+ BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& item, mapAddressBook)
+ {
+ const CTxDestination& address = item.first;
+ const string& strName = item.second.name;
+ if (strName == strAccount)
+ result.insert(address);
+ }
+ return result;
+}
+
bool CReserveKey::GetReservedKey(CPubKey& pubkey)
{
if (nIndex == -1)
@@ -1832,7 +1838,7 @@ bool CReserveKey::GetReservedKey(CPubKey& pubkey)
vchPubKey = keypool.vchPubKey;
else {
if (pwallet->vchDefaultKey.IsValid()) {
- printf("CReserveKey::GetReservedKey(): Warning: Using default key instead of a new key, top up your keypool!");
+ LogPrintf("CReserveKey::GetReservedKey(): Warning: Using default key instead of a new key, top up your keypool!");
vchPubKey = pwallet->vchDefaultKey;
} else
return false;
@@ -1930,7 +1936,7 @@ void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64> &mapKeyBirth) const {
mapKeyBirth[it->first] = it->second.nCreateTime;
// map in which we'll infer heights of other keys
- CBlockIndex *pindexMax = FindBlockByHeight(std::max(0, nBestHeight - 144)); // the tip can be reorganised; use a 144-block safety margin
+ CBlockIndex *pindexMax = chainActive[std::max(0, chainActive.Height() - 144)]; // the tip can be reorganised; use a 144-block safety margin
std::map<CKeyID, CBlockIndex*> mapKeyFirstBlock;
std::set<CKeyID> setKeys;
GetKeys(setKeys);
@@ -1950,7 +1956,7 @@ void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64> &mapKeyBirth) const {
// iterate over all wallet transactions...
const CWalletTx &wtx = (*it).second;
std::map<uint256, CBlockIndex*>::const_iterator blit = mapBlockIndex.find(wtx.hashBlock);
- if (blit != mapBlockIndex.end() && blit->second->IsInMainChain()) {
+ if (blit != mapBlockIndex.end() && chainActive.Contains(blit->second)) {
// ... which are already in a block
int nHeight = blit->second->nHeight;
BOOST_FOREACH(const CTxOut &txout, wtx.vout) {