BIP for OP_VAULT

BIP for OP_VAULT
2023-03-01 15:05 ` Greg Sanders
  2023-03-11 20:53 ` Luke Dashjr
  
From: James O'Beirne @ 2023-02-13 21:09 UTC ( / )
  To: Bitcoin Protocol Discussion



Since the last related correspondence on this list [0], a number of
improvements have been made to the OP_VAULT draft [1]:

* There is no longer a hard dependence on package relay/ephemeral
  anchors for fee management. When using "authorized recovery," all
  vault-related transactions can be bundled with unrelated inputs and
  outputs, facilitating fee management that is self contained to the
  transaction. Consequently, the contents of this proposal are in theory
  usable today.

* Specific output locations are no longer hardcoded in any of the
  transaction validation algorithms. This means that the proposal is now
  compatible with future changes like SIGHASH_GROUP, and
  transaction shapes for vault operations are more flexible.

---

I've written a BIP that fully describes the proposal here:


https://github.com/jamesob/bips/blob/jamesob-23-02-opvault/bip-vaults.mediawiki

The corresponding PR is here:

  https://github.com/bitcoin/bips/pull/1421

My next steps will be to try for a merge to the inquisition repo.

Thanks to everyone who has participated so far, but especially to AJ and
Greg for all the advice.

James

[0]:
https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2023-January/021318.html
[1]: https://github.com/bitcoin/bitcoin/pull/26857
2023-02-13 21:09 [bitcoin-dev] BIP for OP_VAULT James O'Beirne

  2023-03-02  4:46   ` Anthony Towns
  2023-03-11 20:53 ` Luke Dashjr
  
From: Greg Sanders @ 2023-03-01 15:05 UTC (permalink / raw)
  To: James O'Beirne, Bitcoin Protocol Discussion

[-- Attachment #1: Type: text/plain, Size: 6352 bytes --]

Hello James,

First off, thank you for crafting an interesting idea like this that is
aimed at solving a serious problem. I see a lot of excitement about the use
cases, and I think it's worth iterating on.

Attempting to keep the idealized functionality constant, I'd like to
explore a design detour. I'm attempting to decouple the 3 functionalities
of `OP_VAULT` and `OP_UNVAULT` into their constituent functions with names
I just made up.

The goals of this e-mail:

1) Removing variable number of arguments based on values of arguments for
the opcodes.
To me as a spec reader, I find it very difficult to parse what's precisely
happening when. I think the only/last opcode to support this behavior was
OP_CHECKMULTISIG(could be wrong), and now I know another reason why OP_CSA
construct is nicer going forward with taproot.

2) Remove the recursive evaluation functionality used for authentication,
without reducing the efficacy of the targeted solution. Recursive
evaluation has a fraught history in Bitcoin script, makes composing
functionality with tooling likely more difficult, and has a lot of
templated behavior. If we can rely on regular old tapscript to get us where
we need to go, I'd prefer that.

3) Increase legibility of the spec. There's a ton going on, breaking things
up and naming them based on the method rather than the goal may help here.

4) Not (greatly) increase the expressiveness of the proposal. It's a
targeted proposal, and I'd like to respect that. These covenant opcodes are
intended to be drop-in replacements for the OP_(UN)VAULT opcodes.

To recap, there are three things happen in idealized OP_VAULT scenario:
1) Money comes out, then has to wait (trigger transaction)
2) Money waits long enough, then withdrawals to dynamic set of outputs that
are declared at trigger time (withdrawal transaction)
3) Money to single specified output script picked up front, with no wait
(recovery)

Below is a sketch of a replacement for the two opcodes. Ignore my
inconsistency on VERIFY/non-VERIFY behavior, seeing if people agree with
this general direction:

`OP_TRIGGER_FORWARD`: Takes exactly three arguments:
1) output index to match against (provided at spend time normally)
2) target-outputs-hash: 32 byte hash to be forwarded to output given at (1)
(provided at spend time normally)
3) spend-delay: value to be forwarded to output given at (1)

Fails script immediately if there aren't enough inputs or they're the wrong
format.

These last two arguments are "forwarded" to output at index declared in
first argument, resulting in:

`EXPR_WITHDRAW: <spend-delay> OP_CHECKSEQUENCEVERIFY OP_DROP
<target-outputs-hash> OP_FORWARD_OUTPUTS`

As the derived tapscript, embedded in a output scriptpubkey of the form:
`tr(NUMS,{...,EXPR_WITHDRAW})`, meaning we literally take the control block
from the spending input, swap the inner pubkey for `NUMS`, use
`EXPR_WITHDRAW` as the tapleaf, reconstruct the merkle root. If the output
scriptpubkey doesnt match, fail.

This TLUV-ish script/inner pubkey replacement is meant to allow arbitrary
other conditions, which is where the "recovery" path comes in for typical
usage.

If output at the target output index doesn't match the constructed script,
the evaluation fails.

`OP_FORWARD_DESTINATION`: Takes exactly two arguments:
1) `dest-vout-idx`: index of output that contains the so-called "recovery"
path
2) <recovery sPK tagged hash (32 bytes)>: the hash of the script destination

Fails immediately if the reconstructed output script doesn't match.

`OP_FORWARD_OUTPUTS` takes exactly one argument:
1) target-outputs-hash: commits to all outputs' scripts and values

Fails immediately if transaction's outputs(including value) hash doesn't
match.

**Typical usage**:
```
DEPOSITING TO VAULT SCRIPT:

EXPR_RECOVERY:   <recovery> <auth> <stuff> <recovery sPK tagged hash (32
bytes)> OP_FORWARD_DESTINATION
EXPR_TRIGGER:     <trigger> <auth> <stuff> <spend-delay> OP_TRIGGER_FORWARD

tr(KEY, {EXPR_RECOVERY, EXPR_TRIGGER})
```

```
EXPR_WITHDRAW: <spend-delay> OP_CHECKSEQUENCEVERIFY OP_DROP
<target-outputs-hash> OP_FORWARD_OUTPUTS
```

```
TRIGGERING WITHDRAWAL TIMER SCRIPT:

tr(NUMS, {EXPR_RECOVERY,EXPR_WITHDRAW}) <--- note EXPR_RECOVERY is forced
by the OP_TRIGGER_FORWARD TLUV action
```

Could save 2 WU having OP_FORWARD_OUTPUTS take the <spend-delay> directly
as an argument, or keep it more general as I did.

Would love to know what you and others think about this direction. I
apologies for any misunderstandings I have about the current OP_VAULT BIP!

Cheers,
Greg

On Mon, Feb 13, 2023 at 4:09 PM James O'Beirne via bitcoin-dev <
bitcoin-dev@lists•linuxfoundation.org> wrote:

> Since the last related correspondence on this list [0], a number of
> improvements have been made to the OP_VAULT draft [1]:
>
> * There is no longer a hard dependence on package relay/ephemeral
>   anchors for fee management. When using "authorized recovery," all
>   vault-related transactions can be bundled with unrelated inputs and
>   outputs, facilitating fee management that is self contained to the
>   transaction. Consequently, the contents of this proposal are in theory
>   usable today.
>
> * Specific output locations are no longer hardcoded in any of the
>   transaction validation algorithms. This means that the proposal is now
>   compatible with future changes like SIGHASH_GROUP, and
>   transaction shapes for vault operations are more flexible.
>
> ---
>
> I've written a BIP that fully describes the proposal here:
>
>
> https://github.com/jamesob/bips/blob/jamesob-23-02-opvault/bip-vaults.mediawiki
>
> The corresponding PR is here:
>
>   https://github.com/bitcoin/bips/pull/1421
>
> My next steps will be to try for a merge to the inquisition repo.
>
> Thanks to everyone who has participated so far, but especially to AJ and
> Greg for all the advice.
>
> James
>
> [0]:
> https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2023-January/021318.html
> [1]: https://github.com/bitcoin/bitcoin/pull/26857
> _______________________________________________
> bitcoin-dev mailing list
> bitcoin-dev@lists•linuxfoundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
>

[-- Attachment #2: Type: text/html, Size: 7779 bytes --]

 permalink raw reply	[|nested]
2023-03-01 15:05 ` Greg Sanders

  2023-03-02 14:54     ` Greg Sanders
  
From: Anthony Towns @ 2023-03-02  4:46 UTC (permalink / raw)
  To: Greg Sanders, Bitcoin Protocol Discussion

On Wed, Mar 01, 2023 at 10:05:47AM -0500, Greg Sanders via bitcoin-dev wrote:
> Below is a sketch of a replacement for the two opcodes. 

I like this! I tried to come up with something along similar lines for
similar reasons, but I think I tried too hard to reduce it to two opcodes
or something and got myself confused.

> `OP_TRIGGER_FORWARD`: Takes exactly three arguments:
> 1) output index to match against (provided at spend time normally)
> 2) target-outputs-hash: 32 byte hash to be forwarded to output given at (1)
> (provided at spend time normally)
> 3) spend-delay: value to be forwarded to output given at (1)

I think you could generalise this as follows:

   idx .. npush script OP_FORWARD_LEAF_UPDATE

(OP_FLU :) with the behaviour being:

   pop script from the stack
   pop npush from the stack (error if non-minimal or <0)
   pop npush entries from the stack,
     prefix script with a minimal push of that entry
   pop idx off the stack (error if idx is not a valid output)
   calculate the spk corresponding to taking the current
     input's spk and replacing the current leaf with the
     given script
   check the output at idx matches this spk, and the
     value from this input accumulates to that output

Then instead of `idx hash delay OP_TRIGGER_FORWARD` you
write `idx hash delay 2 "OP_CSV OP_DROP OP_FORWARD_OUTPUTS"
OP_FORWARD_LEAF_UPDATE`

That's an additional 5 witness bytes, but a much more generic/composable
opcode.

Being able to prefix a script with push opcodes avoids the possibility
of being able to add OP_SUCCESS instructions, so I think this is a fairly
safe way of allowing a TLUV-ish script to be modified, especially compared
to OP_CAT.

I do recognise that it makes it take a variable number of stack elements
though :)

> As the derived tapscript, embedded in a output scriptpubkey of the form:
> `tr(NUMS,{...,EXPR_WITHDRAW})`, meaning we literally take the control block
> from the spending input, swap the inner pubkey for `NUMS`, use
> `EXPR_WITHDRAW` as the tapleaf, reconstruct the merkle root. If the output
> scriptpubkey doesnt match, fail.

I don't think replacing the internal-public-key makes sense -- if it
was immediately spendable via the keypath before there's no reason for
it not to be immediately spendable now.

> Could save 2 WU having OP_FORWARD_OUTPUTS take the <spend-delay> directly
> as an argument, or keep it more general as I did.

Having OP_FORWARD_OUTPUTS not leave its input on the stack would let
you move the OP_CSV to the end and drop the OP_DROP too, saving 1 WU.

> Would love to know what you and others think about this direction. I
> apologies for any misunderstandings I have about the current OP_VAULT BIP!

I think the existing OP_VAULT cleverness would work here, allowing you
to spend two inputs to the same output, accumulating their values.

I don't think it quite gives you a way to "refund" values though -- so
that you can take a vault with 3 BTC, start the <delay> wait to spend
1.4 BTC, and then immediately decide to spend an additional 0.8 BTC on
something else, without the 0.8 BTC effectively having a doubled delay.

I think you could fix that with something as simple as an additional
"idx OP_FORWARD_REFUND" opcode, though -- then the restriction is just
that the output at the refund idx has the same sPK as this input, and
the total value of this input is accumulated amongst all the outputs
specified by OP_FORWARD opcodes. (Maybe you need to specify the refund
amount explicitly as well, to keep verification easy)

That would make maybe three new opcodes to cover the "accumulate value
from one or more inputs into specified outputs":

 - OP_FORWARD_LEAF_UPDATE --> forward input value to modified spk
 - OP_FORWARD_DESTINATION --> forward input value to given spk
 - OP_FORWARD_REFUND --> forward part of input value to same spk

along with OP_CTV:

 - OP_FORWARD_OUTPUTS --> pay to specific outputs

OP_VAULT's "accumulate value" behaviour here makes the OP_IN_OUT_AMOUNT
things from TLUV more implicit and automatic, which is nice. I think
doing TLUV payment pools wouldn't require much more than the ability to
combine OP_FLU and OP_FDEST in a single script, explicitly specifying
how much value is extracted via OP_FDEST with the rest assigned to OP_FLU.

Cheers,
aj


 permalink raw reply	[|nested]
2023-03-02  4:46   ` Anthony Towns

  2023-03-02 19:51       ` Andrew Melnychuk Oseen
                         ` (2 more replies)
  
From: Greg Sanders @ 2023-03-02 14:54 UTC (permalink / raw)
  To: Anthony Towns;  Bitcoin Protocol Discussion

[-- Attachment #1: Type: text/plain, Size: 7308 bytes --]

Greetings AJ,

Glad I could resurrect the idea!

> Then instead of `idx hash delay OP_TRIGGER_FORWARD` you
write `idx hash delay 2 "OP_CSV OP_DROP OP_FORWARD_OUTPUTS"
OP_FORWARD_LEAF_UPDATE`

Interesting idea! (I'll let you be the one to scope creep the proposal :) )

To be pedantic, EXPR_TRIGGER would become:

<trigger> <auth> <stuff> <spend-delay> <2> <OP_CSV OP_DROP
OP_FORWARD_OUTPUTS> OP_FORWARD_LEAF_UPDATE

and at spend time the idx and hash are put into the witness stack.

To be clear, <spend-delay> could be embedded in the <script> too, right,
making <2> a <1> in the above? Any reason for one or the other?

Another bonus from this is that you can introduce withdrawal authorization
as well as part of the <script>. Current proposal has no withdrawal
authorization, from what I understand. So each transition in a vault
construct can have authorization, if it desires it.

> I do recognise that it makes it take a variable number of stack elements
though :)

Just when I thought I was out, they pulled me back in.

> I don't think replacing the internal-public-key makes sense -- if it
was immediately spendable via the keypath before there's no reason for
it not to be immediately spendable now.

Slavishly following the current proposal was the idea to make sure all
functionality was captured; I agree with this change.

> Having OP_FORWARD_OUTPUTS not leave its input on the stack would let
you move the OP_CSV to the end and drop the OP_DROP too, saving 1 WU.

Previously setting CSV timeout to 0 would result in it not being
satisfiable, if I'm understanding the suggestion correctly. I suppose this
was a side-effect of having OP_UNVAULT take this value directly. Indeed
with `OP_FORWARD_OUTPUTS` being split out there's not really a reason to
use a 0 value?

> I think the existing OP_VAULT cleverness would work here, allowing you
to spend two inputs to the same output, accumulating their values.

Yes I think batching story should be same hopefully. I am assuming all the
accounting OP_VAULT is doing is being done here. We match against the hash
passed in, and fits into the "deferred checks" IIUC.

> OP_FORWARD_REFUND

Again, to be pedantic EXPR_TRIGGER becomes:

<trigger> <auth> <stuff> <spend-delay> <2> <OP_CSV OP_DROP
OP_FORWARD_OUTPUTS> OP_FORWARD_LEAF_UPDATE OP_FORWARD_REFUND

Resulting in 2 more WU at spend time(for small idx). So *up front*
committing to a refund path, perhaps with value explicitly passed in.

Totally forgot about the refund path; will need to mull the issue over, see
how it interacts with BYOF schemes, etc.

Cheers,
Greg


On Wed, Mar 1, 2023 at 11:46 PM Anthony Towns <aj@erisian•com.au> wrote:

> On Wed, Mar 01, 2023 at 10:05:47AM -0500, Greg Sanders via bitcoin-dev
> wrote:
> > Below is a sketch of a replacement for the two opcodes.
>
> I like this! I tried to come up with something along similar lines for
> similar reasons, but I think I tried too hard to reduce it to two opcodes
> or something and got myself confused.
>
> > `OP_TRIGGER_FORWARD`: Takes exactly three arguments:
> > 1) output index to match against (provided at spend time normally)
> > 2) target-outputs-hash: 32 byte hash to be forwarded to output given at
> (1)
> > (provided at spend time normally)
> > 3) spend-delay: value to be forwarded to output given at (1)
>
> I think you could generalise this as follows:
>
>    idx .. npush script OP_FORWARD_LEAF_UPDATE
>
> (OP_FLU :) with the behaviour being:
>
>    pop script from the stack
>    pop npush from the stack (error if non-minimal or <0)
>    pop npush entries from the stack,
>      prefix script with a minimal push of that entry
>    pop idx off the stack (error if idx is not a valid output)
>    calculate the spk corresponding to taking the current
>      input's spk and replacing the current leaf with the
>      given script
>    check the output at idx matches this spk, and the
>      value from this input accumulates to that output
>
> Then instead of `idx hash delay OP_TRIGGER_FORWARD` you
> write `idx hash delay 2 "OP_CSV OP_DROP OP_FORWARD_OUTPUTS"
> OP_FORWARD_LEAF_UPDATE`
>
> That's an additional 5 witness bytes, but a much more generic/composable
> opcode.
>
> Being able to prefix a script with push opcodes avoids the possibility
> of being able to add OP_SUCCESS instructions, so I think this is a fairly
> safe way of allowing a TLUV-ish script to be modified, especially compared
> to OP_CAT.
>
> I do recognise that it makes it take a variable number of stack elements
> though :)
>
> > As the derived tapscript, embedded in a output scriptpubkey of the form:
> > `tr(NUMS,{...,EXPR_WITHDRAW})`, meaning we literally take the control
> block
> > from the spending input, swap the inner pubkey for `NUMS`, use
> > `EXPR_WITHDRAW` as the tapleaf, reconstruct the merkle root. If the
> output
> > scriptpubkey doesnt match, fail.
>
> I don't think replacing the internal-public-key makes sense -- if it
> was immediately spendable via the keypath before there's no reason for
> it not to be immediately spendable now.
>
> > Could save 2 WU having OP_FORWARD_OUTPUTS take the <spend-delay> directly
> > as an argument, or keep it more general as I did.
>
> Having OP_FORWARD_OUTPUTS not leave its input on the stack would let
> you move the OP_CSV to the end and drop the OP_DROP too, saving 1 WU.
>
> > Would love to know what you and others think about this direction. I
> > apologies for any misunderstandings I have about the current OP_VAULT
> BIP!
>
> I think the existing OP_VAULT cleverness would work here, allowing you
> to spend two inputs to the same output, accumulating their values.
>
> I don't think it quite gives you a way to "refund" values though -- so
> that you can take a vault with 3 BTC, start the <delay> wait to spend
> 1.4 BTC, and then immediately decide to spend an additional 0.8 BTC on
> something else, without the 0.8 BTC effectively having a doubled delay.
>
> I think you could fix that with something as simple as an additional
> "idx OP_FORWARD_REFUND" opcode, though -- then the restriction is just
> that the output at the refund idx has the same sPK as this input, and
> the total value of this input is accumulated amongst all the outputs
> specified by OP_FORWARD opcodes. (Maybe you need to specify the refund
> amount explicitly as well, to keep verification easy)
>
> That would make maybe three new opcodes to cover the "accumulate value
> from one or more inputs into specified outputs":
>
>  - OP_FORWARD_LEAF_UPDATE --> forward input value to modified spk
>  - OP_FORWARD_DESTINATION --> forward input value to given spk
>  - OP_FORWARD_REFUND --> forward part of input value to same spk
>
> along with OP_CTV:
>
>  - OP_FORWARD_OUTPUTS --> pay to specific outputs
>
> OP_VAULT's "accumulate value" behaviour here makes the OP_IN_OUT_AMOUNT
> things from TLUV more implicit and automatic, which is nice. I think
> doing TLUV payment pools wouldn't require much more than the ability to
> combine OP_FLU and OP_FDEST in a single script, explicitly specifying
> how much value is extracted via OP_FDEST with the rest assigned to OP_FLU.
>
> Cheers,
> aj
>

[-- Attachment #2: Type: text/html, Size: 8876 bytes --]

 permalink raw reply	[|nested]
2023-03-02  4:46   ` Anthony Towns

  2023-03-02 19:51       ` 
                         ` 
  
