Skip to content

Commit 2d2814e

Browse files
kwvgUdjinM6
authored andcommitted
merge bitcoin#18766: disable fee estimation in blocksonly mode (by removing the fee estimates global)
1 parent a5f2012 commit 2d2814e

20 files changed

+98
-65
lines changed

src/context.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
class ChainstateManager;
1212
class CTxMemPool;
13+
class CBlockPolicyEstimator;
1314
struct LLMQContext;
1415
struct NodeContext;
1516
struct WalletContext;
@@ -19,6 +20,7 @@ using CoreContext = std::variant<std::nullopt_t,
1920
std::reference_wrapper<WalletContext>,
2021
std::reference_wrapper<CTxMemPool>,
2122
std::reference_wrapper<ChainstateManager>,
23+
std::reference_wrapper<CBlockPolicyEstimator>,
2224
std::reference_wrapper<LLMQContext>>;
2325

2426
template<typename T>

src/init.cpp

Lines changed: 18 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,6 @@
120120
#include <zmq/zmqrpc.h>
121121
#endif
122122

123-
static bool fFeeEstimatesInitialized = false;
124123
static const bool DEFAULT_PROXYRANDOMIZE = true;
125124
static const bool DEFAULT_REST_ENABLE = false;
126125
static const bool DEFAULT_STOPAFTERBLOCKIMPORT = false;
@@ -136,8 +135,6 @@ static CDSNotificationInterface* pdsNotificationInterface = nullptr;
136135
#define MIN_CORE_FILEDESCRIPTORS 150
137136
#endif
138137

