Skip to content

Commit b874747

Browse files
committed
Remove access to node globals from wallet-linked code
Remove last few instances of accesses to node global variables from wallet code. Also remove accesses to node globals from code in policy/policy.cpp that isn't actually called by wallet code, but does get linked into wallet code. This is the last change needed to allow bitcoin-wallet tool to be linked without depending on libbitcoin_server.a, to ensure wallet code doesn't access node global state and avoid bugs like bitcoin/bitcoin#15557 (comment)
1 parent fbc6bb8 commit b874747

File tree

9 files changed

+65
-18
lines changed

9 files changed

+65
-18
lines changed

src/interfaces/chain.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,12 @@ class ChainImpl : public Chain
363363
{
364364
return MakeUnique<RpcHandlerImpl>(command);
365365
}
366+
bool rpcEnableDeprecated(const std::string& method) override { return IsDeprecatedRPCEnabled(method); }
367+
void rpcRunLater(const std::string& name, std::function<void()> fn, int64_t seconds) override
368+
{
369+
RPCRunLater(name, std::move(fn), seconds);
370+
}
371+
int rpcSerializationFlags() override { return RPCSerializationFlags(); }
366372
void requestMempoolTransactions(Notifications& notifications) override
367373
{
368374
LOCK2(::cs_main, ::mempool.cs);

src/interfaces/chain.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ class Wallet;
5757
//! notifications to the GUI should go away when GUI and wallet can directly
5858
//! communicate with each other without going through the node
5959
//! (https://github.com/bitcoin/bitcoin/pull/15288#discussion_r253321096).
60+
//!
61+
//! * The handleRpc, registerRpcs, rpcEnableDeprecated methods and other RPC
62+
//! methods can go away if wallets listen for HTTP requests on their own
63+
//! ports instead of registering to handle requests on the node HTTP port.
6064
class Chain
6165
{
6266
public:
@@ -274,6 +278,15 @@ class Chain
274278
//! needs to remain valid until Handler is disconnected.
275279
virtual std::unique_ptr<Handler> handleRpc(const CRPCCommand& command) = 0;
276280

281+
//! Check if deprecated RPC is enabled.
282+
virtual bool rpcEnableDeprecated(const std::string& method) = 0;
283+
284+
//! Run function after given number of seconds. Cancel any previous calls with same name.
285+
virtual void rpcRunLater(const std::string& name, std::function<void()> fn, int64_t seconds) = 0;
286+
287+
//! Current RPC serialization flags.
288+
virtual int rpcSerializationFlags() = 0;
289+
277290
//! Synchronously send TransactionAddedToMempool notifications about all
278291
//! current mempool transactions to the specified handler and return after
279292
//! the last one is sent. These notifications aren't coordinated with async

src/policy/policy.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType)
7777
return true;
7878
}
7979

80-
bool IsStandardTx(const CTransaction& tx, std::string& reason)
80+
bool IsStandardTx(const CTransaction& tx, bool permit_bare_multisig, const CFeeRate& dust_relay_fee, std::string& reason)
8181
{
8282
if (tx.nVersion > CTransaction::MAX_STANDARD_VERSION || tx.nVersion < 1) {
8383
reason = "version";
@@ -123,10 +123,10 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason)
123123

124124
if (whichType == TX_NULL_DATA)
125125
nDataOut++;
126-
else if ((whichType == TX_MULTISIG) && (!fIsBareMultisigStd)) {
126+
else if ((whichType == TX_MULTISIG) && (!permit_bare_multisig)) {
127127
reason = "bare-multisig";
128128
return false;
129-
} else if (IsDust(txout, ::dustRelayFee)) {
129+
} else if (IsDust(txout, dust_relay_fee)) {
130130
reason = "dust";
131131
return false;
132132
}
@@ -239,17 +239,17 @@ bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
239239
return true;
240240
}
241241

242-
int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost)
242+
int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost, unsigned int bytes_per_sigop)
243243
{
244-
return (std::max(nWeight, nSigOpCost * nBytesPerSigOp) + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR;
244+
return (std::max(nWeight, nSigOpCost * bytes_per_sigop) + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR;
245245
}
246246

247-
int64_t GetVirtualTransactionSize(const CTransaction& tx, int64_t nSigOpCost)
247+
int64_t GetVirtualTransactionSize(const CTransaction& tx, int64_t nSigOpCost, unsigned int bytes_per_sigop)
248248
{
249-
return GetVirtualTransactionSize(GetTransactionWeight(tx), nSigOpCost);
249+
return GetVirtualTransactionSize(GetTransactionWeight(tx), nSigOpCost, bytes_per_sigop);
250250
}
251251

252-
int64_t GetVirtualTransactionInputSize(const CTxIn& txin, int64_t nSigOpCost)
252+
int64_t GetVirtualTransactionInputSize(const CTxIn& txin, int64_t nSigOpCost, unsigned int bytes_per_sigop)
253253
{
254-
return GetVirtualTransactionSize(GetTransactionInputWeight(txin), nSigOpCost);
254+
return GetVirtualTransactionSize(GetTransactionInputWeight(txin), nSigOpCost, bytes_per_sigop);
255255
}

src/policy/policy.h

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType);
8686
* Check for standard transaction types
8787
* @return True if all outputs (scriptPubKeys) use only standard transaction forms
8888
*/
89-
bool IsStandardTx(const CTransaction& tx, std::string& reason);
89+
bool IsStandardTx(const CTransaction& tx, bool permit_bare_multisig, const CFeeRate& dust_relay_fee, std::string& reason);
9090
/**
9191
* Check for standard transaction types
9292
* @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)
101101
bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs);
102102

103103
/** Compute the virtual transaction size (weight reinterpreted as bytes). */
104-
int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost);
105-
int64_t GetVirtualTransactionSize(const CTransaction& tx, int64_t nSigOpCost = 0);
106-
int64_t GetVirtualTransactionInputSize(const CTxIn& tx, int64_t nSigOpCost = 0);
104+
int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost, unsigned int bytes_per_sigop);
105+
int64_t GetVirtualTransactionSize(const CTransaction& tx, int64_t nSigOpCost, unsigned int bytes_per_sigop);
106+
int64_t GetVirtualTransactionInputSize(const CTxIn& tx, int64_t nSigOpCost, unsigned int bytes_per_sigop);
107+
108+
static inline int64_t GetVirtualTransactionSize(const CTransaction& tx)
109+
{
110+
return GetVirtualTransactionSize(tx, 0, 0);
111+
}
112+
113+
static inline int64_t GetVirtualTransactionInputSize(const CTxIn& tx)
114+
{
115+
return GetVirtualTransactionInputSize(tx, 0, 0);
116+
}
107117

108118
#endif // BITCOIN_POLICY_POLICY_H

src/policy/settings.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,30 @@
66
#ifndef BITCOIN_POLICY_SETTINGS_H
77
#define BITCOIN_POLICY_SETTINGS_H
88

9+
#include <policy/policy.h>
10+
911
class CFeeRate;
12+
class CTransaction;
1013

1114
// Policy settings which are configurable at runtime.
1215
extern CFeeRate incrementalRelayFee;
1316
extern CFeeRate dustRelayFee;
1417
extern unsigned int nBytesPerSigOp;
1518
extern bool fIsBareMultisigStd;
1619

20+
static inline bool IsStandardTx(const CTransaction& tx, std::string& reason)
21+
{
22+
return IsStandardTx(tx, ::fIsBareMultisigStd, ::dustRelayFee, reason);
23+
}
24+
25+
static inline int64_t GetVirtualTransactionSize(int64_t weight, int64_t sigop_cost)
26+
{
27+
return GetVirtualTransactionSize(weight, sigop_cost, ::nBytesPerSigOp);
28+
}
29+
30+
static inline int64_t GetVirtualTransactionSize(const CTransaction& tx, int64_t sigop_cost)
31+
{
32+
return GetVirtualTransactionSize(tx, sigop_cost, ::nBytesPerSigOp);
33+
}
34+
1735
#endif // BITCOIN_POLICY_SETTINGS_H

src/rpc/rawtransaction.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <node/transaction.h>
2020
#include <policy/policy.h>
2121
#include <policy/rbf.h>
22+
#include <policy/settings.h>
2223
#include <primitives/transaction.h>
2324
#include <psbt.h>
2425
#include <rpc/rawtransaction_util.h>

src/wallet/feebumper.cpp

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

src/wallet/rpcwallet.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1756,7 +1756,7 @@ static UniValue gettransaction(const JSONRPCRequest& request)
17561756
ListTransactions(*locked_chain, pwallet, wtx, 0, false, details, filter, nullptr /* filter_label */);
17571757
entry.pushKV("details", details);
17581758

1759-
std::string strHex = EncodeHexTx(*wtx.tx, RPCSerializationFlags());
1759+
std::string strHex = EncodeHexTx(*wtx.tx, pwallet->chain().rpcSerializationFlags());
17601760
entry.pushKV("hex", strHex);
17611761

17621762
return entry;
@@ -1974,7 +1974,7 @@ static UniValue walletpassphrase(const JSONRPCRequest& request)
19741974
// wallet before the following callback is called. If a valid shared pointer
19751975
// is acquired in the callback then the wallet is still loaded.
19761976
std::weak_ptr<CWallet> weak_wallet = wallet;
1977-
RPCRunLater(strprintf("lockwallet(%s)", pwallet->GetName()), [weak_wallet] {
1977+
pwallet->chain().rpcRunLater(strprintf("lockwallet(%s)", pwallet->GetName()), [weak_wallet] {
19781978
if (auto shared_wallet = weak_wallet.lock()) {
19791979
LOCK(shared_wallet->cs_wallet);
19801980
shared_wallet->Lock();
@@ -3471,7 +3471,7 @@ class DescribeWalletAddressVisitor : public boost::static_visitor<UniValue>
34713471
UniValue obj(UniValue::VOBJ);
34723472
CScript subscript;
34733473
if (pwallet && pwallet->GetCScript(scriptID, subscript)) {
3474-
ProcessSubScript(subscript, obj, IsDeprecatedRPCEnabled("validateaddress"));
3474+
ProcessSubScript(subscript, obj, pwallet->chain().rpcEnableDeprecated("validateaddress"));
34753475
}
34763476
return obj;
34773477
}

src/wallet/wallet.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1287,7 +1287,6 @@ void CWallet::UpdatedBlockTip()
12871287

12881288

12891289
void CWallet::BlockUntilSyncedToCurrentChain() {
1290-
AssertLockNotHeld(cs_main);
12911290
AssertLockNotHeld(cs_wallet);
12921291

12931292
{

0 commit comments

Comments
 (0)