Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

wallet encapsulation #2130

Closed
wants to merge 14 commits into from

5 participants

@mikegogulski

hopefully a proper rebasing of #2075

The goal here is to work toward a clean interface to the wallet object. For now this involves moving code out of rpc*.cpp which deals with wallet internals and making that code into methods on the CWallet object.

src/wallet.cpp
((44 lines not shown))
+}
+
+bool CWallet::SetAccount(const CTxDestination& dest, const std::string strAccount)
+{
+ // Detect when changing the account of an address that is the 'unused current key' of another account:
+ if (mapAddressBook.count(dest))
+ {
+ string strOldAccount = mapAddressBook[dest];
+ if (dest == GetAccountAddress(strOldAccount, false) && !CBitcoinAddress(GetAccountAddress(strOldAccount, true)).IsValid())
+ return false;
+ }
+
+ return SetAddressBookName(dest, strAccount);
+}
+
+bool CWallet::IsMine(const CBitcoinAddress& address) const
@sipa Owner
sipa added a note

Here's still a CBitcoinAddress left.

I need to hunt that one down yet since I think it's used outside of rpc*.cpp. I'll post a new commit working on that soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@BitcoinPullTester

Automatic sanity-testing: PASSED, see http://jenkins.bluematt.me/pull-tester/943e7768f33a7c766d1be5db8aea64a46e37253b for binaries and test log.

src/rpcwallet.cpp
((32 lines not shown))
string strAccount;
if (params.size() > 1)
strAccount = AccountFromValue(params[1]);
- // Detect when changing the account of an address that is the 'unused current key' of another account:
- if (pwalletMain->mapAddressBook.count(address.Get()))
- {
- string strOldAccount = pwalletMain->mapAddressBook[address.Get()];
- if (address == GetAccountAddress(strOldAccount))
- GetAccountAddress(strOldAccount, true);
- }
-
- pwalletMain->SetAddressBookName(address.Get(), strAccount);
-
+ // TODO: Use the return code for something
@sipa Owner
sipa added a note

Why is this a TODO?

I saw a method returning bool and the return value being ignored, so I put in that note. Looking around the codebase now I see that it's hardly ever used, so maybe it can be ignored. Want a new commit?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@sipa
Owner

Many of your TODO's look like todo's for yourself rather than concrete plans for changes in the source code - leave those out. If there is a concrete plan, and it's obvious: just add a commit that actually implements the change. If it's something big you'd rather leave for a follow-up pull request, a TODO in the code is fine.

Also, squash some commits together. "Indentation fix" certainly doesn't require a separate commit.

@mikegogulski

Okay, I stripped out the todos. Should I squash everything in this branch down to one commit in order to get it pulled? (total git noob here)

@BitcoinPullTester

Automatic sanity-testing: PASSED, see http://jenkins.bluematt.me/pull-tester/4debb8059a3d29a88b72b2bc61a4e0f6bfc7e522 for binaries and test log.

@BitcoinPullTester

Automatic sanity-testing: FAILED MERGE, see http://jenkins.bluematt.me/pull-tester/4debb8059a3d29a88b72b2bc61a4e0f6bfc7e522 for test log.

This pull does not merge cleanly onto current master

@luke-jr

Rebase needed

@jgarzik
Owner

Poke @mikegogulski

The general sentiment towards these changes seems positive. Let's rebase and get this moving, or close.

@luke-jr

I've rebased this as my mikegogulski_walletencap3 branch. It does, however, create a dependency from wallet.cpp -> main.h; I don't see any obvious way to fix this, considering that IsFinalTx is not tied to any class.

@jgarzik
Owner

Closing - non-responsive. Feel free to rebase and reopen.

