aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac6
-rw-r--r--src/policy/rbf.cpp45
-rw-r--r--src/policy/rbf.h11
-rw-r--r--src/rpc/blockchain.cpp84
-rw-r--r--src/rpc/external_signer.cpp7
-rw-r--r--src/rpc/mining.cpp9
-rw-r--r--src/rpc/misc.cpp10
-rw-r--r--src/rpc/net.cpp12
-rw-r--r--src/rpc/rawtransaction.cpp58
-rw-r--r--src/test/fuzz/utxo_snapshot.cpp1
-rw-r--r--src/txmempool.cpp34
-rw-r--r--src/txmempool.h25
-rw-r--r--src/util/rbf.h6
-rw-r--r--src/validation.cpp29
-rw-r--r--src/validation.h13
-rw-r--r--src/wallet/rpcwallet.cpp89
-rwxr-xr-xtest/functional/p2p_addr_relay.py14
-rwxr-xr-xtest/functional/p2p_addrfetch.py13
-rwxr-xr-xtest/functional/p2p_addrv2_relay.py9
-rwxr-xr-xtest/functional/p2p_segwit.py13
-rwxr-xr-xtest/functional/rpc_net.py12
-rwxr-xr-xtest/functional/test_framework/p2p.py2
-rwxr-xr-xtest/get_previous_releases.py1
-rw-r--r--test/sanitizer_suppressions/ubsan2
24 files changed, 267 insertions, 238 deletions
diff --git a/configure.ac b/configure.ac
index 0dc480e6c1..e30159f91b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -568,13 +568,17 @@ AX_CHECK_COMPILE_FLAG([-march=armv8-a+crc+crypto],[[ARM_CRC_CXXFLAGS="-march=arm
TEMP_CXXFLAGS="$CXXFLAGS"
CXXFLAGS="$CXXFLAGS $ARM_CRC_CXXFLAGS"
-AC_MSG_CHECKING(for ARM CRC32 intrinsics)
+AC_MSG_CHECKING(for AArch64 CRC32 intrinsics)
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <arm_acle.h>
#include <arm_neon.h>
]],[[
+#ifdef __aarch64__
__crc32cb(0, 0); __crc32ch(0, 0); __crc32cw(0, 0); __crc32cd(0, 0);
vmull_p64(0, 0);
+#else
+#error "crc32c library does not support hardware acceleration on 32-bit ARM"
+#endif
]])],
[ AC_MSG_RESULT(yes); enable_arm_crc=yes; ],
[ AC_MSG_RESULT(no)]
diff --git a/src/policy/rbf.cpp b/src/policy/rbf.cpp
index 15527afb8a..7ac2e22006 100644
--- a/src/policy/rbf.cpp
+++ b/src/policy/rbf.cpp
@@ -48,17 +48,19 @@ RBFTransactionState IsRBFOptInEmptyMempool(const CTransaction& tx)
}
std::optional<std::string> GetEntriesForConflicts(const CTransaction& tx,
- CTxMemPool& pool,
- const CTxMemPool::setEntries& iters_conflicting,
- CTxMemPool::setEntries& all_conflicts)
+ CTxMemPool& pool,
+ const CTxMemPool::setEntries& iters_conflicting,
+ CTxMemPool::setEntries& all_conflicts)
{
AssertLockHeld(pool.cs);
const uint256 txid = tx.GetHash();
uint64_t nConflictingCount = 0;
for (const auto& mi : iters_conflicting) {
nConflictingCount += mi->GetCountWithDescendants();
- // This potentially overestimates the number of actual descendants but we just want to be
- // conservative to avoid doing too much work.
+ // BIP125 Rule #5: don't consider replacing more than MAX_BIP125_REPLACEMENT_CANDIDATES
+ // entries from the mempool. This potentially overestimates the number of actual
+ // descendants (i.e. if multiple conflicts share a descendant, it will be counted multiple
+ // times), but we just want to be conservative to avoid doing too much work.
if (nConflictingCount > MAX_BIP125_REPLACEMENT_CANDIDATES) {
return strprintf("rejecting replacement %s; too many potential replacements (%d > %d)\n",
txid.ToString(),
@@ -66,8 +68,7 @@ std::optional<std::string> GetEntriesForConflicts(const CTransaction& tx,
MAX_BIP125_REPLACEMENT_CANDIDATES);
}
}
- // If not too many to replace, then calculate the set of
- // transactions that would have to be evicted
+ // Calculate the set of all transactions that would have to be evicted.
for (CTxMemPool::txiter it : iters_conflicting) {
pool.CalculateDescendants(it, all_conflicts);
}
@@ -81,19 +82,19 @@ std::optional<std::string> HasNoNewUnconfirmed(const CTransaction& tx,
AssertLockHeld(pool.cs);
std::set<uint256> parents_of_conflicts;
for (const auto& mi : iters_conflicting) {
- for (const CTxIn &txin : mi->GetTx().vin) {
+ for (const CTxIn& txin : mi->GetTx().vin) {
parents_of_conflicts.insert(txin.prevout.hash);
}
}
for (unsigned int j = 0; j < tx.vin.size(); j++) {
- // We don't want to accept replacements that require low feerate junk to be mined first.
- // Ideally we'd keep track of the ancestor feerates and make the decision based on that, but
- // for now requiring all new inputs to be confirmed works.
+ // BIP125 Rule #2: We don't want to accept replacements that require low feerate junk to be
+ // mined first. Ideally we'd keep track of the ancestor feerates and make the decision
+ // based on that, but for now requiring all new inputs to be confirmed works.
//
// Note that if you relax this to make RBF a little more useful, this may break the
- // CalculateMempoolAncestors RBF relaxation, above. See the comment above the first
- // CalculateMempoolAncestors call for more info.
+ // CalculateMempoolAncestors RBF relaxation which subtracts the conflict count/size from the
+ // descendant limit.
if (!parents_of_conflicts.count(tx.vin[j].prevout.hash)) {
// Rather than check the UTXO set - potentially expensive - it's cheaper to just check
// if the new input refers to a tx that's in the mempool.
@@ -111,7 +112,7 @@ std::optional<std::string> EntriesAndTxidsDisjoint(const CTxMemPool::setEntries&
const uint256& txid)
{
for (CTxMemPool::txiter ancestorIt : ancestors) {
- const uint256 &hashAncestor = ancestorIt->GetTx().GetHash();
+ const uint256& hashAncestor = ancestorIt->GetTx().GetHash();
if (direct_conflicts.count(hashAncestor)) {
return strprintf("%s spends conflicting transaction %s",
txid.ToString(),
@@ -150,24 +151,26 @@ std::optional<std::string> PaysMoreThanConflicts(const CTxMemPool::setEntries& i
std::optional<std::string> PaysForRBF(CAmount original_fees,
CAmount replacement_fees,
size_t replacement_vsize,
+ CFeeRate relay_fee,
const uint256& txid)
{
- // The replacement must pay greater fees than the transactions it
- // replaces - if we did the bandwidth used by those conflicting
- // transactions would not be paid for.
+ // BIP125 Rule #3: The replacement fees must be greater than or equal to fees of the
+ // transactions it replaces, otherwise the bandwidth used by those conflicting transactions
+ // would not be paid for.
if (replacement_fees < original_fees) {
return strprintf("rejecting replacement %s, less fees than conflicting txs; %s < %s",
txid.ToString(), FormatMoney(replacement_fees), FormatMoney(original_fees));
}
- // Finally in addition to paying more fees than the conflicts the
- // new transaction must pay for its own bandwidth.
+ // BIP125 Rule #4: The new transaction must pay for its own bandwidth. Otherwise, we have a DoS
+ // vector where attackers can cause a transaction to be replaced (and relayed) repeatedly by
+ // increasing the fee by tiny amounts.
CAmount additional_fees = replacement_fees - original_fees;
- if (additional_fees < ::incrementalRelayFee.GetFee(replacement_vsize)) {
+ if (additional_fees < relay_fee.GetFee(replacement_vsize)) {
return strprintf("rejecting replacement %s, not enough additional fees to relay; %s < %s",
txid.ToString(),
FormatMoney(additional_fees),
- FormatMoney(::incrementalRelayFee.GetFee(replacement_vsize)));
+ FormatMoney(relay_fee.GetFee(replacement_vsize)));
}
return std::nullopt;
}
diff --git a/src/policy/rbf.h b/src/policy/rbf.h
index 56468a09b2..be8c2e5b8b 100644
--- a/src/policy/rbf.h
+++ b/src/policy/rbf.h
@@ -5,7 +5,12 @@
#ifndef BITCOIN_POLICY_RBF_H
#define BITCOIN_POLICY_RBF_H
+#include <primitives/transaction.h>
#include <txmempool.h>
+#include <uint256.h>
+
+#include <optional>
+#include <string>
/** Maximum number of transactions that can be replaced by BIP125 RBF (Rule #5). This includes all
* mempool conflicts and their descendants. */
@@ -48,14 +53,14 @@ RBFTransactionState IsRBFOptInEmptyMempool(const CTransaction& tx);
std::optional<std::string> GetEntriesForConflicts(const CTransaction& tx, CTxMemPool& pool,
const CTxMemPool::setEntries& iters_conflicting,
CTxMemPool::setEntries& all_conflicts)
- EXCLUSIVE_LOCKS_REQUIRED(pool.cs);
+ EXCLUSIVE_LOCKS_REQUIRED(pool.cs);
/** BIP125 Rule #2: "The replacement transaction may only include an unconfirmed input if that input
* was included in one of the original transactions."
* @returns error message if Rule #2 is broken, otherwise std::nullopt. */
std::optional<std::string> HasNoNewUnconfirmed(const CTransaction& tx, const CTxMemPool& pool,
const CTxMemPool::setEntries& iters_conflicting)
- EXCLUSIVE_LOCKS_REQUIRED(pool.cs);
+ EXCLUSIVE_LOCKS_REQUIRED(pool.cs);
/** Check the intersection between two sets of transactions (a set of mempool entries and a set of
* txids) to make sure they are disjoint.
@@ -84,12 +89,14 @@ std::optional<std::string> PaysMoreThanConflicts(const CTxMemPool::setEntries& i
* @param[in] original_fees Total modified fees of original transaction(s).
* @param[in] replacement_fees Total modified fees of replacement transaction(s).
* @param[in] replacement_vsize Total virtual size of replacement transaction(s).
+ * @param[in] relay_fee The node's minimum feerate for transaction relay.
* @param[in] txid Transaction ID, included in the error message if violation occurs.
* @returns error string if fees are insufficient, otherwise std::nullopt.
*/
std::optional<std::string> PaysForRBF(CAmount original_fees,
CAmount replacement_fees,
size_t replacement_vsize,
+ CFeeRate relay_fee,
const uint256& txid);
#endif // BITCOIN_POLICY_RBF_H
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 909019d796..08d21e0f71 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -1115,11 +1115,11 @@ static RPCHelpMan gettxoutsetinfo()
{RPCResult::Type::NUM, "bogosize", "Database-independent, meaningless metric indicating the UTXO set size"},
{RPCResult::Type::STR_HEX, "hash_serialized_2", /* optional */ true, "The serialized hash (only present if 'hash_serialized_2' hash_type is chosen)"},
{RPCResult::Type::STR_HEX, "muhash", /* optional */ true, "The serialized hash (only present if 'muhash' hash_type is chosen)"},
- {RPCResult::Type::NUM, "transactions", "The number of transactions with unspent outputs (not available when coinstatsindex is used)"},
- {RPCResult::Type::NUM, "disk_size", "The estimated size of the chainstate on disk (not available when coinstatsindex is used)"},
+ {RPCResult::Type::NUM, "transactions", /* optional */ true, "The number of transactions with unspent outputs (not available when coinstatsindex is used)"},
+ {RPCResult::Type::NUM, "disk_size", /* optional */ true, "The estimated size of the chainstate on disk (not available when coinstatsindex is used)"},
{RPCResult::Type::STR_AMOUNT, "total_amount", "The total amount of coins in the UTXO set"},
- {RPCResult::Type::STR_AMOUNT, "total_unspendable_amount", "The total amount of coins permanently excluded from the UTXO set (only available if coinstatsindex is used)"},
- {RPCResult::Type::OBJ, "block_info", "Info on amounts in the block at this block height (only available if coinstatsindex is used)",
+ {RPCResult::Type::STR_AMOUNT, "total_unspendable_amount", /* optional */ true, "The total amount of coins permanently excluded from the UTXO set (only available if coinstatsindex is used)"},
+ {RPCResult::Type::OBJ, "block_info", /* optional */ true, "Info on amounts in the block at this block height (only available if coinstatsindex is used)",
{
{RPCResult::Type::STR_AMOUNT, "prevout_spent", "Total amount of all prevouts spent in this block"},
{RPCResult::Type::STR_AMOUNT, "coinbase", "Coinbase subsidy amount of this block"},
@@ -1436,32 +1436,32 @@ RPCHelpMan getblockchaininfo()
{RPCResult::Type::STR_HEX, "chainwork", "total amount of work in active chain, in hexadecimal"},
{RPCResult::Type::NUM, "size_on_disk", "the estimated size of the block and undo files on disk"},
{RPCResult::Type::BOOL, "pruned", "if the blocks are subject to pruning"},
- {RPCResult::Type::NUM, "pruneheight", "lowest-height complete block stored (only present if pruning is enabled)"},
- {RPCResult::Type::BOOL, "automatic_pruning", "whether automatic pruning is enabled (only present if pruning is enabled)"},
- {RPCResult::Type::NUM, "prune_target_size", "the target size used by pruning (only present if automatic pruning is enabled)"},
+ {RPCResult::Type::NUM, "pruneheight", /* optional */ true, "lowest-height complete block stored (only present if pruning is enabled)"},
+ {RPCResult::Type::BOOL, "automatic_pruning", /* optional */ true, "whether automatic pruning is enabled (only present if pruning is enabled)"},
+ {RPCResult::Type::NUM, "prune_target_size", /* optional */ true, "the target size used by pruning (only present if automatic pruning is enabled)"},
{RPCResult::Type::OBJ_DYN, "softforks", "status of softforks",
{
{RPCResult::Type::OBJ, "xxxx", "name of the softfork",
{
{RPCResult::Type::STR, "type", "one of \"buried\", \"bip9\""},
- {RPCResult::Type::OBJ, "bip9", "status of bip9 softforks (only for \"bip9\" type)",
+ {RPCResult::Type::OBJ, "bip9", /* optional */ true, "status of bip9 softforks (only for \"bip9\" type)",
{
{RPCResult::Type::STR, "status", "one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\""},
- {RPCResult::Type::NUM, "bit", "the bit (0-28) in the block version field used to signal this softfork (only for \"started\" and \"locked_in\" status)"},
+ {RPCResult::Type::NUM, "bit", /* optional */ true, "the bit (0-28) in the block version field used to signal this softfork (only for \"started\" and \"locked_in\" status)"},
{RPCResult::Type::NUM_TIME, "start_time", "the minimum median time past of a block at which the bit gains its meaning"},
{RPCResult::Type::NUM_TIME, "timeout", "the median time past of a block at which the deployment is considered failed if not yet locked in"},
{RPCResult::Type::NUM, "since", "height of the first block to which the status applies"},
{RPCResult::Type::NUM, "min_activation_height", "minimum height of blocks for which the rules may be enforced"},
- {RPCResult::Type::OBJ, "statistics", "numeric statistics about signalling for a softfork (only for \"started\" and \"locked_in\" status)",
+ {RPCResult::Type::OBJ, "statistics", /* optional */ true, "numeric statistics about signalling for a softfork (only for \"started\" and \"locked_in\" status)",
{
{RPCResult::Type::NUM, "period", "the length in blocks of the signalling period"},
- {RPCResult::Type::NUM, "threshold", "the number of blocks with the version bit set required to activate the feature (only for \"started\" status)"},
+ {RPCResult::Type::NUM, "threshold", /* optional */ true, "the number of blocks with the version bit set required to activate the feature (only for \"started\" status)"},
{RPCResult::Type::NUM, "elapsed", "the number of blocks elapsed since the beginning of the current period"},
{RPCResult::Type::NUM, "count", "the number of blocks with the version bit set in the current period"},
- {RPCResult::Type::BOOL, "possible", "returns false if there are not enough blocks left in this period to pass activation threshold (only for \"started\" status)"},
+ {RPCResult::Type::BOOL, "possible", /* optional */ true, "returns false if there are not enough blocks left in this period to pass activation threshold (only for \"started\" status)"},
}},
}},
- {RPCResult::Type::NUM, "height", "height of the first block which the rules are or will be enforced (only for \"buried\" type, or \"bip9\" type with \"active\" status)"},
+ {RPCResult::Type::NUM, "height", /* optional */ true, "height of the first block which the rules are or will be enforced (only for \"buried\" type, or \"bip9\" type with \"active\" status)"},
{RPCResult::Type::BOOL, "active", "true if the rules are enforced for the mempool and the next block"},
}},
}},
@@ -1971,11 +1971,11 @@ static RPCHelpMan getblockstats()
RPCResult{
RPCResult::Type::OBJ, "", "",
{
- {RPCResult::Type::NUM, "avgfee", "Average fee in the block"},
- {RPCResult::Type::NUM, "avgfeerate", "Average feerate (in satoshis per virtual byte)"},
- {RPCResult::Type::NUM, "avgtxsize", "Average transaction size"},
- {RPCResult::Type::STR_HEX, "blockhash", "The block hash (to check for potential reorgs)"},
- {RPCResult::Type::ARR_FIXED, "feerate_percentiles", "Feerates at the 10th, 25th, 50th, 75th, and 90th percentile weight unit (in satoshis per virtual byte)",
+ {RPCResult::Type::NUM, "avgfee", /* optional */ true, "Average fee in the block"},
+ {RPCResult::Type::NUM, "avgfeerate", /* optional */ true, "Average feerate (in satoshis per virtual byte)"},
+ {RPCResult::Type::NUM, "avgtxsize", /* optional */ true, "Average transaction size"},
+ {RPCResult::Type::STR_HEX, "blockhash", /* optional */ true, "The block hash (to check for potential reorgs)"},
+ {RPCResult::Type::ARR_FIXED, "feerate_percentiles", /* optional */ true, "Feerates at the 10th, 25th, 50th, 75th, and 90th percentile weight unit (in satoshis per virtual byte)",
{
{RPCResult::Type::NUM, "10th_percentile_feerate", "The 10th percentile feerate"},
{RPCResult::Type::NUM, "25th_percentile_feerate", "The 25th percentile feerate"},
@@ -1983,30 +1983,30 @@ static RPCHelpMan getblockstats()
{RPCResult::Type::NUM, "75th_percentile_feerate", "The 75th percentile feerate"},
{RPCResult::Type::NUM, "90th_percentile_feerate", "The 90th percentile feerate"},
}},
- {RPCResult::Type::NUM, "height", "The height of the block"},
- {RPCResult::Type::NUM, "ins", "The number of inputs (excluding coinbase)"},
- {RPCResult::Type::NUM, "maxfee", "Maximum fee in the block"},
- {RPCResult::Type::NUM, "maxfeerate", "Maximum feerate (in satoshis per virtual byte)"},
- {RPCResult::Type::NUM, "maxtxsize", "Maximum transaction size"},
- {RPCResult::Type::NUM, "medianfee", "Truncated median fee in the block"},
- {RPCResult::Type::NUM, "mediantime", "The block median time past"},
- {RPCResult::Type::NUM, "mediantxsize", "Truncated median transaction size"},
- {RPCResult::Type::NUM, "minfee", "Minimum fee in the block"},
- {RPCResult::Type::NUM, "minfeerate", "Minimum feerate (in satoshis per virtual byte)"},
- {RPCResult::Type::NUM, "mintxsize", "Minimum transaction size"},
- {RPCResult::Type::NUM, "outs", "The number of outputs"},
- {RPCResult::Type::NUM, "subsidy", "The block subsidy"},
- {RPCResult::Type::NUM, "swtotal_size", "Total size of all segwit transactions"},
- {RPCResult::Type::NUM, "swtotal_weight", "Total weight of all segwit transactions"},
- {RPCResult::Type::NUM, "swtxs", "The number of segwit transactions"},
- {RPCResult::Type::NUM, "time", "The block time"},
- {RPCResult::Type::NUM, "total_out", "Total amount in all outputs (excluding coinbase and thus reward [ie subsidy + totalfee])"},
- {RPCResult::Type::NUM, "total_size", "Total size of all non-coinbase transactions"},
- {RPCResult::Type::NUM, "total_weight", "Total weight of all non-coinbase transactions"},
- {RPCResult::Type::NUM, "totalfee", "The fee total"},
- {RPCResult::Type::NUM, "txs", "The number of transactions (including coinbase)"},
- {RPCResult::Type::NUM, "utxo_increase", "The increase/decrease in the number of unspent outputs"},
- {RPCResult::Type::NUM, "utxo_size_inc", "The increase/decrease in size for the utxo index (not discounting op_return and similar)"},
+ {RPCResult::Type::NUM, "height", /* optional */ true, "The height of the block"},
+ {RPCResult::Type::NUM, "ins", /* optional */ true, "The number of inputs (excluding coinbase)"},
+ {RPCResult::Type::NUM, "maxfee", /* optional */ true, "Maximum fee in the block"},
+ {RPCResult::Type::NUM, "maxfeerate", /* optional */ true, "Maximum feerate (in satoshis per virtual byte)"},
+ {RPCResult::Type::NUM, "maxtxsize", /* optional */ true, "Maximum transaction size"},
+ {RPCResult::Type::NUM, "medianfee", /* optional */ true, "Truncated median fee in the block"},
+ {RPCResult::Type::NUM, "mediantime", /* optional */ true, "The block median time past"},
+ {RPCResult::Type::NUM, "mediantxsize", /* optional */ true, "Truncated median transaction size"},
+ {RPCResult::Type::NUM, "minfee", /* optional */ true, "Minimum fee in the block"},
+ {RPCResult::Type::NUM, "minfeerate", /* optional */ true, "Minimum feerate (in satoshis per virtual byte)"},
+ {RPCResult::Type::NUM, "mintxsize", /* optional */ true, "Minimum transaction size"},
+ {RPCResult::Type::NUM, "outs", /* optional */ true, "The number of outputs"},
+ {RPCResult::Type::NUM, "subsidy", /* optional */ true, "The block subsidy"},
+ {RPCResult::Type::NUM, "swtotal_size", /* optional */ true, "Total size of all segwit transactions"},
+ {RPCResult::Type::NUM, "swtotal_weight", /* optional */ true, "Total weight of all segwit transactions"},
+ {RPCResult::Type::NUM, "swtxs", /* optional */ true, "The number of segwit transactions"},
+ {RPCResult::Type::NUM, "time", /* optional */ true, "The block time"},
+ {RPCResult::Type::NUM, "total_out", /* optional */ true, "Total amount in all outputs (excluding coinbase and thus reward [ie subsidy + totalfee])"},
+ {RPCResult::Type::NUM, "total_size", /* optional */ true, "Total size of all non-coinbase transactions"},
+ {RPCResult::Type::NUM, "total_weight", /* optional */ true, "Total weight of all non-coinbase transactions"},
+ {RPCResult::Type::NUM, "totalfee", /* optional */ true, "The fee total"},
+ {RPCResult::Type::NUM, "txs", /* optional */ true, "The number of transactions (including coinbase)"},
+ {RPCResult::Type::NUM, "utxo_increase", /* optional */ true, "The increase/decrease in the number of unspent outputs"},
+ {RPCResult::Type::NUM, "utxo_size_inc", /* optional */ true, "The increase/decrease in size for the utxo index (not discounting op_return and similar)"},
}},
RPCExamples{
HelpExampleCli("getblockstats", R"('"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09"' '["minfeerate","avgfeerate"]')") +
diff --git a/src/rpc/external_signer.cpp b/src/rpc/external_signer.cpp
index 6ec2b1a07f..60ec15e904 100644
--- a/src/rpc/external_signer.cpp
+++ b/src/rpc/external_signer.cpp
@@ -24,8 +24,11 @@ static RPCHelpMan enumeratesigners()
{
{RPCResult::Type::ARR, "signers", /* optional */ false, "",
{
- {RPCResult::Type::STR_HEX, "masterkeyfingerprint", "Master key fingerprint"},
- {RPCResult::Type::STR, "name", "Device name"},
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR_HEX, "fingerprint", "Master key fingerprint"},
+ {RPCResult::Type::STR, "name", "Device name"},
+ }},
},
}
}
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index 27cbb3a702..eb2d5b9c5f 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -553,6 +553,10 @@ static RPCHelpMan getblocktemplate()
{
{RPCResult::Type::NUM, "rulename", "identifies the bit number as indicating acceptance and readiness for the named softfork rule"},
}},
+ {RPCResult::Type::ARR, "capabilities", "",
+ {
+ {RPCResult::Type::STR, "value", "A supported feature, for example 'proposal'"},
+ }},
{RPCResult::Type::NUM, "vbrequired", "bit mask of versionbits the server requires set in submissions"},
{RPCResult::Type::STR, "previousblockhash", "The hash of current highest block"},
{RPCResult::Type::ARR, "transactions", "contents of non-coinbase transactions that should be included in the next block",
@@ -586,11 +590,12 @@ static RPCHelpMan getblocktemplate()
{RPCResult::Type::STR_HEX, "noncerange", "A range of valid nonces"},
{RPCResult::Type::NUM, "sigoplimit", "limit of sigops in blocks"},
{RPCResult::Type::NUM, "sizelimit", "limit of block size"},
- {RPCResult::Type::NUM, "weightlimit", "limit of block weight"},
+ {RPCResult::Type::NUM, "weightlimit", /* optional */ true, "limit of block weight"},
{RPCResult::Type::NUM_TIME, "curtime", "current timestamp in " + UNIX_EPOCH_TIME},
{RPCResult::Type::STR, "bits", "compressed target of next block"},
{RPCResult::Type::NUM, "height", "The height of the next block"},
- {RPCResult::Type::STR, "default_witness_commitment", /* optional */ true, "a valid witness commitment for the unmodified block template"},
+ {RPCResult::Type::STR_HEX, "signet_challenge", /* optional */ true, "Only on signet"},
+ {RPCResult::Type::STR_HEX, "default_witness_commitment", /* optional */ true, "a valid witness commitment for the unmodified block template"},
}},
},
RPCExamples{
diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp
index 14b0e5a984..dff2129980 100644
--- a/src/rpc/misc.cpp
+++ b/src/rpc/misc.cpp
@@ -44,10 +44,10 @@ static RPCHelpMan validateaddress()
RPCResult::Type::OBJ, "", "",
{
{RPCResult::Type::BOOL, "isvalid", "If the address is valid or not"},
- {RPCResult::Type::STR, "address", "The bitcoin address validated"},
- {RPCResult::Type::STR_HEX, "scriptPubKey", "The hex-encoded scriptPubKey generated by the address"},
- {RPCResult::Type::BOOL, "isscript", "If the key is a script"},
- {RPCResult::Type::BOOL, "iswitness", "If the address is a witness address"},
+ {RPCResult::Type::STR, "address", /* optional */ true, "The bitcoin address validated"},
+ {RPCResult::Type::STR_HEX, "scriptPubKey", /* optional */ true, "The hex-encoded scriptPubKey generated by the address"},
+ {RPCResult::Type::BOOL, "isscript", /* optional */ true, "If the key is a script"},
+ {RPCResult::Type::BOOL, "iswitness", /* optional */ true, "If the address is a witness address"},
{RPCResult::Type::NUM, "witness_version", /* optional */ true, "The version number of the witness program"},
{RPCResult::Type::STR_HEX, "witness_program", /* optional */ true, "The hex value of the witness program"},
{RPCResult::Type::STR, "error", /* optional */ true, "Error message, if any"},
@@ -717,7 +717,7 @@ static RPCHelpMan getindexinfo()
{"index_name", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "Filter results for an index with a specific name."},
},
RPCResult{
- RPCResult::Type::OBJ, "", "", {
+ RPCResult::Type::OBJ_DYN, "", "", {
{
RPCResult::Type::OBJ, "name", "The name of the index",
{
diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp
index 227eec722f..a9bee33c5d 100644
--- a/src/rpc/net.cpp
+++ b/src/rpc/net.cpp
@@ -116,10 +116,10 @@ static RPCHelpMan getpeerinfo()
{
{RPCResult::Type::NUM, "id", "Peer index"},
{RPCResult::Type::STR, "addr", "(host:port) The IP address and port of the peer"},
- {RPCResult::Type::STR, "addrbind", "(ip:port) Bind address of the connection to the peer"},
- {RPCResult::Type::STR, "addrlocal", "(ip:port) Local address as reported by the peer"},
+ {RPCResult::Type::STR, "addrbind", /* optional */ true, "(ip:port) Bind address of the connection to the peer"},
+ {RPCResult::Type::STR, "addrlocal", /* optional */ true, "(ip:port) Local address as reported by the peer"},
{RPCResult::Type::STR, "network", "Network (" + Join(GetNetworkNames(/* append_unroutable */ true), ", ") + ")"},
- {RPCResult::Type::NUM, "mapped_as", "The AS in the BGP route to the peer used for diversifying\n"
+ {RPCResult::Type::NUM, "mapped_as", /* optional */ true, "The AS in the BGP route to the peer used for diversifying\n"
"peer selection (only available if the asmap config flag is set)"},
{RPCResult::Type::STR_HEX, "services", "The services offered"},
{RPCResult::Type::ARR, "servicesnames", "the services offered, in human-readable form",
@@ -135,9 +135,9 @@ static RPCHelpMan getpeerinfo()
{RPCResult::Type::NUM, "bytesrecv", "The total bytes received"},
{RPCResult::Type::NUM_TIME, "conntime", "The " + UNIX_EPOCH_TIME + " of the connection"},
{RPCResult::Type::NUM, "timeoffset", "The time offset in seconds"},
- {RPCResult::Type::NUM, "pingtime", "ping time (if available)"},
- {RPCResult::Type::NUM, "minping", "minimum observed ping time (if any at all)"},
- {RPCResult::Type::NUM, "pingwait", "ping wait (if non-zero)"},
+ {RPCResult::Type::NUM, "pingtime", /* optional */ true, "ping time (if available)"},
+ {RPCResult::Type::NUM, "minping", /* optional */ true, "minimum observed ping time (if any at all)"},
+ {RPCResult::Type::NUM, "pingwait", /* optional */ true, "ping wait (if non-zero)"},
{RPCResult::Type::NUM, "version", "The peer version, such as 70001"},
{RPCResult::Type::STR, "subver", "The string version"},
{RPCResult::Type::BOOL, "inbound", "Inbound (true) or Outbound (false)"},
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index 00e77d89e5..737abf6ca9 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -94,7 +94,7 @@ static RPCHelpMan getrawtransaction()
RPCResult{"if verbose is set to true",
RPCResult::Type::OBJ, "", "",
{
- {RPCResult::Type::BOOL, "in_active_chain", "Whether specified block is in the active chain or not (only present with explicit \"blockhash\" argument)"},
+ {RPCResult::Type::BOOL, "in_active_chain", /* optional */ true, "Whether specified block is in the active chain or not (only present with explicit \"blockhash\" argument)"},
{RPCResult::Type::STR_HEX, "hex", "The serialized, hex-encoded data for 'txid'"},
{RPCResult::Type::STR_HEX, "txid", "The transaction id (same as provided)"},
{RPCResult::Type::STR_HEX, "hash", "The transaction hash (differs from txid for witness transactions)"},
@@ -115,7 +115,7 @@ static RPCHelpMan getrawtransaction()
{RPCResult::Type::STR_HEX, "hex", "hex"},
}},
{RPCResult::Type::NUM, "sequence", "The script sequence number"},
- {RPCResult::Type::ARR, "txinwitness", "",
+ {RPCResult::Type::ARR, "txinwitness", /* optional */ true, "",
{
{RPCResult::Type::STR_HEX, "hex", "hex-encoded witness data (if any)"},
}},
@@ -141,10 +141,10 @@ static RPCHelpMan getrawtransaction()
}},
}},
}},
- {RPCResult::Type::STR_HEX, "blockhash", "the block hash"},
- {RPCResult::Type::NUM, "confirmations", "The confirmations"},
- {RPCResult::Type::NUM_TIME, "blocktime", "The block time expressed in " + UNIX_EPOCH_TIME},
- {RPCResult::Type::NUM, "time", "Same as \"blocktime\""},
+ {RPCResult::Type::STR_HEX, "blockhash", /* optional */ true, "the block hash"},
+ {RPCResult::Type::NUM, "confirmations", /* optional */ true, "The confirmations"},
+ {RPCResult::Type::NUM_TIME, "blocktime", /* optional */ true, "The block time expressed in " + UNIX_EPOCH_TIME},
+ {RPCResult::Type::NUM, "time", /* optional */ true, "Same as \"blocktime\""},
}
},
},
@@ -470,14 +470,15 @@ static RPCHelpMan decoderawtransaction()
{
{RPCResult::Type::OBJ, "", "",
{
- {RPCResult::Type::STR_HEX, "txid", "The transaction id"},
- {RPCResult::Type::NUM, "vout", "The output number"},
- {RPCResult::Type::OBJ, "scriptSig", "The script",
+ {RPCResult::Type::STR_HEX, "coinbase", /* optional */ true, ""},
+ {RPCResult::Type::STR_HEX, "txid", /* optional */ true, "The transaction id"},
+ {RPCResult::Type::NUM, "vout", /* optional */ true, "The output number"},
+ {RPCResult::Type::OBJ, "scriptSig", /* optional */ true, "The script",
{
{RPCResult::Type::STR, "asm", "asm"},
{RPCResult::Type::STR_HEX, "hex", "hex"},
}},
- {RPCResult::Type::ARR, "txinwitness", "",
+ {RPCResult::Type::ARR, "txinwitness", /* optional */ true, "",
{
{RPCResult::Type::STR_HEX, "hex", "hex-encoded witness data (if any)"},
}},
@@ -559,8 +560,8 @@ static RPCHelpMan decodescript()
{
{RPCResult::Type::STR, "address", "bitcoin address"},
}},
- {RPCResult::Type::STR, "p2sh", "address of P2SH script wrapping this redeem script (not returned if the script is already a P2SH)"},
- {RPCResult::Type::OBJ, "segwit", "Result of a witness script public key wrapping this redeem script (not returned if the script is a P2SH or witness)",
+ {RPCResult::Type::STR, "p2sh", /* optional */ true, "address of P2SH script wrapping this redeem script (not returned if the script is already a P2SH)"},
+ {RPCResult::Type::OBJ, "segwit", /* optional */ true, "Result of a witness script public key wrapping this redeem script (not returned if the script is a P2SH or witness)",
{
{RPCResult::Type::STR, "asm", "String representation of the script public key"},
{RPCResult::Type::STR_HEX, "hex", "Hex string of the script public key"},
@@ -772,6 +773,10 @@ static RPCHelpMan signrawtransactionwithkey()
{
{RPCResult::Type::STR_HEX, "txid", "The hash of the referenced, previous transaction"},
{RPCResult::Type::NUM, "vout", "The index of the output to spent and used as input"},
+ {RPCResult::Type::ARR, "witness", "",
+ {
+ {RPCResult::Type::STR_HEX, "witness", ""},
+ }},
{RPCResult::Type::STR_HEX, "scriptSig", "The hex-encoded signature script"},
{RPCResult::Type::NUM, "sequence", "Script sequence number"},
{RPCResult::Type::STR, "error", "Verification or signing error related to the input"},
@@ -909,15 +914,15 @@ static RPCHelpMan testmempoolaccept()
{
{RPCResult::Type::STR_HEX, "txid", "The transaction hash in hex"},
{RPCResult::Type::STR_HEX, "wtxid", "The transaction witness hash in hex"},
- {RPCResult::Type::STR, "package-error", "Package validation error, if any (only possible if rawtxs had more than 1 transaction)."},
- {RPCResult::Type::BOOL, "allowed", "Whether this tx would be accepted to the mempool and pass client-specified maxfeerate."
+ {RPCResult::Type::STR, "package-error", /* optional */ true, "Package validation error, if any (only possible if rawtxs had more than 1 transaction)."},
+ {RPCResult::Type::BOOL, "allowed", /* optional */ true, "Whether this tx would be accepted to the mempool and pass client-specified maxfeerate. "
"If not present, the tx was not fully validated due to a failure in another tx in the list."},
- {RPCResult::Type::NUM, "vsize", "Virtual transaction size as defined in BIP 141. This is different from actual serialized size for witness transactions as witness data is discounted (only present when 'allowed' is true)"},
- {RPCResult::Type::OBJ, "fees", "Transaction fees (only present if 'allowed' is true)",
+ {RPCResult::Type::NUM, "vsize", /* optional */ true, "Virtual transaction size as defined in BIP 141. This is different from actual serialized size for witness transactions as witness data is discounted (only present when 'allowed' is true)"},
+ {RPCResult::Type::OBJ, "fees", /* optional */ true, "Transaction fees (only present if 'allowed' is true)",
{
{RPCResult::Type::STR_AMOUNT, "base", "transaction fee in " + CURRENCY_UNIT},
}},
- {RPCResult::Type::STR, "reject-reason", "Rejection string (only present when 'allowed' is false)"},
+ {RPCResult::Type::STR, "reject-reason", /* optional */ true, "Rejection string (only present when 'allowed' is false)"},
}},
}
},
@@ -1056,7 +1061,7 @@ static RPCHelpMan decodepsbt()
{RPCResult::Type::STR, "asm", "The asm"},
{RPCResult::Type::STR_HEX, "hex", "The hex"},
{RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
- {RPCResult::Type::STR, "address"," Bitcoin address if there is one"},
+ {RPCResult::Type::STR, "address", /*optional=*/true, "Bitcoin address if there is one"},
}},
}},
{RPCResult::Type::OBJ_DYN, "partial_signatures", /* optional */ true, "",
@@ -1078,22 +1083,23 @@ static RPCHelpMan decodepsbt()
}},
{RPCResult::Type::ARR, "bip32_derivs", /* optional */ true, "",
{
- {RPCResult::Type::OBJ, "pubkey", /* optional */ true, "The public key with the derivation path as the value.",
+ {RPCResult::Type::OBJ, "", "",
{
+ {RPCResult::Type::STR, "pubkey", "The public key with the derivation path as the value."},
{RPCResult::Type::STR, "master_fingerprint", "The fingerprint of the master key"},
{RPCResult::Type::STR, "path", "The path"},
}},
}},
- {RPCResult::Type::OBJ, "final_scriptsig", /* optional */ true, "",
+ {RPCResult::Type::OBJ, "final_scriptSig", /* optional */ true, "",
{
{RPCResult::Type::STR, "asm", "The asm"},
{RPCResult::Type::STR, "hex", "The hex"},
}},
- {RPCResult::Type::ARR, "final_scriptwitness", "",
+ {RPCResult::Type::ARR, "final_scriptwitness", /* optional */ true, "",
{
{RPCResult::Type::STR_HEX, "", "hex-encoded witness data (if any)"},
}},
- {RPCResult::Type::OBJ_DYN, "unknown", "The unknown global fields",
+ {RPCResult::Type::OBJ_DYN, "unknown", /* optional */ true, "The unknown global fields",
{
{RPCResult::Type::STR_HEX, "key", "(key-value pair) An unknown key-value pair"},
}},
@@ -1124,7 +1130,7 @@ static RPCHelpMan decodepsbt()
{RPCResult::Type::STR, "path", "The path"},
}},
}},
- {RPCResult::Type::OBJ_DYN, "unknown", "The unknown global fields",
+ {RPCResult::Type::OBJ_DYN, "unknown", /* optional */ true, "The unknown global fields",
{
{RPCResult::Type::STR_HEX, "key", "(key-value pair) An unknown key-value pair"},
}},
@@ -1398,8 +1404,8 @@ static RPCHelpMan finalizepsbt()
RPCResult{
RPCResult::Type::OBJ, "", "",
{
- {RPCResult::Type::STR, "psbt", "The base64-encoded partially signed transaction if not extracted"},
- {RPCResult::Type::STR_HEX, "hex", "The hex-encoded network transaction if extracted"},
+ {RPCResult::Type::STR, "psbt", /* optional */ true, "The base64-encoded partially signed transaction if not extracted"},
+ {RPCResult::Type::STR_HEX, "hex", /* optional */ true, "The hex-encoded network transaction if extracted"},
{RPCResult::Type::BOOL, "complete", "If the transaction has a complete set of signatures"},
}
},
@@ -1791,7 +1797,7 @@ static RPCHelpMan analyzepsbt()
RPCResult {
RPCResult::Type::OBJ, "", "",
{
- {RPCResult::Type::ARR, "inputs", "",
+ {RPCResult::Type::ARR, "inputs", /* optional */ true, "",
{
{RPCResult::Type::OBJ, "", "",
{
diff --git a/src/test/fuzz/utxo_snapshot.cpp b/src/test/fuzz/utxo_snapshot.cpp
index 6f2bc081c6..8d2a06f11a 100644
--- a/src/test/fuzz/utxo_snapshot.cpp
+++ b/src/test/fuzz/utxo_snapshot.cpp
@@ -4,6 +4,7 @@
#include <chainparams.h>
#include <consensus/validation.h>
+#include <node/utxo_snapshot.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index 3cf62f3c0e..5a93f30c8a 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -21,23 +21,23 @@
#include <cmath>
#include <optional>
-CTxMemPoolEntry::CTxMemPoolEntry(const CTransactionRef& _tx, const CAmount& _nFee,
- int64_t _nTime, unsigned int _entryHeight,
- bool _spendsCoinbase, int64_t _sigOpsCost, LockPoints lp)
- : tx(_tx), nFee(_nFee), nTxWeight(GetTransactionWeight(*tx)), nUsageSize(RecursiveDynamicUsage(tx)), nTime(_nTime), entryHeight(_entryHeight),
- spendsCoinbase(_spendsCoinbase), sigOpCost(_sigOpsCost), lockPoints(lp)
-{
- nCountWithDescendants = 1;
- nSizeWithDescendants = GetTxSize();
- nModFeesWithDescendants = nFee;
-
- feeDelta = 0;
-
- nCountWithAncestors = 1;
- nSizeWithAncestors = GetTxSize();
- nModFeesWithAncestors = nFee;
- nSigOpCostWithAncestors = sigOpCost;
-}
+CTxMemPoolEntry::CTxMemPoolEntry(const CTransactionRef& tx, CAmount fee,
+ int64_t time, unsigned int entry_height,
+ bool spends_coinbase, int64_t sigops_cost, LockPoints lp)
+ : tx{tx},
+ nFee{fee},
+ nTxWeight(GetTransactionWeight(*tx)),
+ nUsageSize{RecursiveDynamicUsage(tx)},
+ nTime{time},
+ entryHeight{entry_height},
+ spendsCoinbase{spends_coinbase},
+ sigOpCost{sigops_cost},
+ lockPoints{lp},
+ nSizeWithDescendants{GetTxSize()},
+ nModFeesWithDescendants{nFee},
+ nSizeWithAncestors{GetTxSize()},
+ nModFeesWithAncestors{nFee},
+ nSigOpCostWithAncestors{sigOpCost} {}
void CTxMemPoolEntry::UpdateFeeDelta(int64_t newFeeDelta)
{
diff --git a/src/txmempool.h b/src/txmempool.h
index d1308aeeed..27ee0628a7 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -37,19 +37,16 @@ extern RecursiveMutex cs_main;
/** Fake height value used in Coin to signify they are only in the memory pool (since 0.8) */
static const uint32_t MEMPOOL_HEIGHT = 0x7FFFFFFF;
-struct LockPoints
-{
+struct LockPoints {
// Will be set to the blockchain height and median time past
// values that would be necessary to satisfy all relative locktime
// constraints (BIP68) of this tx given our view of block chain history
- int height;
- int64_t time;
+ int height{0};
+ int64_t time{0};
// As long as the current chain descends from the highest height block
// containing one of the inputs used in the calculation, then the cached
// values are still valid even after a reorg.
- CBlockIndex* maxInputBlock;
-
- LockPoints() : height(0), time(0), maxInputBlock(nullptr) { }
+ CBlockIndex* maxInputBlock{nullptr};
};
struct CompareIteratorByHash {
@@ -98,27 +95,27 @@ private:
const unsigned int entryHeight; //!< Chain height when entering the mempool
const bool spendsCoinbase; //!< keep track of transactions that spend a coinbase
const int64_t sigOpCost; //!< Total sigop cost
- int64_t feeDelta; //!< Used for determining the priority of the transaction for mining in a block
+ int64_t feeDelta{0}; //!< Used for determining the priority of the transaction for mining in a block
LockPoints lockPoints; //!< Track the height and time at which tx was final
// Information about descendants of this transaction that are in the
// mempool; if we remove this transaction we must remove all of these
// descendants as well.
- uint64_t nCountWithDescendants; //!< number of descendant transactions
+ uint64_t nCountWithDescendants{1}; //!< number of descendant transactions
uint64_t nSizeWithDescendants; //!< ... and size
CAmount nModFeesWithDescendants; //!< ... and total fees (all including us)
// Analogous statistics for ancestor transactions
- uint64_t nCountWithAncestors;
+ uint64_t nCountWithAncestors{1};
uint64_t nSizeWithAncestors;
CAmount nModFeesWithAncestors;
int64_t nSigOpCostWithAncestors;
public:
- CTxMemPoolEntry(const CTransactionRef& _tx, const CAmount& _nFee,
- int64_t _nTime, unsigned int _entryHeight,
- bool spendsCoinbase,
- int64_t nSigOpsCost, LockPoints lp);
+ CTxMemPoolEntry(const CTransactionRef& tx, CAmount fee,
+ int64_t time, unsigned int entry_height,
+ bool spends_coinbase,
+ int64_t sigops_cost, LockPoints lp);
const CTransaction& GetTx() const { return *this->tx; }
CTransactionRef GetSharedTx() const { return this->tx; }
diff --git a/src/util/rbf.h b/src/util/rbf.h
index 6d44a2cb83..aa522d8bfb 100644
--- a/src/util/rbf.h
+++ b/src/util/rbf.h
@@ -9,7 +9,7 @@
class CTransaction;
-static const uint32_t MAX_BIP125_RBF_SEQUENCE = 0xfffffffd;
+static constexpr uint32_t MAX_BIP125_RBF_SEQUENCE{0xfffffffd};
/** Check whether the sequence numbers on this transaction are signaling opt-in to replace-by-fee,
* according to BIP 125. Allow opt-out of transaction replacement by setting nSequence >
@@ -17,7 +17,7 @@ static const uint32_t MAX_BIP125_RBF_SEQUENCE = 0xfffffffd;
*
* SEQUENCE_FINAL-1 is picked to still allow use of nLockTime by non-replaceable transactions. All
* inputs rather than just one is for the sake of multi-party protocols, where we don't want a single
-* party to be able to disable replacement. */
-bool SignalsOptInRBF(const CTransaction &tx);
+* party to be able to disable replacement by opting out in their own input. */
+bool SignalsOptInRBF(const CTransaction& tx);
#endif // BITCOIN_UTIL_RBF_H
diff --git a/src/validation.cpp b/src/validation.cpp
index cc87f98913..b052273b50 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -24,6 +24,7 @@
#include <node/blockstorage.h>
#include <node/coinstats.h>
#include <node/ui_interface.h>
+#include <node/utxo_snapshot.h>
#include <policy/policy.h>
#include <policy/rbf.h>
#include <policy/settings.h>
@@ -771,39 +772,43 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
// pathological case by making sure setConflicts and setAncestors don't
// intersect.
if (const auto err_string{EntriesAndTxidsDisjoint(setAncestors, setConflicts, hash)}) {
+ // We classify this as a consensus error because a transaction depending on something it
+ // conflicts with would be inconsistent.
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-spends-conflicting-tx", *err_string);
}
- // If we don't hold the lock allConflicting might be incomplete; the
- // subsequent RemoveStaged() and addUnchecked() calls don't guarantee
- // mempool consistency for us.
fReplacementTransaction = setConflicts.size();
- if (fReplacementTransaction)
- {
+ if (fReplacementTransaction) {
CFeeRate newFeeRate(nModifiedFees, nSize);
+ // It's possible that the replacement pays more fees than its direct conflicts but not more
+ // than all conflicts (i.e. the direct conflicts have high-fee descendants). However, if the
+ // replacement doesn't pay more fees than its direct conflicts, then we can be sure it's not
+ // more economically rational to mine. Before we go digging through the mempool for all
+ // transactions that would need to be removed (direct conflicts and all descendants), check
+ // that the replacement transaction pays more than its direct conflicts.
if (const auto err_string{PaysMoreThanConflicts(setIterConflicting, newFeeRate, hash)}) {
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "insufficient fee", *err_string);
}
- // Calculate all conflicting entries and enforce Rule #5.
+ // Calculate all conflicting entries and enforce BIP125 Rule #5.
if (const auto err_string{GetEntriesForConflicts(tx, m_pool, setIterConflicting, allConflicting)}) {
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY,
"too many potential replacements", *err_string);
}
- // Enforce Rule #2.
+ // Enforce BIP125 Rule #2.
if (const auto err_string{HasNoNewUnconfirmed(tx, m_pool, setIterConflicting)}) {
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY,
"replacement-adds-unconfirmed", *err_string);
}
- // Check if it's economically rational to mine this transaction rather
- // than the ones it replaces. Enforce Rules #3 and #4.
+ // Check if it's economically rational to mine this transaction rather than the ones it
+ // replaces and pays for its own relay fees. Enforce BIP125 Rules #3 and #4.
for (CTxMemPool::txiter it : allConflicting) {
nConflictingFees += it->GetModifiedFee();
nConflictingSize += it->GetTxSize();
}
- if (const auto err_string{PaysForRBF(nConflictingFees, nModifiedFees, nSize, hash)}) {
+ if (const auto err_string{PaysForRBF(nConflictingFees, nModifiedFees, nSize, ::incrementalRelayFee, hash)}) {
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "insufficient fee", *err_string);
}
}
@@ -1567,7 +1572,6 @@ static int64_t nTimeForks = 0;
static int64_t nTimeVerify = 0;
static int64_t nTimeConnect = 0;
static int64_t nTimeIndex = 0;
-static int64_t nTimeCallbacks = 0;
static int64_t nTimeTotal = 0;
static int64_t nBlocksTotal = 0;
@@ -1872,9 +1876,6 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state,
int64_t nTime5 = GetTimeMicros(); nTimeIndex += nTime5 - nTime4;
LogPrint(BCLog::BENCH, " - Index writing: %.2fms [%.2fs (%.2fms/blk)]\n", MILLI * (nTime5 - nTime4), nTimeIndex * MICRO, nTimeIndex * MILLI / nBlocksTotal);
- int64_t nTime6 = GetTimeMicros(); nTimeCallbacks += nTime6 - nTime5;
- LogPrint(BCLog::BENCH, " - Callbacks: %.2fms [%.2fs (%.2fms/blk)]\n", MILLI * (nTime6 - nTime5), nTimeCallbacks * MICRO, nTimeCallbacks * MILLI / nBlocksTotal);
-
TRACE7(validation, block_connected,
block.GetHash().ToString().c_str(),
pindex->nHeight,
diff --git a/src/validation.h b/src/validation.h
index 078b988052..a5aa6da39d 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -14,16 +14,10 @@
#include <arith_uint256.h>
#include <attributes.h>
#include <chain.h>
-#include <coins.h>
-#include <consensus/validation.h>
-#include <crypto/common.h> // for ReadLE64
#include <fs.h>
-#include <node/utxo_snapshot.h>
#include <policy/feerate.h>
#include <policy/packages.h>
-#include <protocol.h> // For CMessageHeader::MessageStartChars
#include <script/script_error.h>
-#include <serialize.h>
#include <sync.h>
#include <txdb.h>
#include <txmempool.h> // For CTxMemPool::cs
@@ -44,18 +38,13 @@
#include <vector>
class CChainState;
-class BlockValidationState;
class CBlockTreeDB;
-class CBlockUndo;
class CChainParams;
struct CCheckpointData;
-class CInv;
-class CConnman;
-class CScriptCheck;
class CTxMemPool;
class ChainstateManager;
+class SnapshotMetadata;
struct ChainTxData;
-
struct DisconnectedBlockTransactions;
struct PrecomputedTransactionData;
struct LockPoints;
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 7d194ae262..77757e79a3 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -472,7 +472,7 @@ static RPCHelpMan sendtoaddress()
RPCResult::Type::OBJ, "", "",
{
{RPCResult::Type::STR_HEX, "txid", "The transaction id."},
- {RPCResult::Type::STR, "fee reason", "The transaction fee reason."}
+ {RPCResult::Type::STR, "fee_reason", "The transaction fee reason."}
},
},
},
@@ -899,7 +899,7 @@ static RPCHelpMan sendmany()
{
{RPCResult::Type::STR_HEX, "txid", "The transaction id for the send. Only 1 transaction is created regardless of\n"
"the number of addresses."},
- {RPCResult::Type::STR, "fee reason", "The transaction fee reason."}
+ {RPCResult::Type::STR, "fee_reason", "The transaction fee reason."}
},
},
},
@@ -1213,7 +1213,7 @@ static RPCHelpMan listreceivedbyaddress()
{
{RPCResult::Type::OBJ, "", "",
{
- {RPCResult::Type::BOOL, "involvesWatchonly", "Only returns true if imported addresses were involved in transaction"},
+ {RPCResult::Type::BOOL, "involvesWatchonly", /* optional */ true, "Only returns true if imported addresses were involved in transaction"},
{RPCResult::Type::STR, "address", "The receiving address"},
{RPCResult::Type::STR_AMOUNT, "amount", "The total amount in " + CURRENCY_UNIT + " received by the address"},
{RPCResult::Type::NUM, "confirmations", "The number of confirmations of the most recent transaction included"},
@@ -1261,7 +1261,7 @@ static RPCHelpMan listreceivedbylabel()
{
{RPCResult::Type::OBJ, "", "",
{
- {RPCResult::Type::BOOL, "involvesWatchonly", "Only returns true if imported addresses were involved in transaction"},
+ {RPCResult::Type::BOOL, "involvesWatchonly", /* optional */ true, "Only returns true if imported addresses were involved in transaction"},
{RPCResult::Type::STR_AMOUNT, "amount", "The total amount received by addresses with this label"},
{RPCResult::Type::NUM, "confirmations", "The number of confirmations of the most recent transaction included"},
{RPCResult::Type::STR, "label", "The label of the receiving address. The default label is \"\""},
@@ -1388,20 +1388,24 @@ static const std::vector<RPCResult> TransactionDescriptionString()
{
return{{RPCResult::Type::NUM, "confirmations", "The number of confirmations for the transaction. Negative confirmations means the\n"
"transaction conflicted that many blocks ago."},
- {RPCResult::Type::BOOL, "generated", "Only present if transaction only input is a coinbase one."},
- {RPCResult::Type::BOOL, "trusted", "Only present if we consider transaction to be trusted and so safe to spend from."},
- {RPCResult::Type::STR_HEX, "blockhash", "The block hash containing the transaction."},
- {RPCResult::Type::NUM, "blockheight", "The block height containing the transaction."},
- {RPCResult::Type::NUM, "blockindex", "The index of the transaction in the block that includes it."},
- {RPCResult::Type::NUM_TIME, "blocktime", "The block time expressed in " + UNIX_EPOCH_TIME + "."},
+ {RPCResult::Type::BOOL, "generated", /* optional */ true, "Only present if transaction only input is a coinbase one."},
+ {RPCResult::Type::BOOL, "trusted", /* optional */ true, "Only present if we consider transaction to be trusted and so safe to spend from."},
+ {RPCResult::Type::STR_HEX, "blockhash", /* optional */ true, "The block hash containing the transaction."},
+ {RPCResult::Type::NUM, "blockheight", /* optional */ true, "The block height containing the transaction."},
+ {RPCResult::Type::NUM, "blockindex", /* optional */ true, "The index of the transaction in the block that includes it."},
+ {RPCResult::Type::NUM_TIME, "blocktime", /* optional */ true, "The block time expressed in " + UNIX_EPOCH_TIME + "."},
{RPCResult::Type::STR_HEX, "txid", "The transaction id."},
{RPCResult::Type::ARR, "walletconflicts", "Conflicting transaction ids.",
{
{RPCResult::Type::STR_HEX, "txid", "The transaction id."},
}},
+ {RPCResult::Type::STR_HEX, "replaced_by_txid", /* optional */ true, "The txid if this tx was replaced."},
+ {RPCResult::Type::STR_HEX, "replaces_txid", /* optional */ true, "The txid if the tx replaces one."},
+ {RPCResult::Type::STR, "comment", /* optional */ true, ""},
+ {RPCResult::Type::STR, "to", /* optional */ true, "If a comment to is associated with the transaction."},
{RPCResult::Type::NUM_TIME, "time", "The transaction time expressed in " + UNIX_EPOCH_TIME + "."},
{RPCResult::Type::NUM_TIME, "timereceived", "The time received expressed in " + UNIX_EPOCH_TIME + "."},
- {RPCResult::Type::STR, "comment", "If a comment is associated with the transaction, only present if not empty."},
+ {RPCResult::Type::STR, "comment", /* optional */ true, "If a comment is associated with the transaction, only present if not empty."},
{RPCResult::Type::STR, "bip125-replaceable", "(\"yes|no|unknown\") Whether this transaction could be replaced due to BIP125 (replace-by-fee);\n"
"may be unknown for unconfirmed transactions not in the mempool"}};
}
@@ -1423,7 +1427,7 @@ static RPCHelpMan listtransactions()
{
{RPCResult::Type::OBJ, "", "", Cat(Cat<std::vector<RPCResult>>(
{
- {RPCResult::Type::BOOL, "involvesWatchonly", "Only returns true if imported addresses were involved in transaction."},
+ {RPCResult::Type::BOOL, "involvesWatchonly", /* optional */ true, "Only returns true if imported addresses were involved in transaction."},
{RPCResult::Type::STR, "address", "The bitcoin address of the transaction."},
{RPCResult::Type::STR, "category", "The transaction category.\n"
"\"send\" Transactions sent.\n"
@@ -1433,14 +1437,14 @@ static RPCHelpMan listtransactions()
"\"orphan\" Orphaned coinbase transactions received."},
{RPCResult::Type::STR_AMOUNT, "amount", "The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and is positive\n"
"for all other categories"},
- {RPCResult::Type::STR, "label", "A comment for the address/transaction, if any"},
+ {RPCResult::Type::STR, "label", /* optional */ true, "A comment for the address/transaction, if any"},
{RPCResult::Type::NUM, "vout", "the vout value"},
- {RPCResult::Type::STR_AMOUNT, "fee", "The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the\n"
+ {RPCResult::Type::STR_AMOUNT, "fee", /* optional */ true, "The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the\n"
"'send' category of transactions."},
},
TransactionDescriptionString()),
{
- {RPCResult::Type::BOOL, "abandoned", "'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n"
+ {RPCResult::Type::BOOL, "abandoned", /* optional */ true, "'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n"
"'send' category of transactions."},
})},
}
@@ -1537,7 +1541,7 @@ static RPCHelpMan listsinceblock()
{
{RPCResult::Type::OBJ, "", "", Cat(Cat<std::vector<RPCResult>>(
{
- {RPCResult::Type::BOOL, "involvesWatchonly", "Only returns true if imported addresses were involved in transaction."},
+ {RPCResult::Type::BOOL, "involvesWatchonly", /* optional */ true, "Only returns true if imported addresses were involved in transaction."},
{RPCResult::Type::STR, "address", "The bitcoin address of the transaction."},
{RPCResult::Type::STR, "category", "The transaction category.\n"
"\"send\" Transactions sent.\n"
@@ -1548,18 +1552,17 @@ static RPCHelpMan listsinceblock()
{RPCResult::Type::STR_AMOUNT, "amount", "The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and is positive\n"
"for all other categories"},
{RPCResult::Type::NUM, "vout", "the vout value"},
- {RPCResult::Type::STR_AMOUNT, "fee", "The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the\n"
+ {RPCResult::Type::STR_AMOUNT, "fee", /* optional */ true, "The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the\n"
"'send' category of transactions."},
},
TransactionDescriptionString()),
{
- {RPCResult::Type::BOOL, "abandoned", "'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n"
+ {RPCResult::Type::BOOL, "abandoned", /* optional */ true, "'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n"
"'send' category of transactions."},
- {RPCResult::Type::STR, "label", "A comment for the address/transaction, if any"},
- {RPCResult::Type::STR, "to", "If a comment to is associated with the transaction."},
+ {RPCResult::Type::STR, "label", /* optional */ true, "A comment for the address/transaction, if any"},
})},
}},
- {RPCResult::Type::ARR, "removed", "<structure is the same as \"transactions\" above, only present if include_removed=true>\n"
+ {RPCResult::Type::ARR, "removed", /* optional */ true, "<structure is the same as \"transactions\" above, only present if include_removed=true>\n"
"Note: transactions that were re-added in the active chain will appear as-is in this array, and may thus have a positive confirmation count."
, {{RPCResult::Type::ELISION, "", ""},}},
{RPCResult::Type::STR_HEX, "lastblock", "The hash of the block (target_confirmations-1) from the best block on the main chain, or the genesis hash if the referenced block does not exist yet. This is typically used to feed back into listsinceblock the next time you call it. So you would generally use a target_confirmations of say 6, so you will be continually re-notified of transactions until they've reached 6 confirmations plus any new ones"},
@@ -1672,7 +1675,7 @@ static RPCHelpMan gettransaction()
RPCResult::Type::OBJ, "", "", Cat(Cat<std::vector<RPCResult>>(
{
{RPCResult::Type::STR_AMOUNT, "amount", "The amount in " + CURRENCY_UNIT},
- {RPCResult::Type::STR_AMOUNT, "fee", "The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the\n"
+ {RPCResult::Type::STR_AMOUNT, "fee", /* optional */ true, "The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the\n"
"'send' category of transactions."},
},
TransactionDescriptionString()),
@@ -1681,8 +1684,8 @@ static RPCHelpMan gettransaction()
{
{RPCResult::Type::OBJ, "", "",
{
- {RPCResult::Type::BOOL, "involvesWatchonly", "Only returns true if imported addresses were involved in transaction."},
- {RPCResult::Type::STR, "address", "The bitcoin address involved in the transaction."},
+ {RPCResult::Type::BOOL, "involvesWatchonly", /* optional */ true, "Only returns true if imported addresses were involved in transaction."},
+ {RPCResult::Type::STR, "address", /* optional */ true, "The bitcoin address involved in the transaction."},
{RPCResult::Type::STR, "category", "The transaction category.\n"
"\"send\" Transactions sent.\n"
"\"receive\" Non-coinbase transactions received.\n"
@@ -1690,16 +1693,16 @@ static RPCHelpMan gettransaction()
"\"immature\" Coinbase transactions received with 100 or fewer confirmations.\n"
"\"orphan\" Orphaned coinbase transactions received."},
{RPCResult::Type::STR_AMOUNT, "amount", "The amount in " + CURRENCY_UNIT},
- {RPCResult::Type::STR, "label", "A comment for the address/transaction, if any"},
+ {RPCResult::Type::STR, "label", /* optional */ true, "A comment for the address/transaction, if any"},
{RPCResult::Type::NUM, "vout", "the vout value"},
- {RPCResult::Type::STR_AMOUNT, "fee", "The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n"
+ {RPCResult::Type::STR_AMOUNT, "fee", /* optional */ true, "The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n"
"'send' category of transactions."},
- {RPCResult::Type::BOOL, "abandoned", "'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n"
+ {RPCResult::Type::BOOL, "abandoned", /* optional */ true, "'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n"
"'send' category of transactions."},
}},
}},
{RPCResult::Type::STR_HEX, "hex", "Raw data for transaction"},
- {RPCResult::Type::OBJ, "decoded", "Optional, the decoded transaction (only present when `verbose` is passed)",
+ {RPCResult::Type::OBJ, "decoded", /* optional */ true, "The decoded transaction (only present when `verbose` is passed)",
{
{RPCResult::Type::ELISION, "", "Equivalent to the RPC decoderawtransaction method, or the RPC getrawtransaction method when `verbose` is passed."},
}},
@@ -2362,9 +2365,9 @@ static RPCHelpMan getbalances()
{RPCResult::Type::STR_AMOUNT, "trusted", "trusted balance (outputs created by the wallet or confirmed outputs)"},
{RPCResult::Type::STR_AMOUNT, "untrusted_pending", "untrusted pending balance (outputs created by others that are in the mempool)"},
{RPCResult::Type::STR_AMOUNT, "immature", "balance from immature coinbase outputs"},
- {RPCResult::Type::STR_AMOUNT, "used", "(only present if avoid_reuse is set) balance from coins sent to addresses that were previously spent from (potentially privacy violating)"},
+ {RPCResult::Type::STR_AMOUNT, "used", /* optional */ true, "(only present if avoid_reuse is set) balance from coins sent to addresses that were previously spent from (potentially privacy violating)"},
}},
- {RPCResult::Type::OBJ, "watchonly", "watchonly balances (not present if wallet does not watch anything)",
+ {RPCResult::Type::OBJ, "watchonly", /* optional */ true, "watchonly balances (not present if wallet does not watch anything)",
{
{RPCResult::Type::STR_AMOUNT, "trusted", "trusted balance (outputs created by the wallet or confirmed outputs)"},
{RPCResult::Type::STR_AMOUNT, "untrusted_pending", "untrusted pending balance (outputs created by others that are in the mempool)"},
@@ -2431,9 +2434,9 @@ static RPCHelpMan getwalletinfo()
{RPCResult::Type::STR_AMOUNT, "unconfirmed_balance", "DEPRECATED. Identical to getbalances().mine.untrusted_pending"},
{RPCResult::Type::STR_AMOUNT, "immature_balance", "DEPRECATED. Identical to getbalances().mine.immature"},
{RPCResult::Type::NUM, "txcount", "the total number of transactions in the wallet"},
- {RPCResult::Type::NUM_TIME, "keypoololdest", "the " + UNIX_EPOCH_TIME + " of the oldest pre-generated key in the key pool. Legacy wallets only."},
+ {RPCResult::Type::NUM_TIME, "keypoololdest", /* optional */ true, "the " + UNIX_EPOCH_TIME + " of the oldest pre-generated key in the key pool. Legacy wallets only."},
{RPCResult::Type::NUM, "keypoolsize", "how many new keys are pre-generated (only counts external keys)"},
- {RPCResult::Type::NUM, "keypoolsize_hd_internal", "how many new keys are pre-generated for internal use (used for change outputs, only appears if the wallet is using this feature, otherwise external keys are used)"},
+ {RPCResult::Type::NUM, "keypoolsize_hd_internal", /* optional */ true, "how many new keys are pre-generated for internal use (used for change outputs, only appears if the wallet is using this feature, otherwise external keys are used)"},
{RPCResult::Type::NUM_TIME, "unlocked_until", /* optional */ true, "the " + UNIX_EPOCH_TIME + " until which the wallet is unlocked for transfers, or 0 if the wallet is locked (only present for passphrase-encrypted wallets)"},
{RPCResult::Type::STR_AMOUNT, "paytxfee", "the transaction fee configuration, set in " + CURRENCY_UNIT + "/kvB"},
{RPCResult::Type::STR_HEX, "hdseedid", /* optional */ true, "the Hash160 of the HD seed (only present when HD is enabled)"},
@@ -2955,20 +2958,20 @@ static RPCHelpMan listunspent()
{
{RPCResult::Type::STR_HEX, "txid", "the transaction id"},
{RPCResult::Type::NUM, "vout", "the vout value"},
- {RPCResult::Type::STR, "address", "the bitcoin address"},
- {RPCResult::Type::STR, "label", "The associated label, or \"\" for the default label"},
+ {RPCResult::Type::STR, "address", /* optional */ true, "the bitcoin address"},
+ {RPCResult::Type::STR, "label", /* optional */ true, "The associated label, or \"\" for the default label"},
{RPCResult::Type::STR, "scriptPubKey", "the script key"},
{RPCResult::Type::STR_AMOUNT, "amount", "the transaction output amount in " + CURRENCY_UNIT},
{RPCResult::Type::NUM, "confirmations", "The number of confirmations"},
{RPCResult::Type::NUM, "ancestorcount", /* optional */ true, "The number of in-mempool ancestor transactions, including this one (if transaction is in the mempool)"},
{RPCResult::Type::NUM, "ancestorsize", /* optional */ true, "The virtual transaction size of in-mempool ancestors, including this one (if transaction is in the mempool)"},
{RPCResult::Type::STR_AMOUNT, "ancestorfees", /* optional */ true, "The total fees of in-mempool ancestors (including this one) with fee deltas used for mining priority in " + CURRENCY_ATOM + " (if transaction is in the mempool)"},
- {RPCResult::Type::STR_HEX, "redeemScript", "The redeemScript if scriptPubKey is P2SH"},
- {RPCResult::Type::STR, "witnessScript", "witnessScript if the scriptPubKey is P2WSH or P2SH-P2WSH"},
+ {RPCResult::Type::STR_HEX, "redeemScript", /* optional */ true, "The redeemScript if scriptPubKey is P2SH"},
+ {RPCResult::Type::STR, "witnessScript", /* optional */ true, "witnessScript if the scriptPubKey is P2WSH or P2SH-P2WSH"},
{RPCResult::Type::BOOL, "spendable", "Whether we have the private keys to spend this output"},
{RPCResult::Type::BOOL, "solvable", "Whether we know how to spend this output, ignoring the lack of keys"},
- {RPCResult::Type::BOOL, "reused", "(only present if avoid_reuse is set) Whether this output is reused/dirty (sent to an address that was previously spent from)"},
- {RPCResult::Type::STR, "desc", "(only when solvable) A descriptor for spending this output"},
+ {RPCResult::Type::BOOL, "reused", /* optional */ true, "(only present if avoid_reuse is set) Whether this output is reused/dirty (sent to an address that was previously spent from)"},
+ {RPCResult::Type::STR, "desc", /* optional */ true, "(only when solvable) A descriptor for spending this output"},
{RPCResult::Type::BOOL, "safe", "Whether this output is considered safe to spend. Unconfirmed transactions\n"
"from outside keys and unconfirmed replacement transactions are considered unsafe\n"
"and are not eligible for spending by fundrawtransaction and sendtoaddress."},
@@ -3442,6 +3445,10 @@ RPCHelpMan signrawtransactionwithwallet()
{
{RPCResult::Type::STR_HEX, "txid", "The hash of the referenced, previous transaction"},
{RPCResult::Type::NUM, "vout", "The index of the output to spent and used as input"},
+ {RPCResult::Type::ARR, "witness", "",
+ {
+ {RPCResult::Type::STR_HEX, "witness", ""},
+ }},
{RPCResult::Type::STR_HEX, "scriptSig", "The hex-encoded signature script"},
{RPCResult::Type::NUM, "sequence", "Script sequence number"},
{RPCResult::Type::STR, "error", "Verification or signing error related to the input"},
@@ -4188,9 +4195,9 @@ static RPCHelpMan send()
RPCResult::Type::OBJ, "", "",
{
{RPCResult::Type::BOOL, "complete", "If the transaction has a complete set of signatures"},
- {RPCResult::Type::STR_HEX, "txid", "The transaction id for the send. Only 1 transaction is created regardless of the number of addresses."},
- {RPCResult::Type::STR_HEX, "hex", "If add_to_wallet is false, the hex-encoded raw transaction with signature(s)"},
- {RPCResult::Type::STR, "psbt", "If more signatures are needed, or if add_to_wallet is false, the base64-encoded (partially) signed transaction"}
+ {RPCResult::Type::STR_HEX, "txid", /* optional */ true, "The transaction id for the send. Only 1 transaction is created regardless of the number of addresses."},
+ {RPCResult::Type::STR_HEX, "hex", /* optional */ true, "If add_to_wallet is false, the hex-encoded raw transaction with signature(s)"},
+ {RPCResult::Type::STR, "psbt", /* optional */ true, "If more signatures are needed, or if add_to_wallet is false, the base64-encoded (partially) signed transaction"}
}
},
RPCExamples{""
diff --git a/test/functional/p2p_addr_relay.py b/test/functional/p2p_addr_relay.py
index e93698b08e..15b90fa61f 100755
--- a/test/functional/p2p_addr_relay.py
+++ b/test/functional/p2p_addr_relay.py
@@ -6,22 +6,22 @@
Test addr relay
"""
+import random
+import time
+
from test_framework.messages import (
CAddress,
- NODE_NETWORK,
- NODE_WITNESS,
msg_addr,
msg_getaddr,
- msg_verack
+ msg_verack,
)
from test_framework.p2p import (
P2PInterface,
p2p_lock,
+ P2P_SERVICES,
)
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, assert_greater_than
-import random
-import time
class AddrReceiver(P2PInterface):
@@ -96,7 +96,7 @@ class AddrTest(BitcoinTestFramework):
for i in range(num):
addr = CAddress()
addr.time = self.mocktime + i
- addr.nServices = NODE_NETWORK | NODE_WITNESS
+ addr.nServices = P2P_SERVICES
addr.ip = f"123.123.123.{self.counter % 256}"
addr.port = 8333 + i
addrs.append(addr)
@@ -111,7 +111,7 @@ class AddrTest(BitcoinTestFramework):
for i in range(num):
addr = CAddress()
addr.time = self.mocktime + i
- addr.nServices = NODE_NETWORK | NODE_WITNESS
+ addr.nServices = P2P_SERVICES
addr.ip = f"{random.randrange(128,169)}.{random.randrange(1,255)}.{random.randrange(1,255)}.{random.randrange(1,255)}"
addr.port = 8333
addrs.append(addr)
diff --git a/test/functional/p2p_addrfetch.py b/test/functional/p2p_addrfetch.py
index 2a0f6432a9..25efd50040 100755
--- a/test/functional/p2p_addrfetch.py
+++ b/test/functional/p2p_addrfetch.py
@@ -8,14 +8,21 @@ Test p2p addr-fetch connections
import time
-from test_framework.messages import msg_addr, CAddress, NODE_NETWORK, NODE_WITNESS
-from test_framework.p2p import P2PInterface, p2p_lock
+from test_framework.messages import (
+ CAddress,
+ msg_addr,
+)
+from test_framework.p2p import (
+ P2PInterface,
+ p2p_lock,
+ P2P_SERVICES,
+)
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal
ADDR = CAddress()
ADDR.time = int(time.time())
-ADDR.nServices = NODE_NETWORK | NODE_WITNESS
+ADDR.nServices = P2P_SERVICES
ADDR.ip = "192.0.0.8"
ADDR.port = 18444
diff --git a/test/functional/p2p_addrv2_relay.py b/test/functional/p2p_addrv2_relay.py
index 32c1d42b1c..3833c58680 100755
--- a/test/functional/p2p_addrv2_relay.py
+++ b/test/functional/p2p_addrv2_relay.py
@@ -11,10 +11,11 @@ import time
from test_framework.messages import (
CAddress,
msg_addrv2,
- NODE_NETWORK,
- NODE_WITNESS,
)
-from test_framework.p2p import P2PInterface
+from test_framework.p2p import (
+ P2PInterface,
+ P2P_SERVICES,
+)
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal
@@ -24,7 +25,7 @@ ADDRS = []
for i in range(10):
addr = CAddress()
addr.time = int(time.time()) + i
- addr.nServices = NODE_NETWORK | NODE_WITNESS
+ addr.nServices = P2P_SERVICES
# Add one I2P address at an arbitrary position.
if i == 5:
addr.net = addr.NET_I2P
diff --git a/test/functional/p2p_segwit.py b/test/functional/p2p_segwit.py
index a71f736bd6..26f769e646 100755
--- a/test/functional/p2p_segwit.py
+++ b/test/functional/p2p_segwit.py
@@ -43,6 +43,7 @@ from test_framework.messages import (
from test_framework.p2p import (
P2PInterface,
p2p_lock,
+ P2P_SERVICES,
)
from test_framework.script import (
CScript,
@@ -224,14 +225,14 @@ class SegWitTest(BitcoinTestFramework):
def run_test(self):
# Setup the p2p connections
- # self.test_node sets NODE_WITNESS|NODE_NETWORK
- self.test_node = self.nodes[0].add_p2p_connection(TestP2PConn(), services=NODE_NETWORK | NODE_WITNESS)
+ # self.test_node sets P2P_SERVICES, i.e. NODE_WITNESS | NODE_NETWORK
+ self.test_node = self.nodes[0].add_p2p_connection(TestP2PConn(), services=P2P_SERVICES)
# self.old_node sets only NODE_NETWORK
self.old_node = self.nodes[0].add_p2p_connection(TestP2PConn(), services=NODE_NETWORK)
# self.std_node is for testing node1 (fRequireStandard=true)
- self.std_node = self.nodes[1].add_p2p_connection(TestP2PConn(), services=NODE_NETWORK | NODE_WITNESS)
+ self.std_node = self.nodes[1].add_p2p_connection(TestP2PConn(), services=P2P_SERVICES)
# self.std_wtx_node is for testing node1 with wtxid relay
- self.std_wtx_node = self.nodes[1].add_p2p_connection(TestP2PConn(wtxidrelay=True), services=NODE_NETWORK | NODE_WITNESS)
+ self.std_wtx_node = self.nodes[1].add_p2p_connection(TestP2PConn(wtxidrelay=True), services=P2P_SERVICES)
assert self.test_node.nServices & NODE_WITNESS != 0
@@ -2017,8 +2018,8 @@ class SegWitTest(BitcoinTestFramework):
@subtest # type: ignore
def test_wtxid_relay(self):
# Use brand new nodes to avoid contamination from earlier tests
- self.wtx_node = self.nodes[0].add_p2p_connection(TestP2PConn(wtxidrelay=True), services=NODE_NETWORK | NODE_WITNESS)
- self.tx_node = self.nodes[0].add_p2p_connection(TestP2PConn(wtxidrelay=False), services=NODE_NETWORK | NODE_WITNESS)
+ self.wtx_node = self.nodes[0].add_p2p_connection(TestP2PConn(wtxidrelay=True), services=P2P_SERVICES)
+ self.tx_node = self.nodes[0].add_p2p_connection(TestP2PConn(wtxidrelay=False), services=P2P_SERVICES)
# Check wtxidrelay feature negotiation message through connecting a new peer
def received_wtxidrelay():
diff --git a/test/functional/rpc_net.py b/test/functional/rpc_net.py
index 3fcca97cb7..0f3bbce54c 100755
--- a/test/functional/rpc_net.py
+++ b/test/functional/rpc_net.py
@@ -12,11 +12,10 @@ from itertools import product
import time
from test_framework.blocktools import COINBASE_MATURITY
-from test_framework.p2p import P2PInterface
import test_framework.messages
-from test_framework.messages import (
- NODE_NETWORK,
- NODE_WITNESS,
+from test_framework.p2p import (
+ P2PInterface,
+ P2P_SERVICES,
)
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
@@ -189,7 +188,6 @@ class NetTest(BitcoinTestFramework):
def test_getnodeaddresses(self):
self.log.info("Test getnodeaddresses")
self.nodes[0].add_p2p_connection(P2PInterface())
- services = NODE_NETWORK | NODE_WITNESS
# Add an IPv6 address to the address manager.
ipv6_addr = "1233:3432:2434:2343:3234:2345:6546:4534"
@@ -217,7 +215,7 @@ class NetTest(BitcoinTestFramework):
assert_greater_than(10000, len(node_addresses))
for a in node_addresses:
assert_greater_than(a["time"], 1527811200) # 1st June 2018
- assert_equal(a["services"], services)
+ assert_equal(a["services"], P2P_SERVICES)
assert a["address"] in imported_addrs
assert_equal(a["port"], 8333)
assert_equal(a["network"], "ipv4")
@@ -228,7 +226,7 @@ class NetTest(BitcoinTestFramework):
assert_equal(res[0]["address"], ipv6_addr)
assert_equal(res[0]["network"], "ipv6")
assert_equal(res[0]["port"], 8333)
- assert_equal(res[0]["services"], services)
+ assert_equal(res[0]["services"], P2P_SERVICES)
# Test for the absence of onion and I2P addresses.
for network in ["onion", "i2p"]:
diff --git a/test/functional/test_framework/p2p.py b/test/functional/test_framework/p2p.py
index ec563cc290..78c63b57a1 100755
--- a/test/functional/test_framework/p2p.py
+++ b/test/functional/test_framework/p2p.py
@@ -356,7 +356,7 @@ class P2PInterface(P2PConnection):
return create_conn
- def peer_accept_connection(self, *args, services=NODE_NETWORK | NODE_WITNESS, **kwargs):
+ def peer_accept_connection(self, *args, services=P2P_SERVICES, **kwargs):
create_conn = super().peer_accept_connection(*args, **kwargs)
self.peer_connect_send_version(services)
diff --git a/test/get_previous_releases.py b/test/get_previous_releases.py
index e92bb402b5..62fcad04b3 100755
--- a/test/get_previous_releases.py
+++ b/test/get_previous_releases.py
@@ -190,6 +190,7 @@ def check_host(args) -> int:
'aarch64-*-linux*': 'aarch64-linux-gnu',
'x86_64-*-linux*': 'x86_64-linux-gnu',
'x86_64-apple-darwin*': 'osx64',
+ 'aarch64-apple-darwin*': 'osx64',
}
args.platform = ''
for pattern, target in platforms.items():
diff --git a/test/sanitizer_suppressions/ubsan b/test/sanitizer_suppressions/ubsan
index 63e7c57ddb..b52e105a33 100644
--- a/test/sanitizer_suppressions/ubsan
+++ b/test/sanitizer_suppressions/ubsan
@@ -5,8 +5,6 @@
# names can be used.
# See https://github.com/google/sanitizers/issues/1364
signed-integer-overflow:txmempool.cpp
-# nLastSuccess read from peers.dat might cause an overflow in IsTerrible
-signed-integer-overflow:addrman.cpp
# https://github.com/bitcoin/bitcoin/pull/21798#issuecomment-829180719
signed-integer-overflow:policy/feerate.cpp