Browse Source

removing stuff

miguelfreitas
Miguel Freitas 12 years ago
parent
commit
76f8a901a7
  1. 7
      src/bitcoinrpc.cpp
  2. 22
      src/main.cpp
  3. 302
      src/rpcwallet.cpp
  4. 388
      src/wallet.cpp
  5. 360
      src/wallet.h
  6. 158
      src/walletdb.cpp
  7. 7
      src/walletdb.h

7
src/bitcoinrpc.cpp

@ -217,15 +217,11 @@ static const CRPCCommand vRPCCommands[] =
{ "listreceivedbyaddress", &listreceivedbyaddress, false, false }, { "listreceivedbyaddress", &listreceivedbyaddress, false, false },
{ "listreceivedbyaccount", &listreceivedbyaccount, false, false }, { "listreceivedbyaccount", &listreceivedbyaccount, false, false },
{ "backupwallet", &backupwallet, true, false }, { "backupwallet", &backupwallet, true, false },
{ "keypoolrefill", &keypoolrefill, true, false },
{ "walletpassphrase", &walletpassphrase, true, false }, { "walletpassphrase", &walletpassphrase, true, false },
{ "walletpassphrasechange", &walletpassphrasechange, false, false }, { "walletpassphrasechange", &walletpassphrasechange, false, false },
{ "walletlock", &walletlock, true, false }, { "walletlock", &walletlock, true, false },
{ "encryptwallet", &encryptwallet, false, false }, { "encryptwallet", &encryptwallet, false, false },
{ "validateaddress", &validateaddress, true, false }, { "validateaddress", &validateaddress, true, false },
{ "getbalance", &getbalance, false, false },
{ "move", &movecmd, false, false },
{ "sendfrom", &sendfrom, false, false },
{ "sendmany", &sendmany, false, false }, { "sendmany", &sendmany, false, false },
{ "addmultisigaddress", &addmultisigaddress, false, false }, { "addmultisigaddress", &addmultisigaddress, false, false },
{ "createmultisig", &createmultisig, true, true }, { "createmultisig", &createmultisig, true, true },
@ -234,7 +230,6 @@ static const CRPCCommand vRPCCommands[] =
{ "getblockhash", &getblockhash, false, false }, { "getblockhash", &getblockhash, false, false },
{ "gettransaction", &gettransaction, false, false }, { "gettransaction", &gettransaction, false, false },
{ "listtransactions", &listtransactions, false, false }, { "listtransactions", &listtransactions, false, false },
{ "listaddressgroupings", &listaddressgroupings, false, false },
{ "signmessage", &signmessage, false, false }, { "signmessage", &signmessage, false, false },
{ "verifymessage", &verifymessage, false, false }, { "verifymessage", &verifymessage, false, false },
{ "getwork", &getwork, true, false }, { "getwork", &getwork, true, false },
@ -251,8 +246,6 @@ static const CRPCCommand vRPCCommands[] =
{ "decoderawtransaction", &decoderawtransaction, false, false }, { "decoderawtransaction", &decoderawtransaction, false, false },
{ "signrawtransaction", &signrawtransaction, false, false }, { "signrawtransaction", &signrawtransaction, false, false },
{ "sendrawtransaction", &sendrawtransaction, false, false }, { "sendrawtransaction", &sendrawtransaction, false, false },
{ "lockunspent", &lockunspent, false, false },
{ "listlockunspent", &listlockunspent, false, false },
{ "verifychain", &verifychain, true, false }, { "verifychain", &verifychain, true, false },
}; };

22
src/main.cpp

@ -99,16 +99,6 @@ void UnregisterAllWallets()
setpwalletRegistered.clear(); setpwalletRegistered.clear();
} }
// get the wallet transaction with the given hash (if it exists)
bool static GetTransaction(const uint256& hashTx, CWalletTx& wtx)
{
LOCK(cs_setpwalletRegistered);
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
if (pwallet->GetTransaction(hashTx,wtx))
return true;
return false;
}
// make sure all wallets know about the given transaction, in the given block // make sure all wallets know about the given transaction, in the given block
void SyncWithWallets(const uint256 &hash, const CTransaction& tx, const CBlock* pblock, bool fUpdate) void SyncWithWallets(const uint256 &hash, const CTransaction& tx, const CBlock* pblock, bool fUpdate)
{ {
@ -133,14 +123,6 @@ void static UpdatedTransaction(const uint256& hashTx)
pwallet->UpdatedTransaction(hashTx); pwallet->UpdatedTransaction(hashTx);
} }
// dump all wallets
void static PrintWallets(const CBlock& block)
{
LOCK(cs_setpwalletRegistered);
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
pwallet->PrintWallet(block);
}
// notify wallets about an incoming inventory (for request counts) // notify wallets about an incoming inventory (for request counts)
void static Inventory(const uint256& hash) void static Inventory(const uint256& hash)
{ {
@ -2173,8 +2155,6 @@ void PrintBlockTree()
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", block.GetBlockTime()).c_str(), DateTimeStrFormat("%Y-%m-%d %H:%M:%S", block.GetBlockTime()).c_str(),
block.vtx.size()); block.vtx.size());
PrintWallets(block);
// put the main time-chain first // put the main time-chain first
vector<CBlockIndex*>& vNext = mapNext[pindex]; vector<CBlockIndex*>& vNext = mapNext[pindex];
for (unsigned int i = 0; i < vNext.size(); i++) for (unsigned int i = 0; i < vNext.size(); i++)
@ -3245,10 +3225,12 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
// always trickle our own transactions // always trickle our own transactions
if (!fTrickleWait) if (!fTrickleWait)
{ {
/* [MF] FIXME
CWalletTx wtx; CWalletTx wtx;
if (GetTransaction(inv.hash, wtx)) if (GetTransaction(inv.hash, wtx))
if (wtx.fFromMe) if (wtx.fFromMe)
fTrickleWait = true; fTrickleWait = true;
*/
} }
if (fTrickleWait) if (fTrickleWait)

302
src/rpcwallet.cpp

