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 <bitcoin-dev@lists.linuxfoundation.org> 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
bitcoin-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev