CWallet class

* A new class CKeyStore manages private keys, and script.cpp depends on access to CKeyStore.
* A new class CWallet extends CKeyStore, and contains all former wallet-specific globals; CWallet depends on script.cpp, not the other way around.
* Wallet-specific functions in CTransaction/CTxIn/CTxOut (GetDebit, GetCredit, GetChange, IsMine, IsFromMe), are moved to CWallet, taking their former 'this' argument as an explicit parameter
* CWalletTx objects know which CWallet they belong to, for convenience, so they have their own direct (and caching) GetDebit/... functions.
* Some code was moved from CWalletDB to CWallet, such as handling of reserve keys.
* Main.cpp keeps a set of all 'registered' wallets, which should be informed about updates to the block chain, and does not have any notion about any 'main' wallet. Function in main.cpp that require a wallet (such as GenerateCoins), take an explicit CWallet* argument.
* The actual CWallet instance used by the application is defined in init.cpp as "CWallet* pwalletMain". rpc.cpp and ui.cpp use this variable.
* Functions in main.cpp and db.cpp that are not used by other modules are marked static.
* The code for handling the 'submitorder' message is removed, as it not really compatible with the idea that a node is independent from the wallet(s) connected to it, and obsolete anyway.
This commit is contained in:
Pieter Wuille
2011-06-01 18:28:20 +02:00
parent e89b9f6a2a
commit 64c7ee7e6b
15 changed files with 829 additions and 664 deletions

View File

@@ -15,29 +15,40 @@ using namespace std;
// mapWallet
//
void WalletUpdateSpent(const COutPoint& prevout)
bool CWallet::AddKey(const CKey& key)
{
this->CKeyStore::AddKey(key);
if (!fFileBacked)
return true;
return CWalletDB(strWalletFile).WriteKey(key.GetPubKey(), key.GetPrivKey());
}
void CWallet::WalletUpdateSpent(const CTransaction &tx)
{
// Anytime a signature is successfully verified, it's proof the outpoint is spent.
// Update the wallet spent flag if it doesn't know due to wallet.dat being
// restored from backup or the user making copies of wallet.dat.
CRITICAL_BLOCK(cs_mapWallet)
{
map<uint256, CWalletTx>::iterator mi = mapWallet.find(prevout.hash);
if (mi != mapWallet.end())
BOOST_FOREACH(const CTxIn& txin, tx.vin)
{
CWalletTx& wtx = (*mi).second;
if (!wtx.IsSpent(prevout.n) && wtx.vout[prevout.n].IsMine())
map<uint256, CWalletTx>::iterator mi = mapWallet.find(txin.prevout.hash);
if (mi != mapWallet.end())
{
printf("WalletUpdateSpent found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
wtx.MarkSpent(prevout.n);
wtx.WriteToDisk();
vWalletUpdated.push_back(prevout.hash);
CWalletTx& wtx = (*mi).second;
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());
wtx.MarkSpent(txin.prevout.n);
wtx.WriteToDisk();
vWalletUpdated.push_back(txin.prevout.hash);
}
}
}
}
}
bool AddToWallet(const CWalletTx& wtxIn)
bool CWallet::AddToWallet(const CWalletTx& wtxIn)
{
uint256 hash = wtxIn.GetHash();
CRITICAL_BLOCK(cs_mapWallet)
@@ -45,6 +56,7 @@ bool AddToWallet(const CWalletTx& wtxIn)
// Inserts only if not already there, returns tx inserted or tx found
pair<map<uint256, CWalletTx>::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn));
CWalletTx& wtx = (*ret.first).second;
wtx.pwallet = this;
bool fInsertedNew = ret.second;
if (fInsertedNew)
wtx.nTimeReceived = GetAdjustedTime();
@@ -87,7 +99,9 @@ bool AddToWallet(const CWalletTx& wtxIn)
{
if (txout.scriptPubKey == scriptDefaultKey)
{
CWalletDB walletdb;
if (!fFileBacked)
continue;
CWalletDB walletdb(strWalletFile);
vchDefaultKey = GetKeyFromKeyPool();
walletdb.WriteDefaultKey(vchDefaultKey);
walletdb.WriteName(PubKeyToAddress(vchDefaultKey), "");
@@ -96,6 +110,9 @@ bool AddToWallet(const CWalletTx& wtxIn)
// Notify UI
vWalletUpdated.push_back(hash);
// since AddToWallet is called directly for self-originating transactions, check for consumption of own coins
WalletUpdateSpent(wtx);
}
// Refresh UI
@@ -103,60 +120,64 @@ bool AddToWallet(const CWalletTx& wtxIn)
return true;
}
bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate)
bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate)
{
uint256 hash = tx.GetHash();
bool fExisted = mapWallet.count(hash);
if (fExisted && !fUpdate) return false;
if (fExisted || tx.IsMine() || tx.IsFromMe())
if (fExisted || IsMine(tx) || IsFromMe(tx))
{
CWalletTx wtx(tx);
CWalletTx wtx(this,tx);
// Get merkle branch if transaction was found in a block
if (pblock)
wtx.SetMerkleBranch(pblock);
return AddToWallet(wtx);
}
else
WalletUpdateSpent(tx);
return false;
}
bool EraseFromWallet(uint256 hash)
bool CWallet::EraseFromWallet(uint256 hash)
{
if (!fFileBacked)
return false;
CRITICAL_BLOCK(cs_mapWallet)
{
if (mapWallet.erase(hash))
CWalletDB().EraseTx(hash);
CWalletDB(strWalletFile).EraseTx(hash);
}
return true;
}
bool CTxIn::IsMine() const
bool CWallet::IsMine(const CTxIn &txin) const
{
CRITICAL_BLOCK(cs_mapWallet)
{
map<uint256, CWalletTx>::iterator mi = mapWallet.find(prevout.hash);
map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
if (mi != mapWallet.end())
{
const CWalletTx& prev = (*mi).second;
if (prevout.n < prev.vout.size())
if (prev.vout[prevout.n].IsMine())
if (txin.prevout.n < prev.vout.size())
if (IsMine(prev.vout[txin.prevout.n]))
return true;
}
}
return false;
}
int64 CTxIn::GetDebit() const
int64 CWallet::GetDebit(const CTxIn &txin) const
{
CRITICAL_BLOCK(cs_mapWallet)
{
map<uint256, CWalletTx>::iterator mi = mapWallet.find(prevout.hash);
map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
if (mi != mapWallet.end())
{
const CWalletTx& prev = (*mi).second;
if (prevout.n < prev.vout.size())
if (prev.vout[prevout.n].IsMine())
return prev.vout[prevout.n].nValue;
if (txin.prevout.n < prev.vout.size())
if (IsMine(prev.vout[txin.prevout.n]))
return prev.vout[txin.prevout.n].nValue;
}
}
return 0;
@@ -184,31 +205,31 @@ int CWalletTx::GetRequestCount() const
{
// Returns -1 if it wasn't being tracked
int nRequests = -1;
CRITICAL_BLOCK(cs_mapRequestCount)
CRITICAL_BLOCK(pwallet->cs_mapRequestCount)
{
if (IsCoinBase())
{
// Generated block
if (hashBlock != 0)
{
map<uint256, int>::iterator mi = mapRequestCount.find(hashBlock);
if (mi != mapRequestCount.end())
map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
if (mi != pwallet->mapRequestCount.end())
nRequests = (*mi).second;
}
}
else
{
// Did anyone request this transaction?
map<uint256, int>::iterator mi = mapRequestCount.find(GetHash());
if (mi != mapRequestCount.end())
map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(GetHash());
if (mi != pwallet->mapRequestCount.end())
{
nRequests = (*mi).second;
// How about the block it's in?
if (nRequests == 0 && hashBlock != 0)
{
map<uint256, int>::iterator mi = mapRequestCount.find(hashBlock);
if (mi != mapRequestCount.end())
map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
if (mi != pwallet->mapRequestCount.end())
nRequests = (*mi).second;
else
nRequests = 1; // If it's in someone else's block it must have got out
@@ -230,7 +251,7 @@ void CWalletTx::GetAmounts(int64& nGeneratedImmature, int64& nGeneratedMature, l
if (IsCoinBase())
{
if (GetBlocksToMaturity() > 0)
nGeneratedImmature = CTransaction::GetCredit();
nGeneratedImmature = pwallet->GetCredit(*this);
else
nGeneratedMature = GetCredit();
return;
@@ -263,13 +284,13 @@ void CWalletTx::GetAmounts(int64& nGeneratedImmature, int64& nGeneratedMature, l
}
// Don't report 'change' txouts
if (nDebit > 0 && txout.IsChange())
if (nDebit > 0 && pwallet->IsChange(txout))
continue;
if (nDebit > 0)
listSent.push_back(make_pair(address, txout.nValue));
if (txout.IsMine())
if (pwallet->IsMine(txout))
listReceived.push_back(make_pair(address, txout.nValue));
}
@@ -295,16 +316,15 @@ void CWalletTx::GetAccountAmounts(const string& strAccount, int64& nGenerated, i
nSent += s.second;
nFee = allFee;
}
CRITICAL_BLOCK(cs_mapAddressBook)
CRITICAL_BLOCK(pwallet->cs_mapAddressBook)
{
BOOST_FOREACH(const PAIRTYPE(string,int64)& r, listReceived)
{
if (mapAddressBook.count(r.first))
if (pwallet->mapAddressBook.count(r.first))
{
if (mapAddressBook[r.first] == strAccount)
{
map<string, string>::const_iterator mi = pwallet->mapAddressBook.find(r.first);
if (mi != pwallet->mapAddressBook.end() && (*mi).second == strAccount)
nReceived += r.second;
}
}
else if (strAccount.empty())
{
@@ -326,7 +346,7 @@ void CWalletTx::AddSupportingTransactions(CTxDB& txdb)
vWorkQueue.push_back(txin.prevout.hash);
// This critsect is OK because txdb is already open
CRITICAL_BLOCK(cs_mapWallet)
CRITICAL_BLOCK(pwallet->cs_mapWallet)
{
map<uint256, const CMerkleTx*> mapWalletPrev;
set<uint256> setAlreadyDone;
@@ -338,10 +358,11 @@ void CWalletTx::AddSupportingTransactions(CTxDB& txdb)
setAlreadyDone.insert(hash);
CMerkleTx tx;
if (mapWallet.count(hash))
map<uint256, CWalletTx>::const_iterator mi = pwallet->mapWallet.find(hash);
if (mi != pwallet->mapWallet.end())
{
tx = mapWallet[hash];
BOOST_FOREACH(const CMerkleTx& txWalletPrev, mapWallet[hash].vtxPrev)
tx = (*mi).second;
BOOST_FOREACH(const CMerkleTx& txWalletPrev, (*mi).second.vtxPrev)
mapWalletPrev[txWalletPrev.GetHash()] = &txWalletPrev;
}
else if (mapWalletPrev.count(hash))
@@ -373,10 +394,10 @@ void CWalletTx::AddSupportingTransactions(CTxDB& txdb)
bool CWalletTx::WriteToDisk()
{
return CWalletDB().WriteTx(GetHash(), *this);
return CWalletDB(pwallet->strWalletFile).WriteTx(GetHash(), *this);
}
int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
{
int ret = 0;
@@ -398,7 +419,7 @@ int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
return ret;
}
void ReacceptWalletTransactions()
void CWallet::ReacceptWalletTransactions()
{
CTxDB txdb("r");
bool fRepeat = true;
@@ -426,7 +447,7 @@ void ReacceptWalletTransactions()
{
if (wtx.IsSpent(i))
continue;
if (!txindex.vSpent[i].IsNull() && wtx.vout[i].IsMine())
if (!txindex.vSpent[i].IsNull() && IsMine(wtx.vout[i]))
{
wtx.MarkSpent(i);
fUpdated = true;
@@ -484,7 +505,7 @@ void CWalletTx::RelayWalletTransaction()
RelayWalletTransaction(txdb);
}
void ResendWalletTransactions()
void CWallet::ResendWalletTransactions()
{
// Do this infrequently and randomly to avoid giving away
// that these are our transactions.
@@ -536,16 +557,16 @@ void ResendWalletTransactions()
//
int64 GetBalance()
int64 CWallet::GetBalance() const
{
int64 nStart = GetTimeMillis();
int64 nTotal = 0;
CRITICAL_BLOCK(cs_mapWallet)
{
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
CWalletTx* pcoin = &(*it).second;
const CWalletTx* pcoin = &(*it).second;
if (!pcoin->IsFinal() || !pcoin->IsConfirmed())
continue;
nTotal += pcoin->GetAvailableCredit();
@@ -557,27 +578,27 @@ int64 GetBalance()
}
bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set<pair<CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet)
bool CWallet::SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
{
setCoinsRet.clear();
nValueRet = 0;
// List of values less than target
pair<int64, pair<CWalletTx*,unsigned int> > coinLowestLarger;
pair<int64, pair<const CWalletTx*,unsigned int> > coinLowestLarger;
coinLowestLarger.first = INT64_MAX;
coinLowestLarger.second.first = NULL;
vector<pair<int64, pair<CWalletTx*,unsigned int> > > vValue;
vector<pair<int64, pair<const CWalletTx*,unsigned int> > > vValue;
int64 nTotalLower = 0;
CRITICAL_BLOCK(cs_mapWallet)
{
vector<CWalletTx*> vCoins;
vector<const CWalletTx*> vCoins;
vCoins.reserve(mapWallet.size());
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
vCoins.push_back(&(*it).second);
random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);
BOOST_FOREACH(CWalletTx* pcoin, vCoins)
BOOST_FOREACH(const CWalletTx* pcoin, vCoins)
{
if (!pcoin->IsFinal() || !pcoin->IsConfirmed())
continue;
@@ -591,7 +612,7 @@ bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set<
for (int i = 0; i < pcoin->vout.size(); i++)
{
if (pcoin->IsSpent(i) || !pcoin->vout[i].IsMine())
if (pcoin->IsSpent(i) || !IsMine(pcoin->vout[i]))
continue;
int64 n = pcoin->vout[i].nValue;
@@ -599,7 +620,7 @@ bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set<
if (n <= 0)
continue;
pair<int64,pair<CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin,i));
pair<int64,pair<const CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin,i));
if (n == nTargetValue)
{
@@ -702,7 +723,7 @@ bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set<
return true;
}
bool SelectCoins(int64 nTargetValue, set<pair<CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet)
bool CWallet::SelectCoins(int64 nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
{
return (SelectCoinsMinConf(nTargetValue, 1, 6, setCoinsRet, nValueRet) ||
SelectCoinsMinConf(nTargetValue, 1, 1, setCoinsRet, nValueRet) ||
@@ -712,7 +733,7 @@ bool SelectCoins(int64 nTargetValue, set<pair<CWalletTx*,unsigned int> >& setCoi
bool CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
{
int64 nValue = 0;
BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
@@ -724,6 +745,8 @@ bool CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx&
if (vecSend.empty() || nValue < 0)
return false;
wtxNew.pwallet = this;
CRITICAL_BLOCK(cs_main)
{
// txdb must be opened before the mapWallet lock
@@ -744,11 +767,11 @@ bool CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx&
wtxNew.vout.push_back(CTxOut(s.second, s.first));
// Choose coins to use
set<pair<CWalletTx*,unsigned int> > setCoins;
set<pair<const CWalletTx*,unsigned int> > setCoins;
int64 nValueIn = 0;
if (!SelectCoins(nTotalValue, setCoins, nValueIn))
return false;
BOOST_FOREACH(PAIRTYPE(CWalletTx*, unsigned int) pcoin, setCoins)
BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
{
int64 nCredit = pcoin.first->vout[pcoin.second].nValue;
dPriority += (double)nCredit * pcoin.first->GetDepthInMainChain();
@@ -784,13 +807,13 @@ bool CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx&
reservekey.ReturnKey();
// Fill vin
BOOST_FOREACH(const PAIRTYPE(CWalletTx*,unsigned int)& coin, setCoins)
BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
wtxNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second));
// Sign
int nIn = 0;
BOOST_FOREACH(const PAIRTYPE(CWalletTx*,unsigned int)& coin, setCoins)
if (!SignSignature(*coin.first, wtxNew, nIn++))
BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
if (!SignSignature(*this, *coin.first, wtxNew, nIn++))
return false;
// Limit size
@@ -820,7 +843,7 @@ bool CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx&
return true;
}
bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
bool CWallet::CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
{
vector< pair<CScript, int64> > vecSend;
vecSend.push_back(make_pair(scriptPubKey, nValue));
@@ -828,7 +851,7 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CR
}
// Call after CreateTransaction unless you want to abort
bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
{
CRITICAL_BLOCK(cs_main)
{
@@ -838,7 +861,7 @@ bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
// 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
// maybe makes sense; please don't do it anywhere else.
CWalletDB walletdb("r");
CWalletDB* pwalletdb = fFileBacked ? new CWalletDB(strWalletFile,"r") : NULL;
// Take key pair from key pool so it won't be used again
reservekey.KeepKey();
@@ -851,11 +874,15 @@ bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
set<CWalletTx*> setCoins;
BOOST_FOREACH(const CTxIn& txin, wtxNew.vin)
{
CWalletTx &pcoin = mapWallet[txin.prevout.hash];
pcoin.MarkSpent(txin.prevout.n);
pcoin.WriteToDisk();
vWalletUpdated.push_back(pcoin.GetHash());
CWalletTx &coin = mapWallet[txin.prevout.hash];
coin.pwallet = this;
coin.MarkSpent(txin.prevout.n);
coin.WriteToDisk();
vWalletUpdated.push_back(coin.GetHash());
}
if (fFileBacked)
delete pwalletdb;
}
// Track how many getdata requests our transaction gets
@@ -879,9 +906,9 @@ bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
// requires cs_main lock
string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
{
CReserveKey reservekey;
CReserveKey reservekey(this);
int64 nFeeRequired;
if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired))
{
@@ -907,7 +934,7 @@ string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAs
// requires cs_main lock
string SendMoneyToBitcoinAddress(string strAddress, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
string CWallet::SendMoneyToBitcoinAddress(string strAddress, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
{
// Check amount
if (nValue <= 0)
@@ -926,10 +953,12 @@ string SendMoneyToBitcoinAddress(string strAddress, int64 nValue, CWalletTx& wtx
bool LoadWallet(bool& fFirstRunRet)
bool CWallet::LoadWallet(bool& fFirstRunRet)
{
if (!fFileBacked)
return false;
fFirstRunRet = false;
if (!CWalletDB("cr+").LoadWallet())
if (!CWalletDB(strWalletFile,"cr+").LoadWallet(this))
return false;
fFirstRunRet = vchDefaultKey.empty();
@@ -944,17 +973,52 @@ bool LoadWallet(bool& fFirstRunRet)
// Create new keyUser and set as default key
RandAddSeedPerfmon();
CWalletDB walletdb;
vchDefaultKey = GetKeyFromKeyPool();
walletdb.WriteDefaultKey(vchDefaultKey);
walletdb.WriteName(PubKeyToAddress(vchDefaultKey), "");
if (!SetAddressBookName(PubKeyToAddress(vchDefaultKey), ""))
return false;
CWalletDB(strWalletFile).WriteDefaultKey(keyUser.GetPubKey());
}
CreateThread(ThreadFlushWalletDB, NULL);
CreateThread(ThreadFlushWalletDB, &strWalletFile);
return true;
}
void CWalletDB::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
void CWallet::PrintWallet(const CBlock& block)
{
CRITICAL_BLOCK(cs_mapWallet)
{
if (mapWallet.count(block.vtx[0].GetHash()))
{
CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()];
printf(" mine: %d %d %d", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
}
}
printf("\n");
}
bool CWallet::GetTransaction(const uint256 &hashTx, CWalletTx& wtx)
{
CRITICAL_BLOCK(cs_mapWallet)
{
map<uint256, CWalletTx>::iterator mi = mapWallet.find(hashTx);
if (mi != mapWallet.end())
{
wtx = (*mi).second;
return true;
}
return false;
}
}
bool GetWalletFile(CWallet* pwallet, string &strWalletFileOut)
{
if (!pwallet->fFileBacked)
return false;
strWalletFileOut = pwallet->strWalletFile;
return true;
}
void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
{
nIndex = -1;
keypool.vchPubKey.clear();
@@ -962,6 +1026,8 @@ void CWalletDB::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
CRITICAL_BLOCK(cs_mapWallet)
CRITICAL_BLOCK(cs_setKeyPool)
{
CWalletDB walletdb(strWalletFile);
// Top up key pool
int64 nTargetSize = max(GetArg("-keypool", 100), (int64)0);
while (setKeyPool.size() < nTargetSize+1)
@@ -969,7 +1035,7 @@ void CWalletDB::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
int64 nEnd = 1;
if (!setKeyPool.empty())
nEnd = *(--setKeyPool.end()) + 1;
if (!Write(make_pair(string("pool"), nEnd), CKeyPool(GenerateNewKey())))
if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey())))
throw runtime_error("ReserveKeyFromKeyPool() : writing generated key failed");
setKeyPool.insert(nEnd);
printf("keypool added key %"PRI64d", size=%d\n", nEnd, setKeyPool.size());
@@ -979,7 +1045,7 @@ void CWalletDB::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
assert(!setKeyPool.empty());
nIndex = *(setKeyPool.begin());
setKeyPool.erase(setKeyPool.begin());
if (!Read(make_pair(string("pool"), nIndex), keypool))
if (!walletdb.ReadPool(nIndex, keypool))
throw runtime_error("ReserveKeyFromKeyPool() : read failed");
if (!mapKeys.count(keypool.vchPubKey))
throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool");
@@ -988,18 +1054,21 @@ void CWalletDB::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
}
}
void CWalletDB::KeepKey(int64 nIndex)
void CWallet::KeepKey(int64 nIndex)
{
// Remove from key pool
CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(cs_mapWallet)
if (fFileBacked)
{
Erase(make_pair(string("pool"), nIndex));
CWalletDB walletdb(strWalletFile);
CRITICAL_BLOCK(cs_main)
{
walletdb.ErasePool(nIndex);
}
}
printf("keypool keep %"PRI64d"\n", nIndex);
}
void CWalletDB::ReturnKey(int64 nIndex)
void CWallet::ReturnKey(int64 nIndex)
{
// Return to key pool
CRITICAL_BLOCK(cs_setKeyPool)
@@ -1007,32 +1076,30 @@ void CWalletDB::ReturnKey(int64 nIndex)
printf("keypool return %"PRI64d"\n", nIndex);
}
vector<unsigned char> GetKeyFromKeyPool()
vector<unsigned char> CWallet::GetKeyFromKeyPool()
{
CWalletDB walletdb;
int64 nIndex = 0;
CKeyPool keypool;
walletdb.ReserveKeyFromKeyPool(nIndex, keypool);
walletdb.KeepKey(nIndex);
ReserveKeyFromKeyPool(nIndex, keypool);
KeepKey(nIndex);
return keypool.vchPubKey;
}
int64 GetOldestKeyPoolTime()
int64 CWallet::GetOldestKeyPoolTime()
{
CWalletDB walletdb;
int64 nIndex = 0;
CKeyPool keypool;
walletdb.ReserveKeyFromKeyPool(nIndex, keypool);
walletdb.ReturnKey(nIndex);
ReserveKeyFromKeyPool(nIndex, keypool);
ReturnKey(nIndex);
return keypool.nTime;
}
std::vector<unsigned char> CReserveKey::GetReservedKey()
vector<unsigned char> CReserveKey::GetReservedKey()
{
if (nIndex == -1)
{
CKeyPool keypool;
CWalletDB().ReserveKeyFromKeyPool(nIndex, keypool);
pwallet->ReserveKeyFromKeyPool(nIndex, keypool);
vchPubKey = keypool.vchPubKey;
}
assert(!vchPubKey.empty());
@@ -1042,7 +1109,7 @@ std::vector<unsigned char> CReserveKey::GetReservedKey()
void CReserveKey::KeepKey()
{
if (nIndex != -1)
CWalletDB().KeepKey(nIndex);
pwallet->KeepKey(nIndex);
nIndex = -1;
vchPubKey.clear();
}
@@ -1050,7 +1117,7 @@ void CReserveKey::KeepKey()
void CReserveKey::ReturnKey()
{
if (nIndex != -1)
CWalletDB::ReturnKey(nIndex);
pwallet->ReturnKey(nIndex);
nIndex = -1;
vchPubKey.clear();
}