@jgarzik jgarzik closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
3  src/rpcblockchain.cpp
@@ -9,6 +9,7 @@
using namespace json_spirit;
using namespace std;
+// TODO: move to rpchelpers.cpp
double GetDifficulty(const CBlockIndex* blockindex)
{
// Floating point number that is a multiple of the minimum difficulty,
@@ -40,7 +41,7 @@ double GetDifficulty(const CBlockIndex* blockindex)
return dDiff;
}
-
+// TODO: move to rpchelpers.cpp
Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
{
Object result;
View
1  src/rpcnet.cpp
@@ -19,6 +19,7 @@ Value getconnectioncount(const Array& params, bool fHelp)
return (int)vNodes.size();
}
+// TODO: move to rpchelpers.cpp
static void CopyNodeStats(std::vector<CNodeStats>& vstats)
{
vstats.clear();
View
9 src/rpcrawtransaction.cpp
@@ -22,6 +22,7 @@ using namespace json_spirit;
// Utilities: convert hex-encoded Values
// (throws error if not hex).
//
+// TODO: move to rpchelpers.cpp
uint256 ParseHashV(const Value& v, string strName)
{
string strHex;
@@ -33,10 +34,14 @@ uint256 ParseHashV(const Value& v, string strName)
result.SetHex(strHex);
return result;
}
+
+// TODO: move to rpchelpers.cpp
uint256 ParseHashO(const Object& o, string strKey)
{
return ParseHashV(find_value(o, strKey), strKey);
}
+
+// TODO: move to rpchelpers.cpp
vector<unsigned char> ParseHexV(const Value& v, string strName)
{
string strHex;
@@ -46,11 +51,14 @@ vector<unsigned char> ParseHexV(const Value& v, string strName)
throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be hexadecimal string (not '"+strHex+"')");
return ParseHex(strHex);
}
+
+// TODO: move to rpchelpers.cpp
vector<unsigned char> ParseHexO(const Object& o, string strKey)
{
return ParseHexV(find_value(o, strKey), strKey);
}
+// TODO: move to rpchelpers.cpp
void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out)
{
txnouttype type;
@@ -75,6 +83,7 @@ void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out)
out.push_back(Pair("addresses", a));
}
+// TODO: move to rpchelpers.cpp
void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry)
{
entry.push_back(Pair("txid", tx.GetHash().GetHex()));
View
214 src/rpcwallet.cpp
@@ -6,7 +6,7 @@
#include <boost/assign/list_of.hpp>
#include "wallet.h"
-#include "walletdb.h"
+// NOTE: Do NOT add dependencies on walletdb.h!
#include "bitcoinrpc.h"
#include "init.h"
#include "base58.h"
@@ -47,7 +47,7 @@ void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
entry.push_back(Pair("timereceived", (boost::int64_t)wtx.nTimeReceived));
- BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
+ BOOST_FOREACH(const PAIRTYPE(string, string)& item, wtx.mapValue)
entry.push_back(Pair(item.first, item.second));
}
@@ -88,8 +88,6 @@ Value getinfo(const Array& params, bool fHelp)
return obj;
}
-
-
Value getnewaddress(const Array& params, bool fHelp)
{
if (fHelp || params.size() > 1)
@@ -118,45 +116,6 @@ Value getnewaddress(const Array& params, bool fHelp)
return CBitcoinAddress(keyID).ToString();
}
-
-CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
-{
- CWalletDB walletdb(pwalletMain->strWalletFile);
-
- CAccount account;
- walletdb.ReadAccount(strAccount, account);
-
- bool bKeyUsed = false;
-
- // Check if the current key has been used
- if (account.vchPubKey.IsValid())
- {
- CScript scriptPubKey;
- scriptPubKey.SetDestination(account.vchPubKey.GetID());
- for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
- it != pwalletMain->mapWallet.end() && account.vchPubKey.IsValid();
- ++it)
- {
- const CWalletTx& wtx = (*it).second;
- BOOST_FOREACH(const CTxOut& txout, wtx.vout)
- if (txout.scriptPubKey == scriptPubKey)
- bKeyUsed = true;
- }
- }
-
- // Generate a new key
- if (!account.vchPubKey.IsValid() || bForceNew || bKeyUsed)
- {
- if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
- throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
-
- pwalletMain->SetAddressBookName(account.vchPubKey.GetID(), strAccount);
- walletdb.WriteAccount(strAccount, account);
- }
-
- return CBitcoinAddress(account.vchPubKey.GetID());
-}
-
Value getaccountaddress(const Array& params, bool fHelp)
{
if (fHelp || params.size() != 1)
@@ -166,46 +125,31 @@ Value getaccountaddress(const Array& params, bool fHelp)
// Parse the account first so we don't generate a key if there's an error
string strAccount = AccountFromValue(params[0]);
-
- Value ret;
-
- ret = GetAccountAddress(strAccount).ToString();
-
- return ret;
+ CBitcoinAddress address = CBitcoinAddress(pwalletMain->GetAccountAddress(strAccount, false));
+ if (address.IsValid())
+ return address.ToString();
+ throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
}
-
-
Value setaccount(const Array& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
- "setaccount <bitcoinaddress> <account>\n"
- "Sets the account associated with the given address.");
+ "setaccount <bitcoinaddress> [account]\n"
+ "Sets the address's account to [account] or \"\".");
CBitcoinAddress address(params[0].get_str());
if (!address.IsValid())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
-
string strAccount;
if (params.size() > 1)
strAccount = AccountFromValue(params[1]);
- // Detect when changing the account of an address that is the 'unused current key' of another account:
- if (pwalletMain->mapAddressBook.count(address.Get()))
- {
- string strOldAccount = pwalletMain->mapAddressBook[address.Get()];
- if (address == GetAccountAddress(strOldAccount))
- GetAccountAddress(strOldAccount, true);
- }
-
- pwalletMain->SetAddressBookName(address.Get(), strAccount);
-
+ pwalletMain->SetAccount(address.Get(), strAccount);
return Value::null;
}
-
Value getaccount(const Array& params, bool fHelp)
{
if (fHelp || params.size() != 1)
@@ -224,7 +168,6 @@ Value getaccount(const Array& params, bool fHelp)
return strAccount;
}
-
Value getaddressesbyaccount(const Array& params, bool fHelp)
{
if (fHelp || params.size() != 1)
@@ -235,14 +178,10 @@ Value getaddressesbyaccount(const Array& params, bool fHelp)
string strAccount = AccountFromValue(params[0]);
// Find all addresses that have the given account
+ std::set<CTxDestination> setAddress = pwalletMain->GetAccountAddresses(strAccount);
Array ret;
- BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
- {
- const CBitcoinAddress& address = item.first;
- const string& strName = item.second;
- if (strName == strAccount)
- ret.push_back(address.ToString());
- }
+ BOOST_FOREACH(const CTxDestination& item, setAddress)
+ ret.push_back(CBitcoinAddress(item).ToString());
return ret;
}
@@ -380,7 +319,6 @@ Value verifymessage(const Array& params, bool fHelp)
return (key.GetPubKey().GetID() == keyID);
}
-
Value getreceivedbyaddress(const Array& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 2)
@@ -390,45 +328,13 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
// Bitcoin address
CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
- CScript scriptPubKey;
- if (!address.IsValid())
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
- scriptPubKey.SetDestination(address.Get());
- if (!IsMine(*pwalletMain,scriptPubKey))
- return (double)0.0;
// Minimum confirmations
int nMinDepth = 1;
if (params.size() > 1)
nMinDepth = params[1].get_int();
- // Tally
- int64 nAmount = 0;
- for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
- {
- const CWalletTx& wtx = (*it).second;
- if (wtx.IsCoinBase() || !wtx.IsFinal())
- continue;
-
- BOOST_FOREACH(const CTxOut& txout, wtx.vout)
- if (txout.scriptPubKey == scriptPubKey)
- if (wtx.GetDepthInMainChain() >= nMinDepth)
- nAmount += txout.nValue;
- }
-
- return ValueFromAmount(nAmount);
-}
-
-
-void GetAccountAddresses(string strAccount, set<CTxDestination>& setAddress)
-{
- BOOST_FOREACH(const PAIRTYPE(CTxDestination, string)& item, pwalletMain->mapAddressBook)
- {
- const CTxDestination& address = item.first;
- const string& strName = item.second;
- if (strName == strAccount)
- setAddress.insert(address);
- }
+ return ValueFromAmount(pwalletMain->GetAddressTally(address.Get(), nMinDepth));
}
Value getreceivedbyaccount(const Array& params, bool fHelp)
@@ -445,8 +351,7 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
// Get the set of pub keys assigned to account
string strAccount = AccountFromValue(params[0]);
- set<CTxDestination> setAddress;
- GetAccountAddresses(strAccount, setAddress);
+ set<CTxDestination> setAddress = pwalletMain->GetAccountAddresses(strAccount);
// Tally
int64 nAmount = 0;
@@ -459,7 +364,7 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
{
CTxDestination address;
- if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*pwalletMain, address) && setAddress.count(address))
+ if (ExtractDestination(txout.scriptPubKey, address) && pwalletMain->IsMine(address) && setAddress.count(address))
if (wtx.GetDepthInMainChain() >= nMinDepth)
nAmount += txout.nValue;
}
@@ -468,39 +373,6 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
return (double)nAmount / (double)COIN;
}
-
-int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
-{
- int64 nBalance = 0;
-
- // Tally wallet transactions
- for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
- {
- const CWalletTx& wtx = (*it).second;
- if (!wtx.IsFinal())
- continue;
-
- int64 nReceived, nSent, nFee;
- wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee);
-
- if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
- nBalance += nReceived;
- nBalance -= nSent + nFee;
- }
-
- // Tally internal accounting entries
- nBalance += walletdb.GetAccountCreditDebit(strAccount);
-
- return nBalance;
-}
-
-int64 GetAccountBalance(const string& strAccount, int nMinDepth)
-{
- CWalletDB walletdb(pwalletMain->strWalletFile);
- return GetAccountBalance(walletdb, strAccount, nMinDepth);
-}
-
-
Value getbalance(const Array& params, bool fHelp)
{
if (fHelp || params.size() > 2)
@@ -546,12 +418,11 @@ Value getbalance(const Array& params, bool fHelp)
string strAccount = AccountFromValue(params[0]);
- int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
+ int64 nBalance = pwalletMain->GetAccountBalance(strAccount, nMinDepth);
return ValueFromAmount(nBalance);
}
-
Value movecmd(const Array& params, bool fHelp)
{
if (fHelp || params.size() < 3 || params.size() > 5)
@@ -569,39 +440,11 @@ Value movecmd(const Array& params, bool fHelp)
if (params.size() > 4)
strComment = params[4].get_str();
- CWalletDB walletdb(pwalletMain->strWalletFile);
- if (!walletdb.TxnBegin())
- throw JSONRPCError(RPC_DATABASE_ERROR, "database error");
-
- int64 nNow = GetAdjustedTime();
-
- // Debit
- CAccountingEntry debit;
- debit.nOrderPos = pwalletMain->IncOrderPosNext(&walletdb);
- debit.strAccount = strFrom;
- debit.nCreditDebit = -nAmount;
- debit.nTime = nNow;
- debit.strOtherAccount = strTo;
- debit.strComment = strComment;
- walletdb.WriteAccountingEntry(debit);
-
- // Credit
- CAccountingEntry credit;
- credit.nOrderPos = pwalletMain->IncOrderPosNext(&walletdb);
- credit.strAccount = strTo;
- credit.nCreditDebit = nAmount;
- credit.nTime = nNow;
- credit.strOtherAccount = strFrom;
- credit.strComment = strComment;
- walletdb.WriteAccountingEntry(credit);
-
- if (!walletdb.TxnCommit())
- throw JSONRPCError(RPC_DATABASE_ERROR, "database error");
-
+ if (!pwalletMain->MoveBalance(strFrom, strTo, nAmount, strComment))
+ throw JSONRPCError(RPC_DATABASE_ERROR, "database error");
return true;
}
-
Value sendfrom(const Array& params, bool fHelp)
{
if (fHelp || params.size() < 3 || params.size() > 6)
@@ -629,7 +472,7 @@ Value sendfrom(const Array& params, bool fHelp)
EnsureWalletIsUnlocked();
// Check funds
- int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
+ int64 nBalance = pwalletMain->GetAccountBalance(strAccount, nMinDepth);
if (nAmount > nBalance)
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
@@ -641,7 +484,6 @@ Value sendfrom(const Array& params, bool fHelp)
return wtx.GetHash().GetHex();
}
-
Value sendmany(const Array& params, bool fHelp)
{
if (fHelp || params.size() < 2 || params.size() > 4)
@@ -686,7 +528,7 @@ Value sendmany(const Array& params, bool fHelp)
EnsureWalletIsUnlocked();
// Check funds
- int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
+ int64 nBalance = pwalletMain->GetAccountBalance(strAccount, nMinDepth);
if (totalAmount > nBalance)
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
@@ -808,7 +650,6 @@ Value createmultisig(const Array& params, bool fHelp)
return result;
}
-
struct tallyitem
{
int64 nAmount;
@@ -848,7 +689,7 @@ Value ListReceived(const Array& params, bool fByAccounts)
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
{
CTxDestination address;
- if (!ExtractDestination(txout.scriptPubKey, address) || !IsMine(*pwalletMain, address))
+ if (!ExtractDestination(txout.scriptPubKey, address) || !pwalletMain->IsMine(address))
continue;
tallyitem& item = mapTally[address];
@@ -1090,7 +931,7 @@ Value listaccounts(const Array& params, bool fHelp)
map<string, int64> mapAccountBalances;
BOOST_FOREACH(const PAIRTYPE(CTxDestination, string)& entry, pwalletMain->mapAddressBook) {
- if (IsMine(*pwalletMain, entry.first)) // This address belongs to me
+ if (pwalletMain->IsMine(entry.first)) // This address belongs to me
mapAccountBalances[entry.second] = 0;
}
@@ -1116,7 +957,7 @@ Value listaccounts(const Array& params, bool fHelp)
}
list<CAccountingEntry> acentries;
- CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
+ pwalletMain->ListAccountCreditDebit("*", acentries);
BOOST_FOREACH(const CAccountingEntry& entry, acentries)
mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
@@ -1156,7 +997,6 @@ Value listsinceblock(const Array& params, bool fHelp)
int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
Array transactions;
-
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
{
CWalletTx tx = (*it).second;
@@ -1223,7 +1063,6 @@ Value gettransaction(const Array& params, bool fHelp)
return entry;
}
-
Value backupwallet(const Array& params, bool fHelp)
{
if (fHelp || params.size() != 1)
@@ -1238,7 +1077,6 @@ Value backupwallet(const Array& params, bool fHelp)
return Value::null;
}
-
Value keypoolrefill(const Array& params, bool fHelp)
{
if (fHelp || params.size() > 0)
@@ -1257,7 +1095,6 @@ Value keypoolrefill(const Array& params, bool fHelp)
return Value::null;
}
-
void ThreadTopUpKeyPool(void* parg)
{
// Make this thread recognisable as the key-topping-up thread
@@ -1348,7 +1185,6 @@ Value walletpassphrase(const Array& params, bool fHelp)
return Value::null;
}
-
Value walletpassphrasechange(const Array& params, bool fHelp)
{
if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
@@ -1381,7 +1217,6 @@ Value walletpassphrasechange(const Array& params, bool fHelp)
return Value::null;
}
-
Value walletlock(const Array& params, bool fHelp)
{
if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
@@ -1404,7 +1239,6 @@ Value walletlock(const Array& params, bool fHelp)
return Value::null;
}
-
Value encryptwallet(const Array& params, bool fHelp)
{
if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
@@ -1489,7 +1323,7 @@ Value validateaddress(const Array& params, bool fHelp)
CTxDestination dest = address.Get();
string currentAddress = address.ToString();
ret.push_back(Pair("address", currentAddress));
- bool fMine = IsMine(*pwalletMain, dest);
+ bool fMine = pwalletMain->IsMine(dest);
ret.push_back(Pair("ismine", fMine));
if (fMine) {
Object detail = boost::apply_visitor(DescribeAddressVisitor(), dest);
View
145 src/wallet.cpp
@@ -1804,3 +1804,148 @@ void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts)
}
}
+CTxDestination CWallet::GetAccountAddress(const std::string strAccount, bool bForceNew=false)
+{
+ CWalletDB walletdb(strWalletFile);
+ CAccount account;
+ walletdb.ReadAccount(strAccount, account);
+ bool bKeyUsed = false;
+
+ // Check if the current key has been used
+ if (account.vchPubKey.IsValid())
+ {
+ CScript scriptPubKey;
+ scriptPubKey.SetDestination(account.vchPubKey.GetID());
+ for (map<uint256, CWalletTx>::iterator it = mapWallet.begin();
+ it != mapWallet.end() && account.vchPubKey.IsValid() && !bKeyUsed;
+ ++it)
+ {
+ //const CWalletTx& wtx = (*it).second;
+ BOOST_FOREACH(const CTxOut& txout, (*it).second.vout)
+ if (txout.scriptPubKey == scriptPubKey)
+ {
+ bKeyUsed = true;
+ break;
+ }
+ }
+ }
+
+ // Generate a new key
+ if (!account.vchPubKey.IsValid() || bForceNew || bKeyUsed)
+ {
+ // Caller must check validity to detect keypool depletion
+ if (!GetKeyFromPool(account.vchPubKey, false))
+ return CTxDestination();
+
+ SetAddressBookName(account.vchPubKey.GetID(), strAccount);
+ walletdb.WriteAccount(strAccount, account);
+ }
+
+ return CTxDestination(account.vchPubKey.GetID());
+}
+
+bool CWallet::SetAccount(const CTxDestination& dest, const std::string strAccount)
+{
+ // Detect when changing the account of an address that is the 'unused current key' of another account:
+ if (mapAddressBook.count(dest))
+ {
+ string strOldAccount = mapAddressBook[dest];
+ if (dest == GetAccountAddress(strOldAccount, false) && !CBitcoinAddress(GetAccountAddress(strOldAccount, true)).IsValid())
+ return false;
+ }
+
+ return SetAddressBookName(dest, strAccount);
+}
+
+int64 CWallet::GetAddressTally(const CTxDestination& dest, int nMinDepth)
+{
+ if (!IsMine(dest))
+ return 0;
+
+ int64 nAmount = 0;
+ CScript scriptPubKey;
+ scriptPubKey.SetDestination(dest);
+ for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+ {
+ const CWalletTx& wtx = (*it).second;
+ if (wtx.IsCoinBase() || !wtx.IsFinal())
+ continue;
+
+ BOOST_FOREACH(const CTxOut& txout, wtx.vout)
+ if (txout.scriptPubKey == scriptPubKey && wtx.GetDepthInMainChain() >= nMinDepth)
+ nAmount += txout.nValue;
+ }
+ return nAmount;
+}
+
+int64 CWallet::GetAccountBalance(const string& strAccount, int nMinDepth)
+{
+ CWalletDB walletdb(strWalletFile);
+ int64 nBalance = 0;
+ // Moved out of loop to avoid some unneeded operations
+ int64 nReceived, nSent, nFee;
+
+ // Tally wallet transactions
+ for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+ {
+ const CWalletTx& wtx = (*it).second;
+ if (!wtx.IsFinal())
+ continue;
+
+ wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee);
+
+ if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
+ nBalance += nReceived;
+ nBalance -= nSent + nFee;
+ }
+
+ // Tally internal accounting entries
+ nBalance += walletdb.GetAccountCreditDebit(strAccount);
+
+ return nBalance;
+}
+
+std::set<CTxDestination> CWallet::GetAccountAddresses(std::string strAccount)
+{
+ set<CTxDestination> setRet;
+ BOOST_FOREACH(const PAIRTYPE(CTxDestination, string)& item, mapAddressBook)
+ {
+ if (item.second == strAccount)
+ // push address into set
+ setRet.insert(item.first);
+ }
+ return setRet;
+}
+
+bool CWallet::MoveBalance(const std::string& strFrom, const std::string& strTo, const int64 nAmount, const std::string& strComment)
+{
+ CWalletDB walletdb(strWalletFile);
+ if (!walletdb.TxnBegin())
+ return false;
+
+ int64 nNow = GetAdjustedTime();
+
+ // Debit
+ CAccountingEntry debit;
+ debit.nOrderPos = IncOrderPosNext(&walletdb);
+ debit.strAccount = strFrom;
+ debit.nCreditDebit = -nAmount;
+ debit.nTime = nNow;
+ debit.strOtherAccount = strTo;
+ debit.strComment = strComment;
+ walletdb.WriteAccountingEntry(debit);
+
+ // Credit
+ CAccountingEntry credit;
+ credit.nOrderPos = IncOrderPosNext(&walletdb);
+ credit.strAccount = strTo;
+ credit.nCreditDebit = nAmount;
+ credit.nTime = nNow;
+ credit.strOtherAccount = strFrom;
+ credit.strComment = strComment;
+ walletdb.WriteAccountingEntry(credit);
+
+ if (!walletdb.TxnCommit())
+ return false;
+ return true;
+}
View
15 src/wallet.h
@@ -203,6 +203,10 @@ class CWallet : public CCryptoKeyStore
{
return ::IsMine(*this, txout.scriptPubKey);
}
+ bool IsMine(const CTxDestination& dest) const
+ {
+ return ::IsMine(*this, dest);
+ }
int64 GetCredit(const CTxOut& txout) const
{
if (!MoneyRange(txout.nValue))
@@ -290,7 +294,16 @@ class CWallet : public CCryptoKeyStore
bool GetTransaction(const uint256 &hashTx, CWalletTx& wtx);
bool SetDefaultKey(const CPubKey &vchPubKey);
-
+ CTxDestination GetAccountAddress(const std::string strAccount, bool bForceNew);
+ bool SetAccount(const CTxDestination& dest, const std::string strAccount);
+ int64 GetAccountBalance(const std::string& strAccount, int nMinDepth);
+ int64 GetAddressTally(const CTxDestination& dest, int nMinDepth);
+ std::set<CTxDestination> GetAccountAddresses(std::string strAccount);
+ void ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& entries)
+ {
+ CWalletDB(strWalletFile).ListAccountCreditDebit(strAccount, entries);
+ }
+ bool MoveBalance(const std::string& strFrom, const std::string& strTo, const int64 nAmount, const std::string& strComment);
// signify that a particular wallet feature is now used. this may change nWalletVersion and nWalletMaxVersion if those are lower
bool SetMinVersion(enum WalletFeature, CWalletDB* pwalletdbIn = NULL, bool fExplicit = false);
Something went wrong with that request. Please try again.