Skip to content

Commit cfc4086

Browse files
Merge dashpay#5989: backport: Merge bitcoin#21718, 21759, 21872
00e556a Merge bitcoin#21872: net: Sanitize message type for logging (MarcoFalke) be9781d Merge bitcoin#21759: wallet: document coin selection code (fanquake) ea347e6 Merge bitcoin#21718: rpc: Improve error message for getblock invalid datatype. (fanquake) Pull request description: bitcoin backports Top commit has no ACKs. Tree-SHA512: 110f139b827ae9e489858c6110bec525e0fe08e7a1d0bf98fccb4e0fa2f532ae1c307eecb97975d02d3252f6c36f2b1b0f10367b6d0cbc8f430ac27e0c938758
2 parents df6d666 + 00e556a commit cfc4086

File tree

7 files changed

+153
-45
lines changed

7 files changed

+153
-45
lines changed

src/net.cpp

+6-6
Original file line numberDiff line numberDiff line change
@@ -752,19 +752,19 @@ int V1TransportDeserializer::readHeader(Span<const uint8_t> msg_bytes)
752752
hdrbuf >> hdr;
753753
}
754754
catch (const std::exception&) {
755-
LogPrint(BCLog::NET, "HEADER ERROR - UNABLE TO DESERIALIZE, peer=%d\n", m_node_id);
755+
LogPrint(BCLog::NET, "Header error: Unable to deserialize, peer=%d\n", m_node_id);
756756
return -1;
757757
}
758758

759759
// Check start string, network magic
760760
if (memcmp(hdr.pchMessageStart, m_chain_params.MessageStart(), CMessageHeader::MESSAGE_START_SIZE) != 0) {
761-
LogPrint(BCLog::NET, "HEADER ERROR - MESSAGESTART (%s, %u bytes), received %s, peer=%d\n", hdr.GetCommand(), hdr.nMessageSize, HexStr(hdr.pchMessageStart), m_node_id);
761+
LogPrint(BCLog::NET, "Header error: Wrong MessageStart %s received, peer=%d\n", HexStr(hdr.pchMessageStart), m_node_id);
762762
return -1;
763763
}
764764

765765
// reject messages larger than MAX_SIZE or MAX_PROTOCOL_MESSAGE_LENGTH
766766
if (hdr.nMessageSize > MAX_SIZE || hdr.nMessageSize > MAX_PROTOCOL_MESSAGE_LENGTH) {
767-
LogPrint(BCLog::NET, "HEADER ERROR - SIZE (%s, %u bytes), peer=%d\n", hdr.GetCommand(), hdr.nMessageSize, m_node_id);
767+
LogPrint(BCLog::NET, "Header error: Size too large (%s, %u bytes), peer=%d\n", SanitizeString(hdr.GetCommand()), hdr.nMessageSize, m_node_id);
768768
return -1;
769769
}
770770