@ -73,7 +73,6 @@ Value getinfo(const Array& params, bool fHelp)
obj.push_back(Pair("version", (int)CLIENT_VERSION)); obj.push_back(Pair("version", (int)CLIENT_VERSION));
obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION)); obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
obj.push_back(Pair("walletversion", pwalletMain->GetVersion())); obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
obj.push_back(Pair("blocks", (int)nBestHeight)); obj.push_back(Pair("blocks", (int)nBestHeight));
obj.push_back(Pair("timeoffset", (boost::int64_t)GetTimeOffset())); obj.push_back(Pair("timeoffset", (boost::int64_t)GetTimeOffset()));
obj.push_back(Pair("connections", (int)vNodes.size())); obj.push_back(Pair("connections", (int)vNodes.size()));
@ -105,9 +104,6 @@ Value getnewaddress(const Array& params, bool fHelp)
if (params.size() > 0) if (params.size() > 0)
strAccount = AccountFromValue(params[0]); strAccount = AccountFromValue(params[0]);
if (!pwalletMain->IsLocked())
pwalletMain->TopUpKeyPool();
// Generate a new key that is added to wallet // Generate a new key that is added to wallet
CPubKey newKey; CPubKey newKey;
if (!pwalletMain->GetKeyFromPool(newKey, false)) if (!pwalletMain->GetKeyFromPool(newKey, false))
@ -272,43 +268,13 @@ Value sendtoaddress(const Array& params, bool fHelp)
if (pwalletMain->IsLocked()) if (pwalletMain->IsLocked())
throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first."); throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first.");
string strError = pwalletMain->SendMoneyToDestination(address.Get(), nAmount, wtx); string strError;// = pwalletMain->SendMoneyToDestination(address.Get(), nAmount, wtx);
if (strError != "") if (strError != "")
throw JSONRPCError(RPC_WALLET_ERROR, strError); throw JSONRPCError(RPC_WALLET_ERROR, strError);
return wtx.GetHash().GetHex(); return wtx.GetHash().GetHex();
} }
Value listaddressgroupings(const Array& params, bool fHelp)
{
if (fHelp)
throw runtime_error(
"listaddressgroupings\n"
"Lists groups of addresses which have had their common ownership\n"
"made public by common use as inputs or as the resulting change\n"
"in past transactions");
Array jsonGroupings;
map<CTxDestination, int64> balances = pwalletMain->GetAddressBalances();
BOOST_FOREACH(set<CTxDestination> grouping, pwalletMain->GetAddressGroupings())
{
Array jsonGrouping;
BOOST_FOREACH(CTxDestination address, grouping)
{
Array addressInfo;
addressInfo.push_back(CBitcoinAddress(address).ToString());
addressInfo.push_back(ValueFromAmount(balances[address]));
{
LOCK(pwalletMain->cs_wallet);
if (pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get()) != pwalletMain->mapAddressBook.end())
addressInfo.push_back(pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get())->second);
}
jsonGrouping.push_back(addressInfo);
}
jsonGroupings.push_back(jsonGrouping);
}
return jsonGroupings;
}
Value signmessage(const Array& params, bool fHelp) Value signmessage(const Array& params, bool fHelp)
{ {
@ -472,133 +438,6 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
} }
int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
{
int64 nBalance = 0;
//if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
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)
throw runtime_error(
"getbalance [account] [minconf=1]\n"
"If [account] is not specified, returns the server's total available balance.\n"
"If [account] is specified, returns the balance in the account.");
if (params.size() == 0)
return ValueFromAmount(pwalletMain->GetBalance());
int nMinDepth = 1;
if (params.size() > 1)
nMinDepth = params[1].get_int();
int64 nBalance = 0;
return ValueFromAmount(nBalance);
}
Value movecmd(const Array& params, bool fHelp)
{
if (fHelp || params.size() < 3 || params.size() > 5)
throw runtime_error(
"move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
"Move from one account in your wallet to another.");
string strFrom = AccountFromValue(params[0]);
string strTo = AccountFromValue(params[1]);
int64 nAmount = AmountFromValue(params[2]);
if (params.size() > 3)
// unused parameter, used to be nMinDepth, keep type-checking it though
(void)params[3].get_int();
string strComment;
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");
return true;
}
Value sendfrom(const Array& params, bool fHelp)
{
if (fHelp || params.size() < 3 || params.size() > 6)
throw runtime_error(
"sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
"<amount> is a real and is rounded to the nearest 0.00000001"
+ HelpRequiringPassphrase());
string strAccount = AccountFromValue(params[0]);
CBitcoinAddress address(params[1].get_str());
if (!address.IsValid())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
int64 nAmount = AmountFromValue(params[2]);
int nMinDepth = 1;
if (params.size() > 3)
nMinDepth = params[3].get_int();
CWalletTx wtx;
wtx.strFromAccount = strAccount;
if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
wtx.mapValue["comment"] = params[4].get_str();
if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
wtx.mapValue["to"] = params[5].get_str();
EnsureWalletIsUnlocked();
// Check funds
int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
if (nAmount > nBalance)
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
// Send
string strError = pwalletMain->SendMoneyToDestination(address.Get(), nAmount, wtx);
if (strError != "")
throw JSONRPCError(RPC_WALLET_ERROR, strError);
return wtx.GetHash().GetHex();
}
Value sendmany(const Array& params, bool fHelp) Value sendmany(const Array& params, bool fHelp)
{ {
if (fHelp || params.size() < 2 || params.size() > 4) if (fHelp || params.size() < 2 || params.size() > 4)
@ -642,10 +481,6 @@ Value sendmany(const Array& params, bool fHelp)
EnsureWalletIsUnlocked(); EnsureWalletIsUnlocked();
// Check funds
int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
if (totalAmount > nBalance)
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
// Send // Send
CReserveKey keyChange(pwalletMain); CReserveKey keyChange(pwalletMain);
@ -935,23 +770,6 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
} }
} }
void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
{
bool fAllAccounts = (strAccount == string("*"));
if (fAllAccounts || acentry.strAccount == strAccount)
{
Object entry;
entry.push_back(Pair("account", acentry.strAccount));
entry.push_back(Pair("category", "move"));
entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
entry.push_back(Pair("comment", acentry.strComment));
ret.push_back(entry);
}
}
Value listtransactions(const Array& params, bool fHelp) Value listtransactions(const Array& params, bool fHelp)
{ {
if (fHelp || params.size() > 3) if (fHelp || params.size() > 3)
@ -976,21 +794,6 @@ Value listtransactions(const Array& params, bool fHelp)
Array ret; Array ret;
std::list<CAccountingEntry> acentries;
CWallet::TxItems txOrdered = pwalletMain->OrderedTxItems(acentries, strAccount);
// iterate backwards until we have nCount items to return:
for (CWallet::TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
{
CWalletTx *const pwtx = (*it).second.first;
if (pwtx != 0)
ListTransactions(*pwtx, strAccount, 0, true, ret);
CAccountingEntry *const pacentry = (*it).second.second;
if (pacentry != 0)
AcentryToJSON(*pacentry, strAccount, ret);
if ((int)ret.size() >= (nCount+nFrom)) break;
}
// ret is newest to oldest // ret is newest to oldest
if (nFrom > (int)ret.size()) if (nFrom > (int)ret.size())
@ -1035,16 +838,7 @@ Value listaccounts(const Array& params, bool fHelp)
{ {
} }
} }
Array ret;
list<CAccountingEntry> acentries;
CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
BOOST_FOREACH(const CAccountingEntry& entry, acentries)
mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
Object ret;
BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
}
return ret; return ret;
} }
@ -1153,25 +947,6 @@ Value backupwallet(const Array& params, bool fHelp)
} }
Value keypoolrefill(const Array& params, bool fHelp)
{
if (fHelp || params.size() > 0)
throw runtime_error(
"keypoolrefill\n"
"Fills the keypool."
+ HelpRequiringPassphrase());
EnsureWalletIsUnlocked();
pwalletMain->TopUpKeyPool();
if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
throw JSONRPCError(RPC_WALLET_ERROR, "Error refreshing keypool.");
return Value::null;
}
static void LockWallet(CWallet* pWallet) static void LockWallet(CWallet* pWallet)
{ {
LOCK(cs_nWalletUnlockTime); LOCK(cs_nWalletUnlockTime);
@ -1207,8 +982,6 @@ Value walletpassphrase(const Array& params, bool fHelp)
"walletpassphrase <passphrase> <timeout>\n" "walletpassphrase <passphrase> <timeout>\n"
"Stores the wallet decryption key in memory for <timeout> seconds."); "Stores the wallet decryption key in memory for <timeout> seconds.");
pwalletMain->TopUpKeyPool();
int64 nSleepTime = params[1].get_int64(); int64 nSleepTime = params[1].get_int64();
LOCK(cs_nWalletUnlockTime); LOCK(cs_nWalletUnlockTime);
nWalletUnlockTime = GetTime() + nSleepTime; nWalletUnlockTime = GetTime() + nSleepTime;
@ -1351,74 +1124,3 @@ Value validateaddress(const Array& params, bool fHelp)
return ret; return ret;
} }
Value lockunspent(const Array& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
"lockunspent unlock? [array-of-Objects]\n"
"Updates list of temporarily unspendable outputs.");
if (params.size() == 1)
RPCTypeCheck(params, list_of(bool_type));
else
RPCTypeCheck(params, list_of(bool_type)(array_type));
bool fUnlock = params[0].get_bool();
if (params.size() == 1) {
if (fUnlock)
pwalletMain->UnlockAllCoins();
return true;
}
Array outputs = params[1].get_array();
BOOST_FOREACH(Value& output, outputs)
{
if (output.type() != obj_type)
throw JSONRPCError(-8, "Invalid parameter, expected object");
const Object& o = output.get_obj();
RPCTypeCheck(o, map_list_of("txid", str_type)("vout", int_type));
string txid = find_value(o, "txid").get_str();
if (!IsHex(txid))
throw JSONRPCError(-8, "Invalid parameter, expected hex txid");
int nOutput = find_value(o, "vout").get_int();
if (nOutput < 0)
throw JSONRPCError(-8, "Invalid parameter, vout must be positive");
COutPoint outpt(uint256(txid), nOutput);
if (fUnlock)
pwalletMain->UnlockCoin(outpt);
else
pwalletMain->LockCoin(outpt);
}
return true;
}
Value listlockunspent(const Array& params, bool fHelp)
{
if (fHelp || params.size() > 0)
throw runtime_error(
"listlockunspent\n"
"Returns list of temporarily unspendable outputs.");
vector<COutPoint> vOutpts;
pwalletMain->ListLockedCoins(vOutpts);
Array ret;
BOOST_FOREACH(COutPoint &outpt, vOutpts) {
Object o;
o.push_back(Pair("txid", outpt.hash.GetHex()));
o.push_back(Pair("vout", (int)outpt.n));
ret.push_back(o);
}
return ret;
}