From: Greg Sanders @ 2023-03-02 14:54 UTC (permalink / raw)
  To: Anthony Towns;  Bitcoin Protocol Discussion

[-- Attachment #1: Type: text/plain, Size: 7308 bytes --]

Greetings AJ,

Glad I could resurrect the idea!

> Then instead of `idx hash delay OP_TRIGGER_FORWARD` you
write `idx hash delay 2 "OP_CSV OP_DROP OP_FORWARD_OUTPUTS"
OP_FORWARD_LEAF_UPDATE`

Interesting idea! (I'll let you be the one to scope creep the proposal :) )

To be pedantic, EXPR_TRIGGER would become:

<trigger> <auth> <stuff> <spend-delay> <2> <OP_CSV OP_DROP
OP_FORWARD_OUTPUTS> OP_FORWARD_LEAF_UPDATE

and at spend time the idx and hash are put into the witness stack.

To be clear, <spend-delay> could be embedded in the <script> too, right,
making <2> a <1> in the above? Any reason for one or the other?

Another bonus from this is that you can introduce withdrawal authorization
as well as part of the <script>. Current proposal has no withdrawal
authorization, from what I understand. So each transition in a vault
construct can have authorization, if it desires it.

> I do recognise that it makes it take a variable number of stack elements
though :)

Just when I thought I was out, they pulled me back in.

> I don't think replacing the internal-public-key makes sense -- if it
was immediately spendable via the keypath before there's no reason for
it not to be immediately spendable now.

Slavishly following the current proposal was the idea to make sure all
functionality was captured; I agree with this change.

> Having OP_FORWARD_OUTPUTS not leave its input on the stack would let
you move the OP_CSV to the end and drop the OP_DROP too, saving 1 WU.

Previously setting CSV timeout to 0 would result in it not being
satisfiable, if I'm understanding the suggestion correctly. I suppose this
was a side-effect of having OP_UNVAULT take this value directly. Indeed
with `OP_FORWARD_OUTPUTS` being split out there's not really a reason to
use a 0 value?

> I think the existing OP_VAULT cleverness would work here, allowing you
to spend two inputs to the same output, accumulating their values.

Yes I think batching story should be same hopefully. I am assuming all the
accounting OP_VAULT is doing is being done here. We match against the hash
passed in, and fits into the "deferred checks" IIUC.

> OP_FORWARD_REFUND

Again, to be pedantic EXPR_TRIGGER becomes:

<trigger> <auth> <stuff> <spend-delay> <2> <OP_CSV OP_DROP
OP_FORWARD_OUTPUTS> OP_FORWARD_LEAF_UPDATE OP_FORWARD_REFUND

Resulting in 2 more WU at spend time(for small idx). So *up front*
committing to a refund path, perhaps with value explicitly passed in.

Totally forgot about the refund path; will need to mull the issue over, see
how it interacts with BYOF schemes, etc.

Cheers,
Greg


On Wed, Mar 1, 2023 at 11:46 PM Anthony Towns <aj@erisian•com.au> wrote:

> On Wed, Mar 01, 2023 at 10:05:47AM -0500, Greg Sanders via bitcoin-dev
> wrote:
> > Below is a sketch of a replacement for the two opcodes.
>
> I like this! I tried to come up with something along similar lines for
> similar reasons, but I think I tried too hard to reduce it to two opcodes
> or something and got myself confused.
>
> > `OP_TRIGGER_FORWARD`: Takes exactly three arguments:
> > 1) output index to match against (provided at spend time normally)
> > 2) target-outputs-hash: 32 byte hash to be forwarded to output given at
> (1)
> > (provided at spend time normally)
> > 3) spend-delay: value to be forwarded to output given at (1)
>
> I think you could generalise this as follows:
>
>    idx .. npush script OP_FORWARD_LEAF_UPDATE
>
> (OP_FLU :) with the behaviour being:
>
>    pop script from the stack
>    pop npush from the stack (error if non-minimal or <0)
>    pop npush entries from the stack,
>      prefix script with a minimal push of that entry
>    pop idx off the stack (error if idx is not a valid output)
>    calculate the spk corresponding to taking the current
>      input's spk and replacing the current leaf with the
>      given script
>    check the output at idx matches this spk, and the
>      value from this input accumulates to that output
>
> Then instead of `idx hash delay OP_TRIGGER_FORWARD` you
> write `idx hash delay 2 "OP_CSV OP_DROP OP_FORWARD_OUTPUTS"
> OP_FORWARD_LEAF_UPDATE`
>
> That's an additional 5 witness bytes, but a much more generic/composable
> opcode.
>
> Being able to prefix a script with push opcodes avoids the possibility
> of being able to add OP_SUCCESS instructions, so I think this is a fairly
> safe way of allowing a TLUV-ish script to be modified, especially compared
> to OP_CAT.
>
> I do recognise that it makes it take a variable number of stack elements
> though :)
>
> > As the derived tapscript, embedded in a output scriptpubkey of the form:
> > `tr(NUMS,{...,EXPR_WITHDRAW})`, meaning we literally take the control
> block
> > from the spending input, swap the inner pubkey for `NUMS`, use
> > `EXPR_WITHDRAW` as the tapleaf, reconstruct the merkle root. If the
> output
> > scriptpubkey doesnt match, fail.
>
> I don't think replacing the internal-public-key makes sense -- if it
> was immediately spendable via the keypath before there's no reason for
> it not to be immediately spendable now.
>
> > Could save 2 WU having OP_FORWARD_OUTPUTS take the <spend-delay> directly
> > as an argument, or keep it more general as I did.
>
> Having OP_FORWARD_OUTPUTS not leave its input on the stack would let
> you move the OP_CSV to the end and drop the OP_DROP too, saving 1 WU.
>
> > Would love to know what you and others think about this direction. I
> > apologies for any misunderstandings I have about the current OP_VAULT
> BIP!
>
> I think the existing OP_VAULT cleverness would work here, allowing you
> to spend two inputs to the same output, accumulating their values.
>
> I don't think it quite gives you a way to "refund" values though -- so
> that you can take a vault with 3 BTC, start the <delay> wait to spend
> 1.4 BTC, and then immediately decide to spend an additional 0.8 BTC on
> something else, without the 0.8 BTC effectively having a doubled delay.
>
> I think you could fix that with something as simple as an additional
> "idx OP_FORWARD_REFUND" opcode, though -- then the restriction is just
> that the output at the refund idx has the same sPK as this input, and
> the total value of this input is accumulated amongst all the outputs
> specified by OP_FORWARD opcodes. (Maybe you need to specify the refund
> amount explicitly as well, to keep verification easy)
>
> That would make maybe three new opcodes to cover the "accumulate value
> from one or more inputs into specified outputs":
>
>  - OP_FORWARD_LEAF_UPDATE --> forward input value to modified spk
>  - OP_FORWARD_DESTINATION --> forward input value to given spk
>  - OP_FORWARD_REFUND --> forward part of input value to same spk
>
> along with OP_CTV:
>
>  - OP_FORWARD_OUTPUTS --> pay to specific outputs
>
> OP_VAULT's "accumulate value" behaviour here makes the OP_IN_OUT_AMOUNT
> things from TLUV more implicit and automatic, which is nice. I think
> doing TLUV payment pools wouldn't require much more than the ability to
> combine OP_FLU and OP_FDEST in a single script, explicitly specifying
> how much value is extracted via OP_FDEST with the rest assigned to OP_FLU.
>
> Cheers,
> aj
>

[-- Attachment #2: Type: text/html, Size: 8876 bytes --]

 permalink raw reply	[|nested]
2023-03-02 14:54     ` Greg Sanders
  2023-03-02 19:51       ` Andrew Melnychuk Oseen

  2023-03-06 16:07         ` Greg Sanders
  2023-03-07 12:45         ` Anthony Towns
  2023-03-13 19:03       ` Brandon Black
  
From: James O'Beirne @ 2023-03-06 15:25 UTC (permalink / raw)
  To: Greg Sanders;  Bitcoin Protocol Discussion, Anthony Towns

[-- Attachment #1: Type: text/plain, Size: 6693 bytes --]

I'm glad to see that Greg and AJ are forming a habit of hammering
this proposal into shape. Nice work fellas.

To summarize:

What Greg is proposing above is to in essence TLUV-ify this proposal.

I.e. instead of relying on hashed commitments and recursive script
execution (e.g. <trigger-sPK-hash> + later presentation of preimage
script for execution), OP_VAULT would instead move through its
withdrawal process by swapping out tapleaf contents according to
specialized rules. If this is opaque (as it was to me), don't fret -
I'll describe it below in the "mechanics" section.


The benefits of this TLUVification are

- we can avoid any nested/recursive script execution. I know the
  recursive stuff rankles some greybeards even in spite of it being
  bounded to a single call. I'm not sure I share the concern but
  maintaining the status quo seems good.

- the spec is easier to reason about, more or less. The opcodes
  introduced don't have variadic witness requirements, and each opcode
  is only consumed in a single way.

- there's less general indirection. Instead of saying "okay, here's the
  hash of the script I'm going to use to authorize trigger
  transactions," we're just outright including the trigger auth script
  in the tapleaf at the birth of the vault as regular 'ol script that is
  evaluated before execution of the OP_VAULT instruction.

  Similarly, instead of relying on an implicit rule that an OP_VAULT can
  be claimed by a recovery flow, we're relying on a specific tapleaf that
  facilitates that recovery with OP_VAULT_RECOVER, described below.

Basically, OP_VAULT would just be implemented in a way that feels
more native to Taproot primitives.

Greg also introduces different opcodes to facilitate consistent
witness structure, rather than the variable ones we have now
since OP_VAULT and OP_UNVAULT can each be spent in two different
contexts. I've changed those a little here; instead of the three general
ones Greg gave, we whittled it down to two: OP_VAULT and
OP_VAULT_RECOVER.


So I think that, barring significant implementation complexity - which
I'll find out about soon and don't expect - this is a good change to the
proposal. As Greg noted, it doesn't really change anything about the
usage or expressiveness... other than the fact that, as a bonus, it
might allow an optional withdrawal authorization script (i.e. trigger
output => final target), which could be useful if e.g. some kind of
size-limiting opcode (e.g. OP_TX_MAXSIZE or something) came around in
the future as a kind of pinning fix.

If that last bit lost you, don't worry - that is speculative, but the
point is that this rework composes well with other stuff.


# CTV use

Another thing that has dawned on us is that we might as well just reuse
OP_CHECKTEMPLATEVERIFY for withdrawal target spends. Ben Carmen and
others realized early on that you can synthesize CTV-like behavior by
spending to a 0-delay OP_UNVAULT output, so something CTVish has always
implicitly been a part of the proposal. But CTV is better studied and
basically as simple as the OP_UNVAULT spend semantics, so the thought is
that we might as well reuse all the existing work (and scrutiny) from
CTV.

As a concrete example, an issue with the existing proposal is that the
existing CTVish OP_UNVAULT behavior has txid malleability, since it
doesn't commit to nVersion or nLockTime or the input sequences. Using
CTV solves this issue. Otherwise we'd basically reinvent it - "something
something convergent evolution."

I think this is a satisfying development, because there's clearly demand
for CTV use in other contexts (DLC efficiency, e.g.), and if it's
required behavior for practical vaults, I think pulling in the existing
BIP-119 that's been worked over for years reduces the conceptual
surface area added by OP_VAULT.


# New mechanics of the proposal

So here I'm going to describe my rendering of Greg and AJ's suggestions.


## Required opcodes

- OP_VAULT: spent to trigger withdrawal
- OP_VAULT_RECOVER: spent to recover
- OP_CHECKTEMPLATEVERIFY: spent into final withdrawal target


Creating an initial deposit
---------------------------

For each vault, vaulted coins are spent to an output with the taproot
structure

  taproot(internal_key, {$recovery_leaf, $trigger_leaf, ...})

where

  internal_key =
    unchanged from original proposal (some very safe recovery key)

  $recovery_leaf =
    [<opt.> <recovery> <auth>] <recovery sPK hash> OP_VAULT_RECOVER

  $trigger_leaf =
    <trigger> <auth> <script> <spend-delay> OP_VAULT

  ... =
    other (optional) leaves in the taptree


Triggering a withdrawal request
-------------------------------

To trigger the start of the withdrawal process, an output of the above
form is spent with a witness that contains

  - Taproot control block pointing to $trigger_leaf.
  - <trigger-vout-idx>, indicating the trigger output which must abide
    by the rules given below.


## Output structure

  taproot(internal_key, {$recovery_leaf, $expr_withdraw, ...})

where

  $recovery_leaf is preserved exactly
  $expr_withdraw =
    <spend-delay> OP_CSV OP_DROP <target-ctv-hash> OP_CTV
  ... is preserved exactly


(Spoiler: note here that the only thing that is changing is
s/expr_trigger/expr_withdrawl/ from the initial vault ouput.)

Of course $expr_withdraw *could* be prefixed by an optional "withdrawal
authorization" script, if some sensible use for that is found.

The validation rules are essentially unchanged from the existing
proposal:

- The total amount of all OP_VAULT inputs with matching $recovery_leaf
  values must be reflected in output <trigger-vout-idx>

- <trigger-vout-idx> must correspond to an output that is identical to
  the input taptree but with the spent tapleaf (OP_VAULT) swapped out
  for the timelocked CTV constructed using <target-ctv-hash> and
  <spend-delay> as extracted from the spent tapleaf
  - internal_key is preserved
  - the whole rest of the taptree is preserved
  - (this is what ensures the parameters of the vault are forwarded)

All batching, fee management characteristics are the same.


Finalizing withdrawal
---------------------

Happens via script-path spend to $expr_withdraw, i.e. a timelocked
OP_CTV.


Recovery
--------

Can happen from any of the above outputs using the $recovery_leaf
script path in a way very similar to the existing OP_VAULT proposal.


---

To reiterate, all aspects of the existing OP_VAULT proposal are either
preserved or improved upon in terms of malleability reduction,
composability, and flexibility. So big thanks to AJ and Greg.

I'll undertake implementing these changes in the coming days to verify
that they are, as expected, workable.

James

[-- Attachment #2: Type: text/html, Size: 7624 bytes --]

 permalink raw reply	[|nested]
2023-03-06 15:25       ` James O'Beirne

  2023-03-07 12:45         ` Anthony Towns
  
From: Greg Sanders @ 2023-03-06 16:07 UTC (permalink / raw)
  To: James O'Beirne;  Bitcoin Protocol Discussion, Anthony Towns

[-- Attachment #1: Type: text/plain, Size: 7823 bytes --]

Hi James,

I think everything except the hinted "withdrawal authorization" is spot on.

For withdrawal authorization, I think we'll have to go deeper into the TLUV
direction
as AJ suggested for at least a couple reasons:

1) You need the withdrawal authorization committed at deposit time
2) You need to make sure cheeky opcodes cannot be prepended to the script
at spend time

OP_FORWARD_LEAF_UPDATE(OP_FLU) seems to fit the bill, at the cost of maybe
adding another opcode for "refunds" as he notes.

Cheers,
Greg

On Mon, Mar 6, 2023 at 10:25 AM James O'Beirne <james.obeirne@gmail•com>
wrote:

> I'm glad to see that Greg and AJ are forming a habit of hammering
> this proposal into shape. Nice work fellas.
>
> To summarize:
>
> What Greg is proposing above is to in essence TLUV-ify this proposal.
>
> I.e. instead of relying on hashed commitments and recursive script
> execution (e.g. <trigger-sPK-hash> + later presentation of preimage
> script for execution), OP_VAULT would instead move through its
> withdrawal process by swapping out tapleaf contents according to
> specialized rules. If this is opaque (as it was to me), don't fret -
> I'll describe it below in the "mechanics" section.
>
>
> The benefits of this TLUVification are
>
> - we can avoid any nested/recursive script execution. I know the
>   recursive stuff rankles some greybeards even in spite of it being
>   bounded to a single call. I'm not sure I share the concern but
>   maintaining the status quo seems good.
>
> - the spec is easier to reason about, more or less. The opcodes
>   introduced don't have variadic witness requirements, and each opcode
>   is only consumed in a single way.
>
> - there's less general indirection. Instead of saying "okay, here's the
>   hash of the script I'm going to use to authorize trigger
>   transactions," we're just outright including the trigger auth script
>   in the tapleaf at the birth of the vault as regular 'ol script that is
>   evaluated before execution of the OP_VAULT instruction.
>
>   Similarly, instead of relying on an implicit rule that an OP_VAULT can
>   be claimed by a recovery flow, we're relying on a specific tapleaf that
>   facilitates that recovery with OP_VAULT_RECOVER, described below.
>
> Basically, OP_VAULT would just be implemented in a way that feels
> more native to Taproot primitives.
>
> Greg also introduces different opcodes to facilitate consistent
> witness structure, rather than the variable ones we have now
> since OP_VAULT and OP_UNVAULT can each be spent in two different
> contexts. I've changed those a little here; instead of the three general
> ones Greg gave, we whittled it down to two: OP_VAULT and
> OP_VAULT_RECOVER.
>
>
> So I think that, barring significant implementation complexity - which
> I'll find out about soon and don't expect - this is a good change to the
> proposal. As Greg noted, it doesn't really change anything about the
> usage or expressiveness... other than the fact that, as a bonus, it
> might allow an optional withdrawal authorization script (i.e. trigger
> output => final target), which could be useful if e.g. some kind of
> size-limiting opcode (e.g. OP_TX_MAXSIZE or something) came around in
> the future as a kind of pinning fix.
>
> If that last bit lost you, don't worry - that is speculative, but the
> point is that this rework composes well with other stuff.
>
>
> # CTV use
>
> Another thing that has dawned on us is that we might as well just reuse
> OP_CHECKTEMPLATEVERIFY for withdrawal target spends. Ben Carmen and
> others realized early on that you can synthesize CTV-like behavior by
> spending to a 0-delay OP_UNVAULT output, so something CTVish has always
> implicitly been a part of the proposal. But CTV is better studied and
> basically as simple as the OP_UNVAULT spend semantics, so the thought is
> that we might as well reuse all the existing work (and scrutiny) from
> CTV.
>
> As a concrete example, an issue with the existing proposal is that the
> existing CTVish OP_UNVAULT behavior has txid malleability, since it
> doesn't commit to nVersion or nLockTime or the input sequences. Using
> CTV solves this issue. Otherwise we'd basically reinvent it - "something
> something convergent evolution."
>
> I think this is a satisfying development, because there's clearly demand
> for CTV use in other contexts (DLC efficiency, e.g.), and if it's
> required behavior for practical vaults, I think pulling in the existing
> BIP-119 that's been worked over for years reduces the conceptual
> surface area added by OP_VAULT.
>
>
> # New mechanics of the proposal
>
> So here I'm going to describe my rendering of Greg and AJ's suggestions.
>
>
> ## Required opcodes
>
> - OP_VAULT: spent to trigger withdrawal
> - OP_VAULT_RECOVER: spent to recover
> - OP_CHECKTEMPLATEVERIFY: spent into final withdrawal target
>
>
> Creating an initial deposit
> ---------------------------
>
> For each vault, vaulted coins are spent to an output with the taproot
> structure
>
>   taproot(internal_key, {$recovery_leaf, $trigger_leaf, ...})
>
> where
>
>   internal_key =
>     unchanged from original proposal (some very safe recovery key)
>
>   $recovery_leaf =
>     [<opt.> <recovery> <auth>] <recovery sPK hash> OP_VAULT_RECOVER
>
>   $trigger_leaf =
>     <trigger> <auth> <script> <spend-delay> OP_VAULT
>
>   ... =
>     other (optional) leaves in the taptree
>
>
> Triggering a withdrawal request
> -------------------------------
>
> To trigger the start of the withdrawal process, an output of the above
> form is spent with a witness that contains
>
>   - Taproot control block pointing to $trigger_leaf.
>   - <trigger-vout-idx>, indicating the trigger output which must abide
>     by the rules given below.
>
>
> ## Output structure
>
>   taproot(internal_key, {$recovery_leaf, $expr_withdraw, ...})
>
> where
>
>   $recovery_leaf is preserved exactly
>   $expr_withdraw =
>     <spend-delay> OP_CSV OP_DROP <target-ctv-hash> OP_CTV
>   ... is preserved exactly
>
>
> (Spoiler: note here that the only thing that is changing is
> s/expr_trigger/expr_withdrawl/ from the initial vault ouput.)
>
> Of course $expr_withdraw *could* be prefixed by an optional "withdrawal
> authorization" script, if some sensible use for that is found.
>
> The validation rules are essentially unchanged from the existing
> proposal:
>
> - The total amount of all OP_VAULT inputs with matching $recovery_leaf
>   values must be reflected in output <trigger-vout-idx>
>
> - <trigger-vout-idx> must correspond to an output that is identical to
>   the input taptree but with the spent tapleaf (OP_VAULT) swapped out
>   for the timelocked CTV constructed using <target-ctv-hash> and
>   <spend-delay> as extracted from the spent tapleaf
>   - internal_key is preserved
>   - the whole rest of the taptree is preserved
>   - (this is what ensures the parameters of the vault are forwarded)
>
> All batching, fee management characteristics are the same.
>
>
> Finalizing withdrawal
> ---------------------
>
> Happens via script-path spend to $expr_withdraw, i.e. a timelocked
> OP_CTV.
>
>
> Recovery
> --------
>
> Can happen from any of the above outputs using the $recovery_leaf
> script path in a way very similar to the existing OP_VAULT proposal.
>
>
> ---
>
> To reiterate, all aspects of the existing OP_VAULT proposal are either
> preserved or improved upon in terms of malleability reduction,
> composability, and flexibility. So big thanks to AJ and Greg.
>
> I'll undertake implementing these changes in the coming days to verify
> that they are, as expected, workable.
>
> James
>

[-- Attachment #2: Type: text/html, Size: 8686 bytes --]

 permalink raw reply	[|nested]
2023-03-06 15:25       ` James O'Beirne
  2023-03-06 16:07         ` Greg Sanders

  2023-03-09 18:45           ` Greg Sanders
  2023-03-24 12:10           ` Anthony Towns
  
From: Anthony Towns @ 2023-03-07 12:45 UTC (permalink / raw)
  To: James O'Beirne, Bitcoin Protocol Discussion;  Greg Sanders

On Mon, Mar 06, 2023 at 10:25:38AM -0500, James O'Beirne via bitcoin-dev wrote:
> What Greg is proposing above is to in essence TLUV-ify this proposal.

FWIW, the way I'm thinking about this is that the "OP_VAULT" concept is
introducing two things:

 a) the concept of "forwarding" the input amount to specified
    outputs in a way that elegantly allows merging/splitting

 b) various restrictions on the form of the output scripts

These concepts go together well, because restricting an output script is
only an interesting thing to do if you're moving value from this input
into it. And then it's just a matter of figuring out a nice way to pick
opcodes that combine those two concepts in interesting ways.

This is different from TLUV, in that TLUV only did part (b), and
assumed you'd do part (a) manually somehow, eg via "OP_IN_OUT_AMOUNT"
and arithmetic opcodes. The advantage of this new approach over that
one is that it makes it really easy to get the logic right (I often
forgot to include the IN_OUT_AMOUNT checks at all, for instance), and
also makes spending multiple inputs to a single output really simple,
something that would otherwise require kind-of gnarly logic.

I think there are perhaps four opcodes that are interesting in this class:

   idx sPK OP_FORWARD_TARGET
     -- sends the value to a particular output (given by idx), and
        requires that output have a particular scriptPubKey (given
        by sPK).

   idx [...] n script OP_FORWARD_LEAF_UPDATE
     -- sends the value to a particular output (given by idx), and
	requires that output to have almost the same scriptPubKey as this
	input, _except_ that the current leaf is replaced by "script",
	with that script prefixed by "n" pushes (of values given by [...])

   idx OP_FORWARD_SELF
     -- sends the value to a particular output (given by idx), and
        requires that output to have the same scriptPubKey as this input

   amt OP_FORWARD_PARTIAL
     -- modifies the next OP_FORWARD_* opcode to only affect "amt",
        rather than the entire balance. opcodes after that affect the
	remaining balance, after "amt" has been subtracted. if "amt" is
	0, the next OP_FORWARD_* becomes a no-op.

Then each time you see OP_FORWARD_TARGET or OP_FORWARD_LEAF_UPDATE, you
accumulate the value that's expected to be forwarded to the output by
each input, and verify that the amount for that output is greater-or-equal
to the accumulated value.

> ## Required opcodes
> - OP_VAULT: spent to trigger withdrawal
> - OP_VAULT_RECOVER: spent to recover

Naming here is OP_VAULT ~= OP_FORWARD_LEAF_UPDATE; OP_VAULT_RECOVER ~=
OP_FORWARD_TARGET.

> For each vault, vaulted coins are spent to an output with the taproot
> structure
> 
>   taproot(internal_key, {$recovery_leaf, $trigger_leaf, ...})
> 
> where
> 
>   $trigger_leaf =
>     <trigger> <auth> <script> <spend-delay> OP_VAULT

With the opcodes above, the trigger_leaf (for spending some of the
vaulted funds via your hot wallet) script might look like:

   OP_FORWARD_PARTIAL OP_FORWARD_SELF
   1 "288 OP_CSV OP_DROP OP_CTV" OP_FORWARD_LEAF_UPDATE
   key CHECKSIG

So if you have 2.0 BTC in a vault utxo, you might spend 0.4 BTC by
supplying the witness data:

  160000000  (1.6BTC in sats)
  0 (output 0 puts 1.6BTC goes back into the vault)
  <ctvhash> (the outputs where you want the remaining 0.4 BTC to end up)
  1 (the output idx that will be spend via the CTV path once the CSV
     delay is done)
  <sig> (a signature of this transaction via the hot wallet "key")

That is, the script becomes:

  160000000 FORWARD_PARTIAL
  0 FORWARD_SELF
  1 <ctvhash> 1 "288 CSV DROP CTV" FORWARD_LEAF_UPDATE
  sig key CHECKSIG

Output 1 would then have a tapscript of "<ctvhash> 288 OP_CSV OP_DROP
OP_CTV", satisfied with an empty witness stack (along with the recovery
path, etc).

Output 0 is just 1.6BTC back in your vault, and immediately available 
for use.

Other inputs/outputs (for fees etc) would still be committed to by <sig>,
so nothing here is malleable. The script here is about 45 bytes (compared
to 34 for a simple "key CHECKSIG") and the witness data is about 105 bytes
(compared to 65 bytes for just a signature), which seems pretty nice.

>   ... =
>     other (optional) leaves in the taptree

This would allow you to have multiple hot wallets (if any of them are
compromised you can still use the recovery path to avoid loss of funds;
but if some hot wallet becomes temporarily *inaccessible* you can still
easily spend the funds via one of the alternative hot wallets), or,
if you have multiple watchtowers validating your spends and recovering
funds to your cold wallet on a violation, you could have multiple recovery
paths to provide some auditability for who triggered the recovery.

> Happens via script-path spend to $expr_withdraw, i.e. a timelocked
> OP_CTV.

Note that if you calculated the OP_CTV incorrectly (eg, you don't set a
correct nSequence timelock, so that any tx that passes OP_CTV won't pass
the OP_CSV check, and vice-versa) then this spend path becomes invalid,
and the funds can only be reclaimed via some other path (key path spend,
recovery tapscript, potentially an alternative hotwallet script path).

OP_FORWARD_LEAF_UPDATE is equivalent to a very specific form of TLUV,
namely "FALSE <h> 2 TLUV", where "<h>" is calculated by building the
script, prefixing the pushes, then doing the Hash_TapLeaf calculation.

Not being able to tweak the internal public key ("FALSE" rather than
"<x>") means this can't be used to build a coinpool with unilateral
exit -- you can't remove your key from the key path, which screws over
everyone who's still in the coinpool.

On the other hand, not tweaking the internal public key avoids introducing
all the x-only pubkey complications, and keeps it relatively simple,
which is nice, and keeping things simple and targeted now means there's
still plenty of OP_SUCCESS opcodes available later for something more
general, if that turns out to be desirable.

Cheers,
aj


 permalink raw reply	[|nested]
2023-03-07 12:45         ` Anthony Towns

  2023-03-10  1:08             ` Anthony Towns
  2023-03-24 12:10           ` Anthony Towns
  
From: Greg Sanders @ 2023-03-09 18:45 UTC (permalink / raw)
  To: Anthony Towns;  Bitcoin Protocol Discussion

[-- Attachment #1: Type: text/plain, Size: 7991 bytes --]

AJ,

Interesting stuff! Just a couple thoughts on these proposed opcodes, at
least one we discussed elsewhere:

1) OP_FORWARD_SELF is a JET of OP_FLU in the revaulting common case. Maybe
obvious but I missed this initially and thought it was useful to be pointed
out.

2)  Using these extended primitives, you can do rate-limiting of the two
step unvaulting, or just a single step vault by committing to the partial
values. For the single stage case it's something like:

