https://github.com/bitcoin/bitcoin/pull/28765

Motivation

This PR is part of the Erlay, and it targets keeping track of the per-peer reconciliation sets that will be used exchange transactions using Erlay, that is, what transactions are kept in the sets that will be reconciled and which ones are sent using the traditional transaction exchange protocol (fanout)

Thoughts/Questions

txreconciliation.{h, cpp}

GetFanoutTargets

I’m a bit confused abut how this method works. Let’s dissect it and try to understand it bit by bit:

double integer_part;        
double fractional_peer = std::modf(limit, &integer_part);

It looks like first we are splitting the limit, which is a function parameter into its integral and fractional parts. The name of the variables there is wrong. It should be integral_part and fractional_part.

After that, we are trying to define how many items we will be dealing with, with depends on how big the integral_part is, that is, whether we round up or down I think

const bool add_extra = deterministic_randomizer_with_wtxid.Finalize() > fractional_peer * double(UINT64_MAX);
const size_t targets = add_extra ? size_t(integer_part): size_t(integer_part) + 1;

I’m not following how the computation of add_extra works, nor why we are using double(UINT64_MAX) here. However I think targets is using add_extra wrongly, either that, or the name should not not_add_extra (i.e. +1 is being used in the negative case).

Next we are defining a set of peers (called best_peers) and, I think, defining the comparison function for the collection so it can be properly sorted

auto cmp_by_key = [](const std::pair<uint64_t, NodeId>& left, const std::pair<uint64_t, NodeId>& right) {
            return left.first > right.first;
};
std::set<std::pair<uint64_t, NodeId>, decltype(cmp_by_key)> best_peers(cmp_by_key);

Next we iterate over the reconciliation states of our peers (m_states) and order the ones that match the direction we are interested in (m_we_initiate == we_initiate). For the we use the previously generated set which will sort them based on their hash_key

for (auto indexed_state : m_states) {
    const auto cur_state = std::get_if<TxReconciliationState>(&indexed_state.second);
    if (cur_state && cur_state->m_we_initiate == we_initiate) {
        uint64_t hash_key = deterministic_randomizer_with_wtxid.Write(cur_state->m_k0).Finalize();
        best_peers.insert(std::make_pair(hash_key, indexed_state.first));
    }
}