> 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 <oracle_sig> <alice_sig> 2 CHECKMULTISIG
        ELSE 2 <oracle_sig> <bob_sig> 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 <aj@erisian.com.au> 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 <alice+bob> DUP 0 6 TLUV CHECKSIGVERIFY IN_OUT_AMOUNT SUB 2BTC LESSTHAN
CD = same but for carol+dave
A = <alice> DUP <B'> 10 TLUV CHECKSIGVERIFY IN_OUT_AMOUNT SUB 1BTC LESSTHAN
B' = <bob> 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 = <alice+carol> CHECKSIGVERIFY <oracle> 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