Re: [bitcoin-dev] TAPLEAF_UPDATE_VERIFY covenant opcode

2021-09-22 Thread Olaoluwa Osuntokun via bitcoin-dev
Hi AJ,

Happy to see that this proposal has finally seen the light of day! I've been
hearing about it in hinted background convos over the past few months, so
happy I can finally dig into the specifics of its operation.

> So the idea is to do just that via a new opcode "TAPLEAF_UPDATE_VERIFY"
> (TLUV) that takes three inputs: one that specifies how to update the
> internal public key (X), one that specifies a new step for the merkle path
> (F), and one that specifies whether to remove the current script and/or
> how many merkle path steps to remove

What if instead, it obtained the script from the _annex_? I think this small
modification would make the op code even _more_ powerful. Consider that this
allows a new script to be passed _dynamically_ after the output has been
created, possibly by a threshold of parties that control the output, or them
all (mu sig, etc, etc). This serves to create a generic "upgrade" mechanism
for any tapscript output (covenant or not). Functionally, this is similar to
the existence of "admin keys" or voted DAO upgrades that exists in chains
that utilize an account based systems. This is really useful as it allows a
script any given output to optional add in graftroot like behavior (leaf in
tree that accepts script updates), and also allows contract developers to
progressively upgrade or fix issues in prior versions of their deployed
contracts.

This little trick is secure since unlike the witness itself, the annex is
actually _signed_ within the sighash like everything else. Incorporating
this proposal would require the addition of an OP_PUSH_ANNEX op code, which
by itself seems expertly useful. If one views the annex as a sort of
authenticated associated data that can be passed into the script execution
context, then this actually serves to absorb _some_ uses cases of a
hypothetical OP_CHECKSIG_FROM_STACK opcode. A push annex op code also makes
doing things like output delegation to a given key passed into the witness
secure since the prior "owner" of the output commits to the key within the
sighash.

Even assuming a more powerful type of covenant that allows partial
application of binding logic, something like this is still super useful
since the action of re-creating a new tapscript tree based in dynamic input
data would generate a rather large witness if only something like OP_CAT was
available. The unique "update" nature of this appears to augment any other
type of covenant, which is pretty cool. Consider that it would allow you
(with the annex addition above), take something like a CTV congestion tree,
and add in _new_ users at the tree is already being unrolled (just a toy
example).

It would also allow an individual to _join_ the payment pool construct
described earlier which makes it 1000x more useful (vs just supporting
unrolling). I haven't written it all down yet, but I think this along with
something like CTV or CSFS makes it possible to implement a Plasma Cash [4]
like Commit Chain [5], which is super exciting (assume a counter is embedded
in the main script that tracks the next free leaf slot(s). With this model
an "operator" is able to include a single transaction in the chain that
stamps a batch of updates in the payment tree.  Users then get a
contestation period where they can refute a modification to the tree in
order to withdraw their funds.

> And second, it doesn't provide a way for utxos to "interact",

This is due to the fact that the op code doesn't allow any sort of late
binding or pattern matching then constraining _where_ (or whence?) the coins
can Be sent to. There's a group of developers that are attempting to make an
AMM-like system on Liquid [1] using more generic stack based covenants [2]
(see the `OP_INSPECTINPUT` op code, which seems very much inspired by
jl2012's old proposal). However one challenge that still need to be tackled
in the UTXO model is allowing multiple participants to easily interact w/
the
contract in a single block w/o a coordination layer to synchronize the
access.

One solution to this concurrency issue, that I believe is already employed
by Chia is to allow "contracts" to be identified via a fixed ID (as long as
their active in the chain) [3]. This lets transactions spend/interact with a
contract, without always needing to know the set of active UTXOs where that
contract lives. Transactions then specify their contract and "regular"
inputs, with the requirement that every transaction spends at least a single
regular input.

The trade-off here is that nodes need to maintain this extra index into the
UTXO set. However, this can be alleviated by applying a utreexo like
solution: nodes maintain some merklized data structure over the index and
require that spending transactions provide an _inclusion_ proof of the
active contract. Nodes then only need to maintain root hashes of the UTXO
and contract set.

I'm super happy w.r.t how the covenant space has been processing over the
past few years. IMO its the single most 

Re: [bitcoin-dev] Proposal: Package Mempool Accept and Package RBF

2021-09-22 Thread Gloria Zhao via bitcoin-dev
Hi Bastien,

> A package A + C will be able to replace A' + B regardless of
> the weight of A' + B?

Correct, the weight of A' + B will not prevent A+C from replacing it (as
long as A+C pays enough fees). In example 2C, we would be able to replace A
with a package.

Best,
Gloria

On Wed, Sep 22, 2021 at 8:10 AM Bastien TEINTURIER  wrote:

> Great, thanks for this clarification!
>
> Can you confirm that this won't be an issue either with your
> example 2C (in your first set of diagrams)? If I understand it
> correctly it shouldn't, but I'd rather be 100% sure.
>
> A package A + C will be able to replace A' + B regardless of
> the weight of A' + B?
>
> Thanks,
> Bastien
>
> Le mar. 21 sept. 2021 à 18:42, Gloria Zhao  a
> écrit :
>
>> Hi Bastien,
>>
>> Excellent diagram :D
>>
>> > Here the issue is that a revoked commitment tx A' is pinned in other
>> > mempools, with a long chain of descendants (or descendants that reach
>> > the maximum replaceable size).
>> > We would really like A + C to be able to replace this pinned A'.
>> > We can't submit individually because A on its own won't replace A'...
>>
>> Right, this is a key motivation for having Package RBF. In this case, A+C
>> can replace A' + B1...B24.
>>
>> Due to the descendant limit (each node operator can increase it on their
>> own node, but the default is 25), A' should have no more than 25
>> descendants, even including CPFP carve out. As long as A only conflicts
>> with A', it won't be trying to replace more than 100 transactions. The
>> proposed package RBF will allow C to pay for A's conflicts, since their
>> package feerate is used in the fee comparisons. A is not a descendant of
>> A', so the existence of B1...B24 does not prevent the replacement.
>>
>> Best,
>> Gloria
>>
>> On Tue, Sep 21, 2021 at 4:18 PM Bastien TEINTURIER 
>> wrote:
>>
>>> Hi Gloria,
>>>
>>> > I believe this attack is mitigated as long as we attempt to submit
>>> transactions individually
>>>
>>> Unfortunately not, as there exists a pinning scenario in LN where a
>>> different commit tx is pinned, but you actually can't know which one.
>>>
>>> Since I really like your diagrams, I made one as well to illustrate:
>>>
>>> https://user-images.githubusercontent.com/31281497/134198114-5e9c6857-e8fc-405a-be57-18181d5e54cb.jpg
>>>
>>> Here the issue is that a revoked commitment tx A' is pinned in other
>>> mempools, with a long chain of descendants (or descendants that reach
>>> the maximum replaceable size).
>>>
>>> We would really like A + C to be able to replace this pinned A'.
>>> We can't submit individually because A on its own won't replace A'...
>>>
>>> > I would note that this proposal doesn't accommodate something like
>>> diagram B, where C is getting CPFP carve out and wants to bring a +1
>>>
>>> No worries, that case shouldn't be a concern.
>>> I believe any L2 protocol can always ensure it confirms such tx trees
>>> "one depth after the other" without impacting funds safety, so it
>>> only needs to ensure A + C can get into mempools.
>>>
>>> Thanks,
>>> Bastien
>>>
>>> Le mar. 21 sept. 2021 à 13:18, Gloria Zhao  a
>>> écrit :
>>>
 Hi Bastien,

 Thank you for your feedback!

 > In your example we have a parent transaction A already in the mempool
 > and an unrelated child B. We submit a package C + D where C spends
 > another of A's inputs. You're highlighting that this package may be
 > rejected because of the unrelated transaction(s) B.

 > The way I see this, an attacker can abuse this rule to ensure
 > transaction A stays pinned in the mempool without confirming by
 > broadcasting a set of child transactions that reach these limits
 > and pay low fees (where A would be a commit tx in LN).

 I believe you are describing a pinning attack in which your adversarial
 counterparty attempts to monopolize the mempool descendant limit of the
 shared  transaction A in order to prevent you from submitting a fee-bumping
 child C; I've tried to illustrate this as diagram A here:
 https://user-images.githubusercontent.com/25183001/134159860-068080d0-bbb6-4356-ae74-00df00644c74.png
 (please let me know if I'm misunderstanding).

 I believe this attack is mitigated as long as we attempt to submit
 transactions individually (and thus take advantage of CPFP carve out)
 before attempting package validation. So, in scenario A2, even if the
 mempool receives a package with A+C, it would deduplicate A, submit C as an
 individual transaction, and allow it due to the CPFP carve out exemption. A
 more general goal is: if a transaction would propagate successfully on its
 own now, it should still propagate regardless of whether it is included in
 a package. The best way to ensure this, as far as I can tell, is to always
 try to submit them individually first.

 I would note that this proposal doesn't accommodate something like
 diagram B, where C is getting 

Re: [bitcoin-dev] Proposal: Package Mempool Accept and Package RBF

2021-09-22 Thread Bastien TEINTURIER via bitcoin-dev
Great, thanks for this clarification!

Can you confirm that this won't be an issue either with your
example 2C (in your first set of diagrams)? If I understand it
correctly it shouldn't, but I'd rather be 100% sure.

A package A + C will be able to replace A' + B regardless of
the weight of A' + B?

Thanks,
Bastien

Le mar. 21 sept. 2021 à 18:42, Gloria Zhao  a écrit :

> Hi Bastien,
>
> Excellent diagram :D
>
> > Here the issue is that a revoked commitment tx A' is pinned in other
> > mempools, with a long chain of descendants (or descendants that reach
> > the maximum replaceable size).
> > We would really like A + C to be able to replace this pinned A'.
> > We can't submit individually because A on its own won't replace A'...
>
> Right, this is a key motivation for having Package RBF. In this case, A+C
> can replace A' + B1...B24.
>
> Due to the descendant limit (each node operator can increase it on their
> own node, but the default is 25), A' should have no more than 25
> descendants, even including CPFP carve out. As long as A only conflicts
> with A', it won't be trying to replace more than 100 transactions. The
> proposed package RBF will allow C to pay for A's conflicts, since their
> package feerate is used in the fee comparisons. A is not a descendant of
> A', so the existence of B1...B24 does not prevent the replacement.
>
> Best,
> Gloria
>
> On Tue, Sep 21, 2021 at 4:18 PM Bastien TEINTURIER 
> wrote:
>
>> Hi Gloria,
>>
>> > I believe this attack is mitigated as long as we attempt to submit
>> transactions individually
>>
>> Unfortunately not, as there exists a pinning scenario in LN where a
>> different commit tx is pinned, but you actually can't know which one.
>>
>> Since I really like your diagrams, I made one as well to illustrate:
>>
>> https://user-images.githubusercontent.com/31281497/134198114-5e9c6857-e8fc-405a-be57-18181d5e54cb.jpg
>>
>> Here the issue is that a revoked commitment tx A' is pinned in other
>> mempools, with a long chain of descendants (or descendants that reach
>> the maximum replaceable size).
>>
>> We would really like A + C to be able to replace this pinned A'.
>> We can't submit individually because A on its own won't replace A'...
>>
>> > I would note that this proposal doesn't accommodate something like
>> diagram B, where C is getting CPFP carve out and wants to bring a +1
>>
>> No worries, that case shouldn't be a concern.
>> I believe any L2 protocol can always ensure it confirms such tx trees
>> "one depth after the other" without impacting funds safety, so it
>> only needs to ensure A + C can get into mempools.
>>
>> Thanks,
>> Bastien
>>
>> Le mar. 21 sept. 2021 à 13:18, Gloria Zhao  a
>> écrit :
>>
>>> Hi Bastien,
>>>
>>> Thank you for your feedback!
>>>
>>> > In your example we have a parent transaction A already in the mempool
>>> > and an unrelated child B. We submit a package C + D where C spends
>>> > another of A's inputs. You're highlighting that this package may be
>>> > rejected because of the unrelated transaction(s) B.
>>>
>>> > The way I see this, an attacker can abuse this rule to ensure
>>> > transaction A stays pinned in the mempool without confirming by
>>> > broadcasting a set of child transactions that reach these limits
>>> > and pay low fees (where A would be a commit tx in LN).
>>>
>>> I believe you are describing a pinning attack in which your adversarial
>>> counterparty attempts to monopolize the mempool descendant limit of the
>>> shared  transaction A in order to prevent you from submitting a fee-bumping
>>> child C; I've tried to illustrate this as diagram A here:
>>> https://user-images.githubusercontent.com/25183001/134159860-068080d0-bbb6-4356-ae74-00df00644c74.png
>>> (please let me know if I'm misunderstanding).
>>>
>>> I believe this attack is mitigated as long as we attempt to submit
>>> transactions individually (and thus take advantage of CPFP carve out)
>>> before attempting package validation. So, in scenario A2, even if the
>>> mempool receives a package with A+C, it would deduplicate A, submit C as an
>>> individual transaction, and allow it due to the CPFP carve out exemption. A
>>> more general goal is: if a transaction would propagate successfully on its
>>> own now, it should still propagate regardless of whether it is included in
>>> a package. The best way to ensure this, as far as I can tell, is to always
>>> try to submit them individually first.
>>>
>>> I would note that this proposal doesn't accommodate something like
>>> diagram B, where C is getting CPFP carve out and wants to bring a +1 (e.g.
>>> C has very low fees and is bumped by D). I don't think this is a use case
>>> since C should be the one fee-bumping A, but since we're talking about
>>> limitations around the CPFP carve out, this is it.
>>>
>>> Let me know if this addresses your concerns?
>>>
>>> Thanks,
>>> Gloria
>>>
>>> On Mon, Sep 20, 2021 at 10:19 AM Bastien TEINTURIER 
>>> wrote:
>>>
 Hi Gloria,

 Thanks for this detailed 

Re: [bitcoin-dev] TAPLEAF_UPDATE_VERIFY covenant opcode

2021-09-22 Thread Antoine Riard via bitcoin-dev
> Hmm, I'm reading C5 as "If an oracle says X, and Alice and Carol agree,
> they can distribute all the remaining funds as they see fit".

Should be read as an OR:

IF 2   2 CHECKMULTISIG
ELSE 2   2 CHECKMULTISIG
ENDIF
<> 2 IN_OUT_AMOUNT

The empty vector is a wildcard on the spent amount, as this tapscript may
be executed before/
after the split or any withdraw option.

> (Relative timelocks would probably be annoying for everyone who wasn't
> the first to exit the pool)

And I think unsafe, if you're wrapping a time-sensitive output in your
withdraw scriptPubkey.

> I think the above fixes that -- when AB is spent it deletes itself and
> the (A,B) pair; when A is spent, it deletes (A, B and AB) and replaces
> them with B'; when B' is spent it just deletes itself.

Right, here the subtlety in reading the scripts is about the B'
substitution tapscript in the
A one. And it sounds correct to me that AB exercise deletes the withdraw
pair (A, B).

Le lun. 20 sept. 2021 à 10:52, Anthony Towns  a écrit :

> On Sat, Sep 18, 2021 at 10:11:10AM -0400, Antoine Riard wrote:
> > I think one design advantage of combining scope-minimal opcodes like
> MERKLESUB
> > with sighash malleability is the ability to update a subset of the
> off-chain
> > contract transactions fields after the funding phase.
>
> Note that it's not "update" so much as "add to"; and I mostly think
> graftroot (and friends), or just updating the utxo onchain, are a better
> general purpose way of doing that. It's definitely a tradeoff though.
>
> > Yes this is a different contract policy that I would like to set up.
> > Let's say you would like to express the following set of capabilities.
> > C0="Split the 4 BTC funds between Alice/Bob and Caroll/Dave"
> > C1="Alice can withdraw 1 BTC after 2 weeks"
> > C2="Bob can withdraw 1 BTC after 2 weeks"
> > C3="Caroll can withdraw 1 BTC after 2 weeks"
> > C4="Dave can withdraw 1 BTC after 2 weeks"
> > C5="If USDT price=X, Alice can withdraw 2 BTC or Caroll can withdraw 2
> BTC"
>
> Hmm, I'm reading C5 as "If an oracle says X, and Alice and Carol agree,
> they can distribute all the remaining funds as they see fit".
>
> > If C4 is exercised, to avoid trust in the remaining counterparty, both
> Alice or
> > Caroll should be able to conserve the C5 option, without relying on the
> updated
> > key path.
>
> > As you're saying, as we know the group in advance, one way to setup the
> tree
> > could be:
> >(A, (B, C), BC), D), BCD), E, F), EF), G), EFG)))
>
> Make it:
>
>   (((AB, (A,B)), (CD, (C,D))), ACO)
>
> AB = DROP  DUP 0 6 TLUV CHECKSIGVERIFY IN_OUT_AMOUNT SUB 2BTC
> LESSTHAN
> CD = same but for carol+dave
> A =  DUP  10 TLUV CHECKSIGVERIFY IN_OUT_AMOUNT SUB 1BTC LESSTHAN
> B' =  DUP 0 2 TLUV CHECKSIGVERIFY IN_OUT_AMOUNT SUB 1BTC LESSTHAN
> B,C,D = same as A but for bob, etc
> A',C',D' = same as B' but for alice, etc
> ACO =  CHECKSIGVERIFY  CHECKSIG
>
> Probably AB, CD, A..D, A'..D' all want a CLTV delay in there as well.
> (Relative timelocks would probably be annoying for everyone who wasn't
> the first to exit the pool)
>
> > Note, this solution isn't really satisfying as the G path isn't
> neutralized on
> > the Caroll/Dave fork and could be replayed by Alice or Bob...
>
> I think the above fixes that -- when AB is spent it deletes itself and
> the (A,B) pair; when A is spent, it deletes (A, B and AB) and replaces
> them with B'; when B' is spent it just deletes itself.
>
> Cheers,
> aj
>
___
bitcoin-dev mailing list
bitcoin-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev