diff options
Diffstat (limited to 'src/wallet/wallet.cpp')
-rw-r--r-- | src/wallet/wallet.cpp | 304 |
1 files changed, 174 insertions, 130 deletions
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index dbc1760c80..8c392434fc 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -8,11 +8,9 @@ #include <checkpoints.h> #include <chain.h> #include <wallet/coincontrol.h> -#include <wallet/coinselection.h> #include <consensus/consensus.h> #include <consensus/validation.h> #include <fs.h> -#include <wallet/init.h> #include <key.h> #include <key_io.h> #include <keystore.h> @@ -27,16 +25,53 @@ #include <scheduler.h> #include <timedata.h> #include <txmempool.h> -#include <util.h> #include <utilmoneystr.h> #include <wallet/fees.h> +#include <algorithm> #include <assert.h> #include <future> #include <boost/algorithm/string/replace.hpp> -std::vector<CWalletRef> vpwallets; +static std::vector<CWallet*> vpwallets; + +bool AddWallet(CWallet* wallet) +{ + assert(wallet); + std::vector<CWallet*>::const_iterator i = std::find(vpwallets.begin(), vpwallets.end(), wallet); + if (i != vpwallets.end()) return false; + vpwallets.push_back(wallet); + return true; +} + +bool RemoveWallet(CWallet* wallet) +{ + assert(wallet); + std::vector<CWallet*>::iterator i = std::find(vpwallets.begin(), vpwallets.end(), wallet); + if (i == vpwallets.end()) return false; + vpwallets.erase(i); + return true; +} + +bool HasWallets() +{ + return !vpwallets.empty(); +} + +std::vector<CWallet*> GetWallets() +{ + return vpwallets; +} + +CWallet* GetWallet(const std::string& name) +{ + for (CWallet* wallet : vpwallets) { + if (wallet->GetName() == name) return wallet; + } + return nullptr; +} + /** Transaction fee set by the user */ CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE); unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET; @@ -132,7 +167,7 @@ const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const return &(it->second); } -CPubKey CWallet::GenerateNewKey(CWalletDB &walletdb, bool internal) +CPubKey CWallet::GenerateNewKey(WalletBatch &batch, bool internal) { AssertLockHeld(cs_wallet); // mapKeyMetadata bool fCompressed = CanSupportFeature(FEATURE_COMPRPUBKEY); // default to compressed public keys if we want 0.6.0 wallets @@ -145,7 +180,7 @@ CPubKey CWallet::GenerateNewKey(CWalletDB &walletdb, bool internal) // use HD key derivation if HD was enabled during wallet creation if (IsHDEnabled()) { - DeriveNewChildKey(walletdb, metadata, secret, (CanSupportFeature(FEATURE_HD_SPLIT) ? internal : false)); + DeriveNewChildKey(batch, metadata, secret, (CanSupportFeature(FEATURE_HD_SPLIT) ? internal : false)); } else { secret.MakeNewKey(fCompressed); } @@ -161,13 +196,13 @@ CPubKey CWallet::GenerateNewKey(CWalletDB &walletdb, bool internal) mapKeyMetadata[pubkey.GetID()] = metadata; UpdateTimeFirstKey(nCreationTime); - if (!AddKeyPubKeyWithDB(walletdb, secret, pubkey)) { + if (!AddKeyPubKeyWithDB(batch, secret, pubkey)) { throw std::runtime_error(std::string(__func__) + ": AddKey failed"); } return pubkey; } -void CWallet::DeriveNewChildKey(CWalletDB &walletdb, CKeyMetadata& metadata, CKey& secret, bool internal) +void CWallet::DeriveNewChildKey(WalletBatch &batch, CKeyMetadata& metadata, CKey& secret, bool internal) { // for now we use a fixed keypath scheme of m/0'/0'/k CKey key; //master key seed (256bit) @@ -209,26 +244,26 @@ void CWallet::DeriveNewChildKey(CWalletDB &walletdb, CKeyMetadata& metadata, CKe secret = childKey.key; metadata.hdMasterKeyID = hdChain.masterKeyID; // update the chain model in the database - if (!walletdb.WriteHDChain(hdChain)) + if (!batch.WriteHDChain(hdChain)) throw std::runtime_error(std::string(__func__) + ": Writing HD chain model failed"); } -bool CWallet::AddKeyPubKeyWithDB(CWalletDB &walletdb, const CKey& secret, const CPubKey &pubkey) +bool CWallet::AddKeyPubKeyWithDB(WalletBatch &batch, const CKey& secret, const CPubKey &pubkey) { AssertLockHeld(cs_wallet); // mapKeyMetadata // CCryptoKeyStore has no concept of wallet databases, but calls AddCryptedKey // which is overridden below. To avoid flushes, the database handle is // tunneled through to it. - bool needsDB = !pwalletdbEncryption; + bool needsDB = !encrypted_batch; if (needsDB) { - pwalletdbEncryption = &walletdb; + encrypted_batch = &batch; } if (!CCryptoKeyStore::AddKeyPubKey(secret, pubkey)) { - if (needsDB) pwalletdbEncryption = nullptr; + if (needsDB) encrypted_batch = nullptr; return false; } - if (needsDB) pwalletdbEncryption = nullptr; + if (needsDB) encrypted_batch = nullptr; // check if we need to remove from watch-only CScript script; @@ -242,7 +277,7 @@ bool CWallet::AddKeyPubKeyWithDB(CWalletDB &walletdb, const CKey& secret, const } if (!IsCrypted()) { - return walletdb.WriteKey(pubkey, + return batch.WriteKey(pubkey, secret.GetPrivKey(), mapKeyMetadata[pubkey.GetID()]); } @@ -251,8 +286,8 @@ bool CWallet::AddKeyPubKeyWithDB(CWalletDB &walletdb, const CKey& secret, const bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey) { - CWalletDB walletdb(*dbw); - return CWallet::AddKeyPubKeyWithDB(walletdb, secret, pubkey); + WalletBatch batch(*database); + return CWallet::AddKeyPubKeyWithDB(batch, secret, pubkey); } bool CWallet::AddCryptedKey(const CPubKey &vchPubKey, @@ -262,12 +297,12 @@ bool CWallet::AddCryptedKey(const CPubKey &vchPubKey, return false; { LOCK(cs_wallet); - if (pwalletdbEncryption) - return pwalletdbEncryption->WriteCryptedKey(vchPubKey, + if (encrypted_batch) + return encrypted_batch->WriteCryptedKey(vchPubKey, vchCryptedSecret, mapKeyMetadata[vchPubKey.GetID()]); else - return CWalletDB(*dbw).WriteCryptedKey(vchPubKey, + return WalletBatch(*database).WriteCryptedKey(vchPubKey, vchCryptedSecret, mapKeyMetadata[vchPubKey.GetID()]); } @@ -314,7 +349,7 @@ bool CWallet::AddCScript(const CScript& redeemScript) { if (!CCryptoKeyStore::AddCScript(redeemScript)) return false; - return CWalletDB(*dbw).WriteCScript(Hash160(redeemScript), redeemScript); + return WalletBatch(*database).WriteCScript(Hash160(redeemScript), redeemScript); } bool CWallet::LoadCScript(const CScript& redeemScript) @@ -340,7 +375,7 @@ bool CWallet::AddWatchOnly(const CScript& dest) const CKeyMetadata& meta = m_script_metadata[CScriptID(dest)]; UpdateTimeFirstKey(meta.nCreateTime); NotifyWatchonlyChanged(true); - return CWalletDB(*dbw).WriteWatchOnly(dest, meta); + return WalletBatch(*database).WriteWatchOnly(dest, meta); } bool CWallet::AddWatchOnly(const CScript& dest, int64_t nCreateTime) @@ -356,7 +391,7 @@ bool CWallet::RemoveWatchOnly(const CScript &dest) return false; if (!HaveWatchOnly()) NotifyWatchonlyChanged(false); - if (!CWalletDB(*dbw).EraseWatchOnly(dest)) + if (!WalletBatch(*database).EraseWatchOnly(dest)) return false; return true; @@ -422,7 +457,7 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, return false; if (!crypter.Encrypt(_vMasterKey, pMasterKey.second.vchCryptedKey)) return false; - CWalletDB(*dbw).WriteMasterKey(pMasterKey.first, pMasterKey.second); + WalletBatch(*database).WriteMasterKey(pMasterKey.first, pMasterKey.second); if (fWasLocked) Lock(); return true; @@ -435,11 +470,11 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, void CWallet::SetBestChain(const CBlockLocator& loc) { - CWalletDB walletdb(*dbw); - walletdb.WriteBestBlock(loc); + WalletBatch batch(*database); + batch.WriteBestBlock(loc); } -bool CWallet::SetMinVersion(enum WalletFeature nVersion, CWalletDB* pwalletdbIn, bool fExplicit) +bool CWallet::SetMinVersion(enum WalletFeature nVersion, WalletBatch* batch_in, bool fExplicit) { LOCK(cs_wallet); // nWalletVersion if (nWalletVersion >= nVersion) @@ -455,11 +490,11 @@ bool CWallet::SetMinVersion(enum WalletFeature nVersion, CWalletDB* pwalletdbIn, nWalletMaxVersion = nVersion; { - CWalletDB* pwalletdb = pwalletdbIn ? pwalletdbIn : new CWalletDB(*dbw); + WalletBatch* batch = batch_in ? batch_in : new WalletBatch(*database); if (nWalletVersion > 40000) - pwalletdb->WriteMinVersion(nWalletVersion); - if (!pwalletdbIn) - delete pwalletdb; + batch->WriteMinVersion(nWalletVersion); + if (!batch_in) + delete batch; } return true; @@ -509,7 +544,7 @@ bool CWallet::HasWalletSpend(const uint256& txid) const void CWallet::Flush(bool shutdown) { - dbw->Flush(shutdown); + database->Flush(shutdown); } void CWallet::SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator> range) @@ -632,36 +667,36 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) { LOCK(cs_wallet); mapMasterKeys[++nMasterKeyMaxID] = kMasterKey; - assert(!pwalletdbEncryption); - pwalletdbEncryption = new CWalletDB(*dbw); - if (!pwalletdbEncryption->TxnBegin()) { - delete pwalletdbEncryption; - pwalletdbEncryption = nullptr; + assert(!encrypted_batch); + encrypted_batch = new WalletBatch(*database); + if (!encrypted_batch->TxnBegin()) { + delete encrypted_batch; + encrypted_batch = nullptr; return false; } - pwalletdbEncryption->WriteMasterKey(nMasterKeyMaxID, kMasterKey); + encrypted_batch->WriteMasterKey(nMasterKeyMaxID, kMasterKey); if (!EncryptKeys(_vMasterKey)) { - pwalletdbEncryption->TxnAbort(); - delete pwalletdbEncryption; + encrypted_batch->TxnAbort(); + delete encrypted_batch; // We now probably have half of our keys encrypted in memory, and half not... // die and let the user reload the unencrypted wallet. assert(false); } // Encryption was introduced in version 0.4.0 - SetMinVersion(FEATURE_WALLETCRYPT, pwalletdbEncryption, true); + SetMinVersion(FEATURE_WALLETCRYPT, encrypted_batch, true); - if (!pwalletdbEncryption->TxnCommit()) { - delete pwalletdbEncryption; + if (!encrypted_batch->TxnCommit()) { + delete encrypted_batch; // We now have keys encrypted in memory, but not on disk... // die to avoid confusion and let the user reload the unencrypted wallet. assert(false); } - delete pwalletdbEncryption; - pwalletdbEncryption = nullptr; + delete encrypted_batch; + encrypted_batch = nullptr; Lock(); Unlock(strWalletPassphrase); @@ -678,7 +713,7 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) // Need to completely rewrite the wallet file; if we don't, bdb might keep // bits of the unencrypted private key in slack space in the database file. - dbw->Rewrite(); + database->Rewrite(); } NotifyStatusChanged(this); @@ -689,7 +724,7 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) DBErrors CWallet::ReorderTransactions() { LOCK(cs_wallet); - CWalletDB walletdb(*dbw); + WalletBatch batch(*database); // Old wallets didn't have any defined order for transactions // Probably a bad idea to change the output of this @@ -705,7 +740,7 @@ DBErrors CWallet::ReorderTransactions() txByTime.insert(std::make_pair(wtx->nTimeReceived, TxPair(wtx, nullptr))); } std::list<CAccountingEntry> acentries; - walletdb.ListAccountCreditDebit("", acentries); + batch.ListAccountCreditDebit("", acentries); for (CAccountingEntry& entry : acentries) { txByTime.insert(std::make_pair(entry.nTime, TxPair(nullptr, &entry))); @@ -726,11 +761,11 @@ DBErrors CWallet::ReorderTransactions() if (pwtx) { - if (!walletdb.WriteTx(*pwtx)) + if (!batch.WriteTx(*pwtx)) return DBErrors::LOAD_FAIL; } else - if (!walletdb.WriteAccountingEntry(pacentry->nEntryNo, *pacentry)) + if (!batch.WriteAccountingEntry(pacentry->nEntryNo, *pacentry)) return DBErrors::LOAD_FAIL; } else @@ -750,60 +785,60 @@ DBErrors CWallet::ReorderTransactions() // Since we're changing the order, write it back if (pwtx) { - if (!walletdb.WriteTx(*pwtx)) + if (!batch.WriteTx(*pwtx)) return DBErrors::LOAD_FAIL; } else - if (!walletdb.WriteAccountingEntry(pacentry->nEntryNo, *pacentry)) + if (!batch.WriteAccountingEntry(pacentry->nEntryNo, *pacentry)) return DBErrors::LOAD_FAIL; } } - walletdb.WriteOrderPosNext(nOrderPosNext); + batch.WriteOrderPosNext(nOrderPosNext); return DBErrors::LOAD_OK; } -int64_t CWallet::IncOrderPosNext(CWalletDB *pwalletdb) +int64_t CWallet::IncOrderPosNext(WalletBatch *batch) { AssertLockHeld(cs_wallet); // nOrderPosNext int64_t nRet = nOrderPosNext++; - if (pwalletdb) { - pwalletdb->WriteOrderPosNext(nOrderPosNext); + if (batch) { + batch->WriteOrderPosNext(nOrderPosNext); } else { - CWalletDB(*dbw).WriteOrderPosNext(nOrderPosNext); + WalletBatch(*database).WriteOrderPosNext(nOrderPosNext); } return nRet; } bool CWallet::AccountMove(std::string strFrom, std::string strTo, CAmount nAmount, std::string strComment) { - CWalletDB walletdb(*dbw); - if (!walletdb.TxnBegin()) + WalletBatch batch(*database); + if (!batch.TxnBegin()) return false; int64_t nNow = GetAdjustedTime(); // Debit CAccountingEntry debit; - debit.nOrderPos = IncOrderPosNext(&walletdb); + debit.nOrderPos = IncOrderPosNext(&batch); debit.strAccount = strFrom; debit.nCreditDebit = -nAmount; debit.nTime = nNow; debit.strOtherAccount = strTo; debit.strComment = strComment; - AddAccountingEntry(debit, &walletdb); + AddAccountingEntry(debit, &batch); // Credit CAccountingEntry credit; - credit.nOrderPos = IncOrderPosNext(&walletdb); + credit.nOrderPos = IncOrderPosNext(&batch); credit.strAccount = strTo; credit.nCreditDebit = nAmount; credit.nTime = nNow; credit.strOtherAccount = strFrom; credit.strComment = strComment; - AddAccountingEntry(credit, &walletdb); + AddAccountingEntry(credit, &batch); - if (!walletdb.TxnCommit()) + if (!batch.TxnCommit()) return false; return true; @@ -811,10 +846,10 @@ bool CWallet::AccountMove(std::string strFrom, std::string strTo, CAmount nAmoun bool CWallet::GetLabelDestination(CTxDestination &dest, const std::string& label, bool bForceNew) { - CWalletDB walletdb(*dbw); + WalletBatch batch(*database); CAccount account; - walletdb.ReadAccount(label, account); + batch.ReadAccount(label, account); if (!bForceNew) { if (!account.vchPubKey.IsValid()) @@ -841,7 +876,7 @@ bool CWallet::GetLabelDestination(CTxDestination &dest, const std::string& label LearnRelatedScripts(account.vchPubKey, m_default_address_type); dest = GetDestinationForKey(account.vchPubKey, m_default_address_type); SetAddressBook(dest, label, "receive"); - walletdb.WriteAccount(label, account); + batch.WriteAccount(label, account); } else { dest = GetDestinationForKey(account.vchPubKey, m_default_address_type); } @@ -874,11 +909,11 @@ bool CWallet::MarkReplaced(const uint256& originalHash, const uint256& newHash) wtx.mapValue["replaced_by_txid"] = newHash.ToString(); - CWalletDB walletdb(*dbw, "r+"); + WalletBatch batch(*database, "r+"); bool success = true; - if (!walletdb.WriteTx(wtx)) { - LogPrintf("%s: Updating walletdb tx %s failed\n", __func__, wtx.GetHash().ToString()); + if (!batch.WriteTx(wtx)) { + LogPrintf("%s: Updating batch tx %s failed\n", __func__, wtx.GetHash().ToString()); success = false; } @@ -891,7 +926,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose) { LOCK(cs_wallet); - CWalletDB walletdb(*dbw, "r+", fFlushOnClose); + WalletBatch batch(*database, "r+", fFlushOnClose); uint256 hash = wtxIn.GetHash(); @@ -903,7 +938,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose) if (fInsertedNew) { wtx.nTimeReceived = GetAdjustedTime(); - wtx.nOrderPos = IncOrderPosNext(&walletdb); + wtx.nOrderPos = IncOrderPosNext(&batch); wtxOrdered.insert(std::make_pair(wtx.nOrderPos, TxPair(&wtx, nullptr))); wtx.nTimeSmart = ComputeTimeSmart(wtx); AddToSpends(hash); @@ -950,7 +985,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose) // Write to disk if (fInsertedNew || fUpdated) - if (!walletdb.WriteTx(wtx)) + if (!batch.WriteTx(wtx)) return false; // Break debit/credit balance caches: @@ -1075,7 +1110,7 @@ bool CWallet::AbandonTransaction(const uint256& hashTx) { LOCK2(cs_main, cs_wallet); - CWalletDB walletdb(*dbw, "r+"); + WalletBatch batch(*database, "r+"); std::set<uint256> todo; std::set<uint256> done; @@ -1107,7 +1142,7 @@ bool CWallet::AbandonTransaction(const uint256& hashTx) wtx.nIndex = -1; wtx.setAbandoned(); wtx.MarkDirty(); - walletdb.WriteTx(wtx); + batch.WriteTx(wtx); NotifyTransactionChanged(this, wtx.GetHash(), CT_UPDATED); // Iterate over all its outputs, and mark transactions in the wallet that spend them abandoned too TxSpends::const_iterator iter = mapTxSpends.lower_bound(COutPoint(hashTx, 0)); @@ -1149,7 +1184,7 @@ void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx) return; // Do not flush the wallet here for performance reasons - CWalletDB walletdb(*dbw, "r+", false); + WalletBatch batch(*database, "r+", false); std::set<uint256> todo; std::set<uint256> done; @@ -1170,7 +1205,7 @@ void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx) wtx.nIndex = -1; wtx.hashBlock = hashBlock; wtx.MarkDirty(); - walletdb.WriteTx(wtx); + batch.WriteTx(wtx); // Iterate over all its outputs, and mark transactions in the wallet that spend them conflicted too TxSpends::const_iterator iter = mapTxSpends.lower_bound(COutPoint(now, 0)); while (iter != mapTxSpends.end() && iter->first.hash == now) { @@ -1474,7 +1509,7 @@ bool CWallet::SetHDMasterKey(const CPubKey& pubkey) bool CWallet::SetHDChain(const CHDChain& chain, bool memonly) { LOCK(cs_wallet); - if (!memonly && !CWalletDB(*dbw).WriteHDChain(chain)) + if (!memonly && !WalletBatch(*database).WriteHDChain(chain)) throw std::runtime_error(std::string(__func__) + ": writing chain failed"); hdChain = chain; @@ -1538,7 +1573,7 @@ bool CWallet::DummySignInput(CTxIn &tx_in, const CTxOut &txout) const const CScript& scriptPubKey = txout.scriptPubKey; SignatureData sigdata; - if (!ProduceSignature(DummySignatureCreator(this), scriptPubKey, sigdata)) + if (!ProduceSignature(*this, DUMMY_SIGNATURE_CREATOR, scriptPubKey, sigdata)) { return false; } else { @@ -1717,6 +1752,9 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, CBlock CBlockIndex* pindex = pindexStart; CBlockIndex* ret = nullptr; + + if (pindex) LogPrintf("Rescan started from block %d...\n", pindex->nHeight); + { fAbortRescan = false; ShowProgress(_("Rescanning..."), 0); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup @@ -2232,7 +2270,7 @@ CAmount CWallet::GetLegacyBalance(const isminefilter& filter, int minDepth, cons } if (account) { - balance += CWalletDB(*dbw).GetAccountCreditDebit(*account); + balance += WalletBatch(*database).GetAccountCreditDebit(*account); } return balance; @@ -2582,7 +2620,7 @@ bool CWallet::SignTransaction(CMutableTransaction &tx) const CScript& scriptPubKey = mi->second.tx->vout[input.prevout.n].scriptPubKey; const CAmount& amount = mi->second.tx->vout[input.prevout.n].nValue; SignatureData sigdata; - if (!ProduceSignature(TransactionSignatureCreator(this, &txNewConst, nIn, amount, SIGHASH_ALL), scriptPubKey, sigdata)) { + if (!ProduceSignature(*this, TransactionSignatureCreator(&txNewConst, nIn, amount, SIGHASH_ALL), scriptPubKey, sigdata)) { return false; } UpdateTransaction(tx, nIn, sigdata); @@ -3011,7 +3049,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac const CScript& scriptPubKey = coin.txout.scriptPubKey; SignatureData sigdata; - if (!ProduceSignature(TransactionSignatureCreator(this, &txNewConst, nIn, coin.txout.nValue, SIGHASH_ALL), scriptPubKey, sigdata)) + if (!ProduceSignature(*this, TransactionSignatureCreator(&txNewConst, nIn, coin.txout.nValue, SIGHASH_ALL), scriptPubKey, sigdata)) { strFailReason = _("Signing transaction failed"); return false; @@ -3076,7 +3114,7 @@ bool CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::ve wtxNew.fTimeReceivedIsTxTime = true; wtxNew.fFromMe = true; - LogPrintf("CommitTransaction:\n%s", wtxNew.tx->ToString()); + LogPrintf("CommitTransaction:\n%s", wtxNew.tx->ToString()); /* Continued */ { // Take key pair from key pool so it won't be used again reservekey.KeepKey(); @@ -3116,20 +3154,20 @@ bool CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::ve } void CWallet::ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& entries) { - CWalletDB walletdb(*dbw); - return walletdb.ListAccountCreditDebit(strAccount, entries); + WalletBatch batch(*database); + return batch.ListAccountCreditDebit(strAccount, entries); } bool CWallet::AddAccountingEntry(const CAccountingEntry& acentry) { - CWalletDB walletdb(*dbw); + WalletBatch batch(*database); - return AddAccountingEntry(acentry, &walletdb); + return AddAccountingEntry(acentry, &batch); } -bool CWallet::AddAccountingEntry(const CAccountingEntry& acentry, CWalletDB *pwalletdb) +bool CWallet::AddAccountingEntry(const CAccountingEntry& acentry, WalletBatch *batch) { - if (!pwalletdb->WriteAccountingEntry(++nAccountingEntryNumber, acentry)) { + if (!batch->WriteAccountingEntry(++nAccountingEntryNumber, acentry)) { return false; } @@ -3145,10 +3183,10 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet) LOCK2(cs_main, cs_wallet); fFirstRunRet = false; - DBErrors nLoadWalletRet = CWalletDB(*dbw,"cr+").LoadWallet(this); + DBErrors nLoadWalletRet = WalletBatch(*database,"cr+").LoadWallet(this); if (nLoadWalletRet == DBErrors::NEED_REWRITE) { - if (dbw->Rewrite("\x04pool")) + if (database->Rewrite("\x04pool")) { setInternalKeyPool.clear(); setExternalKeyPool.clear(); @@ -3173,13 +3211,13 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet) DBErrors CWallet::ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256>& vHashOut) { AssertLockHeld(cs_wallet); // mapWallet - DBErrors nZapSelectTxRet = CWalletDB(*dbw,"cr+").ZapSelectTx(vHashIn, vHashOut); + DBErrors nZapSelectTxRet = WalletBatch(*database,"cr+").ZapSelectTx(vHashIn, vHashOut); for (uint256 hash : vHashOut) mapWallet.erase(hash); if (nZapSelectTxRet == DBErrors::NEED_REWRITE) { - if (dbw->Rewrite("\x04pool")) + if (database->Rewrite("\x04pool")) { setInternalKeyPool.clear(); setExternalKeyPool.clear(); @@ -3201,10 +3239,10 @@ DBErrors CWallet::ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256 DBErrors CWallet::ZapWalletTx(std::vector<CWalletTx>& vWtx) { - DBErrors nZapWalletTxRet = CWalletDB(*dbw,"cr+").ZapWalletTx(vWtx); + DBErrors nZapWalletTxRet = WalletBatch(*database,"cr+").ZapWalletTx(vWtx); if (nZapWalletTxRet == DBErrors::NEED_REWRITE) { - if (dbw->Rewrite("\x04pool")) + if (database->Rewrite("\x04pool")) { LOCK(cs_wallet); setInternalKeyPool.clear(); @@ -3236,9 +3274,9 @@ bool CWallet::SetAddressBook(const CTxDestination& address, const std::string& s } NotifyAddressBookChanged(this, address, strName, ::IsMine(*this, address) != ISMINE_NO, strPurpose, (fUpdated ? CT_UPDATED : CT_NEW) ); - if (!strPurpose.empty() && !CWalletDB(*dbw).WritePurpose(EncodeDestination(address), strPurpose)) + if (!strPurpose.empty() && !WalletBatch(*database).WritePurpose(EncodeDestination(address), strPurpose)) return false; - return CWalletDB(*dbw).WriteName(EncodeDestination(address), strName); + return WalletBatch(*database).WriteName(EncodeDestination(address), strName); } bool CWallet::DelAddressBook(const CTxDestination& address) @@ -3250,15 +3288,15 @@ bool CWallet::DelAddressBook(const CTxDestination& address) std::string strAddress = EncodeDestination(address); for (const std::pair<std::string, std::string> &item : mapAddressBook[address].destdata) { - CWalletDB(*dbw).EraseDestData(strAddress, item.first); + WalletBatch(*database).EraseDestData(strAddress, item.first); } mapAddressBook.erase(address); } NotifyAddressBookChanged(this, address, "", ::IsMine(*this, address) != ISMINE_NO, "", CT_DELETED); - CWalletDB(*dbw).ErasePurpose(EncodeDestination(address)); - return CWalletDB(*dbw).EraseName(EncodeDestination(address)); + WalletBatch(*database).ErasePurpose(EncodeDestination(address)); + return WalletBatch(*database).EraseName(EncodeDestination(address)); } const std::string& CWallet::GetLabelName(const CScript& scriptPubKey) const @@ -3284,15 +3322,15 @@ bool CWallet::NewKeyPool() { { LOCK(cs_wallet); - CWalletDB walletdb(*dbw); + WalletBatch batch(*database); for (int64_t nIndex : setInternalKeyPool) { - walletdb.ErasePool(nIndex); + batch.ErasePool(nIndex); } setInternalKeyPool.clear(); for (int64_t nIndex : setExternalKeyPool) { - walletdb.ErasePool(nIndex); + batch.ErasePool(nIndex); } setExternalKeyPool.clear(); @@ -3357,7 +3395,7 @@ bool CWallet::TopUpKeyPool(unsigned int kpSize) missingInternal = 0; } bool internal = false; - CWalletDB walletdb(*dbw); + WalletBatch batch(*database); for (int64_t i = missingInternal + missingExternal; i--;) { if (i < missingInternal) { @@ -3367,8 +3405,8 @@ bool CWallet::TopUpKeyPool(unsigned int kpSize) assert(m_max_keypool_index < std::numeric_limits<int64_t>::max()); // How in the hell did you use so many keys? int64_t index = ++m_max_keypool_index; - CPubKey pubkey(GenerateNewKey(walletdb, internal)); - if (!walletdb.WritePool(index, CKeyPool(pubkey, internal))) { + CPubKey pubkey(GenerateNewKey(batch, internal)); + if (!batch.WritePool(index, CKeyPool(pubkey, internal))) { throw std::runtime_error(std::string(__func__) + ": writing generated key failed"); } @@ -3403,12 +3441,12 @@ void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRe if(setKeyPool.empty()) return; - CWalletDB walletdb(*dbw); + WalletBatch batch(*database); auto it = setKeyPool.begin(); nIndex = *it; setKeyPool.erase(it); - if (!walletdb.ReadPool(nIndex, keypool)) { + if (!batch.ReadPool(nIndex, keypool)) { throw std::runtime_error(std::string(__func__) + ": read failed"); } if (!HaveKey(keypool.vchPubKey.GetID())) { @@ -3427,8 +3465,8 @@ void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRe void CWallet::KeepKey(int64_t nIndex) { // Remove from key pool - CWalletDB walletdb(*dbw); - walletdb.ErasePool(nIndex); + WalletBatch batch(*database); + batch.ErasePool(nIndex); LogPrintf("keypool keep %d\n", nIndex); } @@ -3457,8 +3495,8 @@ bool CWallet::GetKeyFromPool(CPubKey& result, bool internal) if (nIndex == -1) { if (IsLocked()) return false; - CWalletDB walletdb(*dbw); - result = GenerateNewKey(walletdb, internal); + WalletBatch batch(*database); + result = GenerateNewKey(batch, internal); return true; } KeepKey(nIndex); @@ -3467,14 +3505,14 @@ bool CWallet::GetKeyFromPool(CPubKey& result, bool internal) return true; } -static int64_t GetOldestKeyTimeInPool(const std::set<int64_t>& setKeyPool, CWalletDB& walletdb) { +static int64_t GetOldestKeyTimeInPool(const std::set<int64_t>& setKeyPool, WalletBatch& batch) { if (setKeyPool.empty()) { return GetTime(); } CKeyPool keypool; int64_t nIndex = *(setKeyPool.begin()); - if (!walletdb.ReadPool(nIndex, keypool)) { + if (!batch.ReadPool(nIndex, keypool)) { throw std::runtime_error(std::string(__func__) + ": read oldest key in keypool failed"); } assert(keypool.vchPubKey.IsValid()); @@ -3485,12 +3523,12 @@ int64_t CWallet::GetOldestKeyPoolTime() { LOCK(cs_wallet); - CWalletDB walletdb(*dbw); + WalletBatch batch(*database); // load oldest key from keypool, get time and return - int64_t oldestKey = GetOldestKeyTimeInPool(setExternalKeyPool, walletdb); + int64_t oldestKey = GetOldestKeyTimeInPool(setExternalKeyPool, batch); if (IsHDEnabled() && CanSupportFeature(FEATURE_HD_SPLIT)) { - oldestKey = std::max(GetOldestKeyTimeInPool(setInternalKeyPool, walletdb), oldestKey); + oldestKey = std::max(GetOldestKeyTimeInPool(setInternalKeyPool, batch), oldestKey); } return oldestKey; @@ -3643,6 +3681,12 @@ std::set<CTxDestination> CWallet::GetLabelAddresses(const std::string& label) co return result; } +void CWallet::DeleteLabel(const std::string& label) +{ + WalletBatch batch(*database); + batch.EraseAccount(label); +} + bool CReserveKey::GetReservedKey(CPubKey& pubkey, bool internal) { if (nIndex == -1) @@ -3686,17 +3730,17 @@ void CWallet::MarkReserveKeysAsUsed(int64_t keypool_id) std::set<int64_t> *setKeyPool = internal ? &setInternalKeyPool : &setExternalKeyPool; auto it = setKeyPool->begin(); - CWalletDB walletdb(*dbw); + WalletBatch batch(*database); while (it != std::end(*setKeyPool)) { const int64_t& index = *(it); if (index > keypool_id) break; // set*KeyPool is ordered CKeyPool keypool; - if (walletdb.ReadPool(index, keypool)) { //TODO: This should be unnecessary + if (batch.ReadPool(index, keypool)) { //TODO: This should be unnecessary m_pool_key_to_index.erase(keypool.vchPubKey.GetID()); } LearnAllRelatedScripts(keypool.vchPubKey); - walletdb.ErasePool(index); + batch.ErasePool(index); LogPrintf("keypool index %d removed\n", index); it = setKeyPool->erase(it); } @@ -3873,14 +3917,14 @@ bool CWallet::AddDestData(const CTxDestination &dest, const std::string &key, co return false; mapAddressBook[dest].destdata.insert(std::make_pair(key, value)); - return CWalletDB(*dbw).WriteDestData(EncodeDestination(dest), key, value); + return WalletBatch(*database).WriteDestData(EncodeDestination(dest), key, value); } bool CWallet::EraseDestData(const CTxDestination &dest, const std::string &key) { if (!mapAddressBook[dest].destdata.erase(key)) return false; - return CWalletDB(*dbw).EraseDestData(EncodeDestination(dest), key); + return WalletBatch(*database).EraseDestData(EncodeDestination(dest), key); } bool CWallet::LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value) @@ -3929,7 +3973,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path& if (gArgs.GetBoolArg("-zapwallettxes", false)) { uiInterface.InitMessage(_("Zapping all transactions from wallet...")); - std::unique_ptr<CWallet> tempWallet = MakeUnique<CWallet>(name, CWalletDBWrapper::Create(path)); + std::unique_ptr<CWallet> tempWallet = MakeUnique<CWallet>(name, WalletDatabase::Create(path)); DBErrors nZapWalletRet = tempWallet->ZapWalletTx(vWtx); if (nZapWalletRet != DBErrors::LOAD_OK) { InitError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile)); @@ -3941,7 +3985,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path& int64_t nStart = GetTimeMillis(); bool fFirstRun = true; - CWallet *walletInstance = new CWallet(name, CWalletDBWrapper::Create(path)); + CWallet *walletInstance = new CWallet(name, WalletDatabase::Create(path)); DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun); if (nLoadWalletRet != DBErrors::LOAD_OK) { @@ -4046,9 +4090,9 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path& CBlockIndex *pindexRescan = chainActive.Genesis(); if (!gArgs.GetBoolArg("-rescan", false)) { - CWalletDB walletdb(*walletInstance->dbw); + WalletBatch batch(*walletInstance->database); CBlockLocator locator; - if (walletdb.ReadBestBlock(locator)) + if (batch.ReadBestBlock(locator)) pindexRescan = FindForkInGlobalIndex(chainActive, locator); } @@ -4092,12 +4136,12 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path& } LogPrintf(" rescan %15dms\n", GetTimeMillis() - nStart); walletInstance->SetBestChain(chainActive.GetLocator()); - walletInstance->dbw->IncrementUpdateCounter(); + walletInstance->database->IncrementUpdateCounter(); // Restore wallet transaction metadata after -zapwallettxes=1 if (gArgs.GetBoolArg("-zapwallettxes", false) && gArgs.GetArg("-zapwallettxes", "1") != "2") { - CWalletDB walletdb(*walletInstance->dbw); + WalletBatch batch(*walletInstance->database); for (const CWalletTx& wtxOld : vWtx) { @@ -4114,7 +4158,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path& copyTo->fFromMe = copyFrom->fFromMe; copyTo->strFromAccount = copyFrom->strFromAccount; copyTo->nOrderPos = copyFrom->nOrderPos; - walletdb.WriteTx(*copyTo); + batch.WriteTx(*copyTo); } } } @@ -4147,7 +4191,7 @@ void CWallet::postInitProcess(CScheduler& scheduler) bool CWallet::BackupWallet(const std::string& strDest) { - return dbw->Backup(strDest); + return database->Backup(strDest); } CKeyPool::CKeyPool() |