$recovery = Same As Before

$withdrawal = <deposit-delay> OP_CSV OP_DROP <pubkey> OP_CHECKSIG OP_DUP
<V> OP_LESSTHANOREQUAL OP_VERIFY OP_FORWARD_PARTIAL OP_FORWARD_TARGET
OP_FORWARD_SELF

$withdrawal is spent by:

<self-idx> <target-idx> <spk> <0<=v<=V> <signature>

where "V"  is the max allowed withdrawal value, and "deposit-delay" the
required gap in withdrawals

Due to the OP_LEQ, you are bound to ~21 BTC in value for this operation,
but for larger vaults it's pretty trivial to add larder fixed denominations
to "peel out" value until you get to your final ~21 BTC.

This rate-limiting(in either the two-stage or one-stage scheme) can limit
the risk of theft during a watchtower outage to a constant value per utxo
per time period of watchtower failure. As we've seen in the past with LN
infrastructure, software risks are often correlated, so it's a good idea to
build in belt and suspenders where we can or at least have them available
when possible.

Cheers,
Greg


On Tue, Mar 7, 2023 at 7:45 AM Anthony Towns <aj@erisian•com.au> wrote:

> On Mon, Mar 06, 2023 at 10:25:38AM -0500, James O'Beirne via bitcoin-dev
> wrote:
> > What Greg is proposing above is to in essence TLUV-ify this proposal.
>
> FWIW, the way I'm thinking about this is that the "OP_VAULT" concept is
> introducing two things:
>
>  a) the concept of "forwarding" the input amount to specified
>     outputs in a way that elegantly allows merging/splitting
>
>  b) various restrictions on the form of the output scripts
>
> These concepts go together well, because restricting an output script is
> only an interesting thing to do if you're moving value from this input
> into it. And then it's just a matter of figuring out a nice way to pick
> opcodes that combine those two concepts in interesting ways.
>
> This is different from TLUV, in that TLUV only did part (b), and
> assumed you'd do part (a) manually somehow, eg via "OP_IN_OUT_AMOUNT"
> and arithmetic opcodes. The advantage of this new approach over that
> one is that it makes it really easy to get the logic right (I often
> forgot to include the IN_OUT_AMOUNT checks at all, for instance), and
> also makes spending multiple inputs to a single output really simple,
> something that would otherwise require kind-of gnarly logic.
>
> I think there are perhaps four opcodes that are interesting in this class:
>
>    idx sPK OP_FORWARD_TARGET
>      -- sends the value to a particular output (given by idx), and
>         requires that output have a particular scriptPubKey (given
>         by sPK).
>
>    idx [...] n script OP_FORWARD_LEAF_UPDATE
>      -- sends the value to a particular output (given by idx), and
>         requires that output to have almost the same scriptPubKey as this
>         input, _except_ that the current leaf is replaced by "script",
>         with that script prefixed by "n" pushes (of values given by [...])
>
>    idx OP_FORWARD_SELF
>      -- sends the value to a particular output (given by idx), and
>         requires that output to have the same scriptPubKey as this input
>
>    amt OP_FORWARD_PARTIAL
>      -- modifies the next OP_FORWARD_* opcode to only affect "amt",
>         rather than the entire balance. opcodes after that affect the
>         remaining balance, after "amt" has been subtracted. if "amt" is
>         0, the next OP_FORWARD_* becomes a no-op.
>
> Then each time you see OP_FORWARD_TARGET or OP_FORWARD_LEAF_UPDATE, you
> accumulate the value that's expected to be forwarded to the output by
> each input, and verify that the amount for that output is greater-or-equal
> to the accumulated value.
>
> > ## Required opcodes
> > - OP_VAULT: spent to trigger withdrawal
> > - OP_VAULT_RECOVER: spent to recover
>
> Naming here is OP_VAULT ~= OP_FORWARD_LEAF_UPDATE; OP_VAULT_RECOVER ~=
> OP_FORWARD_TARGET.
>
> > For each vault, vaulted coins are spent to an output with the taproot
> > structure
> >
> >   taproot(internal_key, {$recovery_leaf, $trigger_leaf, ...})
> >
> > where
> >
> >   $trigger_leaf =
> >     <trigger> <auth> <script> <spend-delay> OP_VAULT
>
> With the opcodes above, the trigger_leaf (for spending some of the
> vaulted funds via your hot wallet) script might look like:
>
>    OP_FORWARD_PARTIAL OP_FORWARD_SELF
>    1 "288 OP_CSV OP_DROP OP_CTV" OP_FORWARD_LEAF_UPDATE
>    key CHECKSIG
>
> So if you have 2.0 BTC in a vault utxo, you might spend 0.4 BTC by
> supplying the witness data:
>
>   160000000  (1.6BTC in sats)
>   0 (output 0 puts 1.6BTC goes back into the vault)
>   <ctvhash> (the outputs where you want the remaining 0.4 BTC to end up)
>   1 (the output idx that will be spend via the CTV path once the CSV
>      delay is done)
>   <sig> (a signature of this transaction via the hot wallet "key")
>
> That is, the script becomes:
>
>   160000000 FORWARD_PARTIAL
>   0 FORWARD_SELF
>   1 <ctvhash> 1 "288 CSV DROP CTV" FORWARD_LEAF_UPDATE
>   sig key CHECKSIG
>
> Output 1 would then have a tapscript of "<ctvhash> 288 OP_CSV OP_DROP
> OP_CTV", satisfied with an empty witness stack (along with the recovery
> path, etc).
>
> Output 0 is just 1.6BTC back in your vault, and immediately available
> for use.
>
> Other inputs/outputs (for fees etc) would still be committed to by <sig>,
> so nothing here is malleable. The script here is about 45 bytes (compared
> to 34 for a simple "key CHECKSIG") and the witness data is about 105 bytes
> (compared to 65 bytes for just a signature), which seems pretty nice.
>
> >   ... =
> >     other (optional) leaves in the taptree
>
> This would allow you to have multiple hot wallets (if any of them are
> compromised you can still use the recovery path to avoid loss of funds;
> but if some hot wallet becomes temporarily *inaccessible* you can still
> easily spend the funds via one of the alternative hot wallets), or,
> if you have multiple watchtowers validating your spends and recovering
> funds to your cold wallet on a violation, you could have multiple recovery
> paths to provide some auditability for who triggered the recovery.
>
> > Happens via script-path spend to $expr_withdraw, i.e. a timelocked
> > OP_CTV.
>
> Note that if you calculated the OP_CTV incorrectly (eg, you don't set a
> correct nSequence timelock, so that any tx that passes OP_CTV won't pass
> the OP_CSV check, and vice-versa) then this spend path becomes invalid,
> and the funds can only be reclaimed via some other path (key path spend,
> recovery tapscript, potentially an alternative hotwallet script path).
>
> OP_FORWARD_LEAF_UPDATE is equivalent to a very specific form of TLUV,
> namely "FALSE <h> 2 TLUV", where "<h>" is calculated by building the
> script, prefixing the pushes, then doing the Hash_TapLeaf calculation.
>
> Not being able to tweak the internal public key ("FALSE" rather than
> "<x>") means this can't be used to build a coinpool with unilateral
> exit -- you can't remove your key from the key path, which screws over
> everyone who's still in the coinpool.
>
> On the other hand, not tweaking the internal public key avoids introducing
> all the x-only pubkey complications, and keeps it relatively simple,
> which is nice, and keeping things simple and targeted now means there's
> still plenty of OP_SUCCESS opcodes available later for something more
> general, if that turns out to be desirable.
>
> Cheers,
> aj
>