@@ -817,16 +817,16 @@ std::optional<CNetMessage> V1TransportDeserializer::GetMessage(const std::chrono
817817

818818
// Check checksum and header command string
819819
if (memcmp(hash.begin(), hdr.pchChecksum, CMessageHeader::CHECKSUM_SIZE) != 0) {
820-
LogPrint(BCLog::NET, "CHECKSUM ERROR (%s, %u bytes), expected %s was %s, peer=%d\n",
820+
LogPrint(BCLog::NET, "Header error: Wrong checksum (%s, %u bytes), expected %s was %s, peer=%d\n",
821821
SanitizeString(msg->m_command), msg->m_message_size,
822822
HexStr(Span{hash}.first(CMessageHeader::CHECKSUM_SIZE)),
823823
HexStr(hdr.pchChecksum),
824824
m_node_id);
825825
out_err_raw_size = msg->m_raw_message_size;
826826
msg.reset();
827827
} else if (!hdr.IsCommandValid()) {
828-
LogPrint(BCLog::NET, "HEADER ERROR - COMMAND (%s, %u bytes), peer=%d\n",
829-
hdr.GetCommand(), msg->m_message_size, m_node_id);
828+
LogPrint(BCLog::NET, "Header error: Invalid message type (%s, %u bytes), peer=%d\n",
829+
SanitizeString(hdr.GetCommand()), msg->m_message_size, m_node_id);
830830
out_err_raw_size = msg->m_raw_message_size;
831831
msg.reset();
832832
}

src/rpc/blockchain.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -1242,10 +1242,11 @@ static RPCHelpMan getblock()
12421242

12431243
int verbosity = 1;
12441244
if (!request.params[1].isNull()) {
1245-
if(request.params[1].isNum())
1246-
verbosity = request.params[1].get_int();
1247-
else
1245+
if (request.params[1].isBool()) {
12481246
verbosity = request.params[1].get_bool() ? 1 : 0;
1247+
} else {
1248+
verbosity = request.params[1].get_int();
1249+
}
12491250
}
12501251

12511252
const NodeContext& node = EnsureAnyNodeContext(request.context);

src/wallet/coinselection.h

+29-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ static constexpr CAmount MIN_CHANGE{COIN / 100};
1515
//! final minimum change amount after paying for fees
1616
static const CAmount MIN_FINAL_CHANGE = MIN_CHANGE/2;
1717

18+
/** A UTXO under consideration for use in funding a new transaction. */
1819
class CInputCoin {
1920
public:
2021
CInputCoin(const CTransactionRef& tx, unsigned int i)
@@ -56,31 +57,58 @@ class CInputCoin {
5657
}
5758
};
5859

60+
/** Parameters for filtering which OutputGroups we may use in coin selection.
61+
* We start by being very selective and requiring multiple confirmations and
62+
* then get more permissive if we cannot fund the transaction. */
5963
struct CoinEligibilityFilter
6064
{
65+
/** Minimum number of confirmations for outputs that we sent to ourselves.
66+
* We may use unconfirmed UTXOs sent from ourselves, e.g. change outputs. */
6167
const int conf_mine;
68+
/** Minimum number of confirmations for outputs received from a different
69+
* wallet. We never spend unconfirmed foreign outputs as we cannot rely on these funds yet. */
6270
const int conf_theirs;
71+
/** Maximum number of unconfirmed ancestors aggregated across all UTXOs in an OutputGroup. */
6372
const uint64_t max_ancestors;
73+
/** Maximum number of descendants that a single UTXO in the OutputGroup may have. */
6474
const uint64_t max_descendants;
65-
const bool m_include_partial_groups{false}; //! Include partial destination groups when avoid_reuse and there are full groups
75+
/** When avoid_reuse=true and there are full groups (OUTPUT_GROUP_MAX_ENTRIES), whether or not to use any partial groups.*/
76+
const bool m_include_partial_groups{false};
6677

6778
CoinEligibilityFilter(int conf_mine, int conf_theirs, uint64_t max_ancestors) : conf_mine(conf_mine), conf_theirs(conf_theirs), max_ancestors(max_ancestors), max_descendants(max_ancestors) {}
6879
CoinEligibilityFilter(int conf_mine, int conf_theirs, uint64_t max_ancestors, uint64_t max_descendants) : conf_mine(conf_mine), conf_theirs(conf_theirs), max_ancestors(max_ancestors), max_descendants(max_descendants) {}
6980
CoinEligibilityFilter(int conf_mine, int conf_theirs, uint64_t max_ancestors, uint64_t max_descendants, bool include_partial) : conf_mine(conf_mine), conf_theirs(conf_theirs), max_ancestors(max_ancestors), max_descendants(max_descendants), m_include_partial_groups(include_partial) {}
7081
};
7182

83+
/** A group of UTXOs paid to the same output script. */
7284
struct OutputGroup
7385
{
86+
/** The list of UTXOs contained in this output group. */
7487
std::vector<CInputCoin> m_outputs;
88+
/** Whether the UTXOs were sent by the wallet to itself. This is relevant because we may want at
89+
* least a certain number of confirmations on UTXOs received from outside wallets while trusting
90+
* our own UTXOs more. */
7591
bool m_from_me{true};
92+
/** The total value of the UTXOs in sum. */
7693
CAmount m_value{0};
94+
/** The minimum number of confirmations the UTXOs in the group have. Unconfirmed is 0. */
7795
int m_depth{999};
96+
/** The aggregated count of unconfirmed ancestors of all UTXOs in this
97+
* group. Not deduplicated and may overestimate when ancestors are shared. */
7898
size_t m_ancestors{0};
99+
/** The maximum count of descendants of a single UTXO in this output group. */
79100
size_t m_descendants{0};
101+
/** The value of the UTXOs after deducting the cost of spending them at the effective feerate. */
80102
CAmount effective_value{0};
103+
/** The fee to spend these UTXOs at the effective feerate. */
81104
CAmount fee{0};
105+
/** The target feerate of the transaction we're trying to build. */
82106
CFeeRate m_effective_feerate{0};
107+
/** The fee to spend these UTXOs at the long term feerate. */
83108
CAmount long_term_fee{0};
109+
/** The feerate for spending a created change output eventually (i.e. not urgently, and thus at
110+
* a lower feerate). Calculated using long term fee estimate. This is used to decide whether
111+
* it could be economical to create a change output. */
84112
CFeeRate m_long_term_feerate{0};
85113

86114
OutputGroup() {}

src/wallet/wallet.cpp

+49-13
Original file line numberDiff line numberDiff line change
@@ -2877,7 +2877,7 @@ bool CWallet::SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAm
28772877
}
28782878
}
28792879

2880-
// remove preset inputs from vCoins
2880+
// remove preset inputs from vCoins so that Coin Selection doesn't pick them.
28812881
for (std::vector<COutput>::iterator it = vCoins.begin(); it != vCoins.end() && coin_control.HasSelected();)
28822882
{
28832883
if (setPresetCoins.count(it->GetInputCoin()))
@@ -2889,9 +2889,9 @@ bool CWallet::SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAm
28892889
unsigned int limit_ancestor_count = 0;
28902890
unsigned int limit_descendant_count = 0;
28912891
chain().getPackageLimits(limit_ancestor_count, limit_descendant_count);
2892-
size_t max_ancestors = (size_t)std::max<int64_t>(1, limit_ancestor_count);
2893-
size_t max_descendants = (size_t)std::max<int64_t>(1, limit_descendant_count);
2894-
bool fRejectLongChains = gArgs.GetBoolArg("-walletrejectlongchains", DEFAULT_WALLET_REJECT_LONG_CHAINS);
2892+
const size_t max_ancestors = (size_t)std::max<int64_t>(1, limit_ancestor_count);
2893+
const size_t max_descendants = (size_t)std::max<int64_t>(1, limit_descendant_count);
2894+
const bool fRejectLongChains = gArgs.GetBoolArg("-walletrejectlongchains", DEFAULT_WALLET_REJECT_LONG_CHAINS);
28952895

28962896
// form groups from remaining coins; note that preset coins will not
28972897
// automatically have their associated (same address) coins included
@@ -2901,16 +2901,52 @@ bool CWallet::SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAm
29012901
// explicitly shuffling the outputs before processing
29022902
Shuffle(vCoins.begin(), vCoins.end(), FastRandomContext());
29032903
}
2904-
bool res = value_to_select <= 0 ||
2905-
SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(1, 6, 0), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used, nCoinType) ||
2906-
SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(1, 1, 0), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used, nCoinType) ||
2907-
(m_spend_zero_conf_change && SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(0, 1, 2), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used, nCoinType)) ||
2908-
(m_spend_zero_conf_change && SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(0, 1, std::min((size_t)4, max_ancestors/3), std::min((size_t)4, max_descendants/3)), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used, nCoinType)) ||
2909-
(m_spend_zero_conf_change && SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(0, 1, max_ancestors/2, max_descendants/2), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used, nCoinType)) ||
2910-
(m_spend_zero_conf_change && SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(0, 1, max_ancestors-1, max_descendants-1, true /* include_partial_groups */), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used, nCoinType)) ||
2911-
(m_spend_zero_conf_change && !fRejectLongChains && SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(0, 1, std::numeric_limits<uint64_t>::max(), std::numeric_limits<uint64_t>::max(), true /* include_partial_groups */), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used, nCoinType));
2904+
// Coin Selection attempts to select inputs from a pool of eligible UTXOs to fund the
2905+
// transaction at a target feerate. If an attempt fails, more attempts may be made using a more
2906+
// permissive CoinEligibilityFilter.
2907+
const bool res = [&] {
2908+
// Pre-selected inputs already cover the target amount.
2909+
if (value_to_select <= 0) return true;
2910+
2911+
// If possible, fund the transaction with confirmed UTXOs only. Prefer at least six
2912+
// confirmations on outputs received from other wallets and only spend confirmed change.
2913+
if (SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(1, 6, 0), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used, nCoinType)) return true;
2914+
if (SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(1, 1, 0), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used, nCoinType)) return true;
2915+
2916+
// Fall back to using zero confirmation change (but with as few ancestors in the mempool as
2917+
// possible) if we cannot fund the transaction otherwise. We never spend unconfirmed
2918+
// outputs received from other wallets.
2919+
if (m_spend_zero_conf_change) {
2920+
if (SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(0, 1, 2), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used, nCoinType)) return true;
2921+
if (SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(0, 1, std::min((size_t)4, max_ancestors/3), std::min((size_t)4, max_descendants/3)),
2922+
vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used, nCoinType)) {
2923+
return true;
2924+
}
2925+
if (SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(0, 1, max_ancestors/2, max_descendants/2),
2926+
vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used, nCoinType)) {
2927+
return true;
2928+
}
2929+
// If partial groups are allowed, relax the requirement of spending OutputGroups (groups
2930+
// of UTXOs sent to the same address, which are obviously controlled by a single wallet)
2931+
// in their entirety.
2932+
if (SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(0, 1, max_ancestors-1, max_descendants-1, true /* include_partial_groups */),
2933+
vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used, nCoinType)) {
2934+
return true;
2935+
}
2936+
// Try with unlimited ancestors/descendants. The transaction will still need to meet
2937+
// mempool ancestor/descendant policy to be accepted to mempool and broadcasted, but
2938+
// OutputGroups use heuristics that may overestimate ancestor/descendant counts.
2939+
if (!fRejectLongChains && SelectCoinsMinConf(value_to_select,
2940+
CoinEligibilityFilter(0, 1, std::numeric_limits<uint64_t>::max(), std::numeric_limits<uint64_t>::max(), true /* include_partial_groups */),
2941+
vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used, nCoinType)) {
2942+
return true;
2943+
}
2944+
}
2945+
// Coin Selection failed.
2946+
return false;
2947+
}();
29122948

2913-
// because SelectCoinsMinConf clears the setCoinsRet, we now add the possible inputs to the coinset
2949+
// SelectCoinsMinConf clears setCoinsRet, so add the preset inputs from coin_control to the coinset
29142950
util::insert(setCoinsRet, setPresetCoins);
29152951

29162952
// add preset inputs to the total value selected

0 commit comments

Comments
 (0)