139-
static const char* FEE_ESTIMATES_FILENAME="fee_estimates.dat";
140-
141138
static const char* DEFAULT_ASMAP_FILENAME="ip_asn.map";
142139
/**
143140
* The PID file facilities.
@@ -286,17 +283,8 @@ void PrepareShutdown(NodeContext& node)
286283
DumpMempool(*node.mempool);
287284
}
288285

289-
if (fFeeEstimatesInitialized)
290-
{
291-
::feeEstimator.FlushUnconfirmed();
292-
fs::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME;
293-
CAutoFile est_fileout(fsbridge::fopen(est_path, "wb"), SER_DISK, CLIENT_VERSION);
294-
if (!est_fileout.IsNull())
295-
::feeEstimator.Write(est_fileout);
296-
else
297-
LogPrintf("%s: Failed to write fee estimates to %s\n", __func__, est_path.string());
298-
fFeeEstimatesInitialized = false;
299-
}
286+
// Drop transactions we were still watching, and record fee estimations.
287+
if (node.fee_estimator) node.fee_estimator->Flush();
300288

301289
// FlushStateToDisk generates a ChainStateFlushed callback, which we should avoid missing
302290
if (node.chainman) {
@@ -405,6 +393,7 @@ void Shutdown(NodeContext& node)
405393
globalVerifyHandle.reset();
406394
ECC_Stop();
407395
node.mempool.reset();
396+
node.fee_estimator.reset();
408397
node.chainman = nullptr;
409398
node.scheduler.reset();
410399

@@ -1761,11 +1750,21 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
17611750
// is not yet setup and may end up being set up twice if we
17621751
// need to reindex later.
17631752

1753+
// see Step 2: parameter interactions for more information about these
1754+
fListen = args.GetBoolArg("-listen", DEFAULT_LISTEN);
1755+
fDiscover = args.GetBoolArg("-discover", true);
1756+
g_relay_txes = !args.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY);
1757+
17641758
assert(!node.banman);
17651759
node.banman = std::make_unique<BanMan>(GetDataDir() / "banlist.dat", &uiInterface, args.GetArg("-bantime", DEFAULT_MISBEHAVING_BANTIME));
17661760
assert(!node.connman);
17671761
node.connman = std::make_unique<CConnman>(GetRand(std::numeric_limits<uint64_t>::max()), GetRand(std::numeric_limits<uint64_t>::max()));
17681762

1763+
assert(!node.fee_estimator);
1764+
// Don't initialize fee estimation with old data if we don't relay transactions,
1765+
// as they would never get updated.
1766+
if (g_relay_txes) node.fee_estimator = std::make_unique<CBlockPolicyEstimator>();
1767+
17691768
assert(!node.mempool);
17701769
int check_ratio = std::min<int>(std::max<int>(args.GetArg("-checkmempool", chainparams.DefaultConsistencyChecks() ? 1 : 0), 0), 1000000);
17711770
node.mempool = std::make_unique<CTxMemPool>(node.fee_estimator.get(), check_ratio);
@@ -1887,11 +1886,6 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
18871886
}
18881887
}
18891888

1890-
// see Step 2: parameter interactions for more information about these
1891-
fListen = args.GetBoolArg("-listen", DEFAULT_LISTEN);
1892-
fDiscover = args.GetBoolArg("-discover", true);
1893-
g_relay_txes = !args.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY);
1894-
18951889
for (const std::string& strAddr : args.GetArgs("-externalip")) {
18961890
CService addrLocal;
18971891
if (Lookup(strAddr, addrLocal, GetListenPort(), fNameLookup) && addrLocal.IsValid())
@@ -2257,13 +2251,6 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
22572251
return false;
22582252
}
22592253

2260-
fs::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME;
2261-
CAutoFile est_filein(fsbridge::fopen(est_path, "rb"), SER_DISK, CLIENT_VERSION);
2262-
// Allowed to fail as this file IS missing on first startup.
2263-
if (!est_filein.IsNull())
2264-
::feeEstimator.Read(est_filein);
2265-
fFeeEstimatesInitialized = true;
2266-
22672254
// ********************************************************* Step 8: start indexers
22682255
if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {
22692256
g_txindex = std::make_unique<TxIndex>(nTxIndexCache, false, fReindex);
@@ -2318,7 +2305,9 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
23182305

23192306
::coinJoinServer = std::make_unique<CCoinJoinServer>(*node.mempool, *node.connman, ::masternodeSync);
23202307
#ifdef ENABLE_WALLET
2321-
::coinJoinClientQueueManager = std::make_unique<CCoinJoinClientQueueManager>(*node.connman, ::masternodeSync);
2308+
if (g_relay_txes) {
2309+
::coinJoinClientQueueManager = std::make_unique<CCoinJoinClientQueueManager>(*node.connman, ::masternodeSync);
2310+
}
23222311
#endif // ENABLE_WALLET
23232312

23242313
g_wallet_init_interface.InitCoinJoinSettings();
@@ -2389,8 +2378,8 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
23892378
node.scheduler->scheduleEvery(std::bind(&CCoinJoinServer::DoMaintenance, std::ref(*::coinJoinServer)), std::chrono::seconds{1});
23902379
node.scheduler->scheduleEvery(std::bind(&llmq::CDKGSessionManager::CleanupOldContributions, std::ref(*node.llmq_ctx->qdkgsman)), std::chrono::hours{1});
23912380
#ifdef ENABLE_WALLET
2392-
} else if(CCoinJoinClientOptions::IsEnabled()) {
2393-
node.scheduler->scheduleEvery(std::bind(&DoCoinJoinMaintenance, std::ref(*node.connman), std::ref(::feeEstimator), std::ref(*node.mempool)), std::chrono::seconds{1});
2381+
} else if (g_relay_txes && CCoinJoinClientOptions::IsEnabled()) {
2382+
node.scheduler->scheduleEvery(std::bind(&DoCoinJoinMaintenance, std::ref(*node.connman), std::ref(*node.fee_estimator), std::ref(*node.mempool)), std::chrono::seconds{1});
23942383
#endif // ENABLE_WALLET
23952384
}
23962385

src/interfaces/chain.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -312,11 +312,13 @@ class ChainImpl : public Chain
312312
}
313313
CFeeRate estimateSmartFee(int num_blocks, bool conservative, FeeCalculation* calc) override
314314
{
315-
return ::feeEstimator.estimateSmartFee(num_blocks, calc, conservative);
315+
if (!m_node.fee_estimator) return {};
316+
return m_node.fee_estimator->estimateSmartFee(num_blocks, calc, conservative);
316317
}
317318
unsigned int estimateMaxBlocks() override
318319
{
319-
return ::feeEstimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
320+
if (!m_node.fee_estimator) return 0;
321+
return m_node.fee_estimator->HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
320322
}
321323
CFeeRate mempoolMinFee() override
322324
{

src/interfaces/node.cpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -332,15 +332,6 @@ class NodeImpl : public Node
332332
}
333333
}
334334
bool getNetworkActive() override { return m_context->connman && m_context->connman->GetNetworkActive(); }
335-
CFeeRate estimateSmartFee(int num_blocks, bool conservative, int* returned_target = nullptr) override
336-
{
337-
FeeCalculation fee_calc;
338-
CFeeRate result = ::feeEstimator.estimateSmartFee(num_blocks, &fee_calc, conservative);
339-
if (returned_target) {
340-
*returned_target = fee_calc.returnedTarget;
341-
}
342-
return result;
343-
}
344335
CFeeRate getDustRelayFee() override { return ::dustRelayFee; }
345336
UniValue executeRpc(const std::string& command, const UniValue& params, const std::string& uri) override
346337
{

src/interfaces/node.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -253,9 +253,6 @@ class Node
253253
//! Get network active.
254254
virtual bool getNetworkActive() = 0;
255255

256-
//! Estimate smart fee.
257-
virtual CFeeRate estimateSmartFee(int num_blocks, bool conservative, int* returned_target = nullptr) = 0;
258-
259256
//! Get dust relay fee.
260257
virtual CFeeRate getDustRelayFee() = 0;
261258

src/node/context.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <evo/evodb.h>
1111
#include <net.h>
1212
#include <net_processing.h>
13+
#include <policy/fees.h>
1314
#include <scheduler.h>
1415
#include <txmempool.h>
1516

src/node/context.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
class ArgsManager;
1414
class BanMan;
15+
class CBlockPolicyEstimator;
1516
class CConnman;
1617
class CScheduler;
1718
class CTxMemPool;
@@ -38,6 +39,7 @@ class WalletClient;
3839
struct NodeContext {
3940
std::unique_ptr<CConnman> connman;
4041
std::unique_ptr<CTxMemPool> mempool;
42+
std::unique_ptr<CBlockPolicyEstimator> fee_estimator;
4143
std::unique_ptr<PeerLogicValidation> peer_logic;
4244
ChainstateManager* chainman{nullptr}; // Currently a raw pointer because the memory is not managed by this struct
4345
std::unique_ptr<BanMan> banman;

src/policy/fees.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
#include <txmempool.h>
1111
#include <util/system.h>
1212

13+
static const char* FEE_ESTIMATES_FILENAME="fee_estimates.dat";
14+
1315
static constexpr double INF_FEERATE = 1e99;
1416

1517
std::string StringForFeeEstimateHorizon(FeeEstimateHorizon horizon) {
@@ -488,6 +490,7 @@ CBlockPolicyEstimator::CBlockPolicyEstimator()
488490
{
489491
static_assert(MIN_BUCKET_FEERATE > 0, "Min feerate must be nonzero");
490492
size_t bucketIndex = 0;
493+
491494
for (double bucketBoundary = MIN_BUCKET_FEERATE; bucketBoundary <= MAX_BUCKET_FEERATE; bucketBoundary *= FEE_SPACING, bucketIndex++) {
492495
buckets.push_back(bucketBoundary);
493496
bucketMap[bucketBoundary] = bucketIndex;
@@ -499,6 +502,13 @@ CBlockPolicyEstimator::CBlockPolicyEstimator()
499502
feeStats = std::make_unique<TxConfirmStats>(buckets, bucketMap, MED_BLOCK_PERIODS, MED_DECAY, MED_SCALE);
500503
shortStats = std::make_unique<TxConfirmStats>(buckets, bucketMap, SHORT_BLOCK_PERIODS, SHORT_DECAY, SHORT_SCALE);
501504
longStats = std::make_unique<TxConfirmStats>(buckets, bucketMap, LONG_BLOCK_PERIODS, LONG_DECAY, LONG_SCALE);
505+
506+
// If the fee estimation file is present, read recorded estimations
507+
fs::path est_filepath = GetDataDir() / FEE_ESTIMATES_FILENAME;
508+
CAutoFile est_file(fsbridge::fopen(est_filepath, "rb"), SER_DISK, CLIENT_VERSION);
509+
if (est_file.IsNull() || !Read(est_file)) {
510+
LogPrintf("Failed to read fee estimates from %s. Continue anyway.\n", est_filepath.string());
511+
}
502512
}
503513

504514
CBlockPolicyEstimator::~CBlockPolicyEstimator()
@@ -854,6 +864,15 @@ CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, FeeCalculation
854864
return CFeeRate(llround(median));
855865
}
856866

867+
void CBlockPolicyEstimator::Flush() {
868+
FlushUnconfirmed();
869+
870+
fs::path est_filepath = GetDataDir() / FEE_ESTIMATES_FILENAME;
871+
CAutoFile est_file(fsbridge::fopen(est_filepath, "wb"), SER_DISK, CLIENT_VERSION);
872+
if (est_file.IsNull() || !Write(est_file)) {
873+
LogPrintf("Failed to write fee estimates to %s\n", est_filepath.string());
874+
}
875+
}
857876

858877
bool CBlockPolicyEstimator::Write(CAutoFile& fileout) const
859878
{

src/policy/fees.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,9 @@ class CBlockPolicyEstimator
222222
/** Calculation of highest target that estimates are tracked for */
223223
unsigned int HighestTargetTracked(FeeEstimateHorizon horizon) const;
224224

225+
/** Drop still unconfirmed transactions and record current estimations, if the fee estimation file is present. */
226+
void Flush();
227+
225228
private:
226229
mutable CCriticalSection m_cs_fee_estimator;
227230

src/rpc/blockchain.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <node/coinstats.h>
2121
#include <node/context.h>
2222
#include <node/utxo_snapshot.h>
23+
#include <policy/fees.h>
2324
#include <policy/policy.h>
2425
#include <primitives/transaction.h>
2526
#include <rpc/server.h>
@@ -91,6 +92,15 @@ ChainstateManager& EnsureChainman(const CoreContext& context)
9192
return *node.chainman;
9293
}
9394

95+
CBlockPolicyEstimator& EnsureFeeEstimator(const CoreContext& context)
96+
{
97+
NodeContext& node = EnsureNodeContext(context);
98+
if (!node.fee_estimator) {
99+
throw JSONRPCError(RPC_INTERNAL_ERROR, "Fee estimation disabled");
100+
}
101+
return *node.fee_estimator;
102+
}
103+
94104
LLMQContext& EnsureLLMQContext(const CoreContext& context)
95105
{
96106
NodeContext& node = EnsureNodeContext(context);

0 commit comments

Comments
 (0)