Merge #15639: bitcoin-wallet tool: Drop libbitcoin_server.a dependency

78a2fb55c bitcoin-wallet tool: Drop libbitcoin_server.a dependency (Russell Yanofsky)
b874747b5 Remove access to node globals from wallet-linked code (Russell Yanofsky)
fbc6bb8e8 bitcoin-wallet tool: Drop MakeChain calls (Russell Yanofsky)

Pull request description:

  Dropping the `bitcoin-wallet` dependency on `libbitcoin_server.a` ensures wallet code can't access node global state, avoiding bugs like https://github.com/bitcoin/bitcoin/pull/15557#discussion_r267735431

ACKs for commit 78a2fb:
  jnewbery:
    utACK 78a2fb55c9. Nice work, Russ.
  MarcoFalke:
    utACK 78a2fb5
  MeshCollider:
    utACK 78a2fb55c9

Tree-SHA512: ee6ea774f683b936bea66638211dd53c42b8316e1ef03dd58d12fb7ee3891432a43c5c149944173c1e2436aa756b672e1679c39fc10043792ac55cd4d8af2823
This commit is contained in:
MeshCollider 2019-04-11 21:29:33 +12:00
commit c536dfbcb0
No known key found for this signature in database
GPG key ID: D300116E1C875A3D
18 changed files with 89 additions and 47 deletions

View file

@ -593,7 +593,6 @@ endif
bitcoin_wallet_LDADD = \ bitcoin_wallet_LDADD = \
$(LIBBITCOIN_WALLET_TOOL) \ $(LIBBITCOIN_WALLET_TOOL) \
$(LIBBITCOIN_WALLET) \ $(LIBBITCOIN_WALLET) \
$(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_COMMON) \ $(LIBBITCOIN_COMMON) \
$(LIBBITCOIN_CONSENSUS) \ $(LIBBITCOIN_CONSENSUS) \
$(LIBBITCOIN_UTIL) \ $(LIBBITCOIN_UTIL) \

View file

