mirror of
https://github.com/twisterarmy/twister-core.git
synced 2025-01-10 23:07:52 +00:00
removing stuff
This commit is contained in:
parent
fe57966e05
commit
76f8a901a7
@ -217,15 +217,11 @@ static const CRPCCommand vRPCCommands[] =
|
||||
{ "listreceivedbyaddress", &listreceivedbyaddress, false, false },
|
||||
{ "listreceivedbyaccount", &listreceivedbyaccount, false, false },
|
||||
{ "backupwallet", &backupwallet, true, false },
|
||||
{ "keypoolrefill", &keypoolrefill, true, false },
|
||||
{ "walletpassphrase", &walletpassphrase, true, false },
|
||||
{ "walletpassphrasechange", &walletpassphrasechange, false, false },
|
||||
{ "walletlock", &walletlock, true, false },
|
||||
{ "encryptwallet", &encryptwallet, false, false },
|
||||
{ "validateaddress", &validateaddress, true, false },
|
||||
{ "getbalance", &getbalance, false, false },
|
||||
{ "move", &movecmd, false, false },
|
||||
{ "sendfrom", &sendfrom, false, false },
|
||||
{ "sendmany", &sendmany, false, false },
|
||||
{ "addmultisigaddress", &addmultisigaddress, false, false },
|
||||
{ "createmultisig", &createmultisig, true, true },
|
||||
@ -234,7 +230,6 @@ static const CRPCCommand vRPCCommands[] =
|
||||
{ "getblockhash", &getblockhash, false, false },
|
||||
{ "gettransaction", &gettransaction, false, false },
|
||||
{ "listtransactions", &listtransactions, false, false },
|
||||
{ "listaddressgroupings", &listaddressgroupings, false, false },
|
||||
{ "signmessage", &signmessage, false, false },
|
||||
{ "verifymessage", &verifymessage, false, false },
|
||||
{ "getwork", &getwork, true, false },
|
||||
@ -251,8 +246,6 @@ static const CRPCCommand vRPCCommands[] =
|
||||
{ "decoderawtransaction", &decoderawtransaction, false, false },
|
||||
{ "signrawtransaction", &signrawtransaction, false, false },
|
||||
{ "sendrawtransaction", &sendrawtransaction, false, false },
|
||||
{ "lockunspent", &lockunspent, false, false },
|
||||
{ "listlockunspent", &listlockunspent, false, false },
|
||||
{ "verifychain", &verifychain, true, false },
|
||||
};
|
||||
|
||||
|
22
src/main.cpp
22
src/main.cpp
@ -99,16 +99,6 @@ void UnregisterAllWallets()
|
||||
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
|
||||
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);
|
||||
}
|
||||
|
||||
// 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)
|
||||
void static Inventory(const uint256& hash)
|
||||
{
|
||||
@ -2173,8 +2155,6 @@ void PrintBlockTree()
|
||||
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", block.GetBlockTime()).c_str(),
|
||||
block.vtx.size());
|
||||
|
||||
PrintWallets(block);
|
||||
|
||||
// put the main time-chain first
|
||||
vector<CBlockIndex*>& vNext = mapNext[pindex];
|
||||
for (unsigned int i = 0; i < vNext.size(); i++)
|
||||
@ -3245,10 +3225,12 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
|
||||
// always trickle our own transactions
|
||||
if (!fTrickleWait)
|
||||
{
|
||||
/* [MF] FIXME
|
||||
CWalletTx wtx;
|
||||
if (GetTransaction(inv.hash, wtx))
|
||||
if (wtx.fFromMe)
|
||||
fTrickleWait = true;
|
||||
*/
|
||||
}
|
||||
|
||||
if (fTrickleWait)
|
||||
|
@ -73,7 +73,6 @@ Value getinfo(const Array& params, bool fHelp)
|
||||
obj.push_back(Pair("version", (int)CLIENT_VERSION));
|
||||
obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
|
||||
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("timeoffset", (boost::int64_t)GetTimeOffset()));
|
||||
obj.push_back(Pair("connections", (int)vNodes.size()));
|
||||
@ -105,9 +104,6 @@ Value getnewaddress(const Array& params, bool fHelp)
|
||||
if (params.size() > 0)
|
||||
strAccount = AccountFromValue(params[0]);
|
||||
|
||||
if (!pwalletMain->IsLocked())
|
||||
pwalletMain->TopUpKeyPool();
|
||||
|
||||
// Generate a new key that is added to wallet
|
||||
CPubKey newKey;
|
||||
if (!pwalletMain->GetKeyFromPool(newKey, false))
|
||||
@ -272,43 +268,13 @@ Value sendtoaddress(const Array& params, bool fHelp)
|
||||
if (pwalletMain->IsLocked())
|
||||
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 != "")
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, strError);
|
||||
|
||||
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)
|
||||
{
|
||||
@ -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)
|
||||
{
|
||||
if (fHelp || params.size() < 2 || params.size() > 4)
|
||||
@ -642,10 +481,6 @@ Value sendmany(const Array& params, bool fHelp)
|
||||
|
||||
EnsureWalletIsUnlocked();
|
||||
|
||||
// Check funds
|
||||
int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
|
||||
if (totalAmount > nBalance)
|
||||
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
|
||||
|
||||
// Send
|
||||
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)
|
||||
{
|
||||
if (fHelp || params.size() > 3)
|
||||
@ -976,21 +794,6 @@ Value listtransactions(const Array& params, bool fHelp)
|
||||
|
||||
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
|
||||
|
||||
if (nFrom > (int)ret.size())
|
||||
@ -1035,16 +838,7 @@ Value listaccounts(const Array& params, bool fHelp)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
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)));
|
||||
}
|
||||
Array 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)
|
||||
{
|
||||
LOCK(cs_nWalletUnlockTime);
|
||||
@ -1207,8 +982,6 @@ Value walletpassphrase(const Array& params, bool fHelp)
|
||||
"walletpassphrase <passphrase> <timeout>\n"
|
||||
"Stores the wallet decryption key in memory for <timeout> seconds.");
|
||||
|
||||
pwalletMain->TopUpKeyPool();
|
||||
|
||||
int64 nSleepTime = params[1].get_int64();
|
||||
LOCK(cs_nWalletUnlockTime);
|
||||
nWalletUnlockTime = GetTime() + nSleepTime;
|
||||
@ -1351,74 +1124,3 @@ Value validateaddress(const Array& params, bool fHelp)
|
||||
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
388
src/wallet.cpp
@ -297,7 +297,6 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
|
||||
|
||||
Lock();
|
||||
Unlock(strWalletPassphrase);
|
||||
NewKeyPool();
|
||||
Lock();
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
/*
|
||||
BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
|
||||
item.second.MarkDirty();
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
@ -403,40 +351,8 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn)
|
||||
{
|
||||
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;
|
||||
wtx.nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
|
||||
wtx.nTimeSmart = blocktime;
|
||||
}
|
||||
else
|
||||
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;
|
||||
fUpdated = true;
|
||||
}
|
||||
fUpdated |= wtx.UpdateSpent(wtxIn.vfSpent);
|
||||
}
|
||||
|
||||
//// 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
|
||||
NotifyTransactionChanged(this, hash, fInsertedNew ? CT_NEW : CT_UPDATED);
|
||||
@ -533,8 +446,6 @@ bool CWallet::AddToWalletIfInvolvingMe(const uint256 &hash, const CTransaction&
|
||||
wtx.SetMerkleBranch(pblock);
|
||||
return AddToWallet(wtx);
|
||||
}
|
||||
else
|
||||
WalletUpdateSpent(tx);
|
||||
}
|
||||
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 n = nTimeSmart;
|
||||
@ -707,7 +562,7 @@ void CWallet::ReacceptWalletTransactions()
|
||||
BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
|
||||
{
|
||||
CWalletTx& wtx = item.second;
|
||||
if (wtx.IsSpamMessage() && wtx.IsSpent(0))
|
||||
if (wtx.IsSpamMessage() )
|
||||
continue;
|
||||
|
||||
CTransaction tx;
|
||||
@ -817,63 +672,6 @@ void CWallet::ResendWalletTransactions()
|
||||
// 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,
|
||||
CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet, std::string& strFailReason)
|
||||
{
|
||||
@ -1106,8 +904,6 @@ string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew,
|
||||
string 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());
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (fFileBacked)
|
||||
@ -1232,63 +983,6 @@ bool GetWalletFile(CWallet* pwallet, string &strWalletFileOut)
|
||||
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)
|
||||
{
|
||||
@ -1297,9 +991,6 @@ void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
|
||||
if (!IsLocked())
|
||||
TopUpKeyPool();
|
||||
|
||||
// Get the oldest key
|
||||
if(setKeyPool.empty())
|
||||
return;
|
||||
@ -1391,47 +1082,6 @@ int64 CWallet::GetOldestKeyPoolTime()
|
||||
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> > 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 {
|
||||
mapKeyBirth.clear();
|
||||
|
360
src/wallet.h
360
src/wallet.h
@ -19,7 +19,6 @@
|
||||
#include "ui_interface.h"
|
||||
#include "util.h"
|
||||
|
||||
class CAccountingEntry;
|
||||
class CWalletTx;
|
||||
class CReserveKey;
|
||||
class COutput;
|
||||
@ -119,20 +118,11 @@ public:
|
||||
|
||||
CPubKey vchDefaultKey;
|
||||
|
||||
std::set<COutPoint> setLockedCoins;
|
||||
|
||||
int64 nTimeFirstKey;
|
||||
|
||||
// check whether we are allowed to upgrade (or already support) to the named feature
|
||||
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
|
||||
// Generate a new key
|
||||
CPubKey GenerateNewKey(std::string username);
|
||||
@ -161,36 +151,20 @@ public:
|
||||
*/
|
||||
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();
|
||||
bool AddToWallet(const CWalletTx& wtxIn);
|
||||
bool AddToWalletIfInvolvingMe(const uint256 &hash, const CTransaction& tx, const CBlock* pblock, bool fUpdate = false, bool fFindBlock = false);
|
||||
bool EraseFromWallet(uint256 hash);
|
||||
void WalletUpdateSpent(const CTransaction& prevout);
|
||||
int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false);
|
||||
void ReacceptWalletTransactions();
|
||||
void ResendWalletTransactions();
|
||||
int64 GetBalance() const;
|
||||
int64 GetUnconfirmedBalance() const;
|
||||
int64 GetImmatureBalance() const;
|
||||
bool CreateTransaction(const std::vector<std::pair<CScript, int64> >& vecSend,
|
||||
CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet, std::string& strFailReason);
|
||||
bool CreateTransaction(CScript scriptPubKey, int64 nValue,
|
||||
CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet, std::string& strFailReason);
|
||||
bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey);
|
||||
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);
|
||||
void ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool);
|
||||
void KeepKey(int64 nIndex);
|
||||
@ -200,77 +174,14 @@ public:
|
||||
void GetAllReserveKeys(std::set<CKeyID>& setAddress) const;
|
||||
|
||||
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
|
||||
{
|
||||
/* [MF] BOOST_FOREACH(const CTxOut& txout, tx.vout)
|
||||
if (IsMine(txout))
|
||||
return true;
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
bool IsFromMe(const CTransaction& tx) const
|
||||
{
|
||||
return (GetDebit(tx) > 0);
|
||||
}
|
||||
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;
|
||||
return false;
|
||||
}
|
||||
void SetBestChain(const CBlockLocator& loc);
|
||||
|
||||
@ -351,17 +262,6 @@ public:
|
||||
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)
|
||||
{
|
||||
if (nOrderPos == -1)
|
||||
@ -389,18 +289,6 @@ public:
|
||||
std::vector<char> vfSpent; // which outputs are already spent
|
||||
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()
|
||||
{
|
||||
Init(NULL);
|
||||
@ -432,16 +320,6 @@ public:
|
||||
fFromMe = false;
|
||||
strFromAccount.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;
|
||||
}
|
||||
|
||||
@ -478,22 +356,6 @@ public:
|
||||
READWRITE(nTimeReceived);
|
||||
READWRITE(fFromMe);
|
||||
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("version");
|
||||
pthis->mapValue.erase("spent");
|
||||
@ -501,153 +363,14 @@ public:
|
||||
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)
|
||||
{
|
||||
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
|
||||
{
|
||||
return (GetDebit() > 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
#endif
|
||||
|
158
src/walletdb.cpp
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);
|
||||
}
|
||||
|
||||
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 {
|
||||
public:
|
||||
unsigned int nKeys;
|
||||
@ -259,23 +121,6 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
|
||||
// wtx.hashBlock.ToString().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")
|
||||
{
|
||||
CPubKey vchPubKey;
|
||||
@ -494,9 +339,6 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet)
|
||||
if (wss.nFileVersion < CLIENT_VERSION) // Update
|
||||
WriteVersion(CLIENT_VERSION);
|
||||
|
||||
if (wss.fAnyUnordered)
|
||||
result = ReorderTransactions(pwallet);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
class CKeyPool;
|
||||
class CAccount;
|
||||
class CAccountingEntry;
|
||||
class CWallet;
|
||||
class CWalletTx;
|
||||
|
||||
@ -199,13 +198,7 @@ public:
|
||||
bool ReadAccount(const std::string& strAccount, CAccount& account);
|
||||
bool WriteAccount(const std::string& strAccount, const CAccount& account);
|
||||
private:
|
||||
bool WriteAccountingEntry(const uint64 nAccEntryNum, const CAccountingEntry& acentry);
|
||||
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);
|
||||
static bool Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys);
|
||||
static bool Recover(CDBEnv& dbenv, std::string filename);
|
||||
|
Loading…
Reference in New Issue
Block a user