[-- Attachment #2: Type: text/html, Size: 9341 bytes --]

 permalink raw reply	[|nested]
2023-03-09 18:45           ` Greg Sanders

  
From: Anthony Towns @ 2023-03-10  1:08 UTC (permalink / raw)
  To: Greg Sanders, Bitcoin Protocol Discussion, Greg Sanders via bitcoin-dev

On 10 March 2023 4:45:15 am AEST, Greg Sanders via bitcoin-dev <bitcoin-dev@lists•linuxfoundation.org> wrote:
>1) OP_FORWARD_SELF is a JET of OP_FLU in the revaulting common case. Maybe
>obvious but I missed this initially and thought it was useful to be pointed
>out.

That was true for TLUV - iirc "FALSE FALSE 0 TLUV" would preserve the spk - but I don't think it's true for OP_FLU: you can't commit to preserving the current script without a way to observe the current script; trying to include a copy of the script in the script makes the script size infinite, and trying to include a hash of the script inside the script is cryptographically infeasible.

You could just special case "0 0 OP_FLU" to result in the same script rather than an empty one though, which would avoid the need for a dedicated FWD_SELF opcode.

(Not convinced calling things Jets when they're unrelated to simplicity makes sense)

Cheers,
aj

-- 
Sent from my phone.


 permalink raw reply	[|nested]
2023-02-13 21:09 [bitcoin-dev] BIP for OP_VAULT James O'Beirne
  2023-03-01 15:05 ` Greg Sanders

  2023-03-13 14:55   ` Greg Sanders
  
From: Luke Dashjr @ 2023-03-11 20:53 UTC (permalink / raw)
  To: James O'Beirne, Bitcoin Protocol Discussion

I started reviewing the BIP, but stopped part way through, as it seems 
to have a number of conceptual issues.

I left several comments on the PR 
(https://github.com/bitcoin/bips/pull/1421#pullrequestreview-1335925575), 
but ultimately I think it isn't simplified enough for day-to-day use, 
and would harm privacy quite a bit.

Instead, I would suggest a new approach where:

1) Joe receives funds with a taproot output like normal.
2) Joe sends funds to Fred, but Fred cannot spend them until N blocks 
later (covenant-enforced relative locktime). Ideally, this should 
use/support a taproot keypath spend somehow. It would be nice to blind 
the particular relative locktime somehow too, but that may be too expensive.
2b) If Joe's funds were stolen, Joe can spend Fred's UTXO within the N 
block window to a recovery output.

Unfortunately, the implementation details for this kind of setup are 
non-obvious and will likely require yet another address format (or at 
least recipient-wallet changes), but certainly seems within the scope of 
possibility.

Thoughts?

Luke


On 2/13/23 16:09, James O'Beirne via bitcoin-dev wrote:
> Since the last related correspondence on this list [0], a number of
> improvements have been made to the OP_VAULT draft [1]:
>
> * There is no longer a hard dependence on package relay/ephemeral
>   anchors for fee management. When using "authorized recovery," all
>   vault-related transactions can be bundled with unrelated inputs and
>   outputs, facilitating fee management that is self contained to the
>   transaction. Consequently, the contents of this proposal are in theory
>   usable today.
>
> * Specific output locations are no longer hardcoded in any of the
>   transaction validation algorithms. This means that the proposal is now
>   compatible with future changes like SIGHASH_GROUP, and
>   transaction shapes for vault operations are more flexible.
>
> ---
>
> I've written a BIP that fully describes the proposal here:
>
> https://github.com/jamesob/bips/blob/jamesob-23-02-opvault/bip-vaults.mediawiki
>
> The corresponding PR is here:
>
> https://github.com/bitcoin/bips/pull/1421
>
> My next steps will be to try for a merge to the inquisition repo.
>
> Thanks to everyone who has participated so far, but especially to AJ and
> Greg for all the advice.
>
> James
>
> [0]: 
> https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2023-January/021318.html
> [1]: https://github.com/bitcoin/bitcoin/pull/26857
>
> _______________________________________________
> bitcoin-dev mailing list
> bitcoin-dev@lists•linuxfoundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev


 permalink raw reply	[|nested]
2023-03-11 20:53 ` Luke Dashjr

  2023-03-13 14:56     ` Greg Sanders
  
From: Greg Sanders @ 2023-03-13 14:55 UTC (permalink / raw)
  To: Luke Dashjr, Bitcoin Protocol Discussion

[-- Attachment #1: Type: text/plain, Size: 3539 bytes --]

Hi Luke,

Can you elaborate why the current idealized functionality of deposit ->
trigger -> withdrawal is too complicated for
everyday use but the above deposit -> withdrawal ->
resolve(claim/clawback)  wouldn't be? I admit at a high level
it's a fine paradigm, but in practice would end

Let's ignore implementation for the discussion, since that's in flux.

Cheers,
Greg

On Sat, Mar 11, 2023 at 3:53 PM Luke Dashjr via bitcoin-dev <
bitcoin-dev@lists•linuxfoundation.org> wrote:

> I started reviewing the BIP, but stopped part way through, as it seems
> to have a number of conceptual issues.
>
> I left several comments on the PR
> (https://github.com/bitcoin/bips/pull/1421#pullrequestreview-1335925575),
> but ultimately I think it isn't simplified enough for day-to-day use,
> and would harm privacy quite a bit.
>
> Instead, I would suggest a new approach where:
>
> 1) Joe receives funds with a taproot output like normal.
> 2) Joe sends funds to Fred, but Fred cannot spend them until N blocks
> later (covenant-enforced relative locktime). Ideally, this should
> use/support a taproot keypath spend somehow. It would be nice to blind
> the particular relative locktime somehow too, but that may be too
> expensive.
> 2b) If Joe's funds were stolen, Joe can spend Fred's UTXO within the N
> block window to a recovery output.
>
> Unfortunately, the implementation details for this kind of setup are
> non-obvious and will likely require yet another address format (or at
> least recipient-wallet changes), but certainly seems within the scope of
> possibility.
>
> Thoughts?
>
> Luke
>
>
> On 2/13/23 16:09, James O'Beirne via bitcoin-dev wrote:
> > Since the last related correspondence on this list [0], a number of
> > improvements have been made to the OP_VAULT draft [1]:
> >
> > * There is no longer a hard dependence on package relay/ephemeral
> >   anchors for fee management. When using "authorized recovery," all
> >   vault-related transactions can be bundled with unrelated inputs and
> >   outputs, facilitating fee management that is self contained to the
> >   transaction. Consequently, the contents of this proposal are in theory
> >   usable today.
> >
> > * Specific output locations are no longer hardcoded in any of the
> >   transaction validation algorithms. This means that the proposal is now
> >   compatible with future changes like SIGHASH_GROUP, and
> >   transaction shapes for vault operations are more flexible.
> >
> > ---
> >
> > I've written a BIP that fully describes the proposal here:
> >
> >
> https://github.com/jamesob/bips/blob/jamesob-23-02-opvault/bip-vaults.mediawiki
> >
> > The corresponding PR is here:
> >
> > https://github.com/bitcoin/bips/pull/1421
> >
> > My next steps will be to try for a merge to the inquisition repo.
> >
> > Thanks to everyone who has participated so far, but especially to AJ and
> > Greg for all the advice.
> >
> > James
> >
> > [0]:
> >
> https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2023-January/021318.html
> > [1]: https://github.com/bitcoin/bitcoin/pull/26857
> >
> > _______________________________________________
> > bitcoin-dev mailing list
> > bitcoin-dev@lists•linuxfoundation.org
> > https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
> _______________________________________________
> bitcoin-dev mailing list
> bitcoin-dev@lists•linuxfoundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
>

[-- Attachment #2: Type: text/html, Size: 5190 bytes --]

 permalink raw reply	[|nested]
2023-03-13 14:55   ` Greg Sanders

  2023-03-13 20:55       ` Luke Dashjr
  
From: Greg Sanders @ 2023-03-13 14:56 UTC (permalink / raw)
  To: Luke Dashjr, Bitcoin Protocol Discussion

[-- Attachment #1: Type: text/plain, Size: 3922 bytes --]

Didn't finish sentence: but in practice would end up with pretty similar
usage flows imho, and as noted in PR, would take a different wallet
paradigm,
among other technical challenges.

On Mon, Mar 13, 2023 at 10:55 AM Greg Sanders <gsanders87@gmail•com> wrote:

> Hi Luke,
>
> Can you elaborate why the current idealized functionality of deposit ->
> trigger -> withdrawal is too complicated for
> everyday use but the above deposit -> withdrawal ->
> resolve(claim/clawback)  wouldn't be? I admit at a high level
> it's a fine paradigm, but in practice would end
>
> Let's ignore implementation for the discussion, since that's in flux.
>
> Cheers,
> Greg
>
> On Sat, Mar 11, 2023 at 3:53 PM Luke Dashjr via bitcoin-dev <
> bitcoin-dev@lists•linuxfoundation.org> wrote:
>
>> I started reviewing the BIP, but stopped part way through, as it seems
>> to have a number of conceptual issues.
>>
>> I left several comments on the PR
>> (https://github.com/bitcoin/bips/pull/1421#pullrequestreview-1335925575),
>>
>> but ultimately I think it isn't simplified enough for day-to-day use,
>> and would harm privacy quite a bit.
>>
>> Instead, I would suggest a new approach where:
>>
>> 1) Joe receives funds with a taproot output like normal.
>> 2) Joe sends funds to Fred, but Fred cannot spend them until N blocks
>> later (covenant-enforced relative locktime). Ideally, this should
>> use/support a taproot keypath spend somehow. It would be nice to blind
>> the particular relative locktime somehow too, but that may be too
>> expensive.
>> 2b) If Joe's funds were stolen, Joe can spend Fred's UTXO within the N
>> block window to a recovery output.
>>
>> Unfortunately, the implementation details for this kind of setup are
>> non-obvious and will likely require yet another address format (or at
>> least recipient-wallet changes), but certainly seems within the scope of
>> possibility.
>>
>> Thoughts?
>>
>> Luke
>>
>>
>> On 2/13/23 16:09, James O'Beirne via bitcoin-dev wrote:
>> > Since the last related correspondence on this list [0], a number of
>> > improvements have been made to the OP_VAULT draft [1]:
>> >
>> > * There is no longer a hard dependence on package relay/ephemeral
>> >   anchors for fee management. When using "authorized recovery," all
>> >   vault-related transactions can be bundled with unrelated inputs and
>> >   outputs, facilitating fee management that is self contained to the
>> >   transaction. Consequently, the contents of this proposal are in theory
>> >   usable today.
>> >
>> > * Specific output locations are no longer hardcoded in any of the
>> >   transaction validation algorithms. This means that the proposal is now
>> >   compatible with future changes like SIGHASH_GROUP, and
>> >   transaction shapes for vault operations are more flexible.
>> >
>> > ---
>> >
>> > I've written a BIP that fully describes the proposal here:
>> >
>> >
>> https://github.com/jamesob/bips/blob/jamesob-23-02-opvault/bip-vaults.mediawiki
>> >
>> > The corresponding PR is here:
>> >
>> > https://github.com/bitcoin/bips/pull/1421
>> >
>> > My next steps will be to try for a merge to the inquisition repo.
>> >
>> > Thanks to everyone who has participated so far, but especially to AJ and
>> > Greg for all the advice.
>> >
>> > James
>> >
>> > [0]:
>> >
>> https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2023-January/021318.html
>> > [1]: https://github.com/bitcoin/bitcoin/pull/26857
>> >
>> > _______________________________________________
>> > bitcoin-dev mailing list
>> > bitcoin-dev@lists•linuxfoundation.org
>> > https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
>> _______________________________________________
>> bitcoin-dev mailing list
>> bitcoin-dev@lists•linuxfoundation.org
>> https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
>>
>

[-- Attachment #2: Type: text/html, Size: 5765 bytes --]

 permalink raw reply	[|nested]
2023-03-02 14:54     ` Greg Sanders
  2023-03-02 19:51       ` Andrew Melnychuk Oseen
  2023-03-06 15:25       ` James O'Beirne

  2023-03-14 14:40         ` Greg Sanders
  
From: Brandon Black @ 2023-03-13 19:03 UTC (permalink / raw)
  To: Greg Sanders, Bitcoin Protocol Discussion;  Anthony Towns

Hi Gents,

> > I don't think replacing the internal-public-key makes sense -- if it
> was immediately spendable via the keypath before there's no reason for
> it not to be immediately spendable now.
> 
> Slavishly following the current proposal was the idea to make sure all
> functionality was captured; I agree with this change.

I think we do need to replace the internal key with a hardcoded NUMS
point to allow us to batch multiple vault inputs which might have
different internal keys but the same OP_FLU/OP_VAULT_TRIGGER script to
the same time+template-restricted output.

I like that in James' current PR proposal we can explicitly batch via
the implied input/output summation rules while avoiding address reuse.
If we can retain some or all of that, I think it would be good for on
chain efficiency and potentially privacy.

My thoughts on batching:

Many inputs with different internal keys can be combined to satisfy the
total output value for a single output, as long as their scriptpubkeys
with FLU and NUMS internal key are equal This enables avoiding address
reuse within the vault.

Many inputs with the same scriptpubkey can be combined to satisfy a
single CTV output template. This allows a user to unfsck themselves if
they initiate a withdrawal that cannot be satisfied because they didn't
send enough sats to satisfy their template.

Best,

--Brandon


 permalink raw reply	[|nested]
2023-03-13 14:56     ` Greg Sanders

  2023-03-16 14:44         ` Greg Sanders
  
From: Luke Dashjr @ 2023-03-13 20:55 UTC (permalink / raw)
  To: Greg Sanders, Bitcoin Protocol Discussion

[-- Attachment #1: Type: text/plain, Size: 4774 bytes --]

In ordinary use cases, you wouldn't clawback; that would only be in the 
extreme case of the wallet being compromised. So typical usage would 
just be receive -> send, like wallets currently do.

Luke


On 3/13/23 10:56, Greg Sanders wrote:
> Didn't finish sentence: but in practice would end up with pretty 
> similar usage flows imho, and as noted in PR, would take a different 
> wallet paradigm,
> among other technical challenges.
>
> On Mon, Mar 13, 2023 at 10:55 AM Greg Sanders <gsanders87@gmail•com> 
> wrote:
>
>     Hi Luke,
>
>     Can you elaborate why the current idealized functionality of
>     deposit -> trigger -> withdrawal is too complicated for
>     everyday use but the above deposit -> withdrawal ->
>     resolve(claim/clawback)  wouldn't be? I admit at a high level
>     it's a fine paradigm, but in practice would end
>
>     Let's ignore implementation for the discussion, since that's in flux.
>
>     Cheers,
>     Greg
>
>     On Sat, Mar 11, 2023 at 3:53 PM Luke Dashjr via bitcoin-dev
>     <bitcoin-dev@lists•linuxfoundation.org> wrote:
>
>         I started reviewing the BIP, but stopped part way through, as
>         it seems
>         to have a number of conceptual issues.
>
>         I left several comments on the PR
>         (https://github.com/bitcoin/bips/pull/1421#pullrequestreview-1335925575),
>
>         but ultimately I think it isn't simplified enough for
>         day-to-day use,
>         and would harm privacy quite a bit.
>
>         Instead, I would suggest a new approach where:
>
>         1) Joe receives funds with a taproot output like normal.
>         2) Joe sends funds to Fred, but Fred cannot spend them until N
>         blocks
>         later (covenant-enforced relative locktime). Ideally, this should
>         use/support a taproot keypath spend somehow. It would be nice
>         to blind
>         the particular relative locktime somehow too, but that may be
>         too expensive.
>         2b) If Joe's funds were stolen, Joe can spend Fred's UTXO
>         within the N
>         block window to a recovery output.
>
>         Unfortunately, the implementation details for this kind of
>         setup are
>         non-obvious and will likely require yet another address format
>         (or at
>         least recipient-wallet changes), but certainly seems within
>         the scope of
>         possibility.
>
>         Thoughts?
>
>         Luke
>
>
>         On 2/13/23 16:09, James O'Beirne via bitcoin-dev wrote:
>         > Since the last related correspondence on this list [0], a
>         number of
>         > improvements have been made to the OP_VAULT draft [1]:
>         >
>         > * There is no longer a hard dependence on package
>         relay/ephemeral
>         >   anchors for fee management. When using "authorized
>         recovery," all
>         >   vault-related transactions can be bundled with unrelated
>         inputs and
>         >   outputs, facilitating fee management that is self
>         contained to the
>         >   transaction. Consequently, the contents of this proposal
>         are in theory
>         >   usable today.
>         >
>         > * Specific output locations are no longer hardcoded in any
>         of the
>         >   transaction validation algorithms. This means that the
>         proposal is now
>         >   compatible with future changes like SIGHASH_GROUP, and
>         >   transaction shapes for vault operations are more flexible.
>         >
>         > ---
>         >
>         > I've written a BIP that fully describes the proposal here:
>         >
>         >
>         https://github.com/jamesob/bips/blob/jamesob-23-02-opvault/bip-vaults.mediawiki
>         >
>         > The corresponding PR is here:
>         >
>         > https://github.com/bitcoin/bips/pull/1421
>         >
>         > My next steps will be to try for a merge to the inquisition
>         repo.
>         >
>         > Thanks to everyone who has participated so far, but
>         especially to AJ and
>         > Greg for all the advice.
>         >
>         > James
>         >
>         > [0]:
>         >
>         https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2023-January/021318.html
>         > [1]: https://github.com/bitcoin/bitcoin/pull/26857
>         >
>         > _______________________________________________
>         > bitcoin-dev mailing list
>         > bitcoin-dev@lists•linuxfoundation.org
>         > https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
>         _______________________________________________
>         bitcoin-dev mailing list
>         bitcoin-dev@lists•linuxfoundation.org
>         https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
>

[-- Attachment #2: Type: text/html, Size: 9192 bytes --]

 permalink raw reply	[|nested]
2023-03-13 19:03       ` Brandon Black

  
From: Greg Sanders @ 2023-03-14 14:40 UTC (permalink / raw)
  To: Greg Sanders, Bitcoin Protocol Discussion, Anthony Towns

[-- Attachment #1: Type: text/plain, Size: 3575 bytes --]

Hi Brandon,

Thank you for chiming in, causing me to think a bit more deeply on the
privacy issues
and what seems possible.

> I like that in James' current PR proposal we can explicitly batch via
the implied input/output summation rules while avoiding address reuse.
If we can retain some or all of that, I think it would be good for on
chain efficiency and potentially privacy.

Rotating trigger authorization keys maintains batchability and stops
address reuse.
Remember that anytime you share any path, like recovery path, for batching,
it becomes
obvious at spend-time. Rotating inner pubkeys only doesn't seem to help
much.

Coinjoins being the other batching scenario which could benefit perhaps are
quite a heavy
lift. You'd need the recovery policy(every other branch) to be agreed upon,
have everyone unvault
to this new joint vault, then mix, and withdrawal back to the original
vault. If someone is going through
all that effort, I suspect they'll just use a NUMS to reduce fingerprinting.

> Many inputs with different internal keys can be combined to satisfy the
total output value for a single output, as long as their scriptpubkeys
with FLU and NUMS internal key are equal This enables avoiding address
reuse within the vault.

To reiterate, we can just cycle any key in the $trigger branch with OP_FLU,
which accomplishes the same thing.
Or in authorization-less $trigger, add a random number which is dropped.

> Many inputs with the same scriptpubkey can be combined to satisfy a
single CTV output template. This allows a user to unfsck themselves if
they initiate a withdrawal that cannot be satisfied because they didn't
send enough sats to satisfy their template.

I think that would fit the deprecated OP_FORWARD_OUTPUTS, but OP_CTV
commits to total
number of inputs to remove txid malleability. I think the real solution to
this mistake would be to hit
the big red RECOVERY button that you're relying on for vault security
anyways.

Cheers,
Greg

On Mon, Mar 13, 2023 at 3:04 PM Brandon Black <freedom@reardencode•com>
wrote:

> Hi Gents,
>
> > > I don't think replacing the internal-public-key makes sense -- if it
> > was immediately spendable via the keypath before there's no reason for
> > it not to be immediately spendable now.
> >
> > Slavishly following the current proposal was the idea to make sure all
> > functionality was captured; I agree with this change.
>
> I think we do need to replace the internal key with a hardcoded NUMS
> point to allow us to batch multiple vault inputs which might have
> different internal keys but the same OP_FLU/OP_VAULT_TRIGGER script to
> the same time+template-restricted output.
>
> I like that in James' current PR proposal we can explicitly batch via
> the implied input/output summation rules while avoiding address reuse.
> If we can retain some or all of that, I think it would be good for on
> chain efficiency and potentially privacy.
>
> My thoughts on batching:
>
> Many inputs with different internal keys can be combined to satisfy the
> total output value for a single output, as long as their scriptpubkeys
> with FLU and NUMS internal key are equal This enables avoiding address
> reuse within the vault.
>
> Many inputs with the same scriptpubkey can be combined to satisfy a
> single CTV output template. This allows a user to unfsck themselves if
> they initiate a withdrawal that cannot be satisfied because they didn't
> send enough sats to satisfy their template.
>
> Best,
>
> --Brandon
>

[-- Attachment #2: Type: text/html, Size: 4301 bytes --]

 permalink raw reply	[|nested]
2023-03-13 20:55       ` Luke Dashjr

  
From: Greg Sanders @ 2023-03-16 14:44 UTC (permalink / raw)
  To: Luke Dashjr;  Bitcoin Protocol Discussion

[-- Attachment #1: Type: text/plain, Size: 5396 bytes --]

Hi Luke,

I think this works as with OP_FLU based construct, for the simplest single
key case.

e.g., single key hot wallet(or MuSig2/FROST wallet)

<hot_pubkey> 1 "<time-delay> OP_CHECKSEQUENCEVERIFY OP_DROP OP_CHECKSIG"
OP_FORWARD_LEAF_UPDATE

The <hot_pubkey> is appended at spending time.

This allows the utxo to go to $recover cold storage at any point like
before, otherwise the time matures and the funds can be spent by a single
key. Rate-limiting like usual can be bolted on as well using OP_FORWARD_*
opcodes, I'm pretty sure. This would as you note require wallet support,
where the hot wallet would have to be aware of the vault, or be scanning
inputs looking for this type of leaf.

Unfortunately this doesn't extend to things like OP_CHECKSIGADD, since the
pubkeys are all pushed first, then the opcodes run. OP_CHECKMULTISIG would
have worked probably.

To generalize I think you'd need recursive taproot, or a proper replacement
for Bitcoin script :)

Cheers,
Greg

On Mon, Mar 13, 2023 at 4:55 PM Luke Dashjr <luke@dashjr•org> wrote:

> In ordinary use cases, you wouldn't clawback; that would only be in the
> extreme case of the wallet being compromised. So typical usage would just
> be receive -> send, like wallets currently do.
>
> Luke
>
>
> On 3/13/23 10:56, Greg Sanders wrote:
>
> Didn't finish sentence: but in practice would end up with pretty similar
> usage flows imho, and as noted in PR, would take a different wallet
> paradigm,
> among other technical challenges.
>
> On Mon, Mar 13, 2023 at 10:55 AM Greg Sanders <gsanders87@gmail•com>
> wrote:
>
>> Hi Luke,
>>
>> Can you elaborate why the current idealized functionality of deposit ->
>> trigger -> withdrawal is too complicated for
>> everyday use but the above deposit -> withdrawal ->
>> resolve(claim/clawback)  wouldn't be? I admit at a high level
>> it's a fine paradigm, but in practice would end
>>
>> Let's ignore implementation for the discussion, since that's in flux.
>>
>> Cheers,
>> Greg
>>
>> On Sat, Mar 11, 2023 at 3:53 PM Luke Dashjr via bitcoin-dev <
>> bitcoin-dev@lists•linuxfoundation.org> wrote:
>>
>>> I started reviewing the BIP, but stopped part way through, as it seems
>>> to have a number of conceptual issues.
>>>
>>> I left several comments on the PR
>>> (https://github.com/bitcoin/bips/pull/1421#pullrequestreview-1335925575),
>>>
>>> but ultimately I think it isn't simplified enough for day-to-day use,
>>> and would harm privacy quite a bit.
>>>
>>> Instead, I would suggest a new approach where:
>>>
>>> 1) Joe receives funds with a taproot output like normal.
>>> 2) Joe sends funds to Fred, but Fred cannot spend them until N blocks
>>> later (covenant-enforced relative locktime). Ideally, this should
>>> use/support a taproot keypath spend somehow. It would be nice to blind
>>> the particular relative locktime somehow too, but that may be too
>>> expensive.
>>> 2b) If Joe's funds were stolen, Joe can spend Fred's UTXO within the N
>>> block window to a recovery output.
>>>
>>> Unfortunately, the implementation details for this kind of setup are
>>> non-obvious and will likely require yet another address format (or at
>>> least recipient-wallet changes), but certainly seems within the scope of
>>> possibility.
>>>
>>> Thoughts?
>>>
>>> Luke
>>>
>>>
>>> On 2/13/23 16:09, James O'Beirne via bitcoin-dev wrote:
>>> > Since the last related correspondence on this list [0], a number of
>>> > improvements have been made to the OP_VAULT draft [1]:
>>> >
>>> > * There is no longer a hard dependence on package relay/ephemeral
>>> >   anchors for fee management. When using "authorized recovery," all
>>> >   vault-related transactions can be bundled with unrelated inputs and
>>> >   outputs, facilitating fee management that is self contained to the
>>> >   transaction. Consequently, the contents of this proposal are in
>>> theory
>>> >   usable today.
>>> >
>>> > * Specific output locations are no longer hardcoded in any of the
>>> >   transaction validation algorithms. This means that the proposal is
>>> now
>>> >   compatible with future changes like SIGHASH_GROUP, and
>>> >   transaction shapes for vault operations are more flexible.
>>> >
>>> > ---
>>> >
>>> > I've written a BIP that fully describes the proposal here:
>>> >
>>> >
>>> https://github.com/jamesob/bips/blob/jamesob-23-02-opvault/bip-vaults.mediawiki
>>> >
>>> > The corresponding PR is here:
>>> >
>>> > https://github.com/bitcoin/bips/pull/1421
>>> >
>>> > My next steps will be to try for a merge to the inquisition repo.
>>> >
>>> > Thanks to everyone who has participated so far, but especially to AJ
>>> and
>>> > Greg for all the advice.
>>> >
>>> > James
>>> >
>>> > [0]:
>>> >
>>> https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2023-January/021318.html
>>> > [1]: https://github.com/bitcoin/bitcoin/pull/26857
>>> >
>>> > _______________________________________________
>>> > bitcoin-dev mailing list
>>> > bitcoin-dev@lists•linuxfoundation.org
>>> > https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
>>> _______________________________________________
>>> bitcoin-dev mailing list
>>> bitcoin-dev@lists•linuxfoundation.org
>>> https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
>>>
>>

[-- Attachment #2: Type: text/html, Size: 9706 bytes --]

 permalink raw reply	[|nested]
2023-03-07 12:45         ` Anthony Towns
  2023-03-09 18:45           ` Greg Sanders

  2023-03-29  7:10             ` Zac Greenwood
  
From: Anthony Towns @ 2023-03-24 12:10 UTC (permalink / raw)
  To: Bitcoin Protocol Discussion;  Greg Sanders

On Tue, Mar 07, 2023 at 10:45:34PM +1000, Anthony Towns via bitcoin-dev wrote:
> I think there are perhaps four opcodes that are interesting in this class:
> 
>    idx sPK OP_FORWARD_TARGET
>      -- sends the value to a particular output (given by idx), and
>         requires that output have a particular scriptPubKey (given
>         by sPK).
> 
>    idx [...] n script OP_FORWARD_LEAF_UPDATE
>      -- sends the value to a particular output (given by idx), and
> 	requires that output to have almost the same scriptPubKey as this
> 	input, _except_ that the current leaf is replaced by "script",
> 	with that script prefixed by "n" pushes (of values given by [...])
> 
>    idx OP_FORWARD_SELF
>      -- sends the value to a particular output (given by idx), and
>         requires that output to have the same scriptPubKey as this input
> 
>    amt OP_FORWARD_PARTIAL
>      -- modifies the next OP_FORWARD_* opcode to only affect "amt",
>         rather than the entire balance. opcodes after that affect the
> 	remaining balance, after "amt" has been subtracted. if "amt" is
> 	0, the next OP_FORWARD_* becomes a no-op.

The BIP 345 draft has been updated [0] [1] and now pretty much defines
OP_VAULT to have the behaviour specced for OP_FORWARD_LEAF_UPDATE above,
and OP_VAULT_RECOVER to behave as OP_FORWARD_TARGET above. Despite
that, for this email I'm going to continue using the OP_FORWARD_*
naming convention.

Given the recent controversy over the Yuga labs ordinal auction [2],
perhaps it's interesting to consider that these proposed opcodes come
close to making it possible to do a fair, non-custodial, on-chain auction
of ordinals [3].

The idea here is that you create a utxo on chain that contains the ordinal
in question, which commits to the address of the current leading bidder,
and can be spent in two ways:

  1) it can be updated to a new bidder, if the bid is raised by at least
     K satoshis, in which case the previous bidder is refunded their
     bid; or,

  2) if there have been no new bids for a day, the current high bidder
     wins, and the ordinal is moved to their address, while the funds
     from their winning bid are sent to the original vendor's address.

I believe this can be implemented in script as follows,
assuming the opcodes OP_FORWARD_TARGET(OP_VAULT_RECOVER),
OP_FORWARD_LEAF_UPDATE(OP_VAULT), OP_FORWARD_PARTIAL (as specced above),
and OP_PUSHCURRENTINPUTINDEX (as implemented in liquid/elements [4])
are all available.

First, figure out the parameters:

 * Set VENDOR to the scriptPubKey corresponding to the vendor's address.
 * Set K to the minimum bid increment [5].
 * Initially, set X equal to VENDOR.
 * Initially, set V to just below the reserve price (V+K is the
   minimum initial bid).

Then construct the following script:

 [X] [V] [SSS] TOALT TOALT TOALT
 0 PUSHCURRENTINPUTINDEX EQUALVERIFY
 DEPTH NOT IF
   0 10000 FORWARD_PARTIAL
   0 FROMALT FORWARD_TARGET
   1 [VENDOR] FWD_TARGET
   144
 ELSE
   FROMALT SWAP TUCK FROMALT
   [K] ADD GREATERTHANOREQUAL VERIFY
   1 SWAP FORWARD_TARGET
   DUP FORWARD_PARTIAL
   0 ROT ROT
   FROMALT DUP 3 SWAP FORWARD_LEAF_UPDATE
   0
 ENDIF
 CSV
 1ADD

where "SSS" is a pushdata of the rest of the script ("TOALT TOALT TOALT
.. 1ADD").

Finally, make that script the sole tapleaf, accompanied by a NUMS point
as the internal public key, calculate the taproot address corresponding
to that, and send the ordinal to that address as the first satoshi.

There are two ways to spend that script. With an empty witness stack,
the following will be executed:

 [X] [V] [SSS] TOALT TOALT TOALT
   -- altstack now contains [SSS V X]
 0 PUSHCURRENTINPUTINDEX EQUALVERIFY
   -- this input is the first, so the ordinal will move to the first
      output
 DEPTH NOT IF
   -- take this branch: the auction is over!
   1 [VENDOR] FWD_TARGET
   -- output 1 gets the entire value of this input, and pays to
      the vendor's hardcoded scriptPubKey
   0 10000 FORWARD_PARTIAL
   0 FROMALT FORWARD_TARGET
   -- we forward at least 10k sats to output 0 (if there were 0 sats,
      the ordinal would end up in output 1 instead, which would be a
      bug), and output 0 pays to scriptPubKey "X"
   144
 ELSE .. ENDIF
   -- skip over the other branch
 CSV
   -- check that this input has baked for 144 blocks (~1 day)
 1ADD
   -- leave 145 on the stack, which is true. success!

Alternatively, if you want to increase the bid you provide a stack with
two items: your scriptPubKey and the new bid [X' V']. Execution this
time looks like:

 [X] [V] [SSS] TOALT TOALT TOALT
   -- stack contains [X' V'], altstack now contains [SSS V X]
 0 PUSHCURRENTINPUTINDEX EQUALVERIFY
   -- this input is the first, so the ordinal will move to the first
      output
 DEPTH NOT IF ... ELSE
   -- skip over the other branch (without violating minimalif rules)
   FROMALT SWAP TUCK FROMALT
   -- stack contains [X' V' X V' V], altstack contains [SSS]
   [K] ADD GREATERTHANOREQUAL VERIFY
   -- check V' >= V+K, stack contains [X' V' X]
   1 SWAP FORWARD_TARGET
   -- output 1 pays to X (previous bidder's scriptPubKey), and the
      entire value of this input goes there; stack contains [X' V']
   DUP FORWARD_PARTIAL
   -- execute "V' FORWARD_PARTIAL", stack contains [X' V']
   0 ROT ROT
   -- stack contains [0 X' V']
   FROMALT DUP 3 SWAP FORWARD_LEAF_UPDATE
   -- execute "0 X' V' SSS 3 SSS FORWARD_LEAF_UPDATE" which checks
      that output 0 spends at least V' satoshis back to the same
      script (because that's how we defined SSS), except the first
      three pushes (previously X V SSS) are replaced by X' V' SSS.
   0
 ENDIF
 CSV
   -- "0 CSV" requires nSequnce to be set, which makes the tx rbf'able,
      which hopefully makes it harder to pin
 1ADD
   -- ends with 1 on the stack; success!

(The "SSS n SSS FORWARD_LEAF_UPDATE" construct is more or less a quine,
ie a program that outputs its own source code)

I think that script is about 211 witness bytes, with an additional 40
witness bytes for X'/V', so when making a bid, your tx would be
something like:

   tx header, 10vb
   input 0: 103vb for the old bid including witness and control block
   input 1: 58vb for a taproot key path spend
   output 0: 43vb for the new bid
   output 1: 43vb for your change

for a total of about 257vb -- slightly larger than a regular 2-in-2-out
transaction, but not terribly much. Mostly because input 0 doesn't require
a signature -- it's size is effectively 6 pubkeys: X, X' VENDOR twice,
and the script code twice, along with a little extra to encode the
various numbers (10000, 144, K, V, V').

This approach seems pretty "MEV" resistant: you pay fees via input 1 if
your bid succeeds; if it doesn't, you don't pay any fees. A potential
scalper might want to put in an early low ball bid, then prevent
higher bidders from winning the auction, take control of the ordinal,
and resell it later, but unless they can prevent another miner from
mining alternative bids for 144 blocks, they will fail at that. The bid
is fixed by the bidder and committed to by the signature on input 1, so
frontrunning a bid can't do anything beyond invalidate the bid entirely.

Obviously, this is a pretty limited auction mechanism in various ways;
eg maybe you'd rather specify K as a percentage than an absoute increment;
maybe you'd like to have the auction definitely finish by some particular
time; maybe you'd like to be able to have the auction be able to continue
above 21.47 BTC (2**31 sats); maybe you'd like to do a dutch auction
rather than an english auction. I think you can probably do all those
things with this set of opcodes and clever scripting, though it probably
gets ugly.

I don't think this is easily extensible to taro or rgb style assets,
as rather than being able to ensure the asset is transferred by
controlling the input/output positions, I think you'd need to build
up merkle trees and do point tweaks beyond what's supported by
OP_FORWARD_LEAF_UPDATE/OP_VAULT. Of course, without something like
OP_PUSHCURRENTINPUTINDEX I don't think you could do it for ordinals
either.

Cheers,
aj

[0] https://github.com/bitcoin/bips/blob/7f747fba82675f28c239df690a07b75529bd0960/bip-0345.mediawiki

[1] https://twitter.com/jamesob/status/1639019107432513537

[2] https://cointelegraph.com/news/scammers-dream-yuga-s-auction-model-for-bitcoin-nfts-sees-criticism

[3] Inscriptions remain a wasteful way of publishing/committing
    to content, however!

[4] https://github.com/ElementsProject/elements/blob/master/doc/tapscript_opcodes.md

[5] Setting K too low probably invites griefing, where a bidder may be
    able to use rbf pinning vectors to prevent people who would be willing
    to bid substantially higher from getting their bid confirmed on
    chain.


 permalink raw reply	[|nested]
2023-03-24 12:10           ` Anthony Towns

  2023-03-29 19:57               ` alicexbt
  
From: Zac Greenwood @ 2023-03-29  7:10 UTC (permalink / raw)
  To: Anthony Towns, Bitcoin Protocol Discussion

[-- Attachment #1: Type: text/plain, Size: 9998 bytes --]

I’m not sure why any effort should be spent on theorizing how new opcodes
might be used to facilitate parasitical use cases of the blockchain.

If anything, business models relying on the ability to abuse the blockchain
as a data store must be made less feasible, not more.

Zac


On Fri, 24 Mar 2023 at 20:10, Anthony Towns via bitcoin-dev <
bitcoin-dev@lists•linuxfoundation.org> wrote:

> On Tue, Mar 07, 2023 at 10:45:34PM +1000, Anthony Towns via bitcoin-dev
> wrote:
> > I think there are perhaps four opcodes that are interesting in this
> class:
> >
> >    idx sPK OP_FORWARD_TARGET
> >      -- sends the value to a particular output (given by idx), and
> >         requires that output have a particular scriptPubKey (given
> >         by sPK).
> >
> >    idx [...] n script OP_FORWARD_LEAF_UPDATE
> >      -- sends the value to a particular output (given by idx), and
> >       requires that output to have almost the same scriptPubKey as this
> >       input, _except_ that the current leaf is replaced by "script",
> >       with that script prefixed by "n" pushes (of values given by [...])
> >
> >    idx OP_FORWARD_SELF
> >      -- sends the value to a particular output (given by idx), and
> >         requires that output to have the same scriptPubKey as this input
> >
> >    amt OP_FORWARD_PARTIAL
> >      -- modifies the next OP_FORWARD_* opcode to only affect "amt",
> >         rather than the entire balance. opcodes after that affect the
> >       remaining balance, after "amt" has been subtracted. if "amt" is
> >       0, the next OP_FORWARD_* becomes a no-op.
>
> The BIP 345 draft has been updated [0] [1] and now pretty much defines
> OP_VAULT to have the behaviour specced for OP_FORWARD_LEAF_UPDATE above,
> and OP_VAULT_RECOVER to behave as OP_FORWARD_TARGET above. Despite
> that, for this email I'm going to continue using the OP_FORWARD_*
> naming convention.
>
> Given the recent controversy over the Yuga labs ordinal auction [2],
> perhaps it's interesting to consider that these proposed opcodes come
> close to making it possible to do a fair, non-custodial, on-chain auction
> of ordinals [3].
>
> The idea here is that you create a utxo on chain that contains the ordinal
> in question, which commits to the address of the current leading bidder,
> and can be spent in two ways:
>
>   1) it can be updated to a new bidder, if the bid is raised by at least
>      K satoshis, in which case the previous bidder is refunded their
>      bid; or,
>
>   2) if there have been no new bids for a day, the current high bidder
>      wins, and the ordinal is moved to their address, while the funds
>      from their winning bid are sent to the original vendor's address.
>
> I believe this can be implemented in script as follows,
> assuming the opcodes OP_FORWARD_TARGET(OP_VAULT_RECOVER),
> OP_FORWARD_LEAF_UPDATE(OP_VAULT), OP_FORWARD_PARTIAL (as specced above),
> and OP_PUSHCURRENTINPUTINDEX (as implemented in liquid/elements [4])
> are all available.
>
> First, figure out the parameters:
>
>  * Set VENDOR to the scriptPubKey corresponding to the vendor's address.
>  * Set K to the minimum bid increment [5].
>  * Initially, set X equal to VENDOR.
>  * Initially, set V to just below the reserve price (V+K is the
>    minimum initial bid).
>
> Then construct the following script:
>
>  [X] [V] [SSS] TOALT TOALT TOALT
>  0 PUSHCURRENTINPUTINDEX EQUALVERIFY
>  DEPTH NOT IF
>    0 10000 FORWARD_PARTIAL
>    0 FROMALT FORWARD_TARGET
>    1 [VENDOR] FWD_TARGET
>    144
>  ELSE
>    FROMALT SWAP TUCK FROMALT
>    [K] ADD GREATERTHANOREQUAL VERIFY
>    1 SWAP FORWARD_TARGET
>    DUP FORWARD_PARTIAL
>    0 ROT ROT
>    FROMALT DUP 3 SWAP FORWARD_LEAF_UPDATE
>    0
>  ENDIF
>  CSV
>  1ADD
>
> where "SSS" is a pushdata of the rest of the script ("TOALT TOALT TOALT
> .. 1ADD").
>
> Finally, make that script the sole tapleaf, accompanied by a NUMS point
> as the internal public key, calculate the taproot address corresponding
> to that, and send the ordinal to that address as the first satoshi.
>
> There are two ways to spend that script. With an empty witness stack,
> the following will be executed:
>
>  [X] [V] [SSS] TOALT TOALT TOALT
>    -- altstack now contains [SSS V X]
>  0 PUSHCURRENTINPUTINDEX EQUALVERIFY
>    -- this input is the first, so the ordinal will move to the first
>       output
>  DEPTH NOT IF
>    -- take this branch: the auction is over!
>    1 [VENDOR] FWD_TARGET
>    -- output 1 gets the entire value of this input, and pays to
>       the vendor's hardcoded scriptPubKey
>    0 10000 FORWARD_PARTIAL
>    0 FROMALT FORWARD_TARGET
>    -- we forward at least 10k sats to output 0 (if there were 0 sats,
>       the ordinal would end up in output 1 instead, which would be a
>       bug), and output 0 pays to scriptPubKey "X"
>    144
>  ELSE .. ENDIF
>    -- skip over the other branch
>  CSV
>    -- check that this input has baked for 144 blocks (~1 day)
>  1ADD
>    -- leave 145 on the stack, which is true. success!
>
> Alternatively, if you want to increase the bid you provide a stack with
> two items: your scriptPubKey and the new bid [X' V']. Execution this
> time looks like:
>
>  [X] [V] [SSS] TOALT TOALT TOALT
>    -- stack contains [X' V'], altstack now contains [SSS V X]
>  0 PUSHCURRENTINPUTINDEX EQUALVERIFY
>    -- this input is the first, so the ordinal will move to the first
>       output
>  DEPTH NOT IF ... ELSE
>    -- skip over the other branch (without violating minimalif rules)
>    FROMALT SWAP TUCK FROMALT
>    -- stack contains [X' V' X V' V], altstack contains [SSS]
>    [K] ADD GREATERTHANOREQUAL VERIFY
>    -- check V' >= V+K, stack contains [X' V' X]
>    1 SWAP FORWARD_TARGET
>    -- output 1 pays to X (previous bidder's scriptPubKey), and the
>       entire value of this input goes there; stack contains [X' V']
>    DUP FORWARD_PARTIAL
>    -- execute "V' FORWARD_PARTIAL", stack contains [X' V']
>    0 ROT ROT
>    -- stack contains [0 X' V']
>    FROMALT DUP 3 SWAP FORWARD_LEAF_UPDATE
>    -- execute "0 X' V' SSS 3 SSS FORWARD_LEAF_UPDATE" which checks
>       that output 0 spends at least V' satoshis back to the same
>       script (because that's how we defined SSS), except the first
>       three pushes (previously X V SSS) are replaced by X' V' SSS.
>    0
>  ENDIF
>  CSV
>    -- "0 CSV" requires nSequnce to be set, which makes the tx rbf'able,
>       which hopefully makes it harder to pin
>  1ADD
>    -- ends with 1 on the stack; success!
>
> (The "SSS n SSS FORWARD_LEAF_UPDATE" construct is more or less a quine,
> ie a program that outputs its own source code)
>
> I think that script is about 211 witness bytes, with an additional 40
> witness bytes for X'/V', so when making a bid, your tx would be
> something like:
>
>    tx header, 10vb
>    input 0: 103vb for the old bid including witness and control block
>    input 1: 58vb for a taproot key path spend
>    output 0: 43vb for the new bid
>    output 1: 43vb for your change
>
> for a total of about 257vb -- slightly larger than a regular 2-in-2-out
> transaction, but not terribly much. Mostly because input 0 doesn't require
> a signature -- it's size is effectively 6 pubkeys: X, X' VENDOR twice,
> and the script code twice, along with a little extra to encode the
> various numbers (10000, 144, K, V, V').
>
> This approach seems pretty "MEV" resistant: you pay fees via input 1 if
> your bid succeeds; if it doesn't, you don't pay any fees. A potential
> scalper might want to put in an early low ball bid, then prevent
> higher bidders from winning the auction, take control of the ordinal,
> and resell it later, but unless they can prevent another miner from
> mining alternative bids for 144 blocks, they will fail at that. The bid
> is fixed by the bidder and committed to by the signature on input 1, so
> frontrunning a bid can't do anything beyond invalidate the bid entirely.
>
> Obviously, this is a pretty limited auction mechanism in various ways;
> eg maybe you'd rather specify K as a percentage than an absoute increment;
> maybe you'd like to have the auction definitely finish by some particular
> time; maybe you'd like to be able to have the auction be able to continue
> above 21.47 BTC (2**31 sats); maybe you'd like to do a dutch auction
> rather than an english auction. I think you can probably do all those
> things with this set of opcodes and clever scripting, though it probably
> gets ugly.
>
> I don't think this is easily extensible to taro or rgb style assets,
> as rather than being able to ensure the asset is transferred by
> controlling the input/output positions, I think you'd need to build
> up merkle trees and do point tweaks beyond what's supported by
> OP_FORWARD_LEAF_UPDATE/OP_VAULT. Of course, without something like
> OP_PUSHCURRENTINPUTINDEX I don't think you could do it for ordinals
> either.
>
> Cheers,
> aj
>
> [0]
> https://github.com/bitcoin/bips/blob/7f747fba82675f28c239df690a07b75529bd0960/bip-0345.mediawiki
>
> [1] https://twitter.com/jamesob/status/1639019107432513537
>
> [2]
> https://cointelegraph.com/news/scammers-dream-yuga-s-auction-model-for-bitcoin-nfts-sees-criticism
>
> [3] Inscriptions remain a wasteful way of publishing/committing
>     to content, however!
>
> [4]
> https://github.com/ElementsProject/elements/blob/master/doc/tapscript_opcodes.md
>
> [5] Setting K too low probably invites griefing, where a bidder may be
>     able to use rbf pinning vectors to prevent people who would be willing
>     to bid substantially higher from getting their bid confirmed on
>     chain.
> _______________________________________________
> bitcoin-dev mailing list
> bitcoin-dev@lists•linuxfoundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
>

[-- Attachment #2: Type: text/html, Size: 12224 bytes --]

 permalink raw reply	[|nested]
2023-03-29  7:10             ` Zac Greenwood

  2023-03-30  0:16                 ` Steve Lee
  2023-03-30 10:39                 ` Zac Greenwood
  
From: alicexbt @ 2023-03-29 19:57 UTC (permalink / raw)
  To: Zac Greenwood;  Bitcoin Protocol Discussion, Anthony Towns

Hi Zac,

Let me share what those parasites achieved:

- Fees paid: 150 BTC
- Lot of users and developers trying bitcoin that either never tried or gave up early in 2013-15
- Mempools of nodes of being busy on weekends and got lots of transactions
- PSBT became cool and application devs are trying their best to use it in different ways
- Some developers exploring taproot and multisig
- AJ shared things how covenants could help in fair, non-custodial, on-chain auction of ordinals that is MEV resistant although I had shared it earlier which involves more steps: https://twitter.com/1440000bytes/status/1634368411760476161
- Investors exploring about funding projects
- Bitcoin more than Bitcoin and people excited about it 

We can have difference of opinion, however I want bitcoin to be money and money means different things for people in this world. Please respect that else it will become like Linux, something used by 1% of world. 

/dev/fd0
floppy disk guy

Sent with Proton Mail secure email.

------- Original Message -------
On Wednesday, March 29th, 2023 at 12:40 PM, Zac Greenwood via bitcoin-dev <bitcoin-dev@lists•linuxfoundation.org> wrote:


> I’m not sure why any effort should be spent on theorizing how new opcodes might be used to facilitate parasitical use cases of the blockchain.
>
> If anything, business models relying on the ability to abuse the blockchain as a data store must be made less feasible, not more.
>
> Zac
>
>
> On Fri, 24 Mar 2023 at 20:10, Anthony Towns via bitcoin-dev <bitcoin-dev@lists•linuxfoundation.org> wrote:
>
> > On Tue, Mar 07, 2023 at 10:45:34PM +1000, Anthony Towns via bitcoin-dev wrote:
> > > I think there are perhaps four opcodes that are interesting in this class:
> > >
> > > idx sPK OP_FORWARD_TARGET
> > > -- sends the value to a particular output (given by idx), and
> > > requires that output have a particular scriptPubKey (given
> > > by sPK).
> > >
> > > idx [...] n script OP_FORWARD_LEAF_UPDATE
> > > -- sends the value to a particular output (given by idx), and
> > > requires that output to have almost the same scriptPubKey as this
> > > input, _except_ that the current leaf is replaced by "script",
> > > with that script prefixed by "n" pushes (of values given by [...])
> > >
> > > idx OP_FORWARD_SELF
> > > -- sends the value to a particular output (given by idx), and
> > > requires that output to have the same scriptPubKey as this input
> > >
> > > amt OP_FORWARD_PARTIAL
> > > -- modifies the next OP_FORWARD_* opcode to only affect "amt",
> > > rather than the entire balance. opcodes after that affect the
> > > remaining balance, after "amt" has been subtracted. if "amt" is
> > > 0, the next OP_FORWARD_* becomes a no-op.
> >
> > The BIP 345 draft has been updated [0] [1] and now pretty much defines
> > OP_VAULT to have the behaviour specced for OP_FORWARD_LEAF_UPDATE above,
> > and OP_VAULT_RECOVER to behave as OP_FORWARD_TARGET above. Despite
> > that, for this email I'm going to continue using the OP_FORWARD_*
> > naming convention.
> >
> > Given the recent controversy over the Yuga labs ordinal auction [2],
> > perhaps it's interesting to consider that these proposed opcodes come
> > close to making it possible to do a fair, non-custodial, on-chain auction
> > of ordinals [3].
> >
> > The idea here is that you create a utxo on chain that contains the ordinal
> > in question, which commits to the address of the current leading bidder,
> > and can be spent in two ways:
> >
> > 1) it can be updated to a new bidder, if the bid is raised by at least
> > K satoshis, in which case the previous bidder is refunded their
> > bid; or,
> >
> > 2) if there have been no new bids for a day, the current high bidder
> > wins, and the ordinal is moved to their address, while the funds
> > from their winning bid are sent to the original vendor's address.
> >
> > I believe this can be implemented in script as follows,
> > assuming the opcodes OP_FORWARD_TARGET(OP_VAULT_RECOVER),
> > OP_FORWARD_LEAF_UPDATE(OP_VAULT), OP_FORWARD_PARTIAL (as specced above),
> > and OP_PUSHCURRENTINPUTINDEX (as implemented in liquid/elements [4])
> > are all available.
> >
> > First, figure out the parameters:
> >
> > * Set VENDOR to the scriptPubKey corresponding to the vendor's address.
> > * Set K to the minimum bid increment [5].
> > * Initially, set X equal to VENDOR.
> > * Initially, set V to just below the reserve price (V+K is the
> > minimum initial bid).
> >
> > Then construct the following script:
> >
> > [X] [V] [SSS] TOALT TOALT TOALT
> > 0 PUSHCURRENTINPUTINDEX EQUALVERIFY
> > DEPTH NOT IF
> > 0 10000 FORWARD_PARTIAL
> > 0 FROMALT FORWARD_TARGET
> > 1 [VENDOR] FWD_TARGET
> > 144
> > ELSE
> > FROMALT SWAP TUCK FROMALT
> > [K] ADD GREATERTHANOREQUAL VERIFY
> > 1 SWAP FORWARD_TARGET
> > DUP FORWARD_PARTIAL
> > 0 ROT ROT
> > FROMALT DUP 3 SWAP FORWARD_LEAF_UPDATE
> > 0
> > ENDIF
> > CSV
> > 1ADD
> >
> > where "SSS" is a pushdata of the rest of the script ("TOALT TOALT TOALT
> > .. 1ADD").
> >
> > Finally, make that script the sole tapleaf, accompanied by a NUMS point
> > as the internal public key, calculate the taproot address corresponding
> > to that, and send the ordinal to that address as the first satoshi.
> >
> > There are two ways to spend that script. With an empty witness stack,
> > the following will be executed:
> >
> > [X] [V] [SSS] TOALT TOALT TOALT
> > -- altstack now contains [SSS V X]
> > 0 PUSHCURRENTINPUTINDEX EQUALVERIFY
> > -- this input is the first, so the ordinal will move to the first
> > output
> > DEPTH NOT IF
> > -- take this branch: the auction is over!
> > 1 [VENDOR] FWD_TARGET
> > -- output 1 gets the entire value of this input, and pays to
> > the vendor's hardcoded scriptPubKey
> > 0 10000 FORWARD_PARTIAL
> > 0 FROMALT FORWARD_TARGET
> > -- we forward at least 10k sats to output 0 (if there were 0 sats,
> > the ordinal would end up in output 1 instead, which would be a
> > bug), and output 0 pays to scriptPubKey "X"
> > 144
> > ELSE .. ENDIF
> > -- skip over the other branch
> > CSV
> > -- check that this input has baked for 144 blocks (~1 day)
> > 1ADD
> > -- leave 145 on the stack, which is true. success!
> >
> > Alternatively, if you want to increase the bid you provide a stack with
> > two items: your scriptPubKey and the new bid [X' V']. Execution this
> > time looks like:
> >
> > [X] [V] [SSS] TOALT TOALT TOALT
> > -- stack contains [X' V'], altstack now contains [SSS V X]
> > 0 PUSHCURRENTINPUTINDEX EQUALVERIFY
> > -- this input is the first, so the ordinal will move to the first
> > output
> > DEPTH NOT IF ... ELSE
> > -- skip over the other branch (without violating minimalif rules)
> > FROMALT SWAP TUCK FROMALT
> > -- stack contains [X' V' X V' V], altstack contains [SSS]
> > [K] ADD GREATERTHANOREQUAL VERIFY
> > -- check V' >= V+K, stack contains [X' V' X]
> > 1 SWAP FORWARD_TARGET
> > -- output 1 pays to X (previous bidder's scriptPubKey), and the
> > entire value of this input goes there; stack contains [X' V']
> > DUP FORWARD_PARTIAL
> > -- execute "V' FORWARD_PARTIAL", stack contains [X' V']
> > 0 ROT ROT
> > -- stack contains [0 X' V']
> > FROMALT DUP 3 SWAP FORWARD_LEAF_UPDATE
> > -- execute "0 X' V' SSS 3 SSS FORWARD_LEAF_UPDATE" which checks
> > that output 0 spends at least V' satoshis back to the same
> > script (because that's how we defined SSS), except the first
> > three pushes (previously X V SSS) are replaced by X' V' SSS.
> > 0
> > ENDIF
> > CSV
> > -- "0 CSV" requires nSequnce to be set, which makes the tx rbf'able,
> > which hopefully makes it harder to pin
> > 1ADD
> > -- ends with 1 on the stack; success!
> >
> > (The "SSS n SSS FORWARD_LEAF_UPDATE" construct is more or less a quine,
> > ie a program that outputs its own source code)
> >
> > I think that script is about 211 witness bytes, with an additional 40
> > witness bytes for X'/V', so when making a bid, your tx would be
> > something like:
> >
> > tx header, 10vb
> > input 0: 103vb for the old bid including witness and control block
> > input 1: 58vb for a taproot key path spend
> > output 0: 43vb for the new bid
> > output 1: 43vb for your change
> >
> > for a total of about 257vb -- slightly larger than a regular 2-in-2-out
> > transaction, but not terribly much. Mostly because input 0 doesn't require
> > a signature -- it's size is effectively 6 pubkeys: X, X' VENDOR twice,
> > and the script code twice, along with a little extra to encode the
> > various numbers (10000, 144, K, V, V').
> >
> > This approach seems pretty "MEV" resistant: you pay fees via input 1 if
> > your bid succeeds; if it doesn't, you don't pay any fees. A potential
> > scalper might want to put in an early low ball bid, then prevent
> > higher bidders from winning the auction, take control of the ordinal,
> > and resell it later, but unless they can prevent another miner from
> > mining alternative bids for 144 blocks, they will fail at that. The bid
> > is fixed by the bidder and committed to by the signature on input 1, so
> > frontrunning a bid can't do anything beyond invalidate the bid entirely.
> >
> > Obviously, this is a pretty limited auction mechanism in various ways;
> > eg maybe you'd rather specify K as a percentage than an absoute increment;
> > maybe you'd like to have the auction definitely finish by some particular
> > time; maybe you'd like to be able to have the auction be able to continue
> > above 21.47 BTC (2**31 sats); maybe you'd like to do a dutch auction
> > rather than an english auction. I think you can probably do all those
> > things with this set of opcodes and clever scripting, though it probably
> > gets ugly.
> >
> > I don't think this is easily extensible to taro or rgb style assets,
> > as rather than being able to ensure the asset is transferred by
> > controlling the input/output positions, I think you'd need to build
> > up merkle trees and do point tweaks beyond what's supported by
> > OP_FORWARD_LEAF_UPDATE/OP_VAULT. Of course, without something like
> > OP_PUSHCURRENTINPUTINDEX I don't think you could do it for ordinals
> > either.
> >
> > Cheers,
> > aj
> >
> > [0] https://github.com/bitcoin/bips/blob/7f747fba82675f28c239df690a07b75529bd0960/bip-0345.mediawiki
> >
> > [1] https://twitter.com/jamesob/status/1639019107432513537
> >
> > [2] https://cointelegraph.com/news/scammers-dream-yuga-s-auction-model-for-bitcoin-nfts-sees-criticism
> >
> > [3] Inscriptions remain a wasteful way of publishing/committing
> > to content, however!
> >
> > [4] https://github.com/ElementsProject/elements/blob/master/doc/tapscript_opcodes.md
> >
> > [5] Setting K too low probably invites griefing, where a bidder may be
> > able to use rbf pinning vectors to prevent people who would be willing
> > to bid substantially higher from getting their bid confirmed on
> > chain.
> > _______________________________________________
> > bitcoin-dev mailing list
> > bitcoin-dev@lists•linuxfoundation.org
> > https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev


 permalink raw reply	[|nested]
2023-03-29 19:57               ` alicexbt

  2023-03-30 10:39                 ` Zac Greenwood
  
From: Steve Lee @ 2023-03-30  0:16 UTC (permalink / raw)
  To: alicexbt, Bitcoin Protocol Discussion;  Anthony Towns

[-- Attachment #1: Type: text/plain, Size: 12351 bytes --]

"want bitcoin to be money and money means different things for people in
this world"

I think we can all agree that a property of money is fungibility, and by
its very definition NFTs are not fungible and thus not money.

On Wed, Mar 29, 2023 at 4:56 PM alicexbt via bitcoin-dev <
bitcoin-dev@lists•linuxfoundation.org> wrote:

> Hi Zac,
>
> Let me share what those parasites achieved:
>
> - Fees paid: 150 BTC
> - Lot of users and developers trying bitcoin that either never tried or
> gave up early in 2013-15
> - Mempools of nodes of being busy on weekends and got lots of transactions
> - PSBT became cool and application devs are trying their best to use it in
> different ways
> - Some developers exploring taproot and multisig
> - AJ shared things how covenants could help in fair, non-custodial,
> on-chain auction of ordinals that is MEV resistant although I had shared it
> earlier which involves more steps:
> https://twitter.com/1440000bytes/status/1634368411760476161
> - Investors exploring about funding projects
> - Bitcoin more than Bitcoin and people excited about it
>
> We can have difference of opinion, however I want bitcoin to be money and
> money means different things for people in this world. Please respect that
> else it will become like Linux, something used by 1% of world.
>
> /dev/fd0
> floppy disk guy
>
> Sent with Proton Mail secure email.
>
> ------- Original Message -------
> On Wednesday, March 29th, 2023 at 12:40 PM, Zac Greenwood via bitcoin-dev <
> bitcoin-dev@lists•linuxfoundation.org> wrote:
>
>
> > I’m not sure why any effort should be spent on theorizing how new
> opcodes might be used to facilitate parasitical use cases of the blockchain.
> >
> > If anything, business models relying on the ability to abuse the
> blockchain as a data store must be made less feasible, not more.
> >
> > Zac
> >
> >
> > On Fri, 24 Mar 2023 at 20:10, Anthony Towns via bitcoin-dev <
> bitcoin-dev@lists•linuxfoundation.org> wrote:
> >
> > > On Tue, Mar 07, 2023 at 10:45:34PM +1000, Anthony Towns via
> bitcoin-dev wrote:
> > > > I think there are perhaps four opcodes that are interesting in this
> class:
> > > >
> > > > idx sPK OP_FORWARD_TARGET
> > > > -- sends the value to a particular output (given by idx), and
> > > > requires that output have a particular scriptPubKey (given
> > > > by sPK).
> > > >
> > > > idx [...] n script OP_FORWARD_LEAF_UPDATE
> > > > -- sends the value to a particular output (given by idx), and
> > > > requires that output to have almost the same scriptPubKey as this
> > > > input, _except_ that the current leaf is replaced by "script",
> > > > with that script prefixed by "n" pushes (of values given by [...])
> > > >
> > > > idx OP_FORWARD_SELF
> > > > -- sends the value to a particular output (given by idx), and
> > > > requires that output to have the same scriptPubKey as this input
> > > >
> > > > amt OP_FORWARD_PARTIAL
> > > > -- modifies the next OP_FORWARD_* opcode to only affect "amt",
> > > > rather than the entire balance. opcodes after that affect the
> > > > remaining balance, after "amt" has been subtracted. if "amt" is
> > > > 0, the next OP_FORWARD_* becomes a no-op.
> > >
> > > The BIP 345 draft has been updated [0] [1] and now pretty much defines
> > > OP_VAULT to have the behaviour specced for OP_FORWARD_LEAF_UPDATE
> above,
> > > and OP_VAULT_RECOVER to behave as OP_FORWARD_TARGET above. Despite
> > > that, for this email I'm going to continue using the OP_FORWARD_*
> > > naming convention.
> > >
> > > Given the recent controversy over the Yuga labs ordinal auction [2],
> > > perhaps it's interesting to consider that these proposed opcodes come
> > > close to making it possible to do a fair, non-custodial, on-chain
> auction
> > > of ordinals [3].
> > >
> > > The idea here is that you create a utxo on chain that contains the
> ordinal
> > > in question, which commits to the address of the current leading
> bidder,
> > > and can be spent in two ways:
> > >
> > > 1) it can be updated to a new bidder, if the bid is raised by at least
> > > K satoshis, in which case the previous bidder is refunded their
> > > bid; or,
> > >
> > > 2) if there have been no new bids for a day, the current high bidder
> > > wins, and the ordinal is moved to their address, while the funds
> > > from their winning bid are sent to the original vendor's address.
> > >
> > > I believe this can be implemented in script as follows,
> > > assuming the opcodes OP_FORWARD_TARGET(OP_VAULT_RECOVER),
> > > OP_FORWARD_LEAF_UPDATE(OP_VAULT), OP_FORWARD_PARTIAL (as specced
> above),
> > > and OP_PUSHCURRENTINPUTINDEX (as implemented in liquid/elements [4])
> > > are all available.
> > >
> > > First, figure out the parameters:
> > >
> > > * Set VENDOR to the scriptPubKey corresponding to the vendor's address.
> > > * Set K to the minimum bid increment [5].
> > > * Initially, set X equal to VENDOR.
> > > * Initially, set V to just below the reserve price (V+K is the
> > > minimum initial bid).
> > >
> > > Then construct the following script:
> > >
> > > [X] [V] [SSS] TOALT TOALT TOALT
> > > 0 PUSHCURRENTINPUTINDEX EQUALVERIFY
> > > DEPTH NOT IF
> > > 0 10000 FORWARD_PARTIAL
> > > 0 FROMALT FORWARD_TARGET
> > > 1 [VENDOR] FWD_TARGET
> > > 144
> > > ELSE
> > > FROMALT SWAP TUCK FROMALT
> > > [K] ADD GREATERTHANOREQUAL VERIFY
> > > 1 SWAP FORWARD_TARGET
> > > DUP FORWARD_PARTIAL
> > > 0 ROT ROT
> > > FROMALT DUP 3 SWAP FORWARD_LEAF_UPDATE
> > > 0
> > > ENDIF
> > > CSV
> > > 1ADD
> > >
> > > where "SSS" is a pushdata of the rest of the script ("TOALT TOALT TOALT
> > > .. 1ADD").
> > >
> > > Finally, make that script the sole tapleaf, accompanied by a NUMS point
> > > as the internal public key, calculate the taproot address corresponding
> > > to that, and send the ordinal to that address as the first satoshi.
> > >
> > > There are two ways to spend that script. With an empty witness stack,
> > > the following will be executed:
> > >
> > > [X] [V] [SSS] TOALT TOALT TOALT
> > > -- altstack now contains [SSS V X]
> > > 0 PUSHCURRENTINPUTINDEX EQUALVERIFY
> > > -- this input is the first, so the ordinal will move to the first
> > > output
> > > DEPTH NOT IF
> > > -- take this branch: the auction is over!
> > > 1 [VENDOR] FWD_TARGET
> > > -- output 1 gets the entire value of this input, and pays to
> > > the vendor's hardcoded scriptPubKey
> > > 0 10000 FORWARD_PARTIAL
> > > 0 FROMALT FORWARD_TARGET
> > > -- we forward at least 10k sats to output 0 (if there were 0 sats,
> > > the ordinal would end up in output 1 instead, which would be a
> > > bug), and output 0 pays to scriptPubKey "X"
> > > 144
> > > ELSE .. ENDIF
> > > -- skip over the other branch
> > > CSV
> > > -- check that this input has baked for 144 blocks (~1 day)
> > > 1ADD
> > > -- leave 145 on the stack, which is true. success!
> > >
> > > Alternatively, if you want to increase the bid you provide a stack with
> > > two items: your scriptPubKey and the new bid [X' V']. Execution this
> > > time looks like:
> > >
> > > [X] [V] [SSS] TOALT TOALT TOALT
> > > -- stack contains [X' V'], altstack now contains [SSS V X]
> > > 0 PUSHCURRENTINPUTINDEX EQUALVERIFY
> > > -- this input is the first, so the ordinal will move to the first
> > > output
> > > DEPTH NOT IF ... ELSE
> > > -- skip over the other branch (without violating minimalif rules)
> > > FROMALT SWAP TUCK FROMALT
> > > -- stack contains [X' V' X V' V], altstack contains [SSS]
> > > [K] ADD GREATERTHANOREQUAL VERIFY
> > > -- check V' >= V+K, stack contains [X' V' X]
> > > 1 SWAP FORWARD_TARGET
> > > -- output 1 pays to X (previous bidder's scriptPubKey), and the
> > > entire value of this input goes there; stack contains [X' V']
> > > DUP FORWARD_PARTIAL
> > > -- execute "V' FORWARD_PARTIAL", stack contains [X' V']
> > > 0 ROT ROT
> > > -- stack contains [0 X' V']
> > > FROMALT DUP 3 SWAP FORWARD_LEAF_UPDATE
> > > -- execute "0 X' V' SSS 3 SSS FORWARD_LEAF_UPDATE" which checks
> > > that output 0 spends at least V' satoshis back to the same
> > > script (because that's how we defined SSS), except the first
> > > three pushes (previously X V SSS) are replaced by X' V' SSS.
> > > 0
> > > ENDIF
> > > CSV
> > > -- "0 CSV" requires nSequnce to be set, which makes the tx rbf'able,
> > > which hopefully makes it harder to pin
> > > 1ADD
> > > -- ends with 1 on the stack; success!
> > >
> > > (The "SSS n SSS FORWARD_LEAF_UPDATE" construct is more or less a quine,
> > > ie a program that outputs its own source code)
> > >
> > > I think that script is about 211 witness bytes, with an additional 40
> > > witness bytes for X'/V', so when making a bid, your tx would be
> > > something like:
> > >
> > > tx header, 10vb
> > > input 0: 103vb for the old bid including witness and control block
> > > input 1: 58vb for a taproot key path spend
> > > output 0: 43vb for the new bid
> > > output 1: 43vb for your change
> > >
> > > for a total of about 257vb -- slightly larger than a regular 2-in-2-out
> > > transaction, but not terribly much. Mostly because input 0 doesn't
> require
> > > a signature -- it's size is effectively 6 pubkeys: X, X' VENDOR twice,
> > > and the script code twice, along with a little extra to encode the
> > > various numbers (10000, 144, K, V, V').
> > >
> > > This approach seems pretty "MEV" resistant: you pay fees via input 1 if
> > > your bid succeeds; if it doesn't, you don't pay any fees. A potential
> > > scalper might want to put in an early low ball bid, then prevent
> > > higher bidders from winning the auction, take control of the ordinal,
> > > and resell it later, but unless they can prevent another miner from
> > > mining alternative bids for 144 blocks, they will fail at that. The bid
> > > is fixed by the bidder and committed to by the signature on input 1, so
> > > frontrunning a bid can't do anything beyond invalidate the bid
> entirely.
> > >
> > > Obviously, this is a pretty limited auction mechanism in various ways;
> > > eg maybe you'd rather specify K as a percentage than an absoute
> increment;
> > > maybe you'd like to have the auction definitely finish by some
> particular
> > > time; maybe you'd like to be able to have the auction be able to
> continue
> > > above 21.47 BTC (2**31 sats); maybe you'd like to do a dutch auction
> > > rather than an english auction. I think you can probably do all those
> > > things with this set of opcodes and clever scripting, though it
> probably
> > > gets ugly.
> > >
> > > I don't think this is easily extensible to taro or rgb style assets,
> > > as rather than being able to ensure the asset is transferred by
> > > controlling the input/output positions, I think you'd need to build
> > > up merkle trees and do point tweaks beyond what's supported by
> > > OP_FORWARD_LEAF_UPDATE/OP_VAULT. Of course, without something like
> > > OP_PUSHCURRENTINPUTINDEX I don't think you could do it for ordinals
> > > either.
> > >
> > > Cheers,
> > > aj
> > >
> > > [0]
> https://github.com/bitcoin/bips/blob/7f747fba82675f28c239df690a07b75529bd0960/bip-0345.mediawiki
> > >
> > > [1] https://twitter.com/jamesob/status/1639019107432513537
> > >
> > > [2]
> https://cointelegraph.com/news/scammers-dream-yuga-s-auction-model-for-bitcoin-nfts-sees-criticism
> > >
> > > [3] Inscriptions remain a wasteful way of publishing/committing
> > > to content, however!
> > >
> > > [4]
> https://github.com/ElementsProject/elements/blob/master/doc/tapscript_opcodes.md
> > >
> > > [5] Setting K too low probably invites griefing, where a bidder may be
> > > able to use rbf pinning vectors to prevent people who would be willing
> > > to bid substantially higher from getting their bid confirmed on
> > > chain.
> > > _______________________________________________
> > > bitcoin-dev mailing list
> > > bitcoin-dev@lists•linuxfoundation.org
> > > https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
> _______________________________________________
> bitcoin-dev mailing list
> bitcoin-dev@lists•linuxfoundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
>

[-- Attachment #2: Type: text/html, Size: 15961 bytes --]

 permalink raw reply	[|nested]
2023-03-29 19:57               ` alicexbt
  2023-03-30  0:16                 ` Steve Lee

  2023-03-30 18:12                   ` alicexbt
  
From: Zac Greenwood @ 2023-03-30 10:39 UTC (permalink / raw)
  To: alicexbt;  Bitcoin Protocol Discussion, Anthony Towns

[-- Attachment #1: Type: text/plain, Size: 13172 bytes --]

Hi alicexbtc,

Under no circumstance should Bitcoin add any functionality intended to
support private businesses that rely on on-chain storage for their business
model.

Regarding “Fees paid: 150 BTC” (uh, *citation needed*):

To optimize for profitability a business would generally attempt to operate
using zero- or low-fee transactions. Therefore they tend to contribute
 comparatively little fees but are depriving public use of these cheap
transactions. Worse, they exert a constant upward pressure on fee levels,
making it more expensive for everyone else to transact.

Unlike miners, node operators do not receive any compensation. They however
incur additional cost for bandwidth, electricity and processing time to not
only support some current business but all businesses in the past that ever
tried to turn a profit at their expense, so also after such business failed
and has been long gone. They foot the bill.

Lastly, I don’t believe there is any value in having for instance Ordinals
spam the blockchain with images of wojaks, bored apes and other crap but
perhaps you wish to clarify why this might be something to be “excited
about”.

Your other arguments are nonsensical so excuse me for ignoring them.


Zac


On Thu, 30 Mar 2023 at 03:57, alicexbt <alicexbt@protonmail•com> wrote:

> Hi Zac,
>
> Let me share what those parasites achieved:
>
> - Fees paid: 150 BTC
> - Lot of users and developers trying bitcoin that either never tried or
> gave up early in 2013-15
> - Mempools of nodes of being busy on weekends and got lots of transactions
> - PSBT became cool and application devs are trying their best to use it in
> different ways
> - Some developers exploring taproot and multisig
> - AJ shared things how covenants could help in fair, non-custodial,
> on-chain auction of ordinals that is MEV resistant although I had shared it
> earlier which involves more steps:
> https://twitter.com/1440000bytes/status/1634368411760476161
> - Investors exploring about funding projects
> - Bitcoin more than Bitcoin and people excited about it
>
> We can have difference of opinion, however I want bitcoin to be money and
> money means different things for people in this world. Please respect that
> else it will become like Linux, something used by 1% of world.
>
> /dev/fd0
> floppy disk guy
>
> Sent with Proton Mail secure email.
>
> ------- Original Message -------
> On Wednesday, March 29th, 2023 at 12:40 PM, Zac Greenwood via bitcoin-dev <
> bitcoin-dev@lists•linuxfoundation.org> wrote:
>
>
> > I’m not sure why any effort should be spent on theorizing how new
> opcodes might be used to facilitate parasitical use cases of the blockchain.
> >
> > If anything, business models relying on the ability to abuse the
> blockchain as a data store must be made less feasible, not more.
> >
> > Zac
> >
> >
> > On Fri, 24 Mar 2023 at 20:10, Anthony Towns via bitcoin-dev <
> bitcoin-dev@lists•linuxfoundation.org> wrote:
> >
> > > On Tue, Mar 07, 2023 at 10:45:34PM +1000, Anthony Towns via
> bitcoin-dev wrote:
> > > > I think there are perhaps four opcodes that are interesting in this
> class:
> > > >
> > > > idx sPK OP_FORWARD_TARGET
> > > > -- sends the value to a particular output (given by idx), and
> > > > requires that output have a particular scriptPubKey (given
> > > > by sPK).
> > > >
> > > > idx [...] n script OP_FORWARD_LEAF_UPDATE
> > > > -- sends the value to a particular output (given by idx), and
> > > > requires that output to have almost the same scriptPubKey as this
> > > > input, _except_ that the current leaf is replaced by "script",
> > > > with that script prefixed by "n" pushes (of values given by [...])
> > > >
> > > > idx OP_FORWARD_SELF
> > > > -- sends the value to a particular output (given by idx), and
> > > > requires that output to have the same scriptPubKey as this input
> > > >
> > > > amt OP_FORWARD_PARTIAL
> > > > -- modifies the next OP_FORWARD_* opcode to only affect "amt",
> > > > rather than the entire balance. opcodes after that affect the
> > > > remaining balance, after "amt" has been subtracted. if "amt" is
> > > > 0, the next OP_FORWARD_* becomes a no-op.
> > >
> > > The BIP 345 draft has been updated [0] [1] and now pretty much defines
> > > OP_VAULT to have the behaviour specced for OP_FORWARD_LEAF_UPDATE
> above,
> > > and OP_VAULT_RECOVER to behave as OP_FORWARD_TARGET above. Despite
> > > that, for this email I'm going to continue using the OP_FORWARD_*
> > > naming convention.
> > >
> > > Given the recent controversy over the Yuga labs ordinal auction [2],
> > > perhaps it's interesting to consider that these proposed opcodes come
> > > close to making it possible to do a fair, non-custodial, on-chain
> auction
> > > of ordinals [3].
> > >
> > > The idea here is that you create a utxo on chain that contains the
> ordinal
> > > in question, which commits to the address of the current leading
> bidder,
> > > and can be spent in two ways:
> > >
> > > 1) it can be updated to a new bidder, if the bid is raised by at least
> > > K satoshis, in which case the previous bidder is refunded their
> > > bid; or,
> > >
> > > 2) if there have been no new bids for a day, the current high bidder
> > > wins, and the ordinal is moved to their address, while the funds
> > > from their winning bid are sent to the original vendor's address.
> > >
> > > I believe this can be implemented in script as follows,
> > > assuming the opcodes OP_FORWARD_TARGET(OP_VAULT_RECOVER),
> > > OP_FORWARD_LEAF_UPDATE(OP_VAULT), OP_FORWARD_PARTIAL (as specced
> above),
> > > and OP_PUSHCURRENTINPUTINDEX (as implemented in liquid/elements [4])
> > > are all available.
> > >
> > > First, figure out the parameters:
> > >
> > > * Set VENDOR to the scriptPubKey corresponding to the vendor's address.
> > > * Set K to the minimum bid increment [5].
> > > * Initially, set X equal to VENDOR.
> > > * Initially, set V to just below the reserve price (V+K is the
> > > minimum initial bid).
> > >
> > > Then construct the following script:
> > >
> > > [X] [V] [SSS] TOALT TOALT TOALT
> > > 0 PUSHCURRENTINPUTINDEX EQUALVERIFY
> > > DEPTH NOT IF
> > > 0 10000 FORWARD_PARTIAL
> > > 0 FROMALT FORWARD_TARGET
> > > 1 [VENDOR] FWD_TARGET
> > > 144
> > > ELSE
> > > FROMALT SWAP TUCK FROMALT
> > > [K] ADD GREATERTHANOREQUAL VERIFY
> > > 1 SWAP FORWARD_TARGET
> > > DUP FORWARD_PARTIAL
> > > 0 ROT ROT
> > > FROMALT DUP 3 SWAP FORWARD_LEAF_UPDATE
> > > 0
> > > ENDIF
> > > CSV
> > > 1ADD
> > >
> > > where "SSS" is a pushdata of the rest of the script ("TOALT TOALT TOALT
> > > .. 1ADD").
> > >
> > > Finally, make that script the sole tapleaf, accompanied by a NUMS point
> > > as the internal public key, calculate the taproot address corresponding
> > > to that, and send the ordinal to that address as the first satoshi.
> > >
> > > There are two ways to spend that script. With an empty witness stack,
> > > the following will be executed:
> > >
> > > [X] [V] [SSS] TOALT TOALT TOALT
> > > -- altstack now contains [SSS V X]
> > > 0 PUSHCURRENTINPUTINDEX EQUALVERIFY
> > > -- this input is the first, so the ordinal will move to the first
> > > output
> > > DEPTH NOT IF
> > > -- take this branch: the auction is over!
> > > 1 [VENDOR] FWD_TARGET
> > > -- output 1 gets the entire value of this input, and pays to
> > > the vendor's hardcoded scriptPubKey
> > > 0 10000 FORWARD_PARTIAL
> > > 0 FROMALT FORWARD_TARGET
> > > -- we forward at least 10k sats to output 0 (if there were 0 sats,
> > > the ordinal would end up in output 1 instead, which would be a
> > > bug), and output 0 pays to scriptPubKey "X"
> > > 144
> > > ELSE .. ENDIF
> > > -- skip over the other branch
> > > CSV
> > > -- check that this input has baked for 144 blocks (~1 day)
> > > 1ADD
> > > -- leave 145 on the stack, which is true. success!
> > >
> > > Alternatively, if you want to increase the bid you provide a stack with
> > > two items: your scriptPubKey and the new bid [X' V']. Execution this
> > > time looks like:
> > >
> > > [X] [V] [SSS] TOALT TOALT TOALT
> > > -- stack contains [X' V'], altstack now contains [SSS V X]
> > > 0 PUSHCURRENTINPUTINDEX EQUALVERIFY
> > > -- this input is the first, so the ordinal will move to the first
> > > output
> > > DEPTH NOT IF ... ELSE
> > > -- skip over the other branch (without violating minimalif rules)
> > > FROMALT SWAP TUCK FROMALT
> > > -- stack contains [X' V' X V' V], altstack contains [SSS]
> > > [K] ADD GREATERTHANOREQUAL VERIFY
> > > -- check V' >= V+K, stack contains [X' V' X]
> > > 1 SWAP FORWARD_TARGET
> > > -- output 1 pays to X (previous bidder's scriptPubKey), and the
> > > entire value of this input goes there; stack contains [X' V']
> > > DUP FORWARD_PARTIAL
> > > -- execute "V' FORWARD_PARTIAL", stack contains [X' V']
> > > 0 ROT ROT
> > > -- stack contains [0 X' V']
> > > FROMALT DUP 3 SWAP FORWARD_LEAF_UPDATE
> > > -- execute "0 X' V' SSS 3 SSS FORWARD_LEAF_UPDATE" which checks
> > > that output 0 spends at least V' satoshis back to the same
> > > script (because that's how we defined SSS), except the first
> > > three pushes (previously X V SSS) are replaced by X' V' SSS.
> > > 0
> > > ENDIF
> > > CSV
> > > -- "0 CSV" requires nSequnce to be set, which makes the tx rbf'able,
> > > which hopefully makes it harder to pin
> > > 1ADD
> > > -- ends with 1 on the stack; success!
> > >
> > > (The "SSS n SSS FORWARD_LEAF_UPDATE" construct is more or less a quine,
> > > ie a program that outputs its own source code)
> > >
> > > I think that script is about 211 witness bytes, with an additional 40
> > > witness bytes for X'/V', so when making a bid, your tx would be
> > > something like:
> > >
> > > tx header, 10vb
> > > input 0: 103vb for the old bid including witness and control block
> > > input 1: 58vb for a taproot key path spend
> > > output 0: 43vb for the new bid
> > > output 1: 43vb for your change
> > >
> > > for a total of about 257vb -- slightly larger than a regular 2-in-2-out
> > > transaction, but not terribly much. Mostly because input 0 doesn't
> require
> > > a signature -- it's size is effectively 6 pubkeys: X, X' VENDOR twice,
> > > and the script code twice, along with a little extra to encode the
> > > various numbers (10000, 144, K, V, V').
> > >
> > > This approach seems pretty "MEV" resistant: you pay fees via input 1 if
> > > your bid succeeds; if it doesn't, you don't pay any fees. A potential
> > > scalper might want to put in an early low ball bid, then prevent
> > > higher bidders from winning the auction, take control of the ordinal,
> > > and resell it later, but unless they can prevent another miner from
> > > mining alternative bids for 144 blocks, they will fail at that. The bid
> > > is fixed by the bidder and committed to by the signature on input 1, so
> > > frontrunning a bid can't do anything beyond invalidate the bid
> entirely.
> > >
> > > Obviously, this is a pretty limited auction mechanism in various ways;
> > > eg maybe you'd rather specify K as a percentage than an absoute
> increment;
> > > maybe you'd like to have the auction definitely finish by some
> particular
> > > time; maybe you'd like to be able to have the auction be able to
> continue
> > > above 21.47 BTC (2**31 sats); maybe you'd like to do a dutch auction
> > > rather than an english auction. I think you can probably do all those
> > > things with this set of opcodes and clever scripting, though it
> probably
> > > gets ugly.
> > >
> > > I don't think this is easily extensible to taro or rgb style assets,
> > > as rather than being able to ensure the asset is transferred by
> > > controlling the input/output positions, I think you'd need to build
> > > up merkle trees and do point tweaks beyond what's supported by
> > > OP_FORWARD_LEAF_UPDATE/OP_VAULT. Of course, without something like
> > > OP_PUSHCURRENTINPUTINDEX I don't think you could do it for ordinals
> > > either.
> > >
> > > Cheers,
> > > aj
> > >
> > > [0]
> https://github.com/bitcoin/bips/blob/7f747fba82675f28c239df690a07b75529bd0960/bip-0345.mediawiki
> > >
> > > [1] https://twitter.com/jamesob/status/1639019107432513537
> > >
> > > [2]
> https://cointelegraph.com/news/scammers-dream-yuga-s-auction-model-for-bitcoin-nfts-sees-criticism
> > >
> > > [3] Inscriptions remain a wasteful way of publishing/committing
> > > to content, however!
> > >
> > > [4]
> https://github.com/ElementsProject/elements/blob/master/doc/tapscript_opcodes.md
> > >
> > > [5] Setting K too low probably invites griefing, where a bidder may be
> > > able to use rbf pinning vectors to prevent people who would be willing
> > > to bid substantially higher from getting their bid confirmed on
> > > chain.
> > > _______________________________________________
> > > bitcoin-dev mailing list
> > > bitcoin-dev@lists•linuxfoundation.org
> > > https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
>

[-- Attachment #2: Type: text/html, Size: 17005 bytes --]

 permalink raw reply	[|nested]
2023-03-30 10:39                 ` Zac Greenwood

  
From: alicexbt @ 2023-03-30 18:12 UTC (permalink / raw)
  To: Zac Greenwood;  Bitcoin Protocol Discussion, Anthony Towns

Hi Zac,

> Regarding “Fees paid: 150 BTC” (uh, *citation needed*):

https://dune.com/queries/2008613/3326984

> Your other arguments are nonsensical so excuse me for ignoring them.

There were zero browser extensions that could sign PSBT to be used in different bitcoin projects that have web interface earlier. Now there are several open source extensions that could be used to sign PSBT. If such development and interest by developers from other chains to build things on bitcoin makes no sense to you that there is nothing much to debate here.

Humans have inscribed things on money since thousands of years when bitcoin didn't even exist. Trying to fight this and going against market wont work.

I do not agree with other things mentioned in your email.

/dev/fd0
floppy disk guy

Sent with Proton Mail secure email.

------- Original Message -------
On Thursday, March 30th, 2023 at 4:09 PM, Zac Greenwood <zachgrw@gmail•com> wrote:


> Hi alicexbtc,
> 
> Under no circumstance should Bitcoin add any functionality intended to support private businesses that rely on on-chain storage for their business model.
> 
> Regarding “Fees paid: 150 BTC” (uh, *citation needed*):
> 
> To optimize for profitability a business would generally attempt to operate using zero- or low-fee transactions. Therefore they tend to contribute comparatively little fees but are depriving public use of these cheap transactions. Worse, they exert a constant upward pressure on fee levels, making it more expensive for everyone else to transact.
> 
> Unlike miners, node operators do not receive any compensation. They however incur additional cost for bandwidth, electricity and processing time to not only support some current business but all businesses in the past that ever tried to turn a profit at their expense, so also after such business failed and has been long gone. They foot the bill.
> 
> Lastly, I don’t believe there is any value in having for instance Ordinals spam the blockchain with images of wojaks, bored apes and other crap but perhaps you wish to clarify why this might be something to be “excited about”.
> 
> Your other arguments are nonsensical so excuse me for ignoring them.
> 
> 
> Zac
> 
> 
> On Thu, 30 Mar 2023 at 03:57, alicexbt <alicexbt@protonmail•com> wrote:
> 
> > Hi Zac,
> > 
> > Let me share what those parasites achieved:
> > 
> > - Fees paid: 150 BTC
> > - Lot of users and developers trying bitcoin that either never tried or gave up early in 2013-15
> > - Mempools of nodes of being busy on weekends and got lots of transactions
> > - PSBT became cool and application devs are trying their best to use it in different ways
> > - Some developers exploring taproot and multisig
> > - AJ shared things how covenants could help in fair, non-custodial, on-chain auction of ordinals that is MEV resistant although I had shared it earlier which involves more steps: https://twitter.com/1440000bytes/status/1634368411760476161
> > - Investors exploring about funding projects
> > - Bitcoin more than Bitcoin and people excited about it
> > 
> > We can have difference of opinion, however I want bitcoin to be money and money means different things for people in this world. Please respect that else it will become like Linux, something used by 1% of world.
> > 
> > /dev/fd0
> > floppy disk guy
> > 
> > Sent with Proton Mail secure email.
> > 
> > ------- Original Message -------
> > On Wednesday, March 29th, 2023 at 12:40 PM, Zac Greenwood via bitcoin-dev <bitcoin-dev@lists•linuxfoundation.org> wrote:
> > 
> > 
> > > I’m not sure why any effort should be spent on theorizing how new opcodes might be used to facilitate parasitical use cases of the blockchain.
> > >
> > > If anything, business models relying on the ability to abuse the blockchain as a data store must be made less feasible, not more.
> > >
> > > Zac
> > >
> > >
> > > On Fri, 24 Mar 2023 at 20:10, Anthony Towns via bitcoin-dev <bitcoin-dev@lists•linuxfoundation.org> wrote:
> > >
> > > > On Tue, Mar 07, 2023 at 10:45:34PM +1000, Anthony Towns via bitcoin-dev wrote:
> > > > > I think there are perhaps four opcodes that are interesting in this class:
> > > > >
> > > > > idx sPK OP_FORWARD_TARGET
> > > > > -- sends the value to a particular output (given by idx), and
> > > > > requires that output have a particular scriptPubKey (given
> > > > > by sPK).
> > > > >
> > > > > idx [...] n script OP_FORWARD_LEAF_UPDATE
> > > > > -- sends the value to a particular output (given by idx), and
> > > > > requires that output to have almost the same scriptPubKey as this
> > > > > input, _except_ that the current leaf is replaced by "script",
> > > > > with that script prefixed by "n" pushes (of values given by [...])
> > > > >
> > > > > idx OP_FORWARD_SELF
> > > > > -- sends the value to a particular output (given by idx), and
> > > > > requires that output to have the same scriptPubKey as this input
> > > > >
> > > > > amt OP_FORWARD_PARTIAL
> > > > > -- modifies the next OP_FORWARD_* opcode to only affect "amt",
> > > > > rather than the entire balance. opcodes after that affect the
> > > > > remaining balance, after "amt" has been subtracted. if "amt" is
> > > > > 0, the next OP_FORWARD_* becomes a no-op.
> > > >
> > > > The BIP 345 draft has been updated [0] [1] and now pretty much defines
> > > > OP_VAULT to have the behaviour specced for OP_FORWARD_LEAF_UPDATE above,
> > > > and OP_VAULT_RECOVER to behave as OP_FORWARD_TARGET above. Despite
> > > > that, for this email I'm going to continue using the OP_FORWARD_*
> > > > naming convention.
> > > >
> > > > Given the recent controversy over the Yuga labs ordinal auction [2],
> > > > perhaps it's interesting to consider that these proposed opcodes come
> > > > close to making it possible to do a fair, non-custodial, on-chain auction
> > > > of ordinals [3].
> > > >
> > > > The idea here is that you create a utxo on chain that contains the ordinal
> > > > in question, which commits to the address of the current leading bidder,
> > > > and can be spent in two ways:
> > > >
> > > > 1) it can be updated to a new bidder, if the bid is raised by at least
> > > > K satoshis, in which case the previous bidder is refunded their
> > > > bid; or,
> > > >
> > > > 2) if there have been no new bids for a day, the current high bidder
> > > > wins, and the ordinal is moved to their address, while the funds
> > > > from their winning bid are sent to the original vendor's address.
> > > >
> > > > I believe this can be implemented in script as follows,
> > > > assuming the opcodes OP_FORWARD_TARGET(OP_VAULT_RECOVER),
> > > > OP_FORWARD_LEAF_UPDATE(OP_VAULT), OP_FORWARD_PARTIAL (as specced above),
> > > > and OP_PUSHCURRENTINPUTINDEX (as implemented in liquid/elements [4])
> > > > are all available.
> > > >
> > > > First, figure out the parameters:
> > > >
> > > > * Set VENDOR to the scriptPubKey corresponding to the vendor's address.
> > > > * Set K to the minimum bid increment [5].
> > > > * Initially, set X equal to VENDOR.
> > > > * Initially, set V to just below the reserve price (V+K is the
> > > > minimum initial bid).
> > > >
> > > > Then construct the following script:
> > > >
> > > > [X] [V] [SSS] TOALT TOALT TOALT
> > > > 0 PUSHCURRENTINPUTINDEX EQUALVERIFY
> > > > DEPTH NOT IF
> > > > 0 10000 FORWARD_PARTIAL
> > > > 0 FROMALT FORWARD_TARGET
> > > > 1 [VENDOR] FWD_TARGET
> > > > 144
> > > > ELSE
> > > > FROMALT SWAP TUCK FROMALT
> > > > [K] ADD GREATERTHANOREQUAL VERIFY
> > > > 1 SWAP FORWARD_TARGET
> > > > DUP FORWARD_PARTIAL
> > > > 0 ROT ROT
> > > > FROMALT DUP 3 SWAP FORWARD_LEAF_UPDATE
> > > > 0
> > > > ENDIF
> > > > CSV
> > > > 1ADD
> > > >
> > > > where "SSS" is a pushdata of the rest of the script ("TOALT TOALT TOALT
> > > > .. 1ADD").
> > > >
> > > > Finally, make that script the sole tapleaf, accompanied by a NUMS point
> > > > as the internal public key, calculate the taproot address corresponding
> > > > to that, and send the ordinal to that address as the first satoshi.
> > > >
> > > > There are two ways to spend that script. With an empty witness stack,
> > > > the following will be executed:
> > > >
> > > > [X] [V] [SSS] TOALT TOALT TOALT
> > > > -- altstack now contains [SSS V X]
> > > > 0 PUSHCURRENTINPUTINDEX EQUALVERIFY
> > > > -- this input is the first, so the ordinal will move to the first
> > > > output
> > > > DEPTH NOT IF
> > > > -- take this branch: the auction is over!
> > > > 1 [VENDOR] FWD_TARGET
> > > > -- output 1 gets the entire value of this input, and pays to
> > > > the vendor's hardcoded scriptPubKey
> > > > 0 10000 FORWARD_PARTIAL
> > > > 0 FROMALT FORWARD_TARGET
> > > > -- we forward at least 10k sats to output 0 (if there were 0 sats,
> > > > the ordinal would end up in output 1 instead, which would be a
> > > > bug), and output 0 pays to scriptPubKey "X"
> > > > 144
> > > > ELSE .. ENDIF
> > > > -- skip over the other branch
> > > > CSV
> > > > -- check that this input has baked for 144 blocks (~1 day)
> > > > 1ADD
> > > > -- leave 145 on the stack, which is true. success!
> > > >
> > > > Alternatively, if you want to increase the bid you provide a stack with
> > > > two items: your scriptPubKey and the new bid [X' V']. Execution this
> > > > time looks like:
> > > >
> > > > [X] [V] [SSS] TOALT TOALT TOALT
> > > > -- stack contains [X' V'], altstack now contains [SSS V X]
> > > > 0 PUSHCURRENTINPUTINDEX EQUALVERIFY
> > > > -- this input is the first, so the ordinal will move to the first
> > > > output
> > > > DEPTH NOT IF ... ELSE
> > > > -- skip over the other branch (without violating minimalif rules)
> > > > FROMALT SWAP TUCK FROMALT
> > > > -- stack contains [X' V' X V' V], altstack contains [SSS]
> > > > [K] ADD GREATERTHANOREQUAL VERIFY
> > > > -- check V' >= V+K, stack contains [X' V' X]
> > > > 1 SWAP FORWARD_TARGET
> > > > -- output 1 pays to X (previous bidder's scriptPubKey), and the
> > > > entire value of this input goes there; stack contains [X' V']
> > > > DUP FORWARD_PARTIAL
> > > > -- execute "V' FORWARD_PARTIAL", stack contains [X' V']
> > > > 0 ROT ROT
> > > > -- stack contains [0 X' V']
> > > > FROMALT DUP 3 SWAP FORWARD_LEAF_UPDATE
> > > > -- execute "0 X' V' SSS 3 SSS FORWARD_LEAF_UPDATE" which checks
> > > > that output 0 spends at least V' satoshis back to the same
> > > > script (because that's how we defined SSS), except the first
> > > > three pushes (previously X V SSS) are replaced by X' V' SSS.
> > > > 0
> > > > ENDIF
> > > > CSV
> > > > -- "0 CSV" requires nSequnce to be set, which makes the tx rbf'able,
> > > > which hopefully makes it harder to pin
> > > > 1ADD
> > > > -- ends with 1 on the stack; success!
> > > >
> > > > (The "SSS n SSS FORWARD_LEAF_UPDATE" construct is more or less a quine,
> > > > ie a program that outputs its own source code)
> > > >
> > > > I think that script is about 211 witness bytes, with an additional 40
> > > > witness bytes for X'/V', so when making a bid, your tx would be
> > > > something like:
> > > >
> > > > tx header, 10vb
> > > > input 0: 103vb for the old bid including witness and control block
> > > > input 1: 58vb for a taproot key path spend
> > > > output 0: 43vb for the new bid
> > > > output 1: 43vb for your change
> > > >
> > > > for a total of about 257vb -- slightly larger than a regular 2-in-2-out
> > > > transaction, but not terribly much. Mostly because input 0 doesn't require
> > > > a signature -- it's size is effectively 6 pubkeys: X, X' VENDOR twice,
> > > > and the script code twice, along with a little extra to encode the
> > > > various numbers (10000, 144, K, V, V').
> > > >
> > > > This approach seems pretty "MEV" resistant: you pay fees via input 1 if
> > > > your bid succeeds; if it doesn't, you don't pay any fees. A potential
> > > > scalper might want to put in an early low ball bid, then prevent
> > > > higher bidders from winning the auction, take control of the ordinal,
> > > > and resell it later, but unless they can prevent another miner from
> > > > mining alternative bids for 144 blocks, they will fail at that. The bid
> > > > is fixed by the bidder and committed to by the signature on input 1, so
> > > > frontrunning a bid can't do anything beyond invalidate the bid entirely.
> > > >
> > > > Obviously, this is a pretty limited auction mechanism in various ways;
> > > > eg maybe you'd rather specify K as a percentage than an absoute increment;
> > > > maybe you'd like to have the auction definitely finish by some particular
> > > > time; maybe you'd like to be able to have the auction be able to continue
> > > > above 21.47 BTC (2**31 sats); maybe you'd like to do a dutch auction
> > > > rather than an english auction. I think you can probably do all those
> > > > things with this set of opcodes and clever scripting, though it probably
> > > > gets ugly.
> > > >
> > > > I don't think this is easily extensible to taro or rgb style assets,
> > > > as rather than being able to ensure the asset is transferred by
> > > > controlling the input/output positions, I think you'd need to build
> > > > up merkle trees and do point tweaks beyond what's supported by
> > > > OP_FORWARD_LEAF_UPDATE/OP_VAULT. Of course, without something like
> > > > OP_PUSHCURRENTINPUTINDEX I don't think you could do it for ordinals
> > > > either.
> > > >
> > > > Cheers,
> > > > aj
> > > >
> > > > [0] https://github.com/bitcoin/bips/blob/7f747fba82675f28c239df690a07b75529bd0960/bip-0345.mediawiki
> > > >
> > > > [1] https://twitter.com/jamesob/status/1639019107432513537
> > > >
> > > > [2] https://cointelegraph.com/news/scammers-dream-yuga-s-auction-model-for-bitcoin-nfts-sees-criticism
> > > >
> > > > [3] Inscriptions remain a wasteful way of publishing/committing
> > > > to content, however!
> > > >
> > > > [4] https://github.com/ElementsProject/elements/blob/master/doc/tapscript_opcodes.md
> > > >
> > > > [5] Setting K too low probably invites griefing, where a bidder may be
> > > > able to use rbf pinning vectors to prevent people who would be willing
> > > > to bid substantially higher from getting their bid confirmed on
> > > > chain.
> > > > _______________________________________________
> > > > bitcoin-dev mailing list
> > > > bitcoin-dev@lists•linuxfoundation.org
> > > > https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev


 permalink raw reply	[|nested]