Merge #13825: [wallet] Kill accounts

c9c32e6b84 [wallet] Kill accounts (John Newbery)

Tree-SHA512: 783272e7df9042fb0a01826fa37a02b97218496459015d7457e56223da8690bdad930c223dd4a903a1d4df57f3f2f4a097d392d272a72419ea9a882b11e599f7
This commit is contained in:
Wladimir J. van der Laan 2018-08-30 16:08:56 +02:00
commit 07033a8f91
No known key found for this signature in database
GPG key ID: 1E4AED62986CD25D
12 changed files with 45 additions and 447 deletions

View file

@ -1,5 +1,5 @@
Accout API removed Account API removed
------------------ -------------------
The 'account' API was deprecated in v0.17 and has been fully removed in v0.18. The 'account' API was deprecated in v0.17 and has been fully removed in v0.18.
The 'label' API was introduced in v0.17 as a replacement for accounts. The 'label' API was introduced in v0.17 as a replacement for accounts.

View file

@ -39,12 +39,11 @@ public:
bool commit(WalletValueMap value_map, bool commit(WalletValueMap value_map,
WalletOrderForm order_form, WalletOrderForm order_form,
std::string from_account,
std::string& reject_reason) override std::string& reject_reason) override
{ {
LOCK2(cs_main, m_wallet.cs_wallet); LOCK2(cs_main, m_wallet.cs_wallet);
CValidationState state; CValidationState state;
if (!m_wallet.CommitTransaction(m_tx, std::move(value_map), std::move(order_form), std::move(from_account), m_key, g_connman.get(), state)) { if (!m_wallet.CommitTransaction(m_tx, std::move(value_map), std::move(order_form), m_key, g_connman.get(), state)) {
reject_reason = state.GetRejectReason(); reject_reason = state.GetRejectReason();
return false; return false;
} }

View file

@ -289,7 +289,6 @@ public:
//! Send pending transaction and commit to wallet. //! Send pending transaction and commit to wallet.
virtual bool commit(WalletValueMap value_map, virtual bool commit(WalletValueMap value_map,
WalletOrderForm order_form, WalletOrderForm order_form,
std::string from_account,
std::string& reject_reason) = 0; std::string& reject_reason) = 0;
}; };

View file

@ -253,7 +253,7 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran
auto& newTx = transaction.getWtx(); auto& newTx = transaction.getWtx();
std::string rejectReason; std::string rejectReason;
if (!newTx->commit({} /* mapValue */, std::move(vOrderForm), {} /* fromAccount */, rejectReason)) if (!newTx->commit({} /* mapValue */, std::move(vOrderForm), rejectReason))
return SendCoinsReturn(TransactionCommitFailed, QString::fromStdString(rejectReason)); return SendCoinsReturn(TransactionCommitFailed, QString::fromStdString(rejectReason));
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);

View file