388
src/wallet.cpp

@ -297,7 +297,6 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
Lock(); Lock();
Unlock(strWalletPassphrase); Unlock(strWalletPassphrase);
NewKeyPool();
Lock(); Lock();
// Need to completely rewrite the wallet file; if we don't, bdb might keep // Need to completely rewrite the wallet file; if we don't, bdb might keep
@ -321,65 +320,14 @@ int64 CWallet::IncOrderPosNext(CWalletDB *pwalletdb)
return nRet; return nRet;
} }
CWallet::TxItems CWallet::OrderedTxItems(std::list<CAccountingEntry>& acentries, std::string strAccount)
{
CWalletDB walletdb(strWalletFile);
// First: get all CWalletTx and CAccountingEntry into a sorted-by-order multimap.
TxItems txOrdered;
// Note: maintaining indices in the database of (account,time) --> txid and (account, time) --> acentry
// would make this much faster for applications that do this a lot.
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
CWalletTx* wtx = &((*it).second);
txOrdered.insert(make_pair(wtx->nOrderPos, TxPair(wtx, (CAccountingEntry*)0)));
}
acentries.clear();
walletdb.ListAccountCreditDebit(strAccount, acentries);
BOOST_FOREACH(CAccountingEntry& entry, acentries)
{
txOrdered.insert(make_pair(entry.nOrderPos, TxPair((CWalletTx*)0, &entry)));
}
return txOrdered;
}
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.
{
LOCK(cs_wallet);
/*
BOOST_FOREACH(const CTxIn& txin, tx.vin)
{
map<uint256, CWalletTx>::iterator mi = mapWallet.find(txin.prevout.hash);
if (mi != mapWallet.end())
{
CWalletTx& wtx = (*mi).second;
if (txin.prevout.n >= wtx.vout.size())
printf("WalletUpdateSpent: bad wtx %s\n", wtx.GetHash().ToString().c_str());
else if (!wtx.IsSpent(txin.prevout.n) && IsMine(wtx.vout[txin.prevout.n]))
{
printf("WalletUpdateSpent found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
wtx.MarkSpent(txin.prevout.n);
wtx.WriteToDisk();
NotifyTransactionChanged(this, txin.prevout.hash, CT_UPDATED);
}
}
}
*/
}
}
void CWallet::MarkDirty() void CWallet::MarkDirty()
{ {
{ {
LOCK(cs_wallet); LOCK(cs_wallet);
/*
BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet) BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
item.second.MarkDirty(); item.second.MarkDirty();
*/
} }
} }
@ -403,40 +351,8 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn)
{ {
if (mapBlockIndex.count(wtxIn.hashBlock)) if (mapBlockIndex.count(wtxIn.hashBlock))
{ {
unsigned int latestNow = wtx.nTimeReceived;
unsigned int latestEntry = 0;
{
// Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future
int64 latestTolerated = latestNow + 300;
std::list<CAccountingEntry> acentries;
TxItems txOrdered = OrderedTxItems(acentries);
for (TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
{
CWalletTx *const pwtx = (*it).second.first;
if (pwtx == &wtx)
continue;
CAccountingEntry *const pacentry = (*it).second.second;
int64 nSmartTime;
if (pwtx)
{
nSmartTime = pwtx->nTimeSmart;
if (!nSmartTime)
nSmartTime = pwtx->nTimeReceived;
}
else
nSmartTime = pacentry->nTime;
if (nSmartTime <= latestTolerated)
{
latestEntry = nSmartTime;
if (nSmartTime > latestNow)
latestNow = nSmartTime;
break;
}
}
}
unsigned int& blocktime = mapBlockIndex[wtxIn.hashBlock]->nTime; unsigned int& blocktime = mapBlockIndex[wtxIn.hashBlock]->nTime;
wtx.nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow)); wtx.nTimeSmart = blocktime;
} }
else else
printf("AddToWallet() : found %s in block %s not in index\n", printf("AddToWallet() : found %s in block %s not in index\n",
@ -465,7 +381,6 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn)
wtx.fFromMe = wtxIn.fFromMe; wtx.fFromMe = wtxIn.fFromMe;
fUpdated = true; fUpdated = true;
} }
fUpdated |= wtx.UpdateSpent(wtxIn.vfSpent);
} }
//// debug print //// debug print
@ -497,8 +412,6 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn)
*/ */
} }
} }
// since AddToWallet is called directly for self-originating transactions, check for consumption of own coins
WalletUpdateSpent(wtx);
// Notify UI of new or updated transaction // Notify UI of new or updated transaction
NotifyTransactionChanged(this, hash, fInsertedNew ? CT_NEW : CT_UPDATED); NotifyTransactionChanged(this, hash, fInsertedNew ? CT_NEW : CT_UPDATED);
@ -533,8 +446,6 @@ bool CWallet::AddToWalletIfInvolvingMe(const uint256 &hash, const CTransaction&
wtx.SetMerkleBranch(pblock); wtx.SetMerkleBranch(pblock);
return AddToWallet(wtx); return AddToWallet(wtx);
} }
else
WalletUpdateSpent(tx);
} }
return false; return false;
} }
@ -552,62 +463,6 @@ bool CWallet::EraseFromWallet(uint256 hash)
} }
bool CWallet::IsMine(const CTxIn &txin) const
{
{
LOCK(cs_wallet);
map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
if (mi != mapWallet.end())
{
const CWalletTx& prev = (*mi).second;
/*
if (txin.prevout.n < prev.vout.size())
if (IsMine(prev.vout[txin.prevout.n]))
return true;
*/
}
}
return false;
}
int64 CWallet::GetDebit(const CTxIn &txin) const
{
{
LOCK(cs_wallet);
map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
if (mi != mapWallet.end())
{
const CWalletTx& prev = (*mi).second;
/*
if (txin.prevout.n < prev.vout.size())
if (IsMine(prev.vout[txin.prevout.n]))
return prev.vout[txin.prevout.n].nValue;
*/
}
}
return 0;
}
bool CWallet::IsChange(const CTxOut& txout) const
{
CTxDestination address;
// TODO: fix handling of 'change' outputs. The assumption is that any
// payment to a TX_PUBKEYHASH that is mine but isn't in the address book
// is change. That assumption is likely to break when we implement multisignature
// wallets that return change back into a multi-signature-protected address;
// a better way of identifying which outputs are 'the send' and which are
// 'the change' will need to be implemented (maybe extend CWalletTx to remember
// which output, if any, was change).
if (ExtractDestination(txout.scriptPubKey, address) && ::IsMine(*this, address))
{
LOCK(cs_wallet);
if (!mapAddressBook.count(address))
return true;
}
return false;
}
int64 CWalletTx::GetTxTime() const int64 CWalletTx::GetTxTime() const
{ {
int64 n = nTimeSmart; int64 n = nTimeSmart;
@ -707,7 +562,7 @@ void CWallet::ReacceptWalletTransactions()
BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet) BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
{ {
CWalletTx& wtx = item.second; CWalletTx& wtx = item.second;
if (wtx.IsSpamMessage() && wtx.IsSpent(0)) if (wtx.IsSpamMessage() )
continue; continue;
CTransaction tx; CTransaction tx;
@ -817,63 +672,6 @@ void CWallet::ResendWalletTransactions()
// Actions // Actions
// //
int64 CWallet::GetBalance() const
{
int64 nTotal = 0;
{
LOCK(cs_wallet);
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
const CWalletTx* pcoin = &(*it).second;
if (pcoin->IsConfirmed())
nTotal += pcoin->GetAvailableCredit();
}
}
return nTotal;
}
int64 CWallet::GetUnconfirmedBalance() const
{
int64 nTotal = 0;
return nTotal;
}
int64 CWallet::GetImmatureBalance() const
{
int64 nTotal = 0;
return nTotal;
}
// populate vCoins with vector of spendable COutputs
void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed) const
{
vCoins.clear();
{
LOCK(cs_wallet);
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
const CWalletTx* pcoin = &(*it).second;
if (fOnlyConfirmed && !pcoin->IsConfirmed())
continue;
if (pcoin->IsSpamMessage() && pcoin->GetBlocksToMaturity() > 0)
continue;
/*
for (unsigned int i = 0; i < pcoin->vout.size(); i++) {
if (!(pcoin->IsSpent(i)) && IsMine(pcoin->vout[i]) &&
!IsLockedCoin((*it).first, i) && pcoin->vout[i].nValue > 0)
vCoins.push_back(COutput(pcoin, i, pcoin->GetDepthInMainChain()));
}
*/
}
}
}
bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend, bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend,
CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet, std::string& strFailReason) CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet, std::string& strFailReason)
{ {
@ -1106,8 +904,6 @@ string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew,
string strError; string strError;
if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired, strError)) if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired, strError))
{ {
if (nValue + nFeeRequired > GetBalance())
strError = strprintf(_("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds!"), FormatMoney(nFeeRequired).c_str());
printf("SendMoney() : %s\n", strError.c_str()); printf("SendMoney() : %s\n", strError.c_str());
return strError; return strError;
} }
@ -1123,24 +919,6 @@ string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew,
string CWallet::SendMoneyToDestination(const CTxDestination& address, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
{
// Check amount
if (nValue <= 0)
return _("Invalid amount");
if (nValue + nTransactionFee > GetBalance())
return _("Insufficient funds");
// Parse Bitcoin address
CScript scriptPubKey;
scriptPubKey.SetDestination(address);
return SendMoney(scriptPubKey, nValue, wtxNew, fAskFee);
}
DBErrors CWallet::LoadWallet(bool& fFirstRunRet) DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
{ {
if (!fFileBacked) if (!fFileBacked)
@ -1186,33 +964,6 @@ bool CWallet::DelAddressBookName(const CTxDestination& address)
} }
void CWallet::PrintWallet(const CBlock& block)
{
{
LOCK(cs_wallet);
if (mapWallet.count(block.vtx[0].GetHash()))
{
CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()];
printf(" mine: %d %d %"PRI64d"", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
}
}
printf("\n");
}
bool CWallet::GetTransaction(const uint256 &hashTx, CWalletTx& wtx)
{
{
LOCK(cs_wallet);
map<uint256, CWalletTx>::iterator mi = mapWallet.find(hashTx);
if (mi != mapWallet.end())
{
wtx = (*mi).second;
return true;
}
}
return false;
}
bool CWallet::SetDefaultKey(const CPubKey &vchPubKey) bool CWallet::SetDefaultKey(const CPubKey &vchPubKey)
{ {
if (fFileBacked) if (fFileBacked)
@ -1232,63 +983,6 @@ bool GetWalletFile(CWallet* pwallet, string &strWalletFileOut)
return true; return true;
} }
//
// Mark old keypool keys as used,
// and generate all new keys
//
bool CWallet::NewKeyPool()
{
/*
{
LOCK(cs_wallet);
CWalletDB walletdb(strWalletFile);
BOOST_FOREACH(int64 nIndex, setKeyPool)
walletdb.ErasePool(nIndex);
setKeyPool.clear();
if (IsLocked())
return false;
int64 nKeys = max(GetArg("-keypool", 100), (int64)0);
for (int i = 0; i < nKeys; i++)
{
int64 nIndex = i+1;
walletdb.WritePool(nIndex, CKeyPool(GenerateNewKey()));
setKeyPool.insert(nIndex);
}
printf("CWallet::NewKeyPool wrote %"PRI64d" new keys\n", nKeys);
}
*/
return true;
}
bool CWallet::TopUpKeyPool()
{
/*
{
LOCK(cs_wallet);
if (IsLocked())
return false;
CWalletDB walletdb(strWalletFile);
// Top up key pool
unsigned int nTargetSize = max(GetArg("-keypool", 100), 0LL);
while (setKeyPool.size() < (nTargetSize + 1))
{
int64 nEnd = 1;
if (!setKeyPool.empty())
nEnd = *(--setKeyPool.end()) + 1;
if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey())))
throw runtime_error("TopUpKeyPool() : writing generated key failed");
setKeyPool.insert(nEnd);
printf("keypool added key %"PRI64d", size=%"PRIszu"\n", nEnd, setKeyPool.size());
}
}
*/
return true;
}
void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool) void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
{ {
@ -1297,9 +991,6 @@ void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
{ {
LOCK(cs_wallet); LOCK(cs_wallet);
if (!IsLocked())
TopUpKeyPool();
// Get the oldest key // Get the oldest key
if(setKeyPool.empty()) if(setKeyPool.empty())
return; return;
@ -1391,47 +1082,6 @@ int64 CWallet::GetOldestKeyPoolTime()
return keypool.nTime; return keypool.nTime;
} }
std::map<CTxDestination, int64> CWallet::GetAddressBalances()
{
map<CTxDestination, int64> balances;
{
LOCK(cs_wallet);
BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet)
{
CWalletTx *pcoin = &walletEntry.second;
if (!pcoin->IsConfirmed())
continue;
if (pcoin->IsSpamMessage() && pcoin->GetBlocksToMaturity() > 0)
continue;
int nDepth = pcoin->GetDepthInMainChain();
if (nDepth < (pcoin->IsFromMe() ? 0 : 1))
continue;
/*
for (unsigned int i = 0; i < pcoin->vout.size(); i++)
{
CTxDestination addr;
if (!IsMine(pcoin->vout[i]))
continue;
if(!ExtractDestination(pcoin->vout[i].scriptPubKey, addr))
continue;
int64 n = pcoin->IsSpent(i) ? 0 : pcoin->vout[i].nValue;
if (!balances.count(addr))
balances[addr] = 0;
balances[addr] += n;
}*/
}
}
return balances;
}
set< set<CTxDestination> > CWallet::GetAddressGroupings() set< set<CTxDestination> > CWallet::GetAddressGroupings()
{ {
set< set<CTxDestination> > groupings; set< set<CTxDestination> > groupings;
@ -1593,36 +1243,6 @@ void CWallet::UpdatedTransaction(const uint256 &hashTx)
} }
} }
void CWallet::LockCoin(COutPoint& output)
{
setLockedCoins.insert(output);
}
void CWallet::UnlockCoin(COutPoint& output)
{
setLockedCoins.erase(output);
}
void CWallet::UnlockAllCoins()
{
setLockedCoins.clear();
}
bool CWallet::IsLockedCoin(uint256 hash, unsigned int n) const
{
COutPoint outpt(hash, n);
return (setLockedCoins.count(outpt) > 0);
}
void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts)
{
for (std::set<COutPoint>::iterator it = setLockedCoins.begin();
it != setLockedCoins.end(); it++) {
COutPoint outpt = (*it);
vOutpts.push_back(outpt);
}
}
void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64> &mapKeyBirth) const { void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64> &mapKeyBirth) const {
mapKeyBirth.clear(); mapKeyBirth.clear();

360
src/wallet.h

@ -19,7 +19,6 @@
#include "ui_interface.h" #include "ui_interface.h"
#include "util.h" #include "util.h"
class CAccountingEntry;
class CWalletTx; class CWalletTx;
class CReserveKey; class CReserveKey;
class COutput; class COutput;
@ -119,20 +118,11 @@ public:
CPubKey vchDefaultKey; CPubKey vchDefaultKey;
std::set<COutPoint> setLockedCoins;
int64 nTimeFirstKey; int64 nTimeFirstKey;
// check whether we are allowed to upgrade (or already support) to the named feature // check whether we are allowed to upgrade (or already support) to the named feature
bool CanSupportFeature(enum WalletFeature wf) { return nWalletMaxVersion >= wf; } bool CanSupportFeature(enum WalletFeature wf) { return nWalletMaxVersion >= wf; }
void AvailableCoins(std::vector<COutput>& vCoins, bool fOnlyConfirmed=true) const;
bool IsLockedCoin(uint256 hash, unsigned int n) const;
void LockCoin(COutPoint& output);
void UnlockCoin(COutPoint& output);
void UnlockAllCoins();
void ListLockedCoins(std::vector<COutPoint>& vOutpts);
// keystore implementation // keystore implementation
// Generate a new key // Generate a new key
CPubKey GenerateNewKey(std::string username); CPubKey GenerateNewKey(std::string username);
@ -161,36 +151,20 @@ public:
*/ */
int64 IncOrderPosNext(CWalletDB *pwalletdb = NULL); int64 IncOrderPosNext(CWalletDB *pwalletdb = NULL);
typedef std::pair<CWalletTx*, CAccountingEntry*> TxPair;
typedef std::multimap<int64, TxPair > TxItems;
/** Get the wallet's activity log
@return multimap of ordered transactions and accounting entries
@warning Returned pointers are *only* valid within the scope of passed acentries
*/
TxItems OrderedTxItems(std::list<CAccountingEntry>& acentries, std::string strAccount = "");
void MarkDirty(); void MarkDirty();
bool AddToWallet(const CWalletTx& wtxIn); bool AddToWallet(const CWalletTx& wtxIn);
bool AddToWalletIfInvolvingMe(const uint256 &hash, const CTransaction& tx, const CBlock* pblock, bool fUpdate = false, bool fFindBlock = false); bool AddToWalletIfInvolvingMe(const uint256 &hash, const CTransaction& tx, const CBlock* pblock, bool fUpdate = false, bool fFindBlock = false);
bool EraseFromWallet(uint256 hash); bool EraseFromWallet(uint256 hash);
void WalletUpdateSpent(const CTransaction& prevout);
int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false); int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false);
void ReacceptWalletTransactions(); void ReacceptWalletTransactions();
void ResendWalletTransactions(); void ResendWalletTransactions();
int64 GetBalance() const;
int64 GetUnconfirmedBalance() const;
int64 GetImmatureBalance() const;
bool CreateTransaction(const std::vector<std::pair<CScript, int64> >& vecSend, bool CreateTransaction(const std::vector<std::pair<CScript, int64> >& vecSend,
CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet, std::string& strFailReason); CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet, std::string& strFailReason);
bool CreateTransaction(CScript scriptPubKey, int64 nValue, bool CreateTransaction(CScript scriptPubKey, int64 nValue,
CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet, std::string& strFailReason); CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet, std::string& strFailReason);
bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey); bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey);
std::string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false); std::string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
std::string SendMoneyToDestination(const CTxDestination &address, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
bool NewKeyPool();
bool TopUpKeyPool();
int64 AddReserveKey(const CKeyPool& keypool); int64 AddReserveKey(const CKeyPool& keypool);
void ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool); void ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool);
void KeepKey(int64 nIndex); void KeepKey(int64 nIndex);
@ -200,77 +174,14 @@ public:
void GetAllReserveKeys(std::set<CKeyID>& setAddress) const; void GetAllReserveKeys(std::set<CKeyID>& setAddress) const;
std::set< std::set<CTxDestination> > GetAddressGroupings(); std::set< std::set<CTxDestination> > GetAddressGroupings();
std::map<CTxDestination, int64> GetAddressBalances();
bool IsMine(const CTxIn& txin) const;
int64 GetDebit(const CTxIn& txin) const;
bool IsMine(const CTxOut& txout) const
{
return ::IsMine(*this, txout.scriptPubKey);
}
int64 GetCredit(const CTxOut& txout) const
{
if (!MoneyRange(txout.nValue))
throw std::runtime_error("CWallet::GetCredit() : value out of range");
return (IsMine(txout) ? txout.nValue : 0);
}
bool IsChange(const CTxOut& txout) const;
int64 GetChange(const CTxOut& txout) const
{
if (!MoneyRange(txout.nValue))
throw std::runtime_error("CWallet::GetChange() : value out of range");
return (IsChange(txout) ? txout.nValue : 0);
}
bool IsMine(const CTransaction& tx) const bool IsMine(const CTransaction& tx) const
{ {
/* [MF] BOOST_FOREACH(const CTxOut& txout, tx.vout)
if (IsMine(txout))
return true;
*/
return false; return false;
} }
bool IsFromMe(const CTransaction& tx) const bool IsFromMe(const CTransaction& tx) const
{ {
return (GetDebit(tx) > 0); return false;
}
int64 GetDebit(const CTransaction& tx) const
{
int64 nDebit = 0;
/* [MF]
BOOST_FOREACH(const CTxIn& txin, tx.vin)
{
nDebit += GetDebit(txin);
if (!MoneyRange(nDebit))
throw std::runtime_error("CWallet::GetDebit() : value out of range");
}
*/
return nDebit;
}
int64 GetCredit(const CTransaction& tx) const
{
int64 nCredit = 0;
/* [MF]
BOOST_FOREACH(const CTxOut& txout, tx.vout)
{
nCredit += GetCredit(txout);
if (!MoneyRange(nCredit))
throw std::runtime_error("CWallet::GetCredit() : value out of range");
}
*/
return nCredit;
}
int64 GetChange(const CTransaction& tx) const
{
int64 nChange = 0;
/*
BOOST_FOREACH(const CTxOut& txout, tx.vout)
{
nChange += GetChange(txout);
if (!MoneyRange(nChange))
throw std::runtime_error("CWallet::GetChange() : value out of range");
}
*/
return nChange;
} }
void SetBestChain(const CBlockLocator& loc); void SetBestChain(const CBlockLocator& loc);
@ -351,17 +262,6 @@ public:
typedef std::map<std::string, std::string> mapValue_t; typedef std::map<std::string, std::string> mapValue_t;
static void ReadOrderPos(int64& nOrderPos, mapValue_t& mapValue)
{
if (!mapValue.count("n"))
{
nOrderPos = -1; // TODO: calculate elsewhere
return;
}
nOrderPos = atoi64(mapValue["n"].c_str());
}
static void WriteOrderPos(const int64& nOrderPos, mapValue_t& mapValue) static void WriteOrderPos(const int64& nOrderPos, mapValue_t& mapValue)
{ {
if (nOrderPos == -1) if (nOrderPos == -1)
@ -389,18 +289,6 @@ public:
std::vector<char> vfSpent; // which outputs are already spent std::vector<char> vfSpent; // which outputs are already spent
int64 nOrderPos; // position in ordered transaction list int64 nOrderPos; // position in ordered transaction list
// memory only
mutable bool fDebitCached;
mutable bool fCreditCached;
mutable bool fImmatureCreditCached;
mutable bool fAvailableCreditCached;
mutable bool fChangeCached;
mutable int64 nDebitCached;
mutable int64 nCreditCached;
mutable int64 nImmatureCreditCached;
mutable int64 nAvailableCreditCached;
mutable int64 nChangeCached;
CWalletTx() CWalletTx()
{ {
Init(NULL); Init(NULL);
@ -432,16 +320,6 @@ public:
fFromMe = false; fFromMe = false;
strFromAccount.clear(); strFromAccount.clear();
vfSpent.clear(); vfSpent.clear();
fDebitCached = false;
fCreditCached = false;
fImmatureCreditCached = false;
fAvailableCreditCached = false;
fChangeCached = false;
nDebitCached = 0;
nCreditCached = 0;
nImmatureCreditCached = 0;
nAvailableCreditCached = 0;
nChangeCached = 0;
nOrderPos = -1; nOrderPos = -1;
} }
@ -478,22 +356,6 @@ public:
READWRITE(nTimeReceived); READWRITE(nTimeReceived);
READWRITE(fFromMe); READWRITE(fFromMe);
READWRITE(fSpent); READWRITE(fSpent);
/*
if (fRead)
{
pthis->strFromAccount = pthis->mapValue["fromaccount"];
if (mapValue.count("spent"))
BOOST_FOREACH(char c, pthis->mapValue["spent"])
pthis->vfSpent.push_back(c != '0');
else
pthis->vfSpent.assign(vout.size(), fSpent);
ReadOrderPos(pthis->nOrderPos, pthis->mapValue);
pthis->nTimeSmart = mapValue.count("timesmart") ? (unsigned int)atoi64(pthis->mapValue["timesmart"]) : 0;
}
*/
pthis->mapValue.erase("fromaccount"); pthis->mapValue.erase("fromaccount");
pthis->mapValue.erase("version"); pthis->mapValue.erase("version");
pthis->mapValue.erase("spent"); pthis->mapValue.erase("spent");
@ -501,153 +363,14 @@ public:
pthis->mapValue.erase("timesmart"); pthis->mapValue.erase("timesmart");
) )
// marks certain txout's as spent
// returns true if any update took place
bool UpdateSpent(const std::vector<char>& vfNewSpent)
{
bool fReturn = false;
for (unsigned int i = 0; i < vfNewSpent.size(); i++)
{
if (i == vfSpent.size())
break;
if (vfNewSpent[i] && !vfSpent[i])
{
vfSpent[i] = true;
fReturn = true;
fAvailableCreditCached = false;
}
}
return fReturn;
}
// make sure balances are recalculated
void MarkDirty()
{
fCreditCached = false;
fAvailableCreditCached = false;
fDebitCached = false;
fChangeCached = false;
}
void BindWallet(CWallet *pwalletIn) void BindWallet(CWallet *pwalletIn)
{ {
pwallet = pwalletIn; pwallet = pwalletIn;
MarkDirty();
} }
void MarkSpent(unsigned int nOut)
{
/*
if (nOut >= vout.size())
throw std::runtime_error("CWalletTx::MarkSpent() : nOut out of range");
vfSpent.resize(vout.size());
if (!vfSpent[nOut])
{
vfSpent[nOut] = true;
fAvailableCreditCached = false;
}
*/
}
bool IsSpent(unsigned int nOut) const
{
/*
if (nOut >= vout.size())
throw std::runtime_error("CWalletTx::IsSpent() : nOut out of range");
if (nOut >= vfSpent.size())
return false;
*/
return (!!vfSpent[nOut]);
}
int64 GetDebit() const
{
/*
if (vin.empty())
return 0;
if (fDebitCached)
return nDebitCached;
*/
nDebitCached = pwallet->GetDebit(*this);
fDebitCached = true;
return nDebitCached;
}
int64 GetCredit(bool fUseCache=true) const
{
// Must wait until coinbase is safely deep enough in the chain before valuing it
if (IsSpamMessage() && GetBlocksToMaturity() > 0)
return 0;
// GetBalance can assume transactions in mapWallet won't change
if (fUseCache && fCreditCached)
return nCreditCached;
nCreditCached = pwallet->GetCredit(*this);
fCreditCached = true;
return nCreditCached;
}
int64 GetImmatureCredit(bool fUseCache=true) const
{
if (IsSpamMessage() && GetBlocksToMaturity() > 0 && IsInMainChain())
{
if (fUseCache && fImmatureCreditCached)
return nImmatureCreditCached;
nImmatureCreditCached = pwallet->GetCredit(*this);
fImmatureCreditCached = true;
return nImmatureCreditCached;
}
return 0;
}
int64 GetAvailableCredit(bool fUseCache=true) const
{
// Must wait until coinbase is safely deep enough in the chain before valuing it
if (IsSpamMessage() && GetBlocksToMaturity() > 0)
return 0;
if (fUseCache && fAvailableCreditCached)
return nAvailableCreditCached;
int64 nCredit = 0;
/*
for (unsigned int i = 0; i < vout.size(); i++)
{
if (!IsSpent(i))
{
const CTxOut &txout = vout[i];
nCredit += pwallet->GetCredit(txout);
if (!MoneyRange(nCredit))
throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range");
}
}
*/
nAvailableCreditCached = nCredit;
fAvailableCreditCached = true;
return nCredit;
}
int64 GetChange() const
{
if (fChangeCached)
return nChangeCached;
nChangeCached = pwallet->GetChange(*this);
fChangeCached = true;
return nChangeCached;
}
void GetAmounts(std::list<std::pair<CTxDestination, int64> >& listReceived,
std::list<std::pair<CTxDestination, int64> >& listSent, int64& nFee, std::string& strSentAccount) const;
void GetAccountAmounts(const std::string& strAccount, int64& nReceived,
int64& nSent, int64& nFee) const;
bool IsFromMe() const bool IsFromMe() const
{ {
return (GetDebit() > 0); return false;
} }
bool IsConfirmed() const bool IsConfirmed() const
@ -759,85 +482,6 @@ public:
}; };
/** Internal transfers.
* Database key is acentry<account><counter>.
*/
class CAccountingEntry
{
public:
std::string strAccount;
int64 nCreditDebit;
int64 nTime;
std::string strOtherAccount;
std::string strComment;
mapValue_t mapValue;
int64 nOrderPos; // position in ordered transaction list
uint64 nEntryNo;
CAccountingEntry()
{
SetNull();
}
void SetNull()
{
nCreditDebit = 0;
nTime = 0;
strAccount.clear();
strOtherAccount.clear();
strComment.clear();
nOrderPos = -1;
}
IMPLEMENT_SERIALIZE
(
CAccountingEntry& me = *const_cast<CAccountingEntry*>(this);
if (!(nType & SER_GETHASH))
READWRITE(nVersion);
// Note: strAccount is serialized as part of the key, not here.
READWRITE(nCreditDebit);
READWRITE(nTime);
READWRITE(strOtherAccount);
if (!fRead)
{
WriteOrderPos(nOrderPos, me.mapValue);
if (!(mapValue.empty() && _ssExtra.empty()))
{
CDataStream ss(nType, nVersion);
ss.insert(ss.begin(), '\0');
ss << mapValue;
ss.insert(ss.end(), _ssExtra.begin(), _ssExtra.end());
me.strComment.append(ss.str());
}
}
READWRITE(strComment);
size_t nSepPos = strComment.find("\0", 0, 1);
if (fRead)
{
me.mapValue.clear();
if (std::string::npos != nSepPos)
{
CDataStream ss(std::vector<char>(strComment.begin() + nSepPos + 1, strComment.end()), nType, nVersion);
ss >> me.mapValue;
me._ssExtra = std::vector<char>(ss.begin(), ss.end());
}
ReadOrderPos(me.nOrderPos, me.mapValue);
}
if (std::string::npos != nSepPos)
me.strComment.erase(nSepPos);
me.mapValue.erase("n");
)
private:
std::vector<char> _ssExtra;
};
bool GetWalletFile(CWallet* pwallet, std::string &strWalletFileOut); bool GetWalletFile(CWallet* pwallet, std::string &strWalletFileOut);
#endif #endif

