aboutsummaryrefslogtreecommitdiff
path: root/src/wallet.cpp
diff options
context:
space:
mode:
authorPieter Wuille <pieter.wuille@gmail.com>2011-06-01 18:28:20 +0200
committerPieter Wuille <pieter.wuille@gmail.com>2011-06-15 11:05:55 +0200
commit64c7ee7e6b9c059d99aaa493c74a6703c6b0fc80 (patch)
tree5ffafe3c7e4486f7b5ff2594bdbbf67e62560677 /src/wallet.cpp
parente89b9f6a2abaa120ff0fc3cea9ae364e8cbd25e4 (diff)
downloadbitcoin-64c7ee7e6b9c059d99aaa493c74a6703c6b0fc80.tar.xz
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.
Diffstat (limited to 'src/wallet.cpp')
-rw-r--r--src/wallet.cpp273
1 files changed, 170 insertions, 103 deletions
diff --git a/src/wallet.cpp b/src/wallet.cpp
index a9fc92fd78..aef8d180e4 100644
--- a/src/wallet.cpp
+++ b/src/wallet.cpp
@@ -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();
}