@ -242,7 +242,7 @@ Result CommitTransaction(CWallet* wallet, const uint256& txid, CMutableTransacti
CReserveKey reservekey(wallet); CReserveKey reservekey(wallet);
CValidationState state; CValidationState state;
if (!wallet->CommitTransaction(tx, std::move(mapValue), oldWtx.vOrderForm, oldWtx.strFromAccount, reservekey, g_connman.get(), state)) { if (!wallet->CommitTransaction(tx, std::move(mapValue), oldWtx.vOrderForm, reservekey, g_connman.get(), state)) {
// NOTE: CommitTransaction never returns false, so this should never happen. // NOTE: CommitTransaction never returns false, so this should never happen.
errors.push_back(strprintf("The transaction was rejected: %s", FormatStateMessage(state))); errors.push_back(strprintf("The transaction was rejected: %s", FormatStateMessage(state)));
return Result::WALLET_ERROR; return Result::WALLET_ERROR;

View file

@ -78,7 +78,7 @@ void WalletInit::AddWalletOptions() const
gArgs.AddArg("-walletnotify=<cmd>", "Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)", false, OptionsCategory::WALLET); gArgs.AddArg("-walletnotify=<cmd>", "Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)", false, OptionsCategory::WALLET);
gArgs.AddArg("-walletrbf", strprintf("Send transactions with full-RBF opt-in enabled (RPC only, default: %u)", DEFAULT_WALLET_RBF), false, OptionsCategory::WALLET); gArgs.AddArg("-walletrbf", strprintf("Send transactions with full-RBF opt-in enabled (RPC only, default: %u)", DEFAULT_WALLET_RBF), false, OptionsCategory::WALLET);
gArgs.AddArg("-zapwallettxes=<mode>", "Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup" gArgs.AddArg("-zapwallettxes=<mode>", "Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup"
" (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)", false, OptionsCategory::WALLET); " (1 = keep tx meta data e.g. payment request information, 2 = drop tx meta data)", false, OptionsCategory::WALLET);
gArgs.AddArg("-dblogsize=<n>", strprintf("Flush wallet database activity from memory to disk log every <n> megabytes (default: %u)", DEFAULT_WALLET_DBLOGSIZE), true, OptionsCategory::WALLET_DEBUG_TEST); gArgs.AddArg("-dblogsize=<n>", strprintf("Flush wallet database activity from memory to disk log every <n> megabytes (default: %u)", DEFAULT_WALLET_DBLOGSIZE), true, OptionsCategory::WALLET_DEBUG_TEST);
gArgs.AddArg("-flushwallet", strprintf("Run a thread to flush wallet periodically (default: %u)", DEFAULT_FLUSHWALLET), true, OptionsCategory::WALLET_DEBUG_TEST); gArgs.AddArg("-flushwallet", strprintf("Run a thread to flush wallet periodically (default: %u)", DEFAULT_FLUSHWALLET), true, OptionsCategory::WALLET_DEBUG_TEST);

View file

@ -196,16 +196,6 @@ static UniValue getnewaddress(const JSONRPCRequest& request)
return EncodeDestination(dest); return EncodeDestination(dest);
} }
CTxDestination GetLabelDestination(CWallet* const pwallet, const std::string& label, bool bForceNew=false)
{
CTxDestination dest;
if (!pwallet->GetLabelDestination(dest, label, bForceNew)) {
throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
}
return dest;
}
static UniValue getrawchangeaddress(const JSONRPCRequest& request) static UniValue getrawchangeaddress(const JSONRPCRequest& request)
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
@ -297,20 +287,6 @@ static UniValue setlabel(const JSONRPCRequest& request)
pwallet->SetAddressBook(dest, label, "send"); pwallet->SetAddressBook(dest, label, "send");
} }
// Detect when there are no addresses using this label.
// If so, delete the account record for it. Labels, unlike addresses, can be deleted,
// and if we wouldn't do this, the record would stick around forever.
bool found_address = false;
for (const std::pair<const CTxDestination, CAddressBookData>& item : pwallet->mapAddressBook) {
if (item.second.name == label) {
found_address = true;
break;
}
}
if (!found_address) {
pwallet->DeleteLabel(old_label);
}
return NullUniValue; return NullUniValue;
} }
@ -348,7 +324,7 @@ static CTransactionRef SendMoney(CWallet * const pwallet, const CTxDestination &
throw JSONRPCError(RPC_WALLET_ERROR, strError); throw JSONRPCError(RPC_WALLET_ERROR, strError);
} }
CValidationState state; CValidationState state;
if (!pwallet->CommitTransaction(tx, std::move(mapValue), {} /* orderForm */, "" /* account */, reservekey, g_connman.get(), state)) { if (!pwallet->CommitTransaction(tx, std::move(mapValue), {} /* orderForm */, reservekey, g_connman.get(), state)) {
strError = strprintf("Error: The transaction was rejected! Reason given: %s", FormatStateMessage(state)); strError = strprintf("Error: The transaction was rejected! Reason given: %s", FormatStateMessage(state));
throw JSONRPCError(RPC_WALLET_ERROR, strError); throw JSONRPCError(RPC_WALLET_ERROR, strError);
} }
@ -904,7 +880,7 @@ static UniValue sendmany(const JSONRPCRequest& request)
EnsureWalletIsUnlocked(pwallet); EnsureWalletIsUnlocked(pwallet);
// Check funds // Check funds
if (totalAmount > pwallet->GetLegacyBalance(ISMINE_SPENDABLE, nMinDepth, nullptr)) { if (totalAmount > pwallet->GetLegacyBalance(ISMINE_SPENDABLE, nMinDepth)) {
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Wallet has insufficient funds"); throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Wallet has insufficient funds");
} }
@ -921,7 +897,7 @@ static UniValue sendmany(const JSONRPCRequest& request)
if (!fCreated) if (!fCreated)
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason); throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason);
CValidationState state; CValidationState state;
if (!pwallet->CommitTransaction(tx, std::move(mapValue), {} /* orderForm */, "" /* account */, keyChange, g_connman.get(), state)) { if (!pwallet->CommitTransaction(tx, std::move(mapValue), {} /* orderForm */, keyChange, g_connman.get(), state)) {
strFailReason = strprintf("Transaction commit failed:: %s", FormatStateMessage(state)); strFailReason = strprintf("Transaction commit failed:: %s", FormatStateMessage(state));
throw JSONRPCError(RPC_WALLET_ERROR, strFailReason); throw JSONRPCError(RPC_WALLET_ERROR, strFailReason);
} }
@ -1404,11 +1380,10 @@ static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
static void ListTransactions(CWallet* const pwallet, const CWalletTx& wtx, int nMinDepth, bool fLong, UniValue& ret, const isminefilter& filter) EXCLUSIVE_LOCKS_REQUIRED(cs_main) static void ListTransactions(CWallet* const pwallet, const CWalletTx& wtx, int nMinDepth, bool fLong, UniValue& ret, const isminefilter& filter) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{ {
CAmount nFee; CAmount nFee;
std::string dummy_account;
std::list<COutputEntry> listReceived; std::list<COutputEntry> listReceived;
std::list<COutputEntry> listSent; std::list<COutputEntry> listSent;
wtx.GetAmounts(listReceived, listSent, nFee, dummy_account, filter); wtx.GetAmounts(listReceived, listSent, nFee, filter);
bool involvesWatchonly = wtx.IsFromMe(ISMINE_WATCH_ONLY); bool involvesWatchonly = wtx.IsFromMe(ISMINE_WATCH_ONLY);
@ -1563,10 +1538,8 @@ UniValue listtransactions(const JSONRPCRequest& request)
// iterate backwards until we have nCount items to return: // iterate backwards until we have nCount items to return:
for (CWallet::TxItems::const_reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) for (CWallet::TxItems::const_reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
{ {
CWalletTx *const pwtx = (*it).second.first; CWalletTx *const pwtx = (*it).second;
if (pwtx != nullptr) { ListTransactions(pwallet, *pwtx, 0, true, ret, filter);
ListTransactions(pwallet, *pwtx, 0, true, ret, filter);
}
if ((int)ret.size() >= (nCount+nFrom)) break; if ((int)ret.size() >= (nCount+nFrom)) break;
} }
} }

View file

@ -297,7 +297,7 @@ public:
CCoinControl dummy; CCoinControl dummy;
BOOST_CHECK(wallet->CreateTransaction({recipient}, tx, reservekey, fee, changePos, error, dummy)); BOOST_CHECK(wallet->CreateTransaction({recipient}, tx, reservekey, fee, changePos, error, dummy));
CValidationState state; CValidationState state;
BOOST_CHECK(wallet->CommitTransaction(tx, {}, {}, {}, reservekey, nullptr, state)); BOOST_CHECK(wallet->CommitTransaction(tx, {}, {}, reservekey, nullptr, state));
CMutableTransaction blocktx; CMutableTransaction blocktx;
{ {
LOCK(wallet->cs_wallet); LOCK(wallet->cs_wallet);

View file

@ -585,7 +585,6 @@ void CWallet::SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator> ran
// nTimeReceived not copied on purpose // nTimeReceived not copied on purpose
copyTo->nTimeSmart = copyFrom->nTimeSmart; copyTo->nTimeSmart = copyFrom->nTimeSmart;
copyTo->fFromMe = copyFrom->fFromMe; copyTo->fFromMe = copyFrom->fFromMe;
copyTo->strFromAccount = copyFrom->strFromAccount;
// nOrderPos not copied on purpose // nOrderPos not copied on purpose
// cached members not copied on purpose // cached members not copied on purpose
} }
@ -735,44 +734,30 @@ DBErrors CWallet::ReorderTransactions()
// Old wallets didn't have any defined order for transactions // Old wallets didn't have any defined order for transactions
// Probably a bad idea to change the output of this // Probably a bad idea to change the output of this
// First: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap. // First: get all CWalletTx into a sorted-by-time multimap.
typedef std::pair<CWalletTx*, CAccountingEntry*> TxPair; typedef std::multimap<int64_t, CWalletTx*> TxItems;
typedef std::multimap<int64_t, TxPair > TxItems;
TxItems txByTime; TxItems txByTime;
for (auto& entry : mapWallet) for (auto& entry : mapWallet)
{ {
CWalletTx* wtx = &entry.second; CWalletTx* wtx = &entry.second;
txByTime.insert(std::make_pair(wtx->nTimeReceived, TxPair(wtx, nullptr))); txByTime.insert(std::make_pair(wtx->nTimeReceived, wtx));
}
std::list<CAccountingEntry> acentries;
batch.ListAccountCreditDebit("", acentries);
for (CAccountingEntry& entry : acentries)
{
txByTime.insert(std::make_pair(entry.nTime, TxPair(nullptr, &entry)));
} }
nOrderPosNext = 0; nOrderPosNext = 0;
std::vector<int64_t> nOrderPosOffsets; std::vector<int64_t> nOrderPosOffsets;
for (TxItems::iterator it = txByTime.begin(); it != txByTime.end(); ++it) for (TxItems::iterator it = txByTime.begin(); it != txByTime.end(); ++it)
{ {
CWalletTx *const pwtx = (*it).second.first; CWalletTx *const pwtx = (*it).second;
CAccountingEntry *const pacentry = (*it).second.second; int64_t& nOrderPos = pwtx->nOrderPos;
int64_t& nOrderPos = (pwtx != nullptr) ? pwtx->nOrderPos : pacentry->nOrderPos;
if (nOrderPos == -1) if (nOrderPos == -1)
{ {
nOrderPos = nOrderPosNext++; nOrderPos = nOrderPosNext++;
nOrderPosOffsets.push_back(nOrderPos); nOrderPosOffsets.push_back(nOrderPos);
if (pwtx) if (!batch.WriteTx(*pwtx))
{ return DBErrors::LOAD_FAIL;
if (!batch.WriteTx(*pwtx))
return DBErrors::LOAD_FAIL;
}
else
if (!batch.WriteAccountingEntry(pacentry->nEntryNo, *pacentry))
return DBErrors::LOAD_FAIL;
} }
else else
{ {
@ -789,14 +774,8 @@ DBErrors CWallet::ReorderTransactions()
continue; continue;
// Since we're changing the order, write it back // Since we're changing the order, write it back
if (pwtx) if (!batch.WriteTx(*pwtx))
{ return DBErrors::LOAD_FAIL;
if (!batch.WriteTx(*pwtx))
return DBErrors::LOAD_FAIL;
}
else
if (!batch.WriteAccountingEntry(pacentry->nEntryNo, *pacentry))
return DBErrors::LOAD_FAIL;
} }
} }
batch.WriteOrderPosNext(nOrderPosNext); batch.WriteOrderPosNext(nOrderPosNext);
@ -816,80 +795,6 @@ int64_t CWallet::IncOrderPosNext(WalletBatch *batch)
return nRet; return nRet;
} }
bool CWallet::AccountMove(std::string strFrom, std::string strTo, CAmount nAmount, std::string strComment)
{
WalletBatch batch(*database);
if (!batch.TxnBegin())
return false;
int64_t nNow = GetAdjustedTime();
// Debit
CAccountingEntry debit;
debit.nOrderPos = IncOrderPosNext(&batch);
debit.strAccount = strFrom;
debit.nCreditDebit = -nAmount;
debit.nTime = nNow;
debit.strOtherAccount = strTo;
debit.strComment = strComment;
AddAccountingEntry(debit, &batch);
// Credit
CAccountingEntry credit;
credit.nOrderPos = IncOrderPosNext(&batch);
credit.strAccount = strTo;
credit.nCreditDebit = nAmount;
credit.nTime = nNow;
credit.strOtherAccount = strFrom;
credit.strComment = strComment;
AddAccountingEntry(credit, &batch);
if (!batch.TxnCommit())
return false;
return true;
}
bool CWallet::GetLabelDestination(CTxDestination &dest, const std::string& label, bool bForceNew)
{
WalletBatch batch(*database);
CAccount account;
batch.ReadAccount(label, account);
if (!bForceNew) {
if (!account.vchPubKey.IsValid())
bForceNew = true;
else {
// Check if the current key has been used (TODO: check other addresses with the same key)
CScript scriptPubKey = GetScriptForDestination(GetDestinationForKey(account.vchPubKey, m_default_address_type));
for (std::map<uint256, CWalletTx>::iterator it = mapWallet.begin();
it != mapWallet.end() && account.vchPubKey.IsValid();
++it)
for (const CTxOut& txout : (*it).second.tx->vout)
if (txout.scriptPubKey == scriptPubKey) {
bForceNew = true;
break;
}
}
}
// Generate a new key
if (bForceNew) {
if (!GetKeyFromPool(account.vchPubKey, false))
return false;
LearnRelatedScripts(account.vchPubKey, m_default_address_type);
dest = GetDestinationForKey(account.vchPubKey, m_default_address_type);
SetAddressBook(dest, label, "receive");
batch.WriteAccount(label, account);
} else {
dest = GetDestinationForKey(account.vchPubKey, m_default_address_type);
}
return true;
}
void CWallet::MarkDirty() void CWallet::MarkDirty()
{ {
{ {
@ -944,7 +849,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)
if (fInsertedNew) { if (fInsertedNew) {
wtx.nTimeReceived = GetAdjustedTime(); wtx.nTimeReceived = GetAdjustedTime();
wtx.nOrderPos = IncOrderPosNext(&batch); wtx.nOrderPos = IncOrderPosNext(&batch);
wtx.m_it_wtxOrdered = wtxOrdered.insert(std::make_pair(wtx.nOrderPos, TxPair(&wtx, nullptr))); wtx.m_it_wtxOrdered = wtxOrdered.insert(std::make_pair(wtx.nOrderPos, &wtx));
wtx.nTimeSmart = ComputeTimeSmart(wtx); wtx.nTimeSmart = ComputeTimeSmart(wtx);
AddToSpends(hash); AddToSpends(hash);
} }
@ -1019,7 +924,7 @@ void CWallet::LoadToWallet(const CWalletTx& wtxIn)
CWalletTx& wtx = ins.first->second; CWalletTx& wtx = ins.first->second;
wtx.BindWallet(this); wtx.BindWallet(this);
if (/* insertion took place */ ins.second) { if (/* insertion took place */ ins.second) {
wtx.m_it_wtxOrdered = wtxOrdered.insert(std::make_pair(wtx.nOrderPos, TxPair(&wtx, nullptr))); wtx.m_it_wtxOrdered = wtxOrdered.insert(std::make_pair(wtx.nOrderPos, &wtx));
} }
AddToSpends(hash); AddToSpends(hash);
for (const CTxIn& txin : wtx.tx->vin) { for (const CTxIn& txin : wtx.tx->vin) {
@ -1615,12 +1520,11 @@ int CalculateMaximumSignedInputSize(const CTxOut& txout, const CWallet* wallet,
} }
void CWalletTx::GetAmounts(std::list<COutputEntry>& listReceived, void CWalletTx::GetAmounts(std::list<COutputEntry>& listReceived,
std::list<COutputEntry>& listSent, CAmount& nFee, std::string& strSentAccount, const isminefilter& filter) const std::list<COutputEntry>& listSent, CAmount& nFee, const isminefilter& filter) const
{ {
nFee = 0; nFee = 0;
listReceived.clear(); listReceived.clear();
listSent.clear(); listSent.clear();
strSentAccount = strFromAccount;
// Compute fee: // Compute fee:
CAmount nDebit = GetDebit(filter); CAmount nDebit = GetDebit(filter);
@ -2189,7 +2093,7 @@ CAmount CWallet::GetImmatureWatchOnlyBalance() const
// wallet, and then subtracts the values of TxIns spending from the wallet. This // wallet, and then subtracts the values of TxIns spending from the wallet. This
// also has fewer restrictions on which unconfirmed transactions are considered // also has fewer restrictions on which unconfirmed transactions are considered
// trusted. // trusted.
CAmount CWallet::GetLegacyBalance(const isminefilter& filter, int minDepth, const std::string* account) const CAmount CWallet::GetLegacyBalance(const isminefilter& filter, int minDepth) const
{ {
LOCK2(cs_main, cs_wallet); LOCK2(cs_main, cs_wallet);
@ -2208,21 +2112,17 @@ CAmount CWallet::GetLegacyBalance(const isminefilter& filter, int minDepth, cons
for (const CTxOut& out : wtx.tx->vout) { for (const CTxOut& out : wtx.tx->vout) {
if (outgoing && IsChange(out)) { if (outgoing && IsChange(out)) {
debit -= out.nValue; debit -= out.nValue;
} else if (IsMine(out) & filter && depth >= minDepth && (!account || *account == GetLabelName(out.scriptPubKey))) { } else if (IsMine(out) & filter && depth >= minDepth) {
balance += out.nValue; balance += out.nValue;
} }
} }
// For outgoing txs, subtract amount debited. // For outgoing txs, subtract amount debited.
if (outgoing && (!account || *account == wtx.strFromAccount)) { if (outgoing) {
balance -= debit; balance -= debit;
} }
} }
if (account) {
balance += WalletBatch(*database).GetAccountCreditDebit(*account);
}
return balance; return balance;
} }
@ -3054,7 +2954,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
/** /**
* Call after CreateTransaction unless you want to abort * Call after CreateTransaction unless you want to abort
*/ */
bool CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector<std::pair<std::string, std::string>> orderForm, std::string fromAccount, CReserveKey& reservekey, CConnman* connman, CValidationState& state) bool CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector<std::pair<std::string, std::string>> orderForm, CReserveKey& reservekey, CConnman* connman, CValidationState& state)
{ {
{ {
LOCK2(cs_main, cs_wallet); LOCK2(cs_main, cs_wallet);
@ -3062,7 +2962,6 @@ bool CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::ve
CWalletTx wtxNew(this, std::move(tx)); CWalletTx wtxNew(this, std::move(tx));
wtxNew.mapValue = std::move(mapValue); wtxNew.mapValue = std::move(mapValue);
wtxNew.vOrderForm = std::move(orderForm); wtxNew.vOrderForm = std::move(orderForm);
wtxNew.strFromAccount = std::move(fromAccount);
wtxNew.fTimeReceivedIsTxTime = true; wtxNew.fTimeReceivedIsTxTime = true;
wtxNew.fFromMe = true; wtxNew.fFromMe = true;
@ -3102,31 +3001,6 @@ bool CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::ve
return true; return true;
} }
void CWallet::ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& entries) {
WalletBatch batch(*database);
return batch.ListAccountCreditDebit(strAccount, entries);
}
bool CWallet::AddAccountingEntry(const CAccountingEntry& acentry)
{
WalletBatch batch(*database);
return AddAccountingEntry(acentry, &batch);
}
bool CWallet::AddAccountingEntry(const CAccountingEntry& acentry, WalletBatch *batch)
{
if (!batch->WriteAccountingEntry(++nAccountingEntryNumber, acentry)) {
return false;
}
laccentries.push_back(acentry);
CAccountingEntry & entry = laccentries.back();
wtxOrdered.insert(std::make_pair(entry.nOrderPos, TxPair(nullptr, &entry)));
return true;
}
DBErrors CWallet::LoadWallet(bool& fFirstRunRet) DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
{ {
LOCK2(cs_main, cs_wallet); LOCK2(cs_main, cs_wallet);
@ -3660,12 +3534,6 @@ std::set<CTxDestination> CWallet::GetLabelAddresses(const std::string& label) co
return result; return result;
} }
void CWallet::DeleteLabel(const std::string& label)
{
WalletBatch batch(*database);
batch.EraseAccount(label);
}
bool CReserveKey::GetReservedKey(CPubKey& pubkey, bool internal) bool CReserveKey::GetReservedKey(CPubKey& pubkey, bool internal)
{ {
if (nIndex == -1) if (nIndex == -1)
@ -3856,19 +3724,14 @@ unsigned int CWallet::ComputeTimeSmart(const CWalletTx& wtx) const
int64_t latestTolerated = latestNow + 300; int64_t latestTolerated = latestNow + 300;
const TxItems& txOrdered = wtxOrdered; const TxItems& txOrdered = wtxOrdered;
for (auto it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) { for (auto it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) {
CWalletTx* const pwtx = it->second.first; CWalletTx* const pwtx = it->second;
if (pwtx == &wtx) { if (pwtx == &wtx) {
continue; continue;
} }
CAccountingEntry* const pacentry = it->second.second;
int64_t nSmartTime; int64_t nSmartTime;
if (pwtx) { nSmartTime = pwtx->nTimeSmart;
nSmartTime = pwtx->nTimeSmart; if (!nSmartTime) {
if (!nSmartTime) { nSmartTime = pwtx->nTimeReceived;
nSmartTime = pwtx->nTimeReceived;
}
} else {
nSmartTime = pacentry->nTime;
} }
if (nSmartTime <= latestTolerated) { if (nSmartTime <= latestTolerated) {
latestEntry = nSmartTime; latestEntry = nSmartTime;
@ -4313,7 +4176,6 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
copyTo->nTimeReceived = copyFrom->nTimeReceived; copyTo->nTimeReceived = copyFrom->nTimeReceived;
copyTo->nTimeSmart = copyFrom->nTimeSmart; copyTo->nTimeSmart = copyFrom->nTimeSmart;
copyTo->fFromMe = copyFrom->fFromMe; copyTo->fFromMe = copyFrom->fFromMe;
copyTo->strFromAccount = copyFrom->strFromAccount;
copyTo->nOrderPos = copyFrom->nOrderPos; copyTo->nOrderPos = copyFrom->nOrderPos;
batch.WriteTx(*copyTo); batch.WriteTx(*copyTo);
} }

View file

@ -340,9 +340,8 @@ public:
* externally and came in through the network or sendrawtransaction RPC. * externally and came in through the network or sendrawtransaction RPC.
*/ */
char fFromMe; char fFromMe;
std::string strFromAccount;
int64_t nOrderPos; //!< position in ordered transaction list int64_t nOrderPos; //!< position in ordered transaction list
std::multimap<int64_t, std::pair<CWalletTx*, CAccountingEntry*>>::const_iterator m_it_wtxOrdered; std::multimap<int64_t, CWalletTx*>::const_iterator m_it_wtxOrdered;
// memory only // memory only
mutable bool fDebitCached; mutable bool fDebitCached;
@ -379,7 +378,6 @@ public:
nTimeReceived = 0; nTimeReceived = 0;
nTimeSmart = 0; nTimeSmart = 0;
fFromMe = false; fFromMe = false;
strFromAccount.clear();
fDebitCached = false; fDebitCached = false;
fCreditCached = false; fCreditCached = false;
fImmatureCreditCached = false; fImmatureCreditCached = false;
@ -408,7 +406,7 @@ public:
char fSpent = false; char fSpent = false;
mapValue_t mapValueCopy = mapValue; mapValue_t mapValueCopy = mapValue;
mapValueCopy["fromaccount"] = strFromAccount; mapValueCopy["fromaccount"] = "";
WriteOrderPos(nOrderPos, mapValueCopy); WriteOrderPos(nOrderPos, mapValueCopy);
if (nTimeSmart) { if (nTimeSmart) {
mapValueCopy["timesmart"] = strprintf("%u", nTimeSmart); mapValueCopy["timesmart"] = strprintf("%u", nTimeSmart);
@ -429,7 +427,6 @@ public:
std::vector<CMerkleTx> vUnused; //!< Used to be vtxPrev std::vector<CMerkleTx> vUnused; //!< Used to be vtxPrev
s >> vUnused >> mapValue >> vOrderForm >> fTimeReceivedIsTxTime >> nTimeReceived >> fFromMe >> fSpent; s >> vUnused >> mapValue >> vOrderForm >> fTimeReceivedIsTxTime >> nTimeReceived >> fFromMe >> fSpent;
strFromAccount = std::move(mapValue["fromaccount"]);
ReadOrderPos(nOrderPos, mapValue); ReadOrderPos(nOrderPos, mapValue);
nTimeSmart = mapValue.count("timesmart") ? (unsigned int)atoi64(mapValue["timesmart"]) : 0; nTimeSmart = mapValue.count("timesmart") ? (unsigned int)atoi64(mapValue["timesmart"]) : 0;
@ -474,7 +471,7 @@ public:
} }
void GetAmounts(std::list<COutputEntry>& listReceived, void GetAmounts(std::list<COutputEntry>& listReceived,
std::list<COutputEntry>& listSent, CAmount& nFee, std::string& strSentAccount, const isminefilter& filter) const; std::list<COutputEntry>& listSent, CAmount& nFee, const isminefilter& filter) const;
bool IsFromMe(const isminefilter& filter) const bool IsFromMe(const isminefilter& filter) const
{ {
@ -569,89 +566,6 @@ public:
} }
}; };
/**
* DEPRECATED Internal transfers.
* Database key is acentry<account><counter>.
*/
class CAccountingEntry
{
public:
std::string strAccount;
CAmount nCreditDebit;
int64_t nTime;
std::string strOtherAccount;
std::string strComment;
mapValue_t mapValue;
int64_t nOrderPos; //!< position in ordered transaction list
uint64_t nEntryNo;
CAccountingEntry()
{
SetNull();
}
void SetNull()
{
nCreditDebit = 0;
nTime = 0;
strAccount.clear();
strOtherAccount.clear();
strComment.clear();
nOrderPos = -1;
nEntryNo = 0;
}
template <typename Stream>
void Serialize(Stream& s) const {
int nVersion = s.GetVersion();
if (!(s.GetType() & SER_GETHASH)) {
s << nVersion;
}
//! Note: strAccount is serialized as part of the key, not here.
s << nCreditDebit << nTime << strOtherAccount;
mapValue_t mapValueCopy = mapValue;
WriteOrderPos(nOrderPos, mapValueCopy);
std::string strCommentCopy = strComment;
if (!mapValueCopy.empty() || !_ssExtra.empty()) {
CDataStream ss(s.GetType(), s.GetVersion());
ss.insert(ss.begin(), '\0');
ss << mapValueCopy;
ss.insert(ss.end(), _ssExtra.begin(), _ssExtra.end());
strCommentCopy.append(ss.str());
}
s << strCommentCopy;
}
template <typename Stream>
void Unserialize(Stream& s) {
int nVersion = s.GetVersion();
if (!(s.GetType() & SER_GETHASH)) {
s >> nVersion;
}
//! Note: strAccount is serialized as part of the key, not here.
s >> nCreditDebit >> nTime >> LIMITED_STRING(strOtherAccount, 65536) >> LIMITED_STRING(strComment, 65536);
size_t nSepPos = strComment.find("\0", 0, 1);
mapValue.clear();
if (std::string::npos != nSepPos) {
CDataStream ss(std::vector<char>(strComment.begin() + nSepPos + 1, strComment.end()), s.GetType(), s.GetVersion());
ss >> mapValue;
_ssExtra = std::vector<char>(ss.begin(), ss.end());
}
ReadOrderPos(nOrderPos, mapValue);
if (std::string::npos != nSepPos) {
strComment.erase(nSepPos);
}
mapValue.erase("n");
}
private:
std::vector<char> _ssExtra;
};
struct CoinSelectionParams struct CoinSelectionParams
{ {
bool use_bnb = true; bool use_bnb = true;
@ -826,10 +740,8 @@ public:
} }
std::map<uint256, CWalletTx> mapWallet; std::map<uint256, CWalletTx> mapWallet;
std::list<CAccountingEntry> laccentries;
typedef std::pair<CWalletTx*, CAccountingEntry*> TxPair; typedef std::multimap<int64_t, CWalletTx*> TxItems;
typedef std::multimap<int64_t, TxPair > TxItems;
TxItems wtxOrdered; TxItems wtxOrdered;
int64_t nOrderPosNext = 0; int64_t nOrderPosNext = 0;
@ -941,8 +853,6 @@ public:
*/ */
int64_t IncOrderPosNext(WalletBatch *batch = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); int64_t IncOrderPosNext(WalletBatch *batch = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
DBErrors ReorderTransactions(); DBErrors ReorderTransactions();
bool AccountMove(std::string strFrom, std::string strTo, CAmount nAmount, std::string strComment = "") EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool GetLabelDestination(CTxDestination &dest, const std::string& label, bool bForceNew = false);
void MarkDirty(); void MarkDirty();
bool AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose=true); bool AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose=true);
@ -962,7 +872,7 @@ public:
CAmount GetImmatureBalance() const; CAmount GetImmatureBalance() const;
CAmount GetUnconfirmedWatchOnlyBalance() const; CAmount GetUnconfirmedWatchOnlyBalance() const;
CAmount GetImmatureWatchOnlyBalance() const; CAmount GetImmatureWatchOnlyBalance() const;
CAmount GetLegacyBalance(const isminefilter& filter, int minDepth, const std::string* account) const; CAmount GetLegacyBalance(const isminefilter& filter, int minDepth) const;
CAmount GetAvailableBalance(const CCoinControl* coinControl = nullptr) const; CAmount GetAvailableBalance(const CCoinControl* coinControl = nullptr) const;
OutputType TransactionChangeType(OutputType change_type, const std::vector<CRecipient>& vecSend); OutputType TransactionChangeType(OutputType change_type, const std::vector<CRecipient>& vecSend);
@ -981,11 +891,8 @@ public:
*/ */
bool CreateTransaction(const std::vector<CRecipient>& vecSend, CTransactionRef& tx, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosInOut, bool CreateTransaction(const std::vector<CRecipient>& vecSend, CTransactionRef& tx, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosInOut,
std::string& strFailReason, const CCoinControl& coin_control, bool sign = true); std::string& strFailReason, const CCoinControl& coin_control, bool sign = true);
bool CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector<std::pair<std::string, std::string>> orderForm, std::string fromAccount, CReserveKey& reservekey, CConnman* connman, CValidationState& state); bool CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector<std::pair<std::string, std::string>> orderForm, CReserveKey& reservekey, CConnman* connman, CValidationState& state);
void ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& entries);
bool AddAccountingEntry(const CAccountingEntry&);
bool AddAccountingEntry(const CAccountingEntry&, WalletBatch *batch);
bool DummySignTx(CMutableTransaction &txNew, const std::set<CTxOut> &txouts, bool use_max_sig = false) const bool DummySignTx(CMutableTransaction &txNew, const std::set<CTxOut> &txouts, bool use_max_sig = false) const
{ {
std::vector<CTxOut> v_txouts(txouts.size()); std::vector<CTxOut> v_txouts(txouts.size());
@ -1044,7 +951,6 @@ public:
std::map<CTxDestination, CAmount> GetAddressBalances() EXCLUSIVE_LOCKS_REQUIRED(cs_main); std::map<CTxDestination, CAmount> GetAddressBalances() EXCLUSIVE_LOCKS_REQUIRED(cs_main);
std::set<CTxDestination> GetLabelAddresses(const std::string& label) const; std::set<CTxDestination> GetLabelAddresses(const std::string& label) const;
void DeleteLabel(const std::string& label);
isminetype IsMine(const CTxIn& txin) const; isminetype IsMine(const CTxIn& txin) const;
/** /**
@ -1253,37 +1159,6 @@ public:
void KeepScript() override { KeepKey(); } void KeepScript() override { KeepKey(); }
}; };
/**
* DEPRECATED Account information.
* Stored in wallet with key "acc"+string account name.
*/
class CAccount
{
public:
CPubKey vchPubKey;
CAccount()
{
SetNull();
}
void SetNull()
{
vchPubKey = CPubKey();
}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
int nVersion = s.GetVersion();
if (!(s.GetType() & SER_GETHASH))
READWRITE(nVersion);
READWRITE(vchPubKey);
}
};
/** RAII object to check and reserve a wallet rescan */ /** RAII object to check and reserve a wallet rescan */
class WalletRescanReserver class WalletRescanReserver
{ {

View file

@ -17,6 +17,7 @@
#include <wallet/wallet.h> #include <wallet/wallet.h>
#include <atomic> #include <atomic>
#include <string>
#include <boost/thread.hpp> #include <boost/thread.hpp>
@ -150,82 +151,6 @@ bool WalletBatch::WriteMinVersion(int nVersion)
return WriteIC(std::string("minversion"), nVersion); return WriteIC(std::string("minversion"), nVersion);
} }
bool WalletBatch::ReadAccount(const std::string& strAccount, CAccount& account)
{
account.SetNull();
return m_batch.Read(std::make_pair(std::string("acc"), strAccount), account);
}
bool WalletBatch::WriteAccount(const std::string& strAccount, const CAccount& account)
{
return WriteIC(std::make_pair(std::string("acc"), strAccount), account);
}
bool WalletBatch::EraseAccount(const std::string& strAccount)
{
return EraseIC(std::make_pair(std::string("acc"), strAccount));
}
bool WalletBatch::WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccountingEntry& acentry)
{
return WriteIC(std::make_pair(std::string("acentry"), std::make_pair(acentry.strAccount, nAccEntryNum)), acentry);
}
CAmount WalletBatch::GetAccountCreditDebit(const std::string& strAccount)
{
std::list<CAccountingEntry> entries;
ListAccountCreditDebit(strAccount, entries);
CAmount nCreditDebit = 0;
for (const CAccountingEntry& entry : entries)
nCreditDebit += entry.nCreditDebit;
return nCreditDebit;
}
void WalletBatch::ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& entries)
{
bool fAllAccounts = (strAccount == "*");
Dbc* pcursor = m_batch.GetCursor();
if (!pcursor)
throw std::runtime_error(std::string(__func__) + ": cannot create DB cursor");
bool setRange = true;
while (true)
{
// Read next record
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
if (setRange)
ssKey << std::make_pair(std::string("acentry"), std::make_pair((fAllAccounts ? std::string("") : strAccount), uint64_t(0)));
CDataStream ssValue(SER_DISK, CLIENT_VERSION);
int ret = m_batch.ReadAtCursor(pcursor, ssKey, ssValue, setRange);
setRange = false;
if (ret == DB_NOTFOUND)
break;
else if (ret != 0)
{
pcursor->close();
throw std::runtime_error(std::string(__func__) + ": error scanning DB");
}
// Unserialize
std::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();
}
class CWalletScanState { class CWalletScanState {
public: public:
unsigned int nKeys; unsigned int nKeys;
@ -284,9 +209,10 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
{ {
char fTmp; char fTmp;
char fUnused; char fUnused;
ssValue >> fTmp >> fUnused >> wtx.strFromAccount; std::string unused_string;
strErr = strprintf("LoadWallet() upgrading tx ver=%d %d '%s' %s", ssValue >> fTmp >> fUnused >> unused_string;
wtx.fTimeReceivedIsTxTime, fTmp, wtx.strFromAccount, hash.ToString()); strErr = strprintf("LoadWallet() upgrading tx ver=%d %d %s",
wtx.fTimeReceivedIsTxTime, fTmp, hash.ToString());
wtx.fTimeReceivedIsTxTime = fTmp; wtx.fTimeReceivedIsTxTime = fTmp;
} }
else else
@ -302,24 +228,6 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
pwallet->LoadToWallet(wtx); pwallet->LoadToWallet(wtx);
} }
else if (strType == "acentry")
{
std::string strAccount;
ssKey >> strAccount;
uint64_t nNumber;
ssKey >> nNumber;
if (nNumber > pwallet->nAccountingEntryNumber) {
pwallet->nAccountingEntryNumber = nNumber;
}
if (!wss.fAnyUnordered)
{
CAccountingEntry acentry;
ssValue >> acentry;
if (acentry.nOrderPos == -1)
wss.fAnyUnordered = true;
}
}
else if (strType == "watchs") else if (strType == "watchs")
{ {
wss.nWatchKeys++; wss.nWatchKeys++;
@ -510,7 +418,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
return false; return false;
} }
} else if (strType != "bestblock" && strType != "bestblock_nomerkle" && } else if (strType != "bestblock" && strType != "bestblock_nomerkle" &&
strType != "minversion") { strType != "minversion" && strType != "acentry") {
wss.m_unknown_records++; wss.m_unknown_records++;
} }
} catch (...) } catch (...)
@ -625,12 +533,6 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
if (wss.fAnyUnordered) if (wss.fAnyUnordered)
result = pwallet->ReorderTransactions(); result = pwallet->ReorderTransactions();
pwallet->laccentries.clear();
ListAccountCreditDebit("*", pwallet->laccentries);
for (CAccountingEntry& entry : pwallet->laccentries) {
pwallet->wtxOrdered.insert(make_pair(entry.nOrderPos, CWallet::TxPair(nullptr, &entry)));
}
return result; return result;
} }

View file

@ -31,8 +31,6 @@
static const bool DEFAULT_FLUSHWALLET = true; static const bool DEFAULT_FLUSHWALLET = true;
class CAccount;
class CAccountingEntry;
struct CBlockLocator; struct CBlockLocator;
class CKeyPool; class CKeyPool;
class CMasterKey; class CMasterKey;
@ -199,21 +197,11 @@ public:
bool WriteMinVersion(int nVersion); bool WriteMinVersion(int nVersion);
/// This writes directly to the database, and will not update the CWallet's cached accounting entries!
/// Use wallet.AddAccountingEntry instead, to write *and* update its caches.
bool WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccountingEntry& acentry);
bool ReadAccount(const std::string& strAccount, CAccount& account);
bool WriteAccount(const std::string& strAccount, const CAccount& account);
bool EraseAccount(const std::string& strAccount);
/// Write destination data key,value tuple to database /// Write destination data key,value tuple to database
bool WriteDestData(const std::string &address, const std::string &key, const std::string &value); bool WriteDestData(const std::string &address, const std::string &key, const std::string &value);
/// Erase destination data tuple from wallet database /// Erase destination data tuple from wallet database
bool EraseDestData(const std::string &address, const std::string &key); bool EraseDestData(const std::string &address, const std::string &key);
CAmount GetAccountCreditDebit(const std::string& strAccount);
void ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& acentries);
DBErrors LoadWallet(CWallet* pwallet); DBErrors LoadWallet(CWallet* pwallet);
DBErrors FindWalletTx(std::vector<uint256>& vTxHash, std::vector<CWalletTx>& vWtx); DBErrors FindWalletTx(std::vector<uint256>& vTxHash, std::vector<CWalletTx>& vWtx);
DBErrors ZapWalletTx(std::vector<CWalletTx>& vWtx); DBErrors ZapWalletTx(std::vector<CWalletTx>& vWtx);