@ -29,7 +29,7 @@ static void addCoin(const CAmount& nValue, const CWallet& wallet, std::vector<st
static void CoinSelection(benchmark::State& state) static void CoinSelection(benchmark::State& state)
{ {
auto chain = interfaces::MakeChain(); auto chain = interfaces::MakeChain();
const CWallet wallet(*chain, WalletLocation(), WalletDatabase::CreateDummy()); const CWallet wallet(chain.get(), WalletLocation(), WalletDatabase::CreateDummy());
std::vector<std::unique_ptr<CWalletTx>> wtxs; std::vector<std::unique_ptr<CWalletTx>> wtxs;
LOCK(wallet.cs_wallet); LOCK(wallet.cs_wallet);
@ -61,7 +61,7 @@ static void CoinSelection(benchmark::State& state)
typedef std::set<CInputCoin> CoinSet; typedef std::set<CInputCoin> CoinSet;
static auto testChain = interfaces::MakeChain(); static auto testChain = interfaces::MakeChain();
static const CWallet testWallet(*testChain, WalletLocation(), WalletDatabase::CreateDummy()); static const CWallet testWallet(testChain.get(), WalletLocation(), WalletDatabase::CreateDummy());
std::vector<std::unique_ptr<CWalletTx>> wtxn; std::vector<std::unique_ptr<CWalletTx>> wtxn;
// Copied from src/wallet/test/coinselector_tests.cpp // Copied from src/wallet/test/coinselector_tests.cpp

View file

@ -363,6 +363,12 @@ public:
{ {
return MakeUnique<RpcHandlerImpl>(command); return MakeUnique<RpcHandlerImpl>(command);
} }
bool rpcEnableDeprecated(const std::string& method) override { return IsDeprecatedRPCEnabled(method); }
void rpcRunLater(const std::string& name, std::function<void()> fn, int64_t seconds) override
{
RPCRunLater(name, std::move(fn), seconds);
}
int rpcSerializationFlags() override { return RPCSerializationFlags(); }
void requestMempoolTransactions(Notifications& notifications) override void requestMempoolTransactions(Notifications& notifications) override
{ {
LOCK2(::cs_main, ::mempool.cs); LOCK2(::cs_main, ::mempool.cs);

View file

@ -57,6 +57,10 @@ class Wallet;
//! notifications to the GUI should go away when GUI and wallet can directly //! notifications to the GUI should go away when GUI and wallet can directly
//! communicate with each other without going through the node //! communicate with each other without going through the node
//! (https://github.com/bitcoin/bitcoin/pull/15288#discussion_r253321096). //! (https://github.com/bitcoin/bitcoin/pull/15288#discussion_r253321096).
//!
//! * The handleRpc, registerRpcs, rpcEnableDeprecated methods and other RPC
//! methods can go away if wallets listen for HTTP requests on their own
//! ports instead of registering to handle requests on the node HTTP port.
class Chain class Chain
{ {
public: public:
@ -274,6 +278,15 @@ public:
//! needs to remain valid until Handler is disconnected. //! needs to remain valid until Handler is disconnected.
virtual std::unique_ptr<Handler> handleRpc(const CRPCCommand& command) = 0; virtual std::unique_ptr<Handler> handleRpc(const CRPCCommand& command) = 0;
//! Check if deprecated RPC is enabled.
virtual bool rpcEnableDeprecated(const std::string& method) = 0;
//! Run function after given number of seconds. Cancel any previous calls with same name.
virtual void rpcRunLater(const std::string& name, std::function<void()> fn, int64_t seconds) = 0;
//! Current RPC serialization flags.
virtual int rpcSerializationFlags() = 0;
//! Synchronously send TransactionAddedToMempool notifications about all //! Synchronously send TransactionAddedToMempool notifications about all
//! current mempool transactions to the specified handler and return after //! current mempool transactions to the specified handler and return after
//! the last one is sent. These notifications aren't coordinated with async //! the last one is sent. These notifications aren't coordinated with async

View file

@ -77,7 +77,7 @@ bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType)
return true; return true;
} }
bool IsStandardTx(const CTransaction& tx, std::string& reason) bool IsStandardTx(const CTransaction& tx, bool permit_bare_multisig, const CFeeRate& dust_relay_fee, std::string& reason)
{ {
if (tx.nVersion > CTransaction::MAX_STANDARD_VERSION || tx.nVersion < 1) { if (tx.nVersion > CTransaction::MAX_STANDARD_VERSION || tx.nVersion < 1) {
reason = "version"; reason = "version";
@ -123,10 +123,10 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason)
if (whichType == TX_NULL_DATA) if (whichType == TX_NULL_DATA)
nDataOut++; nDataOut++;
else if ((whichType == TX_MULTISIG) && (!fIsBareMultisigStd)) { else if ((whichType == TX_MULTISIG) && (!permit_bare_multisig)) {
reason = "bare-multisig"; reason = "bare-multisig";
return false; return false;
} else if (IsDust(txout, ::dustRelayFee)) { } else if (IsDust(txout, dust_relay_fee)) {
reason = "dust"; reason = "dust";
return false; return false;
} }
@ -239,17 +239,17 @@ bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
return true; return true;
} }
int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost) int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost, unsigned int bytes_per_sigop)
{ {
return (std::max(nWeight, nSigOpCost * nBytesPerSigOp) + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR; return (std::max(nWeight, nSigOpCost * bytes_per_sigop) + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR;
} }
int64_t GetVirtualTransactionSize(const CTransaction& tx, int64_t nSigOpCost) int64_t GetVirtualTransactionSize(const CTransaction& tx, int64_t nSigOpCost, unsigned int bytes_per_sigop)
{ {
return GetVirtualTransactionSize(GetTransactionWeight(tx), nSigOpCost); return GetVirtualTransactionSize(GetTransactionWeight(tx), nSigOpCost, bytes_per_sigop);
} }
int64_t GetVirtualTransactionInputSize(const CTxIn& txin, int64_t nSigOpCost) int64_t GetVirtualTransactionInputSize(const CTxIn& txin, int64_t nSigOpCost, unsigned int bytes_per_sigop)
{ {
return GetVirtualTransactionSize(GetTransactionInputWeight(txin), nSigOpCost); return GetVirtualTransactionSize(GetTransactionInputWeight(txin), nSigOpCost, bytes_per_sigop);
} }

View file

@ -86,7 +86,7 @@ bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType);
* Check for standard transaction types * Check for standard transaction types
* @return True if all outputs (scriptPubKeys) use only standard transaction forms * @return True if all outputs (scriptPubKeys) use only standard transaction forms
*/ */
bool IsStandardTx(const CTransaction& tx, std::string& reason); bool IsStandardTx(const CTransaction& tx, bool permit_bare_multisig, const CFeeRate& dust_relay_fee, std::string& reason);
/** /**
* Check for standard transaction types * Check for standard transaction types
* @param[in] mapInputs Map of previous transactions that have outputs we're spending * @param[in] mapInputs Map of previous transactions that have outputs we're spending
@ -101,8 +101,18 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs); bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs);
/** Compute the virtual transaction size (weight reinterpreted as bytes). */ /** Compute the virtual transaction size (weight reinterpreted as bytes). */
int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost); int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost, unsigned int bytes_per_sigop);
int64_t GetVirtualTransactionSize(const CTransaction& tx, int64_t nSigOpCost = 0); int64_t GetVirtualTransactionSize(const CTransaction& tx, int64_t nSigOpCost, unsigned int bytes_per_sigop);
int64_t GetVirtualTransactionInputSize(const CTxIn& tx, int64_t nSigOpCost = 0); int64_t GetVirtualTransactionInputSize(const CTxIn& tx, int64_t nSigOpCost, unsigned int bytes_per_sigop);
static inline int64_t GetVirtualTransactionSize(const CTransaction& tx)
{
return GetVirtualTransactionSize(tx, 0, 0);
}
static inline int64_t GetVirtualTransactionInputSize(const CTxIn& tx)
{
return GetVirtualTransactionInputSize(tx, 0, 0);
}
#endif // BITCOIN_POLICY_POLICY_H #endif // BITCOIN_POLICY_POLICY_H

View file

@ -6,7 +6,10 @@
#ifndef BITCOIN_POLICY_SETTINGS_H #ifndef BITCOIN_POLICY_SETTINGS_H
#define BITCOIN_POLICY_SETTINGS_H #define BITCOIN_POLICY_SETTINGS_H
#include <policy/policy.h>
class CFeeRate; class CFeeRate;
class CTransaction;
// Policy settings which are configurable at runtime. // Policy settings which are configurable at runtime.
extern CFeeRate incrementalRelayFee; extern CFeeRate incrementalRelayFee;
@ -14,4 +17,19 @@ extern CFeeRate dustRelayFee;
extern unsigned int nBytesPerSigOp; extern unsigned int nBytesPerSigOp;
extern bool fIsBareMultisigStd; extern bool fIsBareMultisigStd;
static inline bool IsStandardTx(const CTransaction& tx, std::string& reason)
{
return IsStandardTx(tx, ::fIsBareMultisigStd, ::dustRelayFee, reason);
}
static inline int64_t GetVirtualTransactionSize(int64_t weight, int64_t sigop_cost)
{
return GetVirtualTransactionSize(weight, sigop_cost, ::nBytesPerSigOp);
}
static inline int64_t GetVirtualTransactionSize(const CTransaction& tx, int64_t sigop_cost)
{
return GetVirtualTransactionSize(tx, sigop_cost, ::nBytesPerSigOp);
}
#endif // BITCOIN_POLICY_SETTINGS_H #endif // BITCOIN_POLICY_SETTINGS_H

View file

@ -58,7 +58,7 @@ void TestAddAddressesToSendBook()
{ {
TestChain100Setup test; TestChain100Setup test;
auto chain = interfaces::MakeChain(); auto chain = interfaces::MakeChain();
std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(*chain, WalletLocation(), WalletDatabase::CreateMock()); std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(chain.get(), WalletLocation(), WalletDatabase::CreateMock());
bool firstRun; bool firstRun;
wallet->LoadWallet(firstRun); wallet->LoadWallet(firstRun);

View file

@ -135,7 +135,7 @@ void TestGUI()
test.CreateAndProcessBlock({}, GetScriptForRawPubKey(test.coinbaseKey.GetPubKey())); test.CreateAndProcessBlock({}, GetScriptForRawPubKey(test.coinbaseKey.GetPubKey()));
} }
auto chain = interfaces::MakeChain(); auto chain = interfaces::MakeChain();
std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(*chain, WalletLocation(), WalletDatabase::CreateMock()); std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(chain.get(), WalletLocation(), WalletDatabase::CreateMock());
bool firstRun; bool firstRun;
wallet->LoadWallet(firstRun); wallet->LoadWallet(firstRun);
{ {

View file

@ -19,6 +19,7 @@
#include <node/transaction.h> #include <node/transaction.h>
#include <policy/policy.h> #include <policy/policy.h>
#include <policy/rbf.h> #include <policy/rbf.h>
#include <policy/settings.h>
#include <primitives/transaction.h> #include <primitives/transaction.h>
#include <psbt.h> #include <psbt.h>
#include <rpc/rawtransaction_util.h> #include <rpc/rawtransaction_util.h>

View file

@ -174,7 +174,7 @@ Result CreateTransaction(const CWallet* wallet, const uint256& txid, const CCoin
// This may occur if the user set TotalFee or paytxfee too low, if fallbackfee is too low, or, perhaps, // This may occur if the user set TotalFee or paytxfee too low, if fallbackfee is too low, or, perhaps,
// in a rare situation where the mempool minimum fee increased significantly since the fee estimation just a // in a rare situation where the mempool minimum fee increased significantly since the fee estimation just a
// moment earlier. In this case, we report an error to the user, who may use total_fee to make an adjustment. // moment earlier. In this case, we report an error to the user, who may use total_fee to make an adjustment.
CFeeRate minMempoolFeeRate = mempool.GetMinFee(gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000); CFeeRate minMempoolFeeRate = wallet->chain().mempoolMinFee();
if (nNewFeeRate.GetFeePerK() < minMempoolFeeRate.GetFeePerK()) { if (nNewFeeRate.GetFeePerK() < minMempoolFeeRate.GetFeePerK()) {
errors.push_back(strprintf( errors.push_back(strprintf(
"New fee rate (%s) is lower than the minimum fee rate (%s) to get into the mempool -- " "New fee rate (%s) is lower than the minimum fee rate (%s) to get into the mempool -- "

View file

@ -1756,7 +1756,7 @@ static UniValue gettransaction(const JSONRPCRequest& request)
ListTransactions(*locked_chain, pwallet, wtx, 0, false, details, filter, nullptr /* filter_label */); ListTransactions(*locked_chain, pwallet, wtx, 0, false, details, filter, nullptr /* filter_label */);
entry.pushKV("details", details); entry.pushKV("details", details);
std::string strHex = EncodeHexTx(*wtx.tx, RPCSerializationFlags()); std::string strHex = EncodeHexTx(*wtx.tx, pwallet->chain().rpcSerializationFlags());
entry.pushKV("hex", strHex); entry.pushKV("hex", strHex);
return entry; return entry;
@ -1974,7 +1974,7 @@ static UniValue walletpassphrase(const JSONRPCRequest& request)
// wallet before the following callback is called. If a valid shared pointer // wallet before the following callback is called. If a valid shared pointer
// is acquired in the callback then the wallet is still loaded. // is acquired in the callback then the wallet is still loaded.
std::weak_ptr<CWallet> weak_wallet = wallet; std::weak_ptr<CWallet> weak_wallet = wallet;
RPCRunLater(strprintf("lockwallet(%s)", pwallet->GetName()), [weak_wallet] { pwallet->chain().rpcRunLater(strprintf("lockwallet(%s)", pwallet->GetName()), [weak_wallet] {
if (auto shared_wallet = weak_wallet.lock()) { if (auto shared_wallet = weak_wallet.lock()) {
LOCK(shared_wallet->cs_wallet); LOCK(shared_wallet->cs_wallet);
shared_wallet->Lock(); shared_wallet->Lock();
@ -3471,7 +3471,7 @@ public:
UniValue obj(UniValue::VOBJ); UniValue obj(UniValue::VOBJ);
CScript subscript; CScript subscript;
if (pwallet && pwallet->GetCScript(scriptID, subscript)) { if (pwallet && pwallet->GetCScript(scriptID, subscript)) {
ProcessSubScript(subscript, obj, IsDeprecatedRPCEnabled("validateaddress")); ProcessSubScript(subscript, obj, pwallet->chain().rpcEnableDeprecated("validateaddress"));
} }
return obj; return obj;
} }

View file

@ -29,7 +29,7 @@ typedef std::set<CInputCoin> CoinSet;
static std::vector<COutput> vCoins; static std::vector<COutput> vCoins;
static auto testChain = interfaces::MakeChain(); static auto testChain = interfaces::MakeChain();
static CWallet testWallet(*testChain, WalletLocation(), WalletDatabase::CreateDummy()); static CWallet testWallet(testChain.get(), WalletLocation(), WalletDatabase::CreateDummy());
static CAmount balance = 0; static CAmount balance = 0;
CoinEligibilityFilter filter_standard(1, 6, 0); CoinEligibilityFilter filter_standard(1, 6, 0);

View file

@ -9,7 +9,7 @@
#include <wallet/rpcwallet.h> #include <wallet/rpcwallet.h>
WalletTestingSetup::WalletTestingSetup(const std::string& chainName): WalletTestingSetup::WalletTestingSetup(const std::string& chainName):
TestingSetup(chainName), m_wallet(*m_chain, WalletLocation(), WalletDatabase::CreateMock()) TestingSetup(chainName), m_wallet(m_chain.get(), WalletLocation(), WalletDatabase::CreateMock())
{ {
bool fFirstRun; bool fFirstRun;
m_wallet.LoadWallet(fFirstRun); m_wallet.LoadWallet(fFirstRun);

View file

@ -49,7 +49,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
// Verify ScanForWalletTransactions accommodates a null start block. // Verify ScanForWalletTransactions accommodates a null start block.
{ {
CWallet wallet(*chain, WalletLocation(), WalletDatabase::CreateDummy()); CWallet wallet(chain.get(), WalletLocation(), WalletDatabase::CreateDummy());
AddKey(wallet, coinbaseKey); AddKey(wallet, coinbaseKey);
WalletRescanReserver reserver(&wallet); WalletRescanReserver reserver(&wallet);
reserver.reserve(); reserver.reserve();
@ -64,7 +64,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
// Verify ScanForWalletTransactions picks up transactions in both the old // Verify ScanForWalletTransactions picks up transactions in both the old
// and new block files. // and new block files.
{ {
CWallet wallet(*chain, WalletLocation(), WalletDatabase::CreateDummy()); CWallet wallet(chain.get(), WalletLocation(), WalletDatabase::CreateDummy());
AddKey(wallet, coinbaseKey); AddKey(wallet, coinbaseKey);
WalletRescanReserver reserver(&wallet); WalletRescanReserver reserver(&wallet);
reserver.reserve(); reserver.reserve();
@ -83,7 +83,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
// Verify ScanForWalletTransactions only picks transactions in the new block // Verify ScanForWalletTransactions only picks transactions in the new block
// file. // file.
{ {
CWallet wallet(*chain, WalletLocation(), WalletDatabase::CreateDummy()); CWallet wallet(chain.get(), WalletLocation(), WalletDatabase::CreateDummy());
AddKey(wallet, coinbaseKey); AddKey(wallet, coinbaseKey);
WalletRescanReserver reserver(&wallet); WalletRescanReserver reserver(&wallet);
reserver.reserve(); reserver.reserve();
@ -101,7 +101,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
// Verify ScanForWalletTransactions scans no blocks. // Verify ScanForWalletTransactions scans no blocks.
{ {
CWallet wallet(*chain, WalletLocation(), WalletDatabase::CreateDummy()); CWallet wallet(chain.get(), WalletLocation(), WalletDatabase::CreateDummy());
AddKey(wallet, coinbaseKey); AddKey(wallet, coinbaseKey);
WalletRescanReserver reserver(&wallet); WalletRescanReserver reserver(&wallet);
reserver.reserve(); reserver.reserve();
@ -135,7 +135,7 @@ BOOST_FIXTURE_TEST_CASE(importmulti_rescan, TestChain100Setup)
// before the missing block, and success for a key whose creation time is // before the missing block, and success for a key whose creation time is
// after. // after.
{ {
std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(*chain, WalletLocation(), WalletDatabase::CreateDummy()); std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(chain.get(), WalletLocation(), WalletDatabase::CreateDummy());
AddWallet(wallet); AddWallet(wallet);
UniValue keys; UniValue keys;
keys.setArray(); keys.setArray();
@ -198,7 +198,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
// Import key into wallet and call dumpwallet to create backup file. // Import key into wallet and call dumpwallet to create backup file.
{ {
std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(*chain, WalletLocation(), WalletDatabase::CreateDummy()); std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(chain.get(), WalletLocation(), WalletDatabase::CreateDummy());
LOCK(wallet->cs_wallet); LOCK(wallet->cs_wallet);
wallet->mapKeyMetadata[coinbaseKey.GetPubKey().GetID()].nCreateTime = KEY_TIME; wallet->mapKeyMetadata[coinbaseKey.GetPubKey().GetID()].nCreateTime = KEY_TIME;
wallet->AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey()); wallet->AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey());
@ -214,7 +214,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
// Call importwallet RPC and verify all blocks with timestamps >= BLOCK_TIME // Call importwallet RPC and verify all blocks with timestamps >= BLOCK_TIME
// were scanned, and no prior blocks were scanned. // were scanned, and no prior blocks were scanned.
{ {
std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(*chain, WalletLocation(), WalletDatabase::CreateDummy()); std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(chain.get(), WalletLocation(), WalletDatabase::CreateDummy());
JSONRPCRequest request; JSONRPCRequest request;
request.params.setArray(); request.params.setArray();
@ -245,7 +245,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
BOOST_FIXTURE_TEST_CASE(coin_mark_dirty_immature_credit, TestChain100Setup) BOOST_FIXTURE_TEST_CASE(coin_mark_dirty_immature_credit, TestChain100Setup)
{ {
auto chain = interfaces::MakeChain(); auto chain = interfaces::MakeChain();
CWallet wallet(*chain, WalletLocation(), WalletDatabase::CreateDummy()); CWallet wallet(chain.get(), WalletLocation(), WalletDatabase::CreateDummy());
CWalletTx wtx(&wallet, m_coinbase_txns.back()); CWalletTx wtx(&wallet, m_coinbase_txns.back());
auto locked_chain = chain->lock(); auto locked_chain = chain->lock();
LOCK(wallet.cs_wallet); LOCK(wallet.cs_wallet);
@ -340,7 +340,7 @@ public:
ListCoinsTestingSetup() ListCoinsTestingSetup()
{ {
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())); CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
wallet = MakeUnique<CWallet>(*m_chain, WalletLocation(), WalletDatabase::CreateMock()); wallet = MakeUnique<CWallet>(m_chain.get(), WalletLocation(), WalletDatabase::CreateMock());
bool firstRun; bool firstRun;
wallet->LoadWallet(firstRun); wallet->LoadWallet(firstRun);
AddKey(*wallet, coinbaseKey); AddKey(*wallet, coinbaseKey);
@ -451,7 +451,7 @@ BOOST_FIXTURE_TEST_CASE(ListCoins, ListCoinsTestingSetup)
BOOST_FIXTURE_TEST_CASE(wallet_disableprivkeys, TestChain100Setup) BOOST_FIXTURE_TEST_CASE(wallet_disableprivkeys, TestChain100Setup)
{ {
auto chain = interfaces::MakeChain(); auto chain = interfaces::MakeChain();
std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(*chain, WalletLocation(), WalletDatabase::CreateDummy()); std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(chain.get(), WalletLocation(), WalletDatabase::CreateDummy());
wallet->SetMinVersion(FEATURE_LATEST); wallet->SetMinVersion(FEATURE_LATEST);
wallet->SetWalletFlag(WALLET_FLAG_DISABLE_PRIVATE_KEYS); wallet->SetWalletFlag(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
BOOST_CHECK(!wallet->TopUpKeyPool(1000)); BOOST_CHECK(!wallet->TopUpKeyPool(1000));

View file

@ -1287,7 +1287,6 @@ void CWallet::UpdatedBlockTip()
void CWallet::BlockUntilSyncedToCurrentChain() { void CWallet::BlockUntilSyncedToCurrentChain() {
AssertLockNotHeld(cs_main);
AssertLockNotHeld(cs_wallet); AssertLockNotHeld(cs_wallet);
{ {
@ -3117,7 +3116,6 @@ bool CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::ve
DBErrors CWallet::LoadWallet(bool& fFirstRunRet) DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
{ {
auto locked_chain = chain().lock();
LOCK(cs_wallet); LOCK(cs_wallet);
fFirstRunRet = false; fFirstRunRet = false;
@ -3981,7 +3979,7 @@ bool CWallet::Verify(interfaces::Chain& chain, const WalletLocation& location, b
if (salvage_wallet) { if (salvage_wallet) {
// Recover readable keypairs: // Recover readable keypairs:
CWallet dummyWallet(chain, WalletLocation(), WalletDatabase::CreateDummy()); CWallet dummyWallet(&chain, WalletLocation(), WalletDatabase::CreateDummy());
std::string backup_filename; std::string backup_filename;
if (!WalletBatch::Recover(wallet_path, (void *)&dummyWallet, WalletBatch::RecoverKeysOnlyFilter, backup_filename)) { if (!WalletBatch::Recover(wallet_path, (void *)&dummyWallet, WalletBatch::RecoverKeysOnlyFilter, backup_filename)) {
return false; return false;
@ -4001,7 +3999,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
if (gArgs.GetBoolArg("-zapwallettxes", false)) { if (gArgs.GetBoolArg("-zapwallettxes", false)) {
chain.initMessage(_("Zapping all transactions from wallet...")); chain.initMessage(_("Zapping all transactions from wallet..."));
std::unique_ptr<CWallet> tempWallet = MakeUnique<CWallet>(chain, location, WalletDatabase::Create(location.GetPath())); std::unique_ptr<CWallet> tempWallet = MakeUnique<CWallet>(&chain, location, WalletDatabase::Create(location.GetPath()));
DBErrors nZapWalletRet = tempWallet->ZapWalletTx(vWtx); DBErrors nZapWalletRet = tempWallet->ZapWalletTx(vWtx);
if (nZapWalletRet != DBErrors::LOAD_OK) { if (nZapWalletRet != DBErrors::LOAD_OK) {
chain.initError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile)); chain.initError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile));
@ -4015,7 +4013,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
bool fFirstRun = true; bool fFirstRun = true;
// TODO: Can't use std::make_shared because we need a custom deleter but // TODO: Can't use std::make_shared because we need a custom deleter but
// should be possible to use std::allocate_shared. // should be possible to use std::allocate_shared.
std::shared_ptr<CWallet> walletInstance(new CWallet(chain, location, WalletDatabase::Create(location.GetPath())), ReleaseWallet); std::shared_ptr<CWallet> walletInstance(new CWallet(&chain, location, WalletDatabase::Create(location.GetPath())), ReleaseWallet);
DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun); DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun);
if (nLoadWalletRet != DBErrors::LOAD_OK) if (nLoadWalletRet != DBErrors::LOAD_OK)
{ {

View file

@ -704,7 +704,7 @@ private:
bool AddWatchOnly(const CScript& dest) override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); bool AddWatchOnly(const CScript& dest) override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/** Interface for accessing chain state. */ /** Interface for accessing chain state. */
interfaces::Chain& m_chain; interfaces::Chain* m_chain;
/** Wallet location which includes wallet name (see WalletLocation). */ /** Wallet location which includes wallet name (see WalletLocation). */
WalletLocation m_location; WalletLocation m_location;
@ -767,7 +767,7 @@ public:
unsigned int nMasterKeyMaxID = 0; unsigned int nMasterKeyMaxID = 0;
/** Construct wallet with specified name and database implementation. */ /** Construct wallet with specified name and database implementation. */
CWallet(interfaces::Chain& chain, const WalletLocation& location, std::unique_ptr<WalletDatabase> database) : m_chain(chain), m_location(location), database(std::move(database)) CWallet(interfaces::Chain* chain, const WalletLocation& location, std::unique_ptr<WalletDatabase> database) : m_chain(chain), m_location(location), database(std::move(database))
{ {
} }
@ -795,7 +795,7 @@ public:
std::unique_ptr<interfaces::Handler> m_chain_notifications_handler; std::unique_ptr<interfaces::Handler> m_chain_notifications_handler;
/** Interface for accessing chain state. */ /** Interface for accessing chain state. */
interfaces::Chain& chain() const { return m_chain; } interfaces::Chain& chain() const { assert(m_chain); return *m_chain; }
const CWalletTx* GetWalletTx(const uint256& hash) const; const CWalletTx* GetWalletTx(const uint256& hash) const;

View file

@ -4,7 +4,6 @@
#include <base58.h> #include <base58.h>
#include <fs.h> #include <fs.h>
#include <interfaces/chain.h>
#include <util/system.h> #include <util/system.h>
#include <wallet/wallet.h> #include <wallet/wallet.h>
#include <wallet/walletutil.h> #include <wallet/walletutil.h>
@ -28,8 +27,7 @@ static std::shared_ptr<CWallet> CreateWallet(const std::string& name, const fs::
return nullptr; return nullptr;
} }
// dummy chain interface // dummy chain interface
auto chain = interfaces::MakeChain(); std::shared_ptr<CWallet> wallet_instance(new CWallet(nullptr /* chain */, WalletLocation(name), WalletDatabase::Create(path)), WalletToolReleaseWallet);
std::shared_ptr<CWallet> wallet_instance(new CWallet(*chain, WalletLocation(name), WalletDatabase::Create(path)), WalletToolReleaseWallet);
bool first_run = true; bool first_run = true;
DBErrors load_wallet_ret = wallet_instance->LoadWallet(first_run); DBErrors load_wallet_ret = wallet_instance->LoadWallet(first_run);
if (load_wallet_ret != DBErrors::LOAD_OK) { if (load_wallet_ret != DBErrors::LOAD_OK) {
@ -56,8 +54,7 @@ static std::shared_ptr<CWallet> LoadWallet(const std::string& name, const fs::pa
} }
// dummy chain interface // dummy chain interface
auto chain = interfaces::MakeChain(); std::shared_ptr<CWallet> wallet_instance(new CWallet(nullptr /* chain */, WalletLocation(name), WalletDatabase::Create(path)), WalletToolReleaseWallet);
std::shared_ptr<CWallet> wallet_instance(new CWallet(*chain, WalletLocation(name), WalletDatabase::Create(path)), WalletToolReleaseWallet);
DBErrors load_wallet_ret; DBErrors load_wallet_ret;
try { try {
bool first_run; bool first_run;