public inbox for bitcoindev@googlegroups.com
 help / color / mirror / Atom feed
From: Matt Corallo <lf-lists@mattcorallo.com>
To: ZmnSCPxj <ZmnSCPxj@protonmail.com>
Cc: Bitcoin Protocol Discussion
	<bitcoin-dev@lists.linuxfoundation.org>,
	lightning-dev <lightning-dev@lists.linuxfoundation.org>
Subject: Re: [bitcoin-dev] [Lightning-dev] RBF Pinning with Counterparties and Competing Interest
Date: Wed, 22 Apr 2020 23:21:50 -0700	[thread overview]
Message-ID: <67334082-5ABA-45C7-9C09-FF19B119C80D@mattcorallo.com> (raw)
In-Reply-To: <PtYNeePySy_thDHm8FwIIGEk32EjJpSmiwPctyEg0hOrLZEHjO1IBghm4MWY88g51K-XF2pf_JDnW0UdTL6QSbACEj21h9U1s5ITc_N3I6Q=@protonmail.com>

Great summary, a few notes inline.

> On Apr 22, 2020, at 21:50, ZmnSCPxj <ZmnSCPxj@protonmail.com> wrote:
> 
> Good morning lists et al,
> 
> Let me try to summarize things a little:
> 
> * Suppose we have a forwarding payment A->B->C.
> * Suppose B does not want to maintain a mempool and is running in `blocksonly` mode to reduce operational costs.

Quick point of clarification, due to the mempool lacking a consensus system (that’s the whole point, after all :p), there are several reasons to that just running a full node/having a mempool isn’t sufficient.

> * C triggers B somehow dropping the B<->C channel, such as by sending an `error` message, which will usually cause the other side to drop the channel onchain using its commitment transaction.
> * The dropped B<->C channel has an HTLC (that was set up during the A->B->C forwarding).
> * The HTLC, being used in a Poon-Dryja channel, actually has the following contract text:
> * The fund may be claimed by either of these clauses:
> * C can claim, if C shows the preimage of some hash H (hashlock branch).
> * B and C must agree, and claim after time L (timelock branch).
> * B holds a signature from C that can claim the timelock branch of the HTLC, for a transaction that spends to an output with an `OP_CHECKSEQUENCEVERIFY`.
> * The signature is `SIGHASH_ALL`, so the transaction has a fixed feerate.
> * C can "pin" the HTLC output by spending using the hashlock branch, and creating a large fee, low fee-rate (tree of) transactions.

Another: this is the simplest example. There are also games around the package size limits if I recall correctly.

> * As it is a low fee-rate, miners have no incentive to put this in a block, especially if unrelated higher-fee-rate transactions exist that would earn them more money.
> * Even in a full RBF universe, because of the anti-DoS mempool rules, B cannot evict this pinned transaction by just bidding up the feerate.
> * A replacing transaction cannot evict alternatives unless its absolute fee is greater than the absolute fee of the alternative.
> * The pinning transaction has a high fee, but is blockspace-wasteful, so it is:
>   * Undesirable to mine (low feerate).
>   * Difficult to evict (high fee).
> * Thus, B is unable to get its timelock-branch transaction in the mempools of miners.
> * C waits until the A->B HTLC times out, then:
> * C directly contacts miners with an out-of-band proposal to replace its transaction with an alternative that is much smaller and has a low fee, but much better feerate.

Or they can just wait. For example in today’s mempool it would not be strange for a transaction at 1 sat/vbyte to wait a day but eventually confirm.

> * Miners, being economically rational, accept this proposal and include this in a block.
> 
> The proposal by Matt is then:
> 
> * The hashlock branch should instead be:
> * B and C must agree, and show the preimage of some hash H (hashlock branch).
> * Then B and C agree that B provides a signature spending the hashlock branch, to a transaction with the outputs:
> * Normal payment to C.
> * Hook output to B, which B can use to CPFP this transaction.
> * Hook output to C, which C can use to CPFP this transaction.
> * B can still (somehow) not maintain a mempool, by:
> * B broadcasts its timelock transaction.
> * B tries to CPFP the above hashlock transaction.
> * If CPFP succeeds, it means the above hashlock transaction exists and B queries the peer for this transaction, extracting the preimage and claiming the A->B HTLC.

Note that no query is required. The problem has been solved and the preimage-containing transaction should now confirm just fine.

> Is that a fair summary?

Yep!

> --
> 
> Naively, and remembering I am completely ignorant of the exact details of the mempool rules, it seems to me quite strange that we are allowing an undesirable transaction (tree) into the mempool:
> 
> * Undesirable to mine (low fee-rate).
> * Difficult to evict (high fee).

As noted, such transactions today are profit in 10 hours. Just because they’re big doesn’t mean they don’t pay.

> Miners are not interested in low fee-rate transactions, as long as higher fee-rate transactions exist.
> And being difficult to evict means miners cannot get alternatives that are more lucrative for them.
> 
> The reason (as I understand it) eviction is purposely made difficult here is to prevent certain DoS attacks on Bitcoin nodes, specifically:
> 
> 1. Attacker sends a low fee-rate tx as a "root" transaction.
> 2  Attacker sends thousands of low fee-rate tx that build off the above root.

I believe the limit is 25, though the point stands, mostly from a total-size perspective.

> 3. Attacker sends a slightly higher fee-rate alternative to the root, evicting the above tree of txes.
> 4. Attacker sends thousands of low fee-rate tx that build off the latest root.
> 5. GOTO 3.
> 
> However, it seems to me, naively, that "an ounce of prevention is worth a pound of cure".

