Skip to content

Instantly share code, notes, and snippets.

@glozow
Last active January 24, 2024 10:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save glozow/797bb412868ce959dcd0a2981322fd2a to your computer and use it in GitHub Desktop.
Save glozow/797bb412868ce959dcd0a2981322fd2a to your computer and use it in GitHub Desktop.

Emergency Replace By Feerate

Over the last 5 years, there have been many proposals of the form:

"Instead of Rule 3+4, just enforce some feerate rule for replacements when the replcement would confirm soon."

Examples:

Free Relay Problem

This is looking at a proposal that takes the form:

  • If the replacement tx/package has a mineable feerate / miner score / incentive compatibility score that is in the top (e.g. 1 block) of the mempool and the replacee isn't:
    • instead of Rule 3+4, just enforce that the mineable feerate increases by some multiple (e.g. doubles).
  • Otherwise:
    • use the existing RBF rules.

There's an infinite free relay problem. You can keep broadcasting "high feerate" and "high fee" sets of transactions that replace each other, reusing the same fees and alternating which RBF rules you use.

Let's say the "next block" feerate is 66sat/vB, and 23sat/vB is "bottom of mempool" feerate (just taking today's mempool.space numbers):

  1. Broadcast E (1,250,000sat / 50,000vB = 25sat/vB)
  2. Broadcast F (5,000sat / 200vB = 25sat/vB) which spends from E
  3. Replace F with B (16,500sat / 250vB = 66sat/vB), no longer spending from E, following the one-shot rules: 2. B's "mineable feerate" is 66, high enough for next block 3. F's "mineable feerate" is ((1,250,000 + 5,000) / 52,200 = 24.1), not high enough for next block 4. 66 is more than double 24.1
  4. Replace B and F with C (67,000sat / 1,000vB = 67sat/vB), following the "normal" RBF rules. C spends from E.
    1. Note that C's "mineable feerate" is ((1,250,000sat + 67,000sat) / 51,000vB = 25.4sat/vB), much lower than its individual feerate, because it spends from the large, low feerate E.
    2. (Rule 2) note that while C has a new ancestor E, it does not have any new unconfirmed inputs because it replaces F.
    3. (Rule 3 and 4) New fees = 67,000 - (16,500 + 5,000) = 45,500 which easily covers the size of C at incremental relay feerate
    4. (Rule 6) C has a feerate of 67sat/vB which is higher than B's (66sat/vB) and F's (25sat/vB)
  5. Replace C again with B' (16,500sat / 250vB = 66sat/vB) without spending the output from E, following the one-shot rules:
    1. B''s "mineable feerate" is 66 now that it has no ancestors, high enough for next block
    2. C's "mineable feerate" is 25
    3. 66 is equal to 25 times 2.64
  6. Broadcast F' (5,000sat / 200vB = 25sat/vB) which spends from E.
  7. Replace B' and F' with C'...
  8. Replace C' with B'', etc.

You can do this as many times as you want until one the iterations of B gets mined. But B is small (and low-ish in absolute fee), and E stays in mempool, so you can launch your next DDoS without having paid very much. It scales too - you can be doing 24 of these simultaneously using E as the shared low feerate parent.

The problem here is that there is a huge difference in fees between the largest standard transaction at the low feerate and the smallest transaction at a high feerate. If you want to eliminate this problem, you need to make r closer to this ratio, but then you have something that's just as hard to overcome as Rule 3 pinning with a huge descendant.

It also seems that having 2 sets of RBF rules can easily lead to a situation like this where A can replace B, but B can also replace A... infinitely.

Implementation of miner score

The "mineable feerate" is going to be nontrivial to calculate without building a block template in the middle of mempool validation. In the past when I was playing around with this idea, I suggested keeping a persistent block template for N=1, but most people agreed that would add too much complexity. Cluster mempool fixes this of course - it would be a quick lookup. And one of the perks of v3 topology restrictions is being able to calculate this using ancestor feerate. But the free relay problem would remain.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment