Why is the mempool indexed by descendant_score? #14294

issue RHavar opened this issue on September 22, 2018
  1. RHavar commented at 11:59 PM on September 22, 2018: contributor

    i.e. https://github.com/bitcoin/bitcoin/blob/920c090f63f4990bf0f3b3d1a6d3d8a8bcd14ba0/src/txmempool.h#L466-L471

    I'm probably missing some other usages, but I can only find it in CTxMemPool::TrimToSize

    https://github.com/bitcoin/bitcoin/blob/920c090f63f4990bf0f3b3d1a6d3d8a8bcd14ba0/src/txmempool.cpp#L1024

    which I don't really understand. Wouldn't using ancestor_score make a lot more sense?

  2. MarcoFalke commented at 12:06 AM on September 23, 2018: member

    I guess it returns the max, so that either its own feerate or the feerate with its descandants are considered to allow for fee bumping by spending one (e.g. the change) output and "attaching" a high fee?

  3. MarcoFalke added the label Mempool on Sep 23, 2018
  4. MarcoFalke added the label Questions and Help on Sep 23, 2018
  5. RHavar commented at 12:18 AM on September 23, 2018: contributor

    Yes, I believe it uses the MAX(transactionFeeRate, transactionAndAllDescendantsFeeRate) as the descendant_score. But I'm still struggling to understand why this is useful. I didn't quite get your comment about allowing for fee bumping

  6. fanquake commented at 3:28 AM on September 23, 2018: member
  7. sdaftuar commented at 9:51 AM on September 23, 2018: member

    which I don't really understand. Wouldn't using ancestor_score make a lot more sense?

    I think there are two observations to note here. First, the ancestor score of a transaction T is the feerate of T along with any unconfirmed transactions that T depends on.

    Second, if we evict T from the mempool, then to maintain consistency we must also evict all descendants of T as well, so that no transaction in the mempool is missing its unconfirmed parents.

    Taken together, using the ancestor score wouldn't make any sense -- just because a transaction has a low feerate with ancestor does not mean it's unlikely to be included in the next block. For example, if transaction A is small and has the minimum fee rate of the mempool, but transaction B is a large descendant with a huge feerate, then the ancestor score for A will be small, but it might be selected in the next block, because the ancestor score for B is still very high, causing it to get pulled in when B is selected. Moreover, if you evicted A for being low feerate, then you must also evict B (which is obviously undesirable -- it might have been the most profitable thing to be included in the next block).

    One way to think about this is that while the top transactions according to the ancestor score are likely to be good candidates for inclusion in the next block, you have basically no information about whether things at the bottom of the ancestor index are likely to be included or not (since their descendants are relevant to that determination, and the ancestor score tells us nothing about a transaction's descendants).

    On the other hand, the transaction with the worst descendant score is very unlikely to be a good candidate for inclusion in the next block, as neither the transaction nor its descendants sorts very high -- and again you have basically no information about whether transactions at the top of the descendant index are likely to be included or not (since their ancestors must be included in any block as well, and the descendant score does not include any ancestor information).

    I guess an important point here is that if a low feerate transaction A has two immediate descendants B and C, where B has a high feerate and C has the lowest feerate of the group, then the descendant score of C will be lower than that of A. This is important because the descendant feerate of A might also be low while C is in the mempool even though A+B may be a good candidate for inclusion in the next block, but C would be evicted first (bumping up A's descendant score) before A would be considered for eviction.

    You are correct to observe that the descendant score is only used in TrimToSize. Our mempool limiting algorithm (#6722) works by evicting the least-likely-to-be-mined transactions from the mempool whenever we bump up against our limit, and the descendant score is what we use to measure that.

  8. RHavar commented at 4:34 PM on September 23, 2018: contributor

    Thanks @sdaftuar that makes perfect sense, I'll close the issue.

    I do wonder though if TrimToSize called rarely enough (and at time-non-critical points) that it makes sense to just do a single-pass of the mempool when deciding what to trim in exchange for being able to speed up all the other mempool operations.

  9. RHavar closed this on Sep 23, 2018

  10. DrahtBot locked this on Sep 8, 2021

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-04-13 15:15 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me