158
src/walletdb.cpp

@ -42,144 +42,6 @@ bool CWalletDB::WriteAccount(const string& strAccount, const CAccount& account)
return Write(make_pair(string("acc"), strAccount), account); return Write(make_pair(string("acc"), strAccount), account);
} }
bool CWalletDB::WriteAccountingEntry(const uint64 nAccEntryNum, const CAccountingEntry& acentry)
{
return Write(boost::make_tuple(string("acentry"), acentry.strAccount, nAccEntryNum), acentry);
}
bool CWalletDB::WriteAccountingEntry(const CAccountingEntry& acentry)
{
return WriteAccountingEntry(++nAccountingEntryNumber, acentry);
}
int64 CWalletDB::GetAccountCreditDebit(const string& strAccount)
{
list<CAccountingEntry> entries;
ListAccountCreditDebit(strAccount, entries);
int64 nCreditDebit = 0;
BOOST_FOREACH (const CAccountingEntry& entry, entries)
nCreditDebit += entry.nCreditDebit;
return nCreditDebit;
}
void CWalletDB::ListAccountCreditDebit(const string& strAccount, list<CAccountingEntry>& entries)
{
bool fAllAccounts = (strAccount == "*");
Dbc* pcursor = GetCursor();
if (!pcursor)
throw runtime_error("CWalletDB::ListAccountCreditDebit() : cannot create DB cursor");
unsigned int fFlags = DB_SET_RANGE;
loop
{
// Read next record
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
if (fFlags == DB_SET_RANGE)
ssKey << boost::make_tuple(string("acentry"), (fAllAccounts? string("") : strAccount), uint64(0));
CDataStream ssValue(SER_DISK, CLIENT_VERSION);
int ret = ReadAtCursor(pcursor, ssKey, ssValue, fFlags);
fFlags = DB_NEXT;
if (ret == DB_NOTFOUND)
break;
else if (ret != 0)
{
pcursor->close();
throw runtime_error("CWalletDB::ListAccountCreditDebit() : error scanning DB");
}
// Unserialize
string strType;
ssKey >> strType;
if (strType != "acentry")
break;
CAccountingEntry acentry;
ssKey >> acentry.strAccount;
if (!fAllAccounts && acentry.strAccount != strAccount)
break;
ssValue >> acentry;
ssKey >> acentry.nEntryNo;
entries.push_back(acentry);
}
pcursor->close();
}
DBErrors
CWalletDB::ReorderTransactions(CWallet* pwallet)
{
LOCK(pwallet->cs_wallet);
// Old wallets didn't have any defined order for transactions
// Probably a bad idea to change the output of this
// First: 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 = pwallet->mapWallet.begin(); it != pwallet->mapWallet.end(); ++it)
{
CWalletTx* wtx = &((*it).second);
txByTime.insert(make_pair(wtx->nTimeReceived, TxPair(wtx, (CAccountingEntry*)0)));
}
list<CAccountingEntry> acentries;
ListAccountCreditDebit("", acentries);
BOOST_FOREACH(CAccountingEntry& entry, acentries)
{
txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
}
int64& nOrderPosNext = pwallet->nOrderPosNext;
nOrderPosNext = 0;
std::vector<int64> nOrderPosOffsets;
for (TxItems::iterator it = txByTime.begin(); it != txByTime.end(); ++it)
{
CWalletTx *const pwtx = (*it).second.first;
CAccountingEntry *const pacentry = (*it).second.second;
int64& nOrderPos = (pwtx != 0) ? pwtx->nOrderPos : pacentry->nOrderPos;
if (nOrderPos == -1)
{
nOrderPos = nOrderPosNext++;
nOrderPosOffsets.push_back(nOrderPos);
if (pacentry)
// Have to write accounting regardless, since we don't keep it in memory
if (!WriteAccountingEntry(pacentry->nEntryNo, *pacentry))
return DB_LOAD_FAIL;
}
else
{
int64 nOrderPosOff = 0;
BOOST_FOREACH(const int64& nOffsetStart, nOrderPosOffsets)
{
if (nOrderPos >= nOffsetStart)
++nOrderPosOff;
}
nOrderPos += nOrderPosOff;
nOrderPosNext = std::max(nOrderPosNext, nOrderPos + 1);
if (!nOrderPosOff)
continue;
// Since we're changing the order, write it back
if (pwtx)
{
if (!WriteTx(pwtx->GetHash(), *pwtx))
return DB_LOAD_FAIL;
}
else
if (!WriteAccountingEntry(pacentry->nEntryNo, *pacentry))
return DB_LOAD_FAIL;
}
}
return DB_LOAD_OK;
}
class CWalletScanState { class CWalletScanState {
public: public:
unsigned int nKeys; unsigned int nKeys;
@ -259,23 +121,6 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
// wtx.hashBlock.ToString().c_str(), // wtx.hashBlock.ToString().c_str(),
// wtx.mapValue["message"].c_str()); // wtx.mapValue["message"].c_str());
} }
else if (strType == "acentry")
{
string strAccount;
ssKey >> strAccount;
uint64 nNumber;
ssKey >> nNumber;
if (nNumber > nAccountingEntryNumber)
nAccountingEntryNumber = nNumber;
if (!wss.fAnyUnordered)
{
CAccountingEntry acentry;
ssValue >> acentry;
if (acentry.nOrderPos == -1)
wss.fAnyUnordered = true;
}
}
else if (strType == "key" || strType == "wkey") else if (strType == "key" || strType == "wkey")
{ {
CPubKey vchPubKey; CPubKey vchPubKey;
@ -494,9 +339,6 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet)
if (wss.nFileVersion < CLIENT_VERSION) // Update if (wss.nFileVersion < CLIENT_VERSION) // Update
WriteVersion(CLIENT_VERSION); WriteVersion(CLIENT_VERSION);
if (wss.fAnyUnordered)
result = ReorderTransactions(pwallet);
return result; return result;
} }

7
src/walletdb.h

@ -10,7 +10,6 @@
class CKeyPool; class CKeyPool;
class CAccount; class CAccount;
class CAccountingEntry;
class CWallet; class CWallet;
class CWalletTx; class CWalletTx;
@ -199,13 +198,7 @@ public:
bool ReadAccount(const std::string& strAccount, CAccount& account); bool ReadAccount(const std::string& strAccount, CAccount& account);
bool WriteAccount(const std::string& strAccount, const CAccount& account); bool WriteAccount(const std::string& strAccount, const CAccount& account);
private: private:
bool WriteAccountingEntry(const uint64 nAccEntryNum, const CAccountingEntry& acentry);
public: public:
bool WriteAccountingEntry(const CAccountingEntry& acentry);
int64 GetAccountCreditDebit(const std::string& strAccount);
void ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& acentries);
DBErrors ReorderTransactions(CWallet*);
DBErrors LoadWallet(CWallet* pwallet); DBErrors LoadWallet(CWallet* pwallet);
static bool Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys); static bool Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys);
static bool Recover(CDBEnv& dbenv, std::string filename); static bool Recover(CDBEnv& dbenv, std::string filename);

Loading…
Cancel
Save