This change is good because:
- It moves module-specific init-logic out of the bloated init.cpp
- It removes a global from validation.cpp and places it into the data structure that needs it (mempool)
This change is good because:
Approach ACK
<!--e57a25ab6845829454e8d69fc972939a-->
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.
<!--174a7506f384e20aa4161008e828411d-->
Reviewers, this pull request conflicts with the following ones:
MemPoolBypass by w0xlt)interpreter.cpp by david-bakin)If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.
Concept ACK
Approach ACK
MemPoolOptions seems like the correct place to put these things since full_rbf is already there.
I would put ::incrementalRelayFee, ::minRelayFee, dustRelayFee, fIsBareMultisigStd in the same boat (sorry for scope creep, probably for a future PR).
35 | @@ -33,6 +36,9 @@ struct MemPoolOptions { 36 | int check_ratio{0}; 37 | int64_t max_size_bytes{DEFAULT_MAX_MEMPOOL_SIZE_MB * 1'000'000}; 38 | std::chrono::seconds expiry{std::chrono::hours{DEFAULT_MEMPOOL_EXPIRY_HOURS}}; 39 | + CFeeRate incremental_relay_fee{DEFAULT_INCREMENTAL_RELAY_FEE}; 40 | + /** A fee rate smaller than this is considered zero fee (for relaying, mining and transaction creation) */ 41 | + CFeeRate min_relay_fee{DEFAULT_MIN_RELAY_TX_FEE};
Since you're renaming, I suggest calling them feerates instead of fees. For min relay, incremental, and dust
Thx, done
sorry for scope creep, probably for a future PR
Thx, all done here
Nice! Concept ACK.
19 | @@ -16,7 +20,7 @@ struct MemPoolOptions; 20 | * @param[in] argsman The ArgsManager in which to check set options. 21 | * @param[in,out] mempool_opts The MemPoolOptions to modify according to \p argsman. 22 | */ 23 | -void ApplyArgsManOptions(const ArgsManager& argsman, kernel::MemPoolOptions& mempool_opts); 24 | +std::optional<bilingual_str> ApplyArgsManOptions(const ArgsManager& argsman, const CChainParams& chainparams, kernel::MemPoolOptions& mempool_opts);
nit in fad91bf9a97d62a11a419fda7654107a54454f86
Add documentation to doxygen comment?
Thx, done
840 | @@ -840,7 +841,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws) 841 | return state.Invalid(TxValidationResult::TX_NOT_STANDARD, "bad-txns-too-many-sigops", 842 | strprintf("%d", nSigOpsCost)); 843 | 844 | - // No individual transactions are allowed below minRelayTxFee and mempool min fee except from 845 | + // No individual transactions are allowed below the min relay fee and mempool min fee except from
nit in 2222644eb37da606e1eeabeda78007b687889de6
// No individual transactions are allowed below the min relay feerate and mempool min feerate except from
Thx, done
744 | @@ -745,7 +745,6 @@ BOOST_AUTO_TEST_CASE(test_witness) 745 | 746 | BOOST_AUTO_TEST_CASE(test_IsStandard) 747 | { 748 | - LOCK(cs_main);
not unused as of fa3cc7457c. probably should squash this commit into fa89b895f3, or move it after?
Can you explain how it is used?
oh oops, I thought dustRelayFee needed it for some reason
123 | CTxMemPool::Options mempool_opts{MemPoolOptionsForTest(node)};
124 |
125 | // ...override specific options for this specific fuzz suite
126 | mempool_opts.estimator = nullptr;
127 | mempool_opts.check_ratio = 1;
128 | + mempool_opts.require_standard = fuzzed_data_provider.ConsumeBool();
in fa3b8a8d7dddbb6fcf51ac447acc0b1c16bbde20 Not changed by this PR, but why don't we just fuzz with require standard always on? false just disables some tests, no?
Is there a reason not to fuzz the additional branches?
Not strongly opinionated, resolving this comment, but have a question to clarify my understanding. My thinking here was based on the check_ratio set to 1, since any other value just means you run check() less often. AFAICT it's the same idea with standardness checks; if you turn it off, you're running fewer tests. Is it another branch if the codepaths you can hit with true is a superset of the codepaths you can hit with false? Am I misunderstanding?
I think it is good to also fuzz for non standard transactions, since we support it. Otherwise the validation codepath for non standard transactions that would be executed in "production" would not be fuzzed. On the other hand, "production" is only testnet here since we don't allow -acceptnonstdtxn for mainnet..
nit: Since this is using cycles for a test-only option, maybe we could lower the probability of setting require_standard to false? Something like require_standard = (ConsumeIntegralInRange(1, 10) % 10 != 0)?
AFAICT it's the same idea with standardness checks;
Not really. check will not mutate the mempool. However, require_standard may leave the mempool in a different state with the same ATMP calls, but a different value of require_standard. For example tx-size may create more inputs in the mempool. Or a raw non-standard script may trigger more paths in script evaluation. I think the mempool also uses script caching, so I was hoping for this to also be a check that the mempool doesn't print coins out of thin air.
check will not mutate the mempool. However, require_standard may leave the mempool in a different state with the same ATMP calls, but a different value of require_standar
Ahh yeah, makes sense that it's different branches, thanks!
reviewed up to fac940af80a5e8babc9da79843f324147d8e41f5
63 | + } 64 | + } else if (mempool_opts.incremental_relay_feerate > mempool_opts.min_relay_feerate) { 65 | + // Allow only setting incremental fee to control both 66 | + mempool_opts.min_relay_feerate = mempool_opts.incremental_relay_feerate; 67 | + LogPrintf("Increasing minrelaytxfee to %s to match incrementalrelayfee\n", mempool_opts.min_relay_feerate.ToString()); 68 | + }
in fad51d5dac5b1da1540dd233c6bd096cb3e4a2a5, not changed by this PR, but interesting to note that incremental relay feerate must be set before min relay feerate.
41 | @@ -41,11 +42,11 @@ static const unsigned int MAX_OP_RETURN_RELAY = 83; 42 | /** 43 | * A data carrying output is an unspendable output containing data. The script 44 | * type is designated as TxoutType::NULL_DATA. 45 | + * 46 | + * Maximum size of TxoutType::NULL_DATA scripts that this node considers standard. 47 | + * If nullopt, any size is nonstandard.
Agree with the approach of optional<size> in fac85fe0632eace9b49d5bdbc0e9e47765b01090 :+1:. At first was unsure about introducing a global g_max_datacarrier_bytes, then realized it was moved into policy in fa727f139c38e24fa23a6455b0b274177b41747c.
ACK fa727f139c38e24fa23a6455b0b274177b41747c
Lightly reviewed and tested each commit, nice move and cleanup. Would like at least another reviewer to take a look.
644 | @@ -645,8 +645,11 @@ static RPCHelpMan getnetworkinfo() 645 | obj.pushKV("connections_out", node.connman->GetNodeCount(ConnectionDirection::Out)); 646 | } 647 | obj.pushKV("networks", GetNetworksInfo()); 648 | - obj.pushKV("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())); 649 | - obj.pushKV("incrementalfee", ValueFromAmount(::incrementalRelayFee.GetFeePerK())); 650 | + if (node.mempool) { 651 | + // Those fields can be deprecated, to be replaced by the getmempoolinfo fields
Should we open an issue for this?
Personally I think it is fine to keep them forever, unless there is a strong enough reason to remove them. But this seems to be subjective.
Wondered at first look if launching bitcoind with -blocksonly would make these fields optional but doesn't appear to be the case (and checked that bitcoin-cli -rpcwait getnetworkinfo on a -blocksonly startup returns the fields).
Note that -blocksonly does not mean your node doesn't create a mempool.
43 | - * type is designated as TxoutType::NULL_DATA. 44 | - * 45 | - * Maximum size of TxoutType::NULL_DATA scripts that this node considers standard. 46 | - * If nullopt, any size is nonstandard. 47 | - */ 48 | -extern std::optional<unsigned> g_max_datacarrier_bytes;
nit: nMaxDatacarrierBytes is still mentionned just above in the comment for MAX_OP_RETURN_RELAY.
Thx, fixed.
utACK fa727f139c38e24fa23a6455b0b274177b41747c
Also pass in a (for now unused) reference to the params.
Both changes are needed for the next commit.
Apart from tests, it is only used in one place, so there is no need for
an alias.
Each alias is only used in one place.
It is part of the node library. Also, it won't be moved to the kernel
lib, as it will be pruned of ArgsManager.
-BEGIN VERIFY SCRIPT-
# Move module
git mv src/mempool_args.cpp src/node/
git mv src/mempool_args.h src/node/
# Replacements
sed -i 's:mempool_args\.h:node/mempool_args.h:g' $(git grep -l mempool_args)
sed -i 's:mempool_args\.cpp:node/mempool_args.cpp:g' $(git grep -l mempool_args)
sed -i 's:MEMPOOL_ARGS_H:NODE_MEMPOOL_ARGS_H:g' $(git grep -l MEMPOOL_ARGS_H)
-END VERIFY SCRIPT-
Fixed doc typos and added two commits (let me know if I should drop them)
20 | * 21 | * @param[in] argsman The ArgsManager in which to check set options. 22 | * @param[in,out] mempool_opts The MemPoolOptions to modify according to \p argsman. 23 | */ 24 | -void ApplyArgsManOptions(const ArgsManager& argsman, kernel::MemPoolOptions& mempool_opts); 25 | +[[nodiscard]] std::optional<bilingual_str> ApplyArgsManOptions(const ArgsManager& argsman, const CChainParams& chainparams, kernel::MemPoolOptions& mempool_opts);
Yes, there are also a few other places. See git grep 'std::optional<bilingual_str>'.
17 | @@ -18,6 +18,11 @@ 18 | #include <boost/test/unit_test.hpp> 19 | 20 | // Helpers: 21 | +bool IsStandardTx(const CTransaction& tx, std::string& reason)
In commit "Remove ::IsStandardTx(tx, reason) alias" (fa8a7f01fe1b6db98097021276ed5d929faadbec)
Would be good to declare this static to make sure nobody outside this file can call this
Good point. Will do on the next push or as a follow-up.
Fixed in #25772
Code review ACK ddddd6913b1bdee1cad89a32d363306ea1f7b8d7
49 | + * Maximum size of TxoutType::NULL_DATA scripts that this node considers standard. 50 | + * If nullopt, any size is nonstandard. 51 | + */ 52 | + std::optional<unsigned> max_datacarrier_bytes{DEFAULT_ACCEPT_DATACARRIER ? std::optional{MAX_OP_RETURN_RELAY} : std::nullopt}; 53 | + bool permit_bare_multisig{DEFAULT_PERMIT_BAREMULTISIG}; 54 | + bool require_standard{true};
could be nice to document variables
All options are documented in the manpage. This one under -acceptnonstdtxn. Happy to review a docs pull if there is need for one and someone creates one.
84 | + mempool_opts.max_datacarrier_bytes = argsman.GetIntArg("-datacarriersize", MAX_OP_RETURN_RELAY); 85 | + } else { 86 | + mempool_opts.max_datacarrier_bytes = std::nullopt; 87 | + } 88 | + 89 | + mempool_opts.require_standard = !argsman.GetBoolArg("-acceptnonstdtxn", !chainparams.RequireStandard());
could be called require_txstandard we might have standard package in the future, good to dissociate
require_standard is applied to both txs and packages, so I think the current name is fine, no?
I also think package standardness would be included with -acceptnonstdtxn anyway, can't really think of a reason not to. Feel free to reopen if something changes, we can cross this bridge if/when we come to it.
86 | @@ -87,7 +87,7 @@ CFeeRate GetDiscardRate(const CWallet& wallet) 87 | CFeeRate discard_rate = wallet.chain().estimateSmartFee(highest_target, false /* conservative */); 88 | // Don't let discard_rate be greater than longest possible fee estimate if we get a valid fee estimate 89 | discard_rate = (discard_rate == CFeeRate(0)) ? wallet.m_discard_rate : std::min(discard_rate, wallet.m_discard_rate); 90 | - // Discard rate must be at least dustRelayFee 91 | + // Discard rate must be at least dust relay feerate
m_dust_relay_feerate we do so for other variables doc refs make the code more greppable
wallet.m_dust_relay_feerate doesn't exist, only wallet.chain().relayDustFee(). Happy to switch to relayDustFee or similar, or just remove the comment completely, as the code is self-explanatory. Just let me know.
Light Code Review ACK ddddd69
re ACK ddddd69
changes since last review: