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

@@ -264,14 +264,14 @@ Value setgenerate(const Array& params, bool fHelp)
{
int nGenProcLimit = params[1].get_int();
fLimitProcessors = (nGenProcLimit != -1);
CWalletDB().WriteSetting("fLimitProcessors", fLimitProcessors);
WriteSetting("fLimitProcessors", fLimitProcessors);
if (nGenProcLimit != -1)
CWalletDB().WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit);
WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit);
if (nGenProcLimit == 0)
fGenerate = false;
}
GenerateBitcoins(fGenerate);
GenerateBitcoins(fGenerate, pwalletMain);
return Value::null;
}
@@ -298,7 +298,7 @@ Value getinfo(const Array& params, bool fHelp)
Object obj;
obj.push_back(Pair("version", (int)VERSION));
obj.push_back(Pair("balance", ValueFromAmount(GetBalance())));
obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
obj.push_back(Pair("blocks", (int)nBestHeight));
obj.push_back(Pair("connections", (int)vNodes.size()));
obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
@@ -307,7 +307,7 @@ Value getinfo(const Array& params, bool fHelp)
obj.push_back(Pair("difficulty", (double)GetDifficulty()));
obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
obj.push_back(Pair("testnet", fTestNet));
obj.push_back(Pair("keypoololdest", (boost::int64_t)GetOldestKeyPoolTime()));
obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
obj.push_back(Pair("errors", GetWarnings("statusbar")));
return obj;
@@ -329,9 +329,9 @@ Value getnewaddress(const Array& params, bool fHelp)
strAccount = AccountFromValue(params[0]);
// Generate a new key that is added to wallet
string strAddress = PubKeyToAddress(GetKeyFromKeyPool());
string strAddress = PubKeyToAddress(pwalletMain->GetKeyFromKeyPool());
SetAddressBookName(strAddress, strAccount);
pwalletMain->SetAddressBookName(strAddress, strAccount);
return strAddress;
}
@@ -341,7 +341,7 @@ string GetAccountAddress(string strAccount, bool bForceNew=false)
{
string strAddress;
CWalletDB walletdb;
CWalletDB walletdb(pwalletMain->strWalletFile);
walletdb.TxnBegin();
CAccount account;
@@ -352,8 +352,8 @@ string GetAccountAddress(string strAccount, bool bForceNew=false)
{
CScript scriptPubKey;
scriptPubKey.SetBitcoinAddress(account.vchPubKey);
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin();
it != mapWallet.end() && !account.vchPubKey.empty();
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
++it)
{
const CWalletTx& wtx = (*it).second;
@@ -366,9 +366,9 @@ string GetAccountAddress(string strAccount, bool bForceNew=false)
// Generate a new key
if (account.vchPubKey.empty() || bForceNew)
{
account.vchPubKey = GetKeyFromKeyPool();
account.vchPubKey = pwalletMain->GetKeyFromKeyPool();
string strAddress = PubKeyToAddress(account.vchPubKey);
SetAddressBookName(strAddress, strAccount);
pwalletMain->SetAddressBookName(strAddress, strAccount);
walletdb.WriteAccount(strAccount, account);
}
@@ -391,7 +391,7 @@ Value getaccountaddress(const Array& params, bool fHelp)
Value ret;
CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(cs_mapWallet)
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
{
ret = GetAccountAddress(strAccount);
}
@@ -421,18 +421,18 @@ Value setaccount(const Array& params, bool fHelp)
// Detect when changing the account of an address that is the 'unused current key' of another account:
CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(cs_mapWallet)
CRITICAL_BLOCK(cs_mapAddressBook)
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
{
if (mapAddressBook.count(strAddress))
if (pwalletMain->mapAddressBook.count(strAddress))
{
string strOldAccount = mapAddressBook[strAddress];
string strOldAccount = pwalletMain->mapAddressBook[strAddress];
if (strAddress == GetAccountAddress(strOldAccount))
GetAccountAddress(strOldAccount, true);
}
}
SetAddressBookName(strAddress, strAccount);
pwalletMain->SetAddressBookName(strAddress, strAccount);
return Value::null;
}
@@ -447,10 +447,10 @@ Value getaccount(const Array& params, bool fHelp)
string strAddress = params[0].get_str();
string strAccount;
CRITICAL_BLOCK(cs_mapAddressBook)
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
{
map<string, string>::iterator mi = mapAddressBook.find(strAddress);
if (mi != mapAddressBook.end() && !(*mi).second.empty())
map<string, string>::iterator mi = pwalletMain->mapAddressBook.find(strAddress);
if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
strAccount = (*mi).second;
}
return strAccount;
@@ -468,9 +468,9 @@ Value getaddressesbyaccount(const Array& params, bool fHelp)
// Find all addresses that have the given account
Array ret;
CRITICAL_BLOCK(cs_mapAddressBook)
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
{
BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapAddressBook)
BOOST_FOREACH(const PAIRTYPE(string, string)& item, pwalletMain->mapAddressBook)
{
const string& strAddress = item.first;
const string& strName = item.second;
@@ -523,7 +523,7 @@ Value sendtoaddress(const Array& params, bool fHelp)
CRITICAL_BLOCK(cs_main)
{
string strError = SendMoneyToBitcoinAddress(strAddress, nAmount, wtx);
string strError = pwalletMain->SendMoneyToBitcoinAddress(strAddress, nAmount, wtx);
if (strError != "")
throw JSONRPCError(-4, strError);
}
@@ -544,7 +544,7 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
CScript scriptPubKey;
if (!scriptPubKey.SetBitcoinAddress(strAddress))
throw JSONRPCError(-5, "Invalid bitcoin address");
if (!IsMine(scriptPubKey))
if (!IsMine(*pwalletMain,scriptPubKey))
return (double)0.0;
// Minimum confirmations
@@ -554,9 +554,9 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
// Tally
int64 nAmount = 0;
CRITICAL_BLOCK(cs_mapWallet)
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
{
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
{
const CWalletTx& wtx = (*it).second;
if (wtx.IsCoinBase() || !wtx.IsFinal())
@@ -575,9 +575,9 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
void GetAccountPubKeys(string strAccount, set<CScript>& setPubKey)
{
CRITICAL_BLOCK(cs_mapAddressBook)
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
{
BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapAddressBook)
BOOST_FOREACH(const PAIRTYPE(string, string)& item, pwalletMain->mapAddressBook)
{
const string& strAddress = item.first;
const string& strName = item.second;
@@ -586,7 +586,7 @@ void GetAccountPubKeys(string strAccount, set<CScript>& setPubKey)
// We're only counting our own valid bitcoin addresses and not ip addresses
CScript scriptPubKey;
if (scriptPubKey.SetBitcoinAddress(strAddress))
if (IsMine(scriptPubKey))
if (IsMine(*pwalletMain,scriptPubKey))
setPubKey.insert(scriptPubKey);
}
}
@@ -613,9 +613,9 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
// Tally
int64 nAmount = 0;
CRITICAL_BLOCK(cs_mapWallet)
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
{
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
{
const CWalletTx& wtx = (*it).second;
if (wtx.IsCoinBase() || !wtx.IsFinal())
@@ -635,10 +635,10 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
{
int64 nBalance = 0;
CRITICAL_BLOCK(cs_mapWallet)
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
{
// Tally wallet transactions
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
{
const CWalletTx& wtx = (*it).second;
if (!wtx.IsFinal())
@@ -661,7 +661,7 @@ int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinD
int64 GetAccountBalance(const string& strAccount, int nMinDepth)
{
CWalletDB walletdb;
CWalletDB walletdb(pwalletMain->strWalletFile);
return GetAccountBalance(walletdb, strAccount, nMinDepth);
}
@@ -675,7 +675,7 @@ Value getbalance(const Array& params, bool fHelp)
"If [account] is specified, returns the balance in the account.");
if (params.size() == 0)
return ValueFromAmount(GetBalance());
return ValueFromAmount(pwalletMain->GetBalance());
int nMinDepth = 1;
if (params.size() > 1)
@@ -686,7 +686,7 @@ Value getbalance(const Array& params, bool fHelp)
// (GetBalance() sums up all unspent TxOuts)
// getbalance and getbalance '*' should always return the same number.
int64 nBalance = 0;
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
{
const CWalletTx& wtx = (*it).second;
if (!wtx.IsFinal())
@@ -734,9 +734,9 @@ Value movecmd(const Array& params, bool fHelp)
if (params.size() > 4)
strComment = params[4].get_str();
CRITICAL_BLOCK(cs_mapWallet)
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
{
CWalletDB walletdb;
CWalletDB walletdb(pwalletMain->strWalletFile);
walletdb.TxnBegin();
int64 nNow = GetAdjustedTime();
@@ -787,7 +787,7 @@ Value sendfrom(const Array& params, bool fHelp)
wtx.mapValue["to"] = params[5].get_str();
CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(cs_mapWallet)
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
{
// Check funds
int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
@@ -795,7 +795,7 @@ Value sendfrom(const Array& params, bool fHelp)
throw JSONRPCError(-6, "Account has insufficient funds");
// Send
string strError = SendMoneyToBitcoinAddress(strAddress, nAmount, wtx);
string strError = pwalletMain->SendMoneyToBitcoinAddress(strAddress, nAmount, wtx);
if (strError != "")
throw JSONRPCError(-4, strError);
}
@@ -844,7 +844,7 @@ Value sendmany(const Array& params, bool fHelp)
}
CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(cs_mapWallet)
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
{
// Check funds
int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
@@ -852,16 +852,16 @@ Value sendmany(const Array& params, bool fHelp)
throw JSONRPCError(-6, "Account has insufficient funds");
// Send
CReserveKey keyChange;
CReserveKey keyChange(pwalletMain);
int64 nFeeRequired = 0;
bool fCreated = CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
if (!fCreated)
{
if (totalAmount + nFeeRequired > GetBalance())
if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
throw JSONRPCError(-6, "Insufficient funds");
throw JSONRPCError(-4, "Transaction creation failed");
}
if (!CommitTransaction(wtx, keyChange))
if (!pwalletMain->CommitTransaction(wtx, keyChange))
throw JSONRPCError(-4, "Transaction commit failed");
}
@@ -894,9 +894,9 @@ Value ListReceived(const Array& params, bool fByAccounts)
// Tally
map<uint160, tallyitem> mapTally;
CRITICAL_BLOCK(cs_mapWallet)
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
{
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
{
const CWalletTx& wtx = (*it).second;
if (wtx.IsCoinBase() || !wtx.IsFinal())
@@ -923,9 +923,9 @@ Value ListReceived(const Array& params, bool fByAccounts)
// Reply
Array ret;
map<string, tallyitem> mapAccountTally;
CRITICAL_BLOCK(cs_mapAddressBook)
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
{
BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapAddressBook)
BOOST_FOREACH(const PAIRTYPE(string, string)& item, pwalletMain->mapAddressBook)
{
const string& strAddress = item.first;
const string& strAccount = item.second;
@@ -1061,13 +1061,13 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
// Received
if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
CRITICAL_BLOCK(cs_mapAddressBook)
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
{
BOOST_FOREACH(const PAIRTYPE(string, int64)& r, listReceived)
{
string account;
if (mapAddressBook.count(r.first))
account = mapAddressBook[r.first];
if (pwalletMain->mapAddressBook.count(r.first))
account = pwalletMain->mapAddressBook[r.first];
if (fAllAccounts || (account == strAccount))
{
Object entry;
@@ -1119,16 +1119,16 @@ Value listtransactions(const Array& params, bool fHelp)
nFrom = params[2].get_int();
Array ret;
CWalletDB walletdb;
CWalletDB walletdb(pwalletMain->strWalletFile);
CRITICAL_BLOCK(cs_mapWallet)
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
{
// Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
typedef multimap<int64, TxPair > TxItems;
TxItems txByTime;
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
{
CWalletTx* wtx = &((*it).second);
txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
@@ -1180,16 +1180,16 @@ Value listaccounts(const Array& params, bool fHelp)
nMinDepth = params[0].get_int();
map<string, int64> mapAccountBalances;
CRITICAL_BLOCK(cs_mapWallet)
CRITICAL_BLOCK(cs_mapAddressBook)
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
{
BOOST_FOREACH(const PAIRTYPE(string, string)& entry, mapAddressBook) {
BOOST_FOREACH(const PAIRTYPE(string, string)& entry, pwalletMain->mapAddressBook) {
uint160 hash160;
if(AddressToHash160(entry.first, hash160) && mapPubKeys.count(hash160)) // This address belongs to me
mapAccountBalances[entry.second] = 0;
}
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
{
const CWalletTx& wtx = (*it).second;
int64 nGeneratedImmature, nGeneratedMature, nFee;
@@ -1204,8 +1204,8 @@ Value listaccounts(const Array& params, bool fHelp)
{
mapAccountBalances[""] += nGeneratedMature;
BOOST_FOREACH(const PAIRTYPE(string, int64)& r, listReceived)
if (mapAddressBook.count(r.first))
mapAccountBalances[mapAddressBook[r.first]] += r.second;
if (pwalletMain->mapAddressBook.count(r.first))
mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
else
mapAccountBalances[""] += r.second;
}
@@ -1213,7 +1213,7 @@ Value listaccounts(const Array& params, bool fHelp)
}
list<CAccountingEntry> acentries;
CWalletDB().ListAccountCreditDebit("*", acentries);
CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
BOOST_FOREACH(const CAccountingEntry& entry, acentries)
mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
@@ -1235,11 +1235,11 @@ Value gettransaction(const Array& params, bool fHelp)
hash.SetHex(params[0].get_str());
Object entry;
CRITICAL_BLOCK(cs_mapWallet)
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
{
if (!mapWallet.count(hash))
if (!pwalletMain->mapWallet.count(hash))
throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
const CWalletTx& wtx = mapWallet[hash];
const CWalletTx& wtx = pwalletMain->mapWallet[hash];
int64 nCredit = wtx.GetCredit();
int64 nDebit = wtx.GetDebit();
@@ -1250,10 +1250,10 @@ Value gettransaction(const Array& params, bool fHelp)
if (wtx.IsFromMe())
entry.push_back(Pair("fee", ValueFromAmount(nFee)));
WalletTxToJSON(mapWallet[hash], entry);
WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
Array details;
ListTransactions(mapWallet[hash], "*", 0, false, details);
ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
entry.push_back(Pair("details", details));
}
@@ -1269,7 +1269,7 @@ Value backupwallet(const Array& params, bool fHelp)
"Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
string strDest = params[0].get_str();
BackupWallet(strDest);
BackupWallet(*pwalletMain, strDest);
return Value::null;
}
@@ -1295,10 +1295,10 @@ Value validateaddress(const Array& params, bool fHelp)
string currentAddress = Hash160ToAddress(hash160);
ret.push_back(Pair("address", currentAddress));
ret.push_back(Pair("ismine", (mapPubKeys.count(hash160) > 0)));
CRITICAL_BLOCK(cs_mapAddressBook)
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
{
if (mapAddressBook.count(currentAddress))
ret.push_back(Pair("account", mapAddressBook[currentAddress]));
if (pwalletMain->mapAddressBook.count(currentAddress))
ret.push_back(Pair("account", pwalletMain->mapAddressBook[currentAddress]));
}
}
return ret;
@@ -1325,7 +1325,7 @@ Value getwork(const Array& params, bool fHelp)
static map<uint256, pair<CBlock*, unsigned int> > mapNewBlock;
static vector<CBlock*> vNewBlock;
static CReserveKey reservekey;
static CReserveKey reservekey(pwalletMain);
if (params.size() == 0)
{
@@ -1406,7 +1406,7 @@ Value getwork(const Array& params, bool fHelp)
pblock->vtx[0].vin[0].scriptSig = CScript() << pblock->nBits << CBigNum(nExtraNonce);
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
return CheckWork(pblock, reservekey);
return CheckWork(pblock, *pwalletMain, reservekey);
}
}