Subject: Re: [bitcoin-dev] Using Full-RBF to fix BIP-125 Rule #3 Pinning with nLockTime

From: Antoine Riard <[email-masked]>
Date: Mon, 7 Nov 2022 17:55:59 -0500

Hi Peter,

> We can ensure with high probability that the transaction can be cancelled/mined
> at some point after N blocks by pre-signing a transaction, with nLockTime set
> sufficiently far into the future, spending one or more inputs of the
> transaction with a sufficiently high fee that it would replace transaction(s)
> attempting to exploit Rule #3 pinning (note how the package limits in Bitcoin
> Core help here).

>From my understanding, there are many open questions to such a
pre-signed high-fee solution aiming to address Rule #3 pinning.
Determining the high-fee to guarantee replacements with high odds. I
think it should be superior to current top network mempools sat/vb *
MAX_STANDARD_TX_WEIGHT, otherwise an adversary can pin the multi-party
funded transaction on the ground of Core's
replacement rule ("The replacement transaction's feerate is greater
than the feerates of all directly conflicting transactions''). Though
note the difficulty, the sat/vb is an unknown fact at time of
signatures exchange among the multi-party funded transaction
participants. Solving this issue probably requires from then to
overshoot, and adopt a historical worst-case mempool feerate.

This "historically-worst" sat/vb introduces two new issues, first I
think this is an economic lower bound on the funds that can be staked
in the collaborative transaction. Second I believe this constitutes a
griefing vector, where a participant could deliberately pin to inflict
an asymmetric damage, without entering into any fee competition. This
griefing vector could be leveraged as hard as being triggered by a
miner-as-participant in so-called miner harvesting attacks.

Further, I think this solution relying on nLocktime doesn't solve the
timevalue DoS inflicted to the participants UTXOs, until the
pre-signed high-fee transaction is final. If participants prefer to
save the timevalue of their contributed UTXOs over operation success,
a better approach could be for them to unilaterally spend after a
protocol/implementation timepoint (e.g LN's funding timeout recovery
mechanism).

A more workable solution I believe could be simply to rely on
package-relay, an ephemeral anchor output, and a special replacement
regime (e.g nVersion=3) to allow the multi-party funded transaction
coordinator to unilateral fee-bump, in a step-by-step approach. I.e
without making assumptions on the knowledge of network mempools and
burning directly the worst amount in fees.

Best,
Antoine

Le lun. 7 nov. 2022 à 16:18, Peter Todd via bitcoin-dev <
[email-masked]> a écrit :

> On Mon, Nov 07, 2022 at 03:17:29PM -0500, Peter Todd via bitcoin-dev wrote:
> > tl;dr: We can remove the problem of Rule #5 pinning by ensuring that all
> > transactions in the mempool are always replaceable.
>
> With Rule #5 solved, let's look at the other pinning attack on multi-party
> transactions: BIP-125 Rule #3
>
> tl;dr: In conjunction with full-RBF, nLockTime'd, pre-signed, transactions
> can
> ensure that one party is not forced to pay for all the cost of a rule #3
> replacement.
>
>
> # What is the problem?
>
> When a transaction contains inputs from multiple parties, each party can
> lock
> up funds from the other party by spending their input with a transaction
> that
> is difficult/expensive to replace. Obviously, the clearest example of
> "difficult to
> replace" is a non-BIP-125 (Opt-in-RBF) transaction. But here, we'll assume
> that
> full-rbf is implemented and all transactions are replaceable.
>
> BIP-125 Rule #3 states that:
>
>     The replacement transaction pays an absolute fee of at least the sum
> paid
>     by the original transactions.
>
> The attack is that the malicious party, who we'll call Mallory, broadcasts
> a
> transaction spending their input(s) with a low fee rate transaction that's
> potentially quite large, during a time of high mempool demand. Due to the
> low
> fee rate this transaction will take a significant amount of time to mine.
> The
> other parties to the transaction - who we'll collectively call Alice - are
> now
> unable to spend their inputs unless they broadcast a transaction "paying
> for"
> Mallory's.
>
> This attack works because Mallory doesn't expect the conflicting tx to
> actually
> get mined: he assumes it'll either expire, or Alice will get frustrated and
> have to double spend it. By simple tying up money, Mallory has caused
> Alice to
> actually lose money.
>
>
> # Fixing the problem with nLockTime
>
> Conversely, in the case of an honest multi-party transaction, whose parties
> we'll call Alice and Bob, the parties genuinely intend for one of two
> outcomes:
>
> 1) The multi-party transaction to get mined within N blocks.
> 2) The transaction to be cancelled (most likely by spending one of the
> inputs).
>
> We can ensure with high probability that the transaction can be
> cancelled/mined
> at some point after N blocks by pre-signing a transaction, with nLockTime
> set
> sufficiently far into the future, spending one or more inputs of the
> transaction with a sufficiently high fee that it would replace
> transaction(s)
> attempting to exploit Rule #3 pinning (note how the package limits in
> Bitcoin
> Core help here).
>
> There's a few different ways to implement this, and exactly which one makes
> sense will depend on the specifics of the multi-party protocol. But the
> general
> approach is to defeat the attack by ensuring that Mallory will have to pay
> the
> cost of getting the multi-party transaction unstuck, at some point in the
> future.
>
> For example, in a two party transaction where there's a clearly more
> reputable
> party (Alice), and an untrusted party (Mallory), Alice could simply require
> Mallory to provide a nLockTime'd transaction spending only his input to
> fees,
> multiple days into the future. In the unlikely event that Mallory holds up
> the
> protocol, he will be severely punished. Meanwhile, Alice can always cancel
> at
> no cost.
>
> In a many party transaction where both parties are equally (un)trustworthy
> the
> protocol could simply have both parties sign a series of transactions,
> nLockTimed at decreasingly far into a future, paying a decreasingly amount
> of
> fees. If either party holds up the transaction intentionally, they'll both
> pay
> a high cost. But again, at some point Mallory will have paid the full
> price for
> his attack. This approach also has the beneficial side effect of
> implementing
> fee discovery with rbf. This approach is easier as the number of parties
> increases, eg the Wasabi/Joinmarket transactions with hundreds of inputs
> and
> outputs: they collectively already have to pay a significant fee to get the
> transaction mined, making the extra poential cost needed to defeat pinning
> minimal.
>
>
> # Coordinator Spent Bonds with Package Relay/Replacement
>
> For schemes with a central semi-trusted coordinator, such as Wasabi
> coinjoins,
> with package relay/replacement we can use a two party punishment
> transaction
> consisting of:
>
>     tx1 - spends Mallory's input to a txout spendable by:
>            IF
>                <coordinator> CheckSig
>            Else
>                <delay> CheckSequenceVerify
>                <mallory> CheckSig
>            EndIf
>
>     tx2 - spends tx1 output to as much fees as needed
>
> Whether or not Mallory cheated with a double-spend is provable to third
> parties; the second transaction ensures that Mallory can't simply release
> tx1
> on their own to frame the coordinator. The use of CheckSequenceVerify
> ensures
> that if mallory did try to frame the coordinator, they don't have to do
> anything to return the funds to Mallory.
>
> --
> https://petertodd.org 'peter'[:-1]@petertodd.org
> _______________________________________________
> bitcoin-dev mailing list
> [email-masked]
> https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
>