Sadly, it’s very very easy for this to be a huge amount of CPU + bandwidth.

> As I understand it, the mempool is organized already into "packages" of transactions, and adding a transaction into the mempool involves extending and merging packages.
> Perhaps the size of a package with low fee-rate (relative to the other packages in the mempool) can be limited, so that mempools drop incoming txes that extend a low-fee-rate tree of transactions.
> This means an attacker cannot send thousands of low fee-rate tx that build off some low fee-rate root tx in the first place, so it can still be evicted easily later without much impact.

There have been several proposals before around considering a transactions position in the mempool for various similar criteria. The extreme version being simply heavily rate-limiting transaction relay at low feerates and allowing much more liberal replacement of such packages. It isn’t quite perfect for this issue, though, as it may be easy for the attacker to just fill that rate-limit bucket.

> Naively, it seems to me to prevent the DoS attack as well, as at step 2 it would be prevented from sending thousands of low fee-rate tx building off the root.
> 
> As well, as I understand it, this merely tightens the mempool acceptance rules, preventing low fee-rate packages from growing (analogous to a consensus-layer softfork).
> The "cannot evict high absolute fee" rule can be retained, as the low-fee-rate package is prevented from reaching a large size.
> 
> Would that be workable as a general solution to solve (what I think is) the root cause of this problem?

It’s not clear to me that tightening the acceptance rules wouldn’t break other existing uses. Historically the 25 package size limit has proven to be an issue for users doing (somewhat naïve) centralized wallet withdraws. Sadly many users want that “payment pending” notification instantly, even if we know it to be somewhat lacking in security. Wallets which have over-compacted their UTXOs are thus stuck making long chains.

To revive an old discussion, on the original thread proposing the CPFP Carve-Out, I said this:

> As an alternative proposal, at various points there have been discussions around solving the "RBF-pinning" problem by allowing transactors to mark their transactions as "likely-to-be-RBF'ed", which could enable a relay policy where children of such transactions would be rejected unless the resulting package would be "near the top of the mempool". This would theoretically imply such attacks are not possible to pull off consistently, as any "transaction-delaying" channel participant will have to place the package containing A at an effective feerate which makes confirmation to occur soon with some likelihood. It is, however, possible to pull off this attack with low probability in case of feerate spikes right after broadcast.

To which Rusty responded (and I may be paraphrasing here): “Fuck Yea”. I’m still not much of a fan of this idea as it introduces too many constants (what is “the top of the mempool”, anyway?), and it’s unclear to me what you do as the mempool prevailing feerate changes, but it seems more along the lines or what you’re looking for here.




  reply	other threads:[~2020-04-23  6:21 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-04-21  2:43 [bitcoin-dev] RBF Pinning with Counterparties and Competing Interest Matt Corallo
2020-04-22  4:12 ` [bitcoin-dev] [Lightning-dev] " ZmnSCPxj
2020-04-22  4:18   ` Olaoluwa Osuntokun
2020-04-22  6:08     ` ZmnSCPxj
2020-04-22  8:01       ` Antoine Riard
2020-04-22  8:55         ` Bastien TEINTURIER
2020-04-22 23:05       ` Olaoluwa Osuntokun
2020-04-22 23:11         ` Olaoluwa Osuntokun
2020-04-22 16:56   ` Matt Corallo
2020-04-22  4:13 ` [bitcoin-dev] " Olaoluwa Osuntokun
2020-04-22 11:51   ` David A. Harding
2020-04-27 21:26     ` Rusty Russell
2020-04-22 16:50   ` Matt Corallo
2020-04-22 23:13     ` Olaoluwa Osuntokun
2020-04-22 23:20       ` Matt Corallo
2020-04-22 23:27         ` Olaoluwa Osuntokun
2020-04-23  1:10           ` Matt Corallo
2020-04-23  4:50             ` [bitcoin-dev] [Lightning-dev] " ZmnSCPxj
2020-04-23  6:21               ` Matt Corallo [this message]
2020-04-23 12:46                 ` ZmnSCPxj
2020-04-23 22:47                   ` Matt Corallo
2020-06-19  7:44                     ` Bastien TEINTURIER
2020-06-19 19:58                       ` David A. Harding
2020-06-19 20:52                         ` David A. Harding
2020-06-20  8:54                           ` Bastien TEINTURIER
2020-06-20 10:36                             ` David A. Harding
2020-06-20 16:01                               ` ZmnSCPxj
2020-06-21  2:10                                 ` ZmnSCPxj
2020-06-22  7:35                               ` Bastien TEINTURIER
2020-06-22  8:15                                 ` ZmnSCPxj
2020-06-22  8:25                                   ` Bastien TEINTURIER
2020-06-24  8:32                                     ` Matt Corallo
2020-04-23  1:18           ` [bitcoin-dev] " Jeremy
2020-04-22 18:24 ` David A. Harding
2020-04-22 19:03   ` Antoine Riard
2020-04-22 20:28     ` David A. Harding
2020-04-22 22:53 Matt Corallo
2020-04-23  9:59 ` David A. Harding
2020-04-23 12:52   ` [bitcoin-dev] [Lightning-dev] " ZmnSCPxj

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=67334082-5ABA-45C7-9C09-FF19B119C80D@mattcorallo.com \
    --to=lf-lists@mattcorallo.com \
    --cc=ZmnSCPxj@protonmail.com \
    --cc=bitcoin-dev@lists.linuxfoundation.org \
    --cc=lightning-dev@lists.linuxfoundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox