Re: [bitcoin-dev] Merkleize All The Things

2023-05-30 Thread Johan Torås Halseth via bitcoin-dev
I should clarify: the current proposal already achieves the first part
needed for coin pools: removing some data from the merkle tree (I was
indeed referring to the embedded data, not the taptree).

The thing that is missing is removal of a public key from the taproot
internal key, but as mentioned I do agree that this is out of scope
for this proposal.

I believe you can get many of the benefits by falling back to "old
style multisig" in case someone exits the pool, by having a tap leaf
defining a multisig check amongst the remaining pubkeys.

Cheers,
Johan

> It seems likely that efficient use of the taproot internal pubkey with
> "dynamic key aggregation" is not possible with the current semantics
> (unless one ventures into the fraud proof machinery, which seems
> overkill!).
>
> However, in constructions with MATT opcodes, I would never expect the
> need for data to be stored in the taptree. In particular, for the case
> of CoinPools, the pubkeys of the members could also be stored in the
> embedded data, having a single "unilateral withdrawal" tapleaf.
> Removing a key would then amount to replacing it with a fixed NUMS key
> and computing the new root (re-using the same Merkle proof).
> Note that this is not a lot costlier than using a tapleaf per user:
> instead of paying the cost for the Merkle proof in the control block,
> you pay for it explicitly in the Script witness.
>
> Therefore, I would expect there to be reasonable CoinPools designs
> without additional opcodes − but I am only moderately confident as
> this is beyond the level of sophistication I've been exploring so far.


On Sun, May 28, 2023 at 12:24 PM Salvatore Ingala
 wrote:
>
> Hi Johan,
>
> Exciting to finally see some merkleization, which was only confined
> within the meme, up to this point!
>
> > A simpler way IMO, would be to make OP_CICV and OP_COCV symmetrical:
> > Have OP_CICV take an optional taproot and do the same check as is
> > done for the output: Q == tweak(tweak(X,D), T).
>
> I think that's an excellent suggestion, which I was already exploring
> for a different purpose: bringing externally signed data onto the
> stack. My goal there was to allow eltoo-style replacement.
>
> Until recently, I thought that a clean/efficient version of eltoo
> would require OP_CHECKSIGFROMSTACK or ANYPREVOUT. However, extending
> OP_CHECKINPUTCONTRACTVERIFY to enable introspection of other inputs
> allows a reasonable workaround: producing a separate UTXO signed with
> ANYONECANPAY, with the required data embedded as usual. Spending that
> UTXO together with the channel's UTXO allows one to get that data
> on the stack (with its signature already checked by consensus rules).
> I drafted this idea in a gist [1].
>
> Remark: it still seems easier (and probably slightly more efficient)
> to build eltoo replacement with CSFS or APO in addition to MATT
> opcodes.
>
> A possible semantics for OP_CHECKINPUTCONTRACTVERIFY could then be
> exactly symmetrical to that of OP_CHECKOUTPUTCONTRACTVERIFY, with
> the exception that the special input index -1 would represent the
> current input.
>
> Pushing this further, another option that could be be worth exploring
> is to have a single OP_CHECK_IN_OUT_CONTRACT_VERIFY opcode, with the
> same semantics as OP_CHECKOUTPUTCONTRACTVERIFY from [2], but with an
> additional `flags` argument, which is a bitmap where:
> - the lowest-significant bit determines if the index refers to inputs
>   or outputs (where input index -1 refers to the current input)
> - the second bit specifies if amounts should be preserved with
>   deferred checks as described in [2] (only applicable to outputs)
> - other bits are OP_SUCCESS and reserved for future behaviors.
>
> This would make the opcodes 1-2 bytes larger, but might allow greater
> flexibility, and keep some room for future extensions.
>
> > 2.To make fully functioning CoinPools, one would need functionality
> > similar to OP_MERKLESUB[4]: remove some data from the merkle tree,
> > and remove a key from the aggregated internal key.
>
> It seems likely that efficient use of the taproot internal pubkey with
> "dynamic key aggregation" is not possible with the current semantics
> (unless one ventures into the fraud proof machinery, which seems
> overkill!).
>
> However, in constructions with MATT opcodes, I would never expect the
> need for data to be stored in the taptree. In particular, for the case
> of CoinPools, the pubkeys of the members could also be stored in the
> embedded data, having a single "unilateral withdrawal" tapleaf.
> Removing a key would then amount to replacing it with a fixed NUMS key
> and computing the new root (re-using the same Merkle proof).
> Note that this is not a lot costlier than using a tapleaf per user:
> instead of paying the cost for the Merkle proof in the control block,
> you pay for it explicitly in the Script witness.
>
> Therefore, I would expect there to be reasonable CoinPools designs
> without additional opcodes − but I am 

Re: [bitcoin-dev] Merkleize All The Things

2023-05-28 Thread Salvatore Ingala via bitcoin-dev
Hi Johan,

Exciting to finally see some merkleization, which was only confined
within the meme, up to this point!

> A simpler way IMO, would be to make OP_CICV and OP_COCV symmetrical:
> Have OP_CICV take an optional taproot and do the same check as is
> done for the output: Q == tweak(tweak(X,D), T).

I think that's an excellent suggestion, which I was already exploring
for a different purpose: bringing externally signed data onto the
stack. My goal there was to allow eltoo-style replacement.

Until recently, I thought that a clean/efficient version of eltoo
would require OP_CHECKSIGFROMSTACK or ANYPREVOUT. However, extending
OP_CHECKINPUTCONTRACTVERIFY to enable introspection of other inputs
allows a reasonable workaround: producing a separate UTXO signed with
ANYONECANPAY, with the required data embedded as usual. Spending that
UTXO together with the channel's UTXO allows one to get that data
on the stack (with its signature already checked by consensus rules).
I drafted this idea in a gist [1].

Remark: it still seems easier (and probably slightly more efficient)
to build eltoo replacement with CSFS or APO in addition to MATT
opcodes.

A possible semantics for OP_CHECKINPUTCONTRACTVERIFY could then be
exactly symmetrical to that of OP_CHECKOUTPUTCONTRACTVERIFY, with
the exception that the special input index -1 would represent the
current input.

Pushing this further, another option that could be be worth exploring
is to have a single OP_CHECK_IN_OUT_CONTRACT_VERIFY opcode, with the
same semantics as OP_CHECKOUTPUTCONTRACTVERIFY from [2], but with an
additional `flags` argument, which is a bitmap where:
- the lowest-significant bit determines if the index refers to inputs
  or outputs (where input index -1 refers to the current input)
- the second bit specifies if amounts should be preserved with
  deferred checks as described in [2] (only applicable to outputs)
- other bits are OP_SUCCESS and reserved for future behaviors.

This would make the opcodes 1-2 bytes larger, but might allow greater
flexibility, and keep some room for future extensions.

> 2.To make fully functioning CoinPools, one would need functionality
> similar to OP_MERKLESUB[4]: remove some data from the merkle tree,
> and remove a key from the aggregated internal key.

It seems likely that efficient use of the taproot internal pubkey with
"dynamic key aggregation" is not possible with the current semantics
(unless one ventures into the fraud proof machinery, which seems
overkill!).

However, in constructions with MATT opcodes, I would never expect the
need for data to be stored in the taptree. In particular, for the case
of CoinPools, the pubkeys of the members could also be stored in the
embedded data, having a single "unilateral withdrawal" tapleaf.
Removing a key would then amount to replacing it with a fixed NUMS key
and computing the new root (re-using the same Merkle proof).
Note that this is not a lot costlier than using a tapleaf per user:
instead of paying the cost for the Merkle proof in the control block,
you pay for it explicitly in the Script witness.

Therefore, I would expect there to be reasonable CoinPools designs
without additional opcodes − but I am only moderately confident as
this is beyond the level of sophistication I've been exploring so far.

Best,
Salvatore

[1] - https://gist.github.com/bigspider/041ebd0842c0dcc74d8af087c1783b63
[2] -
https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2023-April/021588.html
___
bitcoin-dev mailing list
bitcoin-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev


Re: [bitcoin-dev] Merkleize All The Things

2023-05-26 Thread Johan Torås Halseth via bitcoin-dev
Hi, Salvatore.

As a further exploration of this idea, I implemented a
proof-of-concept of OP_CICV and OP_COCV in btcd[1] that together with
OP_CAT enables a set of interesting use cases.

One such use case is, as mentioned earlier, CoinPools[2]. The opcodes
let you easily check the "dynamically committed data" of an input you
are spending, and enforce a new commitment on the output. The idea is
to have the set of participants in the pool, and their balances, be
the UTXOs committed data, and  use this to validate the legitimacy of
a transaction, determining whether it permits a peer to exit with a
portion of the pooled funds.

Doing what you suggested above, having the input and output commit to
a merkle tree of participants and balances, we are able to quite
elegantly verify the coin pool exit clause. Here is a working example
of how that could look like: [3]. Obviously this lacks a lot before it
is a working CoinPool implementation, but it demonstrates how
OP_C[I/O]V introduces "memory" to Bitcoin script.

Having done this exercise, I have a few suggestions on how one could
further extend the proposal:

1. In the current proposal for OP_CHECKOUTPUTCONTRACTVERIFY, the
opcodes check whether the output key Q is key X tweaked with data D
and taproot T: Q == tweak(tweak(X,D), T).

OP_CHECKINPUTCONTRACTVERIFY on the other hand, works on the input
internal key, and does not care about the taptree on the input: P ==
tweak(X,D), where Q = tweak(P, T). In most cases this is probably good
enough, since you are already executing the current script and that
way know the spender has provided the correct taproot.

However, in the coin pool script mentioned above, I found that I
wanted to re-use the same taproot for the output (recursively). I
believe this would be a quite common use case. To solve this I
committed the taproot as part of the data itself: D' = hash(T+D),
which was then verified by OP_CICV. If you are aware of more efficient
alternatives, I am eager to hear them.

A simpler way IMO, would be to make OP_CICV and OP_COCV symmetrical:
Have OP_CICV take an optional taproot and do the same check as is done
for the output: Q == tweak(tweak(X,D), T).

2.To make fully functioning CoinPools, one would need functionality
similar to OP_MERKLESUB[4]: remove some data from the merkle tree, and
remove a key from the aggregated internal key.This suggestion may
surpass the intended scope of this proposal, and would likely
necessitate the availability of multiple EC operations to accommodate
various key schemes. If we had opcodes for adding and removing keys
from the internal key this would be even more powerful.

I look forward to hearing your thoughts on these suggestions and
further exploring the possibilities of the proposal!

Cheers,
Johan

[1] 
https://github.com/halseth/btcd/pull/1/commits/90a4065bdcd8029fe3325514a250490cba66fddd
[2] 
https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2020-June/017964.html
[3] https://github.com/halseth/tapsim/tree/matt-demo/examples/matt/coinpool
[4] https://github.com/ariard/bips/blob/coinpool-bips/bip-merklesub.mediawiki


On Fri, May 5, 2023 at 11:18 PM Salvatore Ingala
 wrote:
>
> On Thu, 4 May 2023 at 10:34, Johan Torås Halseth  wrote:
> >
> > It sounds like we can generalize the description of the construct to:
> > Access to (the hash of) embedded data of inputs and outputs, and the
> > enforcement of output keys and (static) taptrees. In other words, as
> > long as you can dynamically compute the output embedded data in
> > Script, you can enforce more or less anything (since you can make the
> > output script enforce presenting a witness "satisfying" the embedded
> > data).
> >
> > Does that sound about right?
>
> Yes. Fraud proofs allow us to extend beyond what Script can do (with the
> necessary tradeoffs), but there is plenty that can be done without them.
>
>
> > For instance, I believe you could simulate coin pools pretty easily:
> > Commit to the set of pubkeys and amounts owned by the participants in
> > the pool, and an output taptree where each participant has their own
> > spending path. Now, to exit the pool unilaterally, the participant
> > must present a proof that their pubkey+amount is committed to in the
> > input and an output where it is no longer committed.
>
> I don't think one would want to have a tapleaf for each participant:
> that would make you pay log n hashes just to reveal the tapleaf, and
> then you still need to pay log n hashes to access the embedded data.
>
> Instead, the "unilateral withdrawal Script" can be the same for all the
> participants. The witness would be the Merkle proof, plus perhaps some
> additional information to identify the leaf in the tree (depending on
> how the Merkle tree is implemented). In a complete Merkle tree for
> N = 2^n participants, the witness could contain the n hashes that allow
> to prove the value of the leaf, plus n bits to identify the path to the
> leaf (0/1 for 'left/right" child), since Script 

Re: [bitcoin-dev] Merkleize All The Things

2023-05-06 Thread Salvatore Ingala via bitcoin-dev
On Thu, 4 May 2023 at 10:34, Johan Torås Halseth  wrote:
>
> It sounds like we can generalize the description of the construct to:
> Access to (the hash of) embedded data of inputs and outputs, and the
> enforcement of output keys and (static) taptrees. In other words, as
> long as you can dynamically compute the output embedded data in
> Script, you can enforce more or less anything (since you can make the
> output script enforce presenting a witness "satisfying" the embedded
> data).
>
> Does that sound about right?

Yes. Fraud proofs allow us to extend beyond what Script can do (with the
necessary tradeoffs), but there is plenty that can be done without them.


> For instance, I believe you could simulate coin pools pretty easily:
> Commit to the set of pubkeys and amounts owned by the participants in
> the pool, and an output taptree where each participant has their own
> spending path. Now, to exit the pool unilaterally, the participant
> must present a proof that their pubkey+amount is committed to in the
> input and an output where it is no longer committed.

I don't think one would want to have a tapleaf for each participant:
that would make you pay log n hashes just to reveal the tapleaf, and
then you still need to pay log n hashes to access the embedded data.

Instead, the "unilateral withdrawal Script" can be the same for all the
participants. The witness would be the Merkle proof, plus perhaps some
additional information to identify the leaf in the tree (depending on
how the Merkle tree is implemented). In a complete Merkle tree for
N = 2^n participants, the witness could contain the n hashes that allow
to prove the value of the leaf, plus n bits to identify the path to the
leaf (0/1 for 'left/right" child), since Script doesn't have enough
opcodes to extract the bits from the leaf index.

The data in the leaf can contain a commitment to all the information
relevant for that participant (e.g.: their balance and pubkey, in a
CoinPool construction).

Then, the same witness can easily be reused to compute the new Merkle
root after the data in the leaf is modified (for example, setting the
amount to 0 for one participant).


> A question that arises is how one would efficiently (in Script) prove
> the inclusion/exclusion of the data in the commitment. One could
> naively hash all the data twice during script execution (once for the
> input, once for the output), but that is costly. It would be natural
> to show merkle tree inclusion/exclusion in script, but perhaps there
> are more efficient ways to prove it?

A Merkle tree as described above commits to an entire vector that you
can index positionally. That's quite versatile, and easier to handle
than more complex constructions like accumulators with exclusion proofs.

A Merkle proof for 2^7 = 128 participants requires about 8 hashes, so
around 250 bytes in total of witness size; 2^10 = 1024 should bring that
to the ballpark of 350 bytes.

Best,
Salvatore Ingala
___
bitcoin-dev mailing list
bitcoin-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev


Re: [bitcoin-dev] Merkleize All The Things

2023-05-04 Thread Johan Torås Halseth via bitcoin-dev
Thank you for the example.

It sounds like we can generalize the description of the construct to:
Access to (the hash of) embedded data of inputs and outputs, and the
enforcement of output keys and (static) taptrees. In other words, as
long as you can dynamically compute the output embedded data in
Script, you can enforce more or less anything (since you can make the
output script enforce presenting a witness "satisfying" the embedded
data).

Does that sound about right?

For instance, I believe you could simulate coin pools pretty easily:
Commit to the set of pubkeys and amounts owned by the participants in
the pool, and an output taptree where each participant has their own
spending path. Now, to exit the pool unilaterally, the participant
must present a proof that their pubkey+amount is committed to in the
input and an output where it is no longer committed.

A question that arises is how one would efficiently (in Script) prove
the inclusion/exclusion of the data in the commitment. One could
naively hash all the data twice during script execution (once for the
input, once for the output), but that is costly. It would be natural
to show merkle tree inclusion/exclusion in script, but perhaps there
are more efficient ways to prove it?

- Johan


On Tue, May 2, 2023 at 12:44 AM Salvatore Ingala via bitcoin-dev
 wrote:
>
> Hi all,
>
> I apologize for a couple of oversights in my last e-mail.
>
> The first is that m_B can't be committed as-is in the contract's
> embedded data, with the current semantics of OP_COCV, which
> only allows 32-byte values. A solution could be to store its
> hash SHA256(m_B), instead.
>
> (I didn't test the Scripts, so there could be other bugs − hopefully the
> general idea is clear, anyway)
>
> On Mon, 1 May 2023 at 15:11, Salvatore Ingala  
> wrote:
>>
>> If the internal_pubkey is a musig-aggregated key of Alice and Bob,
>> the game can be settled entirely offline after the first transaction.
>> Simply, Bob communicates his move to Alice, Alice reveals her move to
>> Bob, and they can settle the bet. The game would be played without
>> any script being executed, therefore all transactions could look like
>> any other P2TR, with the only possible fingerprinting being due to the
>> input amounts.
>
>
> This is incomplete: Alice can't trust Bob by revealing her move, as
> he could then cheat on-chain and play a different move.
>
> The fix should be straightforward, after adding the requirement that the
> internal pubkey of [S1] is a musig2 of both players.
> After Bob reveals his move (say, Rock), Alice will only agree to continue
> the game off-chain if Bob pre-signs transactions for the state [S1] (where
> m_B = Paper, and m_B = Scissors) that send all the money to Alice.
> This guarantees that a cheating Bob is punished.
>
> Best,
> Salvatore Ingala
>
> ___
> 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


Re: [bitcoin-dev] Merkleize All The Things

2023-05-01 Thread Salvatore Ingala via bitcoin-dev
Hi all,

I apologize for a couple of oversights in my last e-mail.

The first is that m_B can't be committed as-is in the contract's
embedded data, with the current semantics of OP_COCV, which
only allows 32-byte values. A solution could be to store its
hash SHA256(m_B), instead.

(I didn't test the Scripts, so there could be other bugs − hopefully the
general idea is clear, anyway)

On Mon, 1 May 2023 at 15:11, Salvatore Ingala 
wrote:

> If the internal_pubkey is a musig-aggregated key of Alice and Bob,
> the game can be settled entirely offline after the first transaction.
> Simply, Bob communicates his move to Alice, Alice reveals her move to
> Bob, and they can settle the bet. The game would be played without
> any script being executed, therefore all transactions could look like
> any other P2TR, with the only possible fingerprinting being due to the
> input amounts.
>

This is incomplete: Alice can't trust Bob by revealing her move, as
he could then cheat on-chain and play a different move.

The fix should be straightforward, after adding the requirement that the
internal pubkey of [S1] is a musig2 of both players.
After Bob reveals his move (say, Rock), Alice will only agree to continue
the game off-chain if Bob pre-signs transactions for the state [S1] (where
m_B = Paper, and m_B = Scissors) that send all the money to Alice.
This guarantees that a cheating Bob is punished.

Best,
Salvatore Ingala
___
bitcoin-dev mailing list
bitcoin-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev


Re: [bitcoin-dev] Merkleize All The Things

2023-05-01 Thread Salvatore Ingala via bitcoin-dev
Hi Johan,

Thanks for your message.

I think games where all the possible futures can be enumerated are
not ideal to showcase MATT, as one could just fully represent them
with just CTV or COCV, and not use the "data embedding" at all.

Perhaps rock-paper-scissors could be a better academic example. [1]

I'm not sure this will fully address your question; however I think
it's quite an instructive example, and I wanted to work it out for
quite some time.

It would be interesting to explore some contracts where the size
of the embedded data is substantially larger, and that could be
a natural next step to think about.


### Rock paper scissors

We want a protocol between Alice and Bob, where they bet 1 coin each:

1. Alice chooses and publishes her move;
2. Bob chooses his move, and the pot is adjudicated as per the rules.

Of course, if implemented naively, this wouldn't be a very fun game:
Bob would just wait to see Alice's move and play accordingly.

That's easy to fix, though:

1. Alice publishes a commitment to her move
2. Bob publishes his move in clear
3. Alice reveals her move, and the pot is adjudicated.

We can encode Rock = 0, Paper = 1, Scissors = 2. Let m_A, m_B be
Alice's and Bob's move, respectively. Then, it's easy to verify that:
− m_B - m_A == 0 (mod 3) ==> it's a tie
− m_B - m_A == 1 (mod 3) ==> Bob wins
− m_B - m_A == 2 (mod 3) ==> Alice wins

In order to create a hiding commitment for Alice, she can choose a
256-bit random number r_A, and compute:

  c_A = SHA256(m_A || r_A)

With that in mind, the full protocol can go like this:

1. Alice chooses her move m_A and a large random number r_A;
   she posts c_A computed as above;
2. Bob chooses m_B and publishes it;
3. Alice publishes m_A and r_A, then the winner is adjudicated.


### MATT playing RPS

To implement this with CICV/COCV, we can use just 3 transactions: in
fact, Alice can already compute c_A and share it with Bob before they
both commit their coins into an encumbered UTXO. That also means that
c_A can actually be hardcoded in the Scripts, rather than taking
space in the UTXO's embedded data.

Therefore, they both put one coin each, and they send to an output
whose script is the state S0 described below.

We assume that the keypath in the P2TR defined below is either a NUMS
point, or perhaps a Musig2 aggregate key that can be used to settle
the game collaboratively.

Note that there are 3 possible payout options that are fully known
when the game starts: either Alice takes all the money, or they split
evenly, or Bob takes all the money.
Similarly to the vault implementation [2], this seems to be another
case where CTV fits very well, as it allows to very efficiently
describe the three possible outcomes by their CTV hashes. Let them
be , , , respectively.

Therefore, this avoids the need for 64-bit maths, and explicit amount
introspection − at least for these contracts.


[State S0] (Start of the game, Alice moved; Bob's turn)
Spending conditions:
 - after , Alice takes the money// (Bob forfaits)
 - Bob posts m_B (0, 1 or 2); the next output is [S1] with data m_B

The first script is:
  // witness: []
  
  OP_CHECKSEQUENCEVERIFY
  OP_DROP
  
  OP_CHECKTEMPLATEVERIFY

The second is
  // witness: [ ]
  OP_DUP 0 3 OP_WITHIN // check that m_B is 0, 1 or 2

   OP_SWAP
  
  OP_CHECKOUTPUTCONTRACTVERIFY // check that the output is correct

  
  OP_CHECKSIG


[State S1] (Alice reveals m_A and adjudicates)
 - after , Bob takes the money// (Alice forfaits)
 - Alice posts correct m_A and r_A compatible with c_A;


The first script is symmetric to Bob's forfait script above.

The second condition can be split into three leaf scripts, one for
each possible value of m_B - m_A (mod 3):

  // witness: [  ]

  OP_OVER OP_DUP OP_TOALTSTACK  // save m_A
  0 3 OP_WITHIN OP_VERIFY   // check that m_A is 0, 1 or 2

  // check that SHA256(m_A || r_A) equals c_A
  OP_2DUP
  OP_CAT OP_SHA256
  
  OP_EQUALVERIFY

  OP_DUP
  , OP_SWAP
  OP_CHECKINPUTCONTRACTVERIFY

  OP_FROMALTSTACK
  OP_SUB   // stack now contains m_B - m_A

  OP_DUP   // if the result is negative, add 3
  0 OP_LESSTHAN
  OP_IF
3
OP_ADD
  OP_ENDIF

  {0, 1, 2}   // draw / Bob wins / Alice wins, respectively
  OP_EQUALVERIFY

  {, , }  // respectively
  OP_CHECKTEMPLATEVERIFY


### Comments

In general, we would have to worry about the possible
malleability of the witness elements, when they are not signatures
or preimages themselves. Here, in particular, it might seem that's
an issue when  is provided while spending the state [S0].
However, here the value of  is also committed to in the output
thanks to COCV; therefore, Bob's signature prevents malleability
also for m_B.

In general, it seems to be the case in MATT contracts that one would
want the signature of the authorized party performing a transition to
some other state of the smart contract with contains embedded data;
this makes the malleability issue less of a problem in practice than
I 

Re: [bitcoin-dev] Merkleize All The Things

2023-04-29 Thread Johan Torås Halseth via bitcoin-dev
Hi, Salvatore.

I find this proposal very interesting. Especially since you seemingly
can achieve such powerful capabilities by such simple opcodes.

I'm still trying to grok how this would look like on-chain (forget
about the off-chain part for now), if we were to play out such a
computation.

Let's say you have a simple game like "one player tic-tac-toe" with
only two tiles: [ _ | _ ]. The player wins if he can get two in a row
(pretty easy game tbh).

Could you give a complete example how you would encode one such state
transition (going from [ X, _ ] -> [ X, X ] for instance) in Bitcoin
script?

Feel free to choose a different game or program if you prefer :)

Thanks!
Johan



On Tue, Dec 13, 2022 at 2:08 PM Billy Tetrud via bitcoin-dev
 wrote:
>
> Re Verkle trees, that's a very interesting construction that would be super 
> useful as a tool for something like Utreexo. A potentially substantial 
> downside is that it seems the cryptography used to get those nice properties 
> of Verkle trees isn't quantum safe. While a lot of things in Bitcoin seems to 
> be going down the path of quantum-unsafe (I'm looking at you, taproot), there 
> are still a lot of people who think quantum safety is important in a lot of 
> contexts.
>
> On Thu, Dec 1, 2022 at 5:52 AM Salvatore Ingala via bitcoin-dev 
>  wrote:
>>
>> Hello Rijndael,
>>
>>
>>
>> On Wed, 30 Nov 2022 at 23:09, Rijndael  wrote:
>>>
>>> Hello Salvatore,
>>>
>>> I found my answer re-reading your original post:
>>> > During the arbitration phase (say at the i-th leaf node of M_T), any 
>>> > party can win the challenge by providing correct values for tr_i = (st_i, 
>>> > op_i, st_{i + 1}). Crucially, only one party is able to provide correct 
>>> > values, and Script can verify that indeed the state moves from st_i to 
>>> > st_{i + 1} by executing op_i. The challenge is over.
>>
>> You are correct, the computation step encoded in a leaf needs to be simple 
>> enough for Script to verify it.
>>
>> For the academic purpose of proving completeness (that is, any computation 
>> can be successfully "proved" by the availability of the corresponding fraud 
>> proof), one can imagine reducing the computation all the way down to a 
>> circuit, where each step (leaf) is as simple as what can be checked with 
>> {OP_NOT, OP_BOOLAND, OP_BOOLOR, OP_EQUAL}.
>>
>> In practice, you would want to utilize Script to its fullest, so for example 
>> you wouldn't compile a SHA256 computation to something else – you'd rather 
>> use OP_SHA256 directly.
>>
>>>
>>> That raises leads to a different question: Alice initially posts a 
>>> commitment to an execution trace of `f(x) = y`, `x`, and `y`. Bob Disagrees 
>>> with `y` so starts the challenge protocol. Is there a commitment to `f`? In 
>>> other words, the dispute protocol (as I read it) finds the leftmost step in 
>>> Alice and Bob's execution traces that differ, and then rewards the coins to 
>>> the participant who's "after-value" is computed by the step's operation 
>>> applied to the "before value". But if the participants each present valid 
>>> steps but with different operations, who wins? In other words, Alice could 
>>> present [64, DECREMENT, 63] and Bob could present [64, INCREMENT, 65]. 
>>> Those steps don't match, but both are valid. Is there something to ensure 
>>> that before the challenge protocol starts, that the execution trace that 
>>> Alice posts is for the right computation and not a different computation 
>>> that yields a favorable result for her (and for which she can generate a 
>>> valid merkle tree)?
>>
>>
>> The function f is already hard-coded in the contract itself, by means of the 
>> tree of scripts − that already commits to the possible futures. Therefore, 
>> once you are at state S14, you know that you are verifying the 6th step of 
>> the computation; and the operation in the 6th step of the computation 
>> depends solely on f, not its inputs. In fact, you made me realize that I 
>> could drop op_i from the i-th leaf commitment, and just embed the 
>> information in the Script of that corresponding state.
>>
>> Note that the states S0 to S14 of the 256x game are not _all_ the possible 
>> states, but only the ones that occurred in that execution of the contract 
>> (corresponding to a path from the root to the leaf of the Merkle tree of the 
>> computation trace), and therefore the ones that materialized in a UTXO. 
>> Different choices made by the parties (by providing different data, and 
>> therefore choosing different branches) would lead to a different leaf, and 
>> therefore to different (but in a certain sense "symmetric") states.
>>
>> 
>>
>> Since we are talking about the fact that f is committed to in the contract, 
>> I'll take the chance to extend on this a bit with a fun construction on top.
>> It is well-known in the academic literature of state channels that you can 
>> create contracts where even the function ("program", or "contract") is not 
>> decided 

Re: [bitcoin-dev] Merkleize All The Things

2022-12-13 Thread Billy Tetrud via bitcoin-dev
Re Verkle trees, that's a very interesting construction that would be super
useful as a tool for something like Utreexo. A potentially substantial
downside is that it seems the cryptography used to get those nice
properties of Verkle trees isn't quantum safe
. While a lot of things
in Bitcoin seems to be going down the path of quantum-unsafe (I'm looking
at you, taproot), there are still a lot of people who think quantum
safety is important in a lot of contexts.

On Thu, Dec 1, 2022 at 5:52 AM Salvatore Ingala via bitcoin-dev <
bitcoin-dev@lists.linuxfoundation.org> wrote:

> Hello Rijndael,
>
>
>
> On Wed, 30 Nov 2022 at 23:09, Rijndael  wrote:
>
>> Hello Salvatore,
>>
>> I found my answer re-reading your original post:
>> > During the arbitration phase (say at the i-th leaf node of M_T), any
>> party can win the challenge by providing correct values for tr_i = (st_i,
>> op_i, st_{i + 1}). Crucially, only one party is able to provide correct
>> values, and Script can verify that indeed the state moves from st_i to
>> st_{i + 1} by executing op_i. The challenge is over.
>>
> You are correct, the computation step encoded in a leaf needs to be simple
> enough for Script to verify it.
>
> For the academic purpose of proving completeness (that is, any computation
> can be successfully "proved" by the availability of the corresponding fraud
> proof), one can imagine reducing the computation all the way down to a
> circuit, where each step (leaf) is as simple as what can be checked with
> {OP_NOT, OP_BOOLAND, OP_BOOLOR, OP_EQUAL}.
>
> In practice, you would want to utilize Script to its fullest, so for
> example you wouldn't compile a SHA256 computation to something else – you'd
> rather use OP_SHA256 directly.
>
>
>> That raises leads to a different question: Alice initially posts a
>> commitment to an execution trace of `f(x) = y`, `x`, and `y`. Bob Disagrees
>> with `y` so starts the challenge protocol. Is there a commitment to `f`? In
>> other words, the dispute protocol (as I read it) finds the leftmost step in
>> Alice and Bob's execution traces that differ, and then rewards the coins to
>> the participant who's "after-value" is computed by the step's operation
>> applied to the "before value". But if the participants each present valid
>> steps but with different operations, who wins? In other words, Alice could
>> present [64, DECREMENT, 63] and Bob could present [64, INCREMENT, 65].
>> Those steps don't match, but both are valid. Is there something to ensure
>> that before the challenge protocol starts, that the execution trace that
>> Alice posts is for the right computation and not a different computation
>> that yields a favorable result for her (and for which she can generate a
>> valid merkle tree)?
>>
>
> The function f is already hard-coded in the contract itself, by means of
> the tree of scripts − that already commits to the possible futures.
> Therefore, once you are at state S14, you know that you are verifying the
> 6th step of the computation; and the operation in the 6th step of the
> computation depends solely on f, not its inputs. In fact, you made me
> realize that I could drop op_i from the i-th leaf commitment, and just
> embed the information in the Script of that corresponding state.
>
> Note that the states S0 to S14 of the 256x game are not _all_ the possible
> states, but only the ones that occurred in that execution of the contract
> (corresponding to a path from the root to the leaf of the Merkle tree of
> the computation trace), and therefore the ones that materialized in a UTXO.
> Different choices made by the parties (by providing different data, and
> therefore choosing different branches) would lead to a different leaf, and
> therefore to different (but in a certain sense "symmetric") states.
>
> 
>
> Since we are talking about the fact that f is committed to in the
> contract, I'll take the chance to extend on this a bit with a fun
> construction on top.
> It is well-known in the academic literature of state channels that you can
> create contracts where even the function ("program", or "contract") is not
> decided when the channel is created.
>
> Since f is generic, we can choose f itself to be a universal Turing
> machine. That is, we can imagine a function f(code, data) that executes a
> program ("code") on the "data" given to it as input.
> Since we can do fraud proofs on statements "f(code, data) == output", we
> could build contracts where the "code" itself is chosen later.
>
> For example, one could build a universal state channel, where parties can
> enter any contract among themselves (e.g.: start playing a chess game)
> entirely inside the channel. The state of this universal channel would
> contain all the states of the individual contracts that are currently open
> in the channel, and even starting/closing contracts can happen entirely
> off-chain.
>
> I believe these constructions are practical (the 

Re: [bitcoin-dev] Merkleize All The Things

2022-12-01 Thread Salvatore Ingala via bitcoin-dev
Hello Rijndael,



On Wed, 30 Nov 2022 at 23:09, Rijndael  wrote:

> Hello Salvatore,
>
> I found my answer re-reading your original post:
> > During the arbitration phase (say at the i-th leaf node of M_T), any
> party can win the challenge by providing correct values for tr_i = (st_i,
> op_i, st_{i + 1}). Crucially, only one party is able to provide correct
> values, and Script can verify that indeed the state moves from st_i to
> st_{i + 1} by executing op_i. The challenge is over.
>
You are correct, the computation step encoded in a leaf needs to be simple
enough for Script to verify it.

For the academic purpose of proving completeness (that is, any computation
can be successfully "proved" by the availability of the corresponding fraud
proof), one can imagine reducing the computation all the way down to a
circuit, where each step (leaf) is as simple as what can be checked with
{OP_NOT, OP_BOOLAND, OP_BOOLOR, OP_EQUAL}.

In practice, you would want to utilize Script to its fullest, so for
example you wouldn't compile a SHA256 computation to something else – you'd
rather use OP_SHA256 directly.


> That raises leads to a different question: Alice initially posts a
> commitment to an execution trace of `f(x) = y`, `x`, and `y`. Bob Disagrees
> with `y` so starts the challenge protocol. Is there a commitment to `f`? In
> other words, the dispute protocol (as I read it) finds the leftmost step in
> Alice and Bob's execution traces that differ, and then rewards the coins to
> the participant who's "after-value" is computed by the step's operation
> applied to the "before value". But if the participants each present valid
> steps but with different operations, who wins? In other words, Alice could
> present [64, DECREMENT, 63] and Bob could present [64, INCREMENT, 65].
> Those steps don't match, but both are valid. Is there something to ensure
> that before the challenge protocol starts, that the execution trace that
> Alice posts is for the right computation and not a different computation
> that yields a favorable result for her (and for which she can generate a
> valid merkle tree)?
>

The function f is already hard-coded in the contract itself, by means of
the tree of scripts − that already commits to the possible futures.
Therefore, once you are at state S14, you know that you are verifying the
6th step of the computation; and the operation in the 6th step of the
computation depends solely on f, not its inputs. In fact, you made me
realize that I could drop op_i from the i-th leaf commitment, and just
embed the information in the Script of that corresponding state.

Note that the states S0 to S14 of the 256x game are not _all_ the possible
states, but only the ones that occurred in that execution of the contract
(corresponding to a path from the root to the leaf of the Merkle tree of
the computation trace), and therefore the ones that materialized in a UTXO.
Different choices made by the parties (by providing different data, and
therefore choosing different branches) would lead to a different leaf, and
therefore to different (but in a certain sense "symmetric") states.



Since we are talking about the fact that f is committed to in the contract,
I'll take the chance to extend on this a bit with a fun construction on top.
It is well-known in the academic literature of state channels that you can
create contracts where even the function ("program", or "contract") is not
decided when the channel is created.

Since f is generic, we can choose f itself to be a universal Turing
machine. That is, we can imagine a function f(code, data) that executes a
program ("code") on the "data" given to it as input.
Since we can do fraud proofs on statements "f(code, data) == output", we
could build contracts where the "code" itself is chosen later.

For example, one could build a universal state channel, where parties can
enter any contract among themselves (e.g.: start playing a chess game)
entirely inside the channel. The state of this universal channel would
contain all the states of the individual contracts that are currently open
in the channel, and even starting/closing contracts can happen entirely
off-chain.

I believe these constructions are practical (the code of universal Turing
machines is not really complicated), so it might be worth exploring further
to figure out useful applications of this approach (supercharging
lightning?).

We should probably start by implementing testnet rock-paper-scissors in
MATT, though :)

Best,
Salvatore Ingala
___
bitcoin-dev mailing list
bitcoin-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev


Re: [bitcoin-dev] Merkleize All The Things

2022-11-30 Thread Rijndael via bitcoin-dev
Hello Salvatore,

I found my answer re-reading your original post:
> During the arbitration phase (say at the i-th leaf node of M_T), any party 
> can win the challenge by providing correct values for tr_i = (st_i, op_i, 
> st_{i + 1}). Crucially, only one party is able to provide correct values, and 
> Script can verify that indeed the state moves from st_i to st_{i + 1} by 
> executing op_i. The challenge is over.

That raises leads to a different question: Alice initially posts a commitment 
to an execution trace of `f(x) = y`, `x`, and `y`. Bob Disagrees with `y` so 
starts the challenge protocol. Is there a commitment to `f`? In other words, 
the dispute protocol (as I read it) finds the leftmost step in Alice and Bob's 
execution traces that differ, and then rewards the coins to the participant 
who's "after-value" is computed by the step's operation applied to the "before 
value". But if the participants each present valid steps but with different 
operations, who wins? In other words, Alice could present [64, DECREMENT, 63] 
and Bob could present [64, INCREMENT, 65]. Those steps don't match, but both 
are valid. Is there something to ensure that before the challenge protocol 
starts, that the execution trace that Alice posts is for the right computation 
and not a different computation that yields a favorable result for her (and for 
which she can generate a valid merkle tree)?

Thanks!

-rijndael

On 11/30/22 2:42 PM, Rijndael via bitcoin-dev wrote:

> Hello Salvatore,
>
> Really interesting idea. The walk-through of the challenge protocol helped.
>
> In the final state:
>
> [S14. state: h_{A;6}, h_{B;6}]
> - Alice can take all the money if she can open h_{A;6} to a correct "n => n + 
> n" computation step
> - Bob can take all the money if he can open h_{B;6} to a correct "n => n + n" 
> computation step
>
> My understanding of your scheme for encoding execution traces is that each 
> leaf is (previous-state, operation, post-state) So in this case when we get 
> to the conflicting step of the execution traces, alice might reveal something 
> like (x=64, x+x, x=127) and bob might reveal something like (x=64, x+x, 
> x=128). So in order for the covenant to enforce which state-transition is 
> valid (who can spend the money), that means that `x+x` needs to be evaluated 
> in script to tell who has posted the incorrect state. Am I understanding this 
> final step of the bisection protocol correctly?
>
> -rijndael
>
> On 11/12/22 10:04 AM, Salvatore Ingala via bitcoin-dev wrote:
>
>> Hi Antoine,
>> It appears that my explanation of the relationship between the covenant and 
>> the bisection protocol is still unclear; I'll do my best to clarify.
>>
>> The bisection's Merkle tree never ends up on-chain, in any form. Therefore, 
>> a bigger computation does not end up in a bigger witness size, which is key 
>> to the scalability of the approach. Only in the case of a challenge, it will 
>> result in a (logarithmically) longer chain of transactions to resolve it. 
>> This chain of transactions could be mapped to a root-to-leaf path in the 
>> Merkle tree of the computation trace.
>>
>> The actual computation trace (and the corresponding Merkle tree) is only 
>> computed by the parties when they execute the computation.
>> What's in the tapleaves is only the valid transitions at the current state 
>> of the protocol; that is, the valid transitions in the Finite State Machine 
>> (and possibly other valid exit conditions that remove the covenant 
>> encumbrance, if any).
>>
>> The bisection protocol only makes sense as a step in a larger protocol that 
>> makes use of it.
>>
>> Perhaps presenting the protocol in a less-than-general case might help to 
>> understand it. So let's play a simpler game using a protocol that includes a 
>> fraud proof.
>>
>> Alice claims that she knows how to multiply by 256, while Bob doesn't 
>> believe her. So they make a bet: they each commit 1 coin; then Bob choses a 
>> number x; then Alice computes y = 256*x by doubling x eight times (expensive 
>> multiplications were disabled in a tragic DDoS accident), and publishes the 
>> result y. Bob independently computes 256 * x (he has a friend who is a 
>> mathematician, he'll know how to do it). If the result is not y, Bob will 
>> start a challenge; otherwise, Alice wins and takes the money.
>>
>> (The example is of course artificial, as redoing the computation in Script 
>> is cheaper than executing the fraud proof in this case!)
>>
>> What follows is an actual execution of the protocol. In the following, each 
>> [Si] is a UTXO corresponding to some possible FSM node, starting with the 
>> S0, the UTXO with 1+1 = 2 coins. Each line with "-" is a possible transition 
>> (script in the taptree), specifying what is the next FSM node after the 
>> "==>" symbol; the encumbrance in the scripts enforce that the state of the 
>> next UTXO is updated correctly (details omitted below), and any other 
>> necessary conditions to ensure 

Re: [bitcoin-dev] Merkleize All The Things

2022-11-30 Thread Rijndael via bitcoin-dev
Hello Salvatore,

Really interesting idea. The walk-through of the challenge protocol helped.

In the final state:

[S14. state: h_{A;6}, h_{B;6}]
- Alice can take all the money if she can open h_{A;6} to a correct "n => n + 
n" computation step
- Bob can take all the money if he can open h_{B;6} to a correct "n => n + n" 
computation step

My understanding of your scheme for encoding execution traces is that each leaf 
is (previous-state, operation, post-state) So in this case when we get to the 
conflicting step of the execution traces, alice might reveal something like 
(x=64, x+x, x=127) and bob might reveal something like (x=64, x+x, x=128). So 
in order for the covenant to enforce which state-transition is valid (who can 
spend the money), that means that `x+x` needs to be evaluated in script to tell 
who has posted the incorrect state. Am I understanding this final step of the 
bisection protocol correctly?

-rijndael

On 11/12/22 10:04 AM, Salvatore Ingala via bitcoin-dev wrote:

> Hi Antoine,
> It appears that my explanation of the relationship between the covenant and 
> the bisection protocol is still unclear; I'll do my best to clarify.
>
> The bisection's Merkle tree never ends up on-chain, in any form. Therefore, a 
> bigger computation does not end up in a bigger witness size, which is key to 
> the scalability of the approach. Only in the case of a challenge, it will 
> result in a (logarithmically) longer chain of transactions to resolve it. 
> This chain of transactions could be mapped to a root-to-leaf path in the 
> Merkle tree of the computation trace.
>
> The actual computation trace (and the corresponding Merkle tree) is only 
> computed by the parties when they execute the computation.
> What's in the tapleaves is only the valid transitions at the current state of 
> the protocol; that is, the valid transitions in the Finite State Machine (and 
> possibly other valid exit conditions that remove the covenant encumbrance, if 
> any).
>
> The bisection protocol only makes sense as a step in a larger protocol that 
> makes use of it.
>
> Perhaps presenting the protocol in a less-than-general case might help to 
> understand it. So let's play a simpler game using a protocol that includes a 
> fraud proof.
>
> Alice claims that she knows how to multiply by 256, while Bob doesn't believe 
> her. So they make a bet: they each commit 1 coin; then Bob choses a number x; 
> then Alice computes y = 256*x by doubling x eight times (expensive 
> multiplications were disabled in a tragic DDoS accident), and publishes the 
> result y. Bob independently computes 256 * x (he has a friend who is a 
> mathematician, he'll know how to do it). If the result is not y, Bob will 
> start a challenge; otherwise, Alice wins and takes the money.
>
> (The example is of course artificial, as redoing the computation in Script is 
> cheaper than executing the fraud proof in this case!)
>
> What follows is an actual execution of the protocol. In the following, each 
> [Si] is a UTXO corresponding to some possible FSM node, starting with the S0, 
> the UTXO with 1+1 = 2 coins. Each line with "-" is a possible transition 
> (script in the taptree), specifying what is the next FSM node after the "==>" 
> symbol; the encumbrance in the scripts enforce that the state of the next 
> UTXO is updated correctly (details omitted below), and any other necessary 
> conditions to ensure the integrity of the protocol.
>
> =
>
> [S0]: Initial UTXO
> - only Bob can spend, he must choose his number x ==> S1
>
> [S1; state: x]:
> - only Alice can spend, she publishes her answer y ==> S2
>
> [S2. state: x, y]:
> - after 1 day: Alice won, she can take the money // Happy case! Usually 
> that's the end
> - Bob disagrees with the answer, post z as his answer. ==> S3
>
> The challenge starts here! Let's put some actual numbers. x = 2; y = 508; z = 
> 512.
>
> This is what Alice computed:
>
> 2 => 4 => 8 => 16 => 32 => 64 => 127 => 254 => 508
>
> This is what Bob computed:
>
> 2 => 4 => 8 => 16 => 32 => 64 => 128 => 256 => 512
>
> At this time, we don't know who is right. They both built a tree that looks 
> like this (ASCII art only working in fixed-width font):
>
> ___H18___
> / \
> / \
> H14 H58
> / \ / \
> / \ / \
> / \ / \
> H12 H34 H56 H78
> / \ / \ / \ / \
> H1 H2 H3 H4 H5 H6 H7 H8
>
> Remember that each internal node commits to: the state of the computation 
> before the leftmost leaf in the subtree, the state after the rightmost leaf, 
> and the hash of sub-trace for the sub-tree. Each leaf just commits to that 
> intermediate computation step (and the operation, which here is always 
> "double the input"). For example, H4 commits to "16 => 32" according to both 
> Alice's and Bob's computation traces.
>
> (From our privileged point of view, we can foresee that the earliest 
> disagreement is on the 6th step of the computation: "64 => 127" according to 
> Alice, "64 => 128" according to Bob).
>
> Let's denote h_{A;18} (resp. 

Re: [bitcoin-dev] Merkleize All The Things

2022-11-12 Thread Salvatore Ingala via bitcoin-dev
Hi Antoine,
It appears that my explanation of the relationship between the covenant and
the bisection protocol is still unclear; I'll do my best to clarify.

The bisection's Merkle tree never ends up on-chain, in any form. Therefore,
a bigger computation does not end up in a bigger witness size, which is key
to the scalability of the approach. Only in the case of a challenge, it
will result in a (logarithmically) longer chain of transactions to resolve
it. This chain of transactions could be mapped to a root-to-leaf path in
the Merkle tree of the computation trace.

The actual computation trace (and the corresponding Merkle tree) is only
computed by the parties when they execute the computation.
What's in the tapleaves is only the valid transitions at the current state
of the protocol; that is, the valid transitions in the Finite State Machine
(and possibly other valid exit conditions that remove the covenant
encumbrance, if any).

The bisection protocol only makes sense as a step in a larger protocol that
makes use of it.

Perhaps presenting the protocol in a less-than-general case might help to
understand it. So let's play a simpler game using a protocol that includes
a fraud proof.

Alice claims that she knows how to multiply by 256, while Bob doesn't
believe her. So they make a bet: they each commit 1 coin; then Bob choses a
number x; then Alice computes y = 256*x by doubling x eight times
(expensive multiplications were disabled in a tragic DDoS accident), and
publishes the result y. Bob independently computes 256 * x (he has a friend
who is a mathematician, he'll know how to do it). If the result is not y,
Bob will start a challenge; otherwise, Alice wins and takes the money.

(The example is of course artificial, as redoing the computation in Script
is cheaper than executing the fraud proof in this case!)

What follows is an actual execution of the protocol. In the following, each
[Si] is a UTXO corresponding to some possible FSM node, starting with the
S0, the UTXO with 1+1 = 2 coins. Each line with "-" is a possible
transition (script in the taptree), specifying what is the next FSM node
after the "==>" symbol; the encumbrance in the scripts enforce that the
state of the next UTXO is updated correctly (details omitted below), and
any other necessary conditions to ensure the integrity of the protocol.


=


[S0]: Initial UTXO
  - only Bob can spend, he must choose his number x ==> S1

[S1; state: x]:
  - only Alice can spend, she publishes her answer y ==> S2

[S2. state: x, y]:
  - after 1 day: Alice won, she can take the money // Happy case!
Usually that's the end
  - Bob disagrees with the answer, post z as his answer. ==> S3

The challenge starts here! Let's put some actual numbers. x = 2; y = 508; z
= 512.

This is what Alice computed:

  2 => 4 => 8 => 16 => 32 => 64 => 127 => 254 => 508

This is what Bob computed:

  2 => 4 => 8 => 16 => 32 => 64 => 128 => 256 => 512

At this time, we don't know who is right. They both built a tree that looks
like this (ASCII art only working in fixed-width font):

 ___H18___
/ \
   /   \
H14 H58
/ \ / \
   /   \   /   \
  / \ / \
H12 H34 H56 H78
/ \ / \ / \ / \
  H1  H2  H3  H4  H5  H6  H7  H8

Remember that each internal node commits to: the state of the computation
before the leftmost leaf in the subtree, the state after the rightmost
leaf, and the hash of sub-trace for the sub-tree. Each leaf just commits to
that intermediate computation step (and the operation, which here is always
"double the input"). For example, H4 commits to "16 => 32" according to
both Alice's and Bob's computation traces.

(From our privileged point of view, we can foresee that the earliest
disagreement is on the 6th step of the computation: "64 => 127" according
to Alice, "64 => 128" according to Bob).

Let's denote h_{A;18} (resp. h_{B;18}) all the information committed to in
the node H18, according to Alice (resp. Bob). Similarly for all the other
nodes.

[S3. state: x, y, z]: Challenge starts!
  - Alice posts the root of her computation trace h_{A;18} ==> S4

[S4. state: x, y, z, h_{A;18}]
  - Bob posts the root of her computation trace h_{B;18} ==> S5

Since they disagree, it must be the case that h_{A;18} != h_{B;18}.

[S5. state: x, y, z, h_{A;18}, h_{B;18}]
  - Alice opens the commitment h_{A;18}, by revealing H14 and H58
(according to her) ==> S6

Note that in this last transition (going to S6), the covenant enforces that
the child commitments are compatible: the transition is only valid if the
starting state of the computation according to h_{A;14} is compatible with
h_{A;18} (that is, it's equal to x); similarly the end state of the
computation in h_{A;58} must be y, and h_{A;18} can be recomputed from the
data provided (ensuring the integrity of the Merkle tree).
This is true for all the commitment openings 

Re: [bitcoin-dev] Merkleize All The Things

2022-11-11 Thread Antoine Riard via bitcoin-dev
Hi Salvatore,

Thanks for bringing forward this MATT proposal!

Here my (rough) understanding of the protocol, the participants decompose
the entire computation into a number N of steps, each assigned a tapleaf,
each computation is a triplet (state_start, operation, state_end), the
tapleaves are built into a Merkle tree, the current state of the FSM is
also encoded in the Taproot output. The Merkle tree is committed in some
Script branch where a timelock is present to guarantee challenge (e.g "f(x)
= ?" OP_CHALLENGE + 100 OP_CSV). A funding transaction is broadcast to lock
the funds, participants can leverage this funding output to play out
off-chain the computation steps. To advance the resolution, a participant
spends the funding output with a witness embedding all the computation
trace encoded as Merkle branch and prove some statement "f(x) = y". Until
the CSV expires, another participant can contest by presenting another
witness with another computation trace. What is unclear to me is how the
contract's state issued off-chain can alter the pre-committed state
transitions. I think what could gain in clarity is the translation of the
bisection protocol steps in more complete new opcodes.

Another high-level remark, even if we assume any arbitrary computation can
be encoded in a Merkle Tree, as the computation grows in complexity, the
corresponding trace also increases in (witness) space. There might be some
economic bounds on the generalized smart contracts you can engage in, as
the worst-case scenario might be beyond your fee-bumping reserves. Less
flexible, but more templated opcodes for the same use-cases might make it
more affordable. At the same time, the ability to encode any cryptosystem
as the function f sounds really interesting.

Best,
Antoine

Le mar. 8 nov. 2022 à 05:13, Salvatore Ingala via bitcoin-dev <
bitcoin-dev@lists.linuxfoundation.org> a écrit :

> Hi list,
>
> I have been working on some notes to describe an approach that uses
> covenants in order to enable general smart contracts in bitcoin. You can
> find them here:
>
> https://merkle.fun
>
> The approach has a number of desirable features:
>
> - small impact to layer 1;
> - not application-specific, very general;
> - it fits well into P2TR;
> - it does not require new cryptographic assumptions, nor any construction
> that has not withstood the test of time.
>
> This content was presented at the BTCAzores unconference, where it
> received the name of MATT − short for Merkleize All The Things.
> In fact, no other cryptographic primitive is required, other than Merkle
> trees.
>
> I believe this construction gets close to answering the question of how
> small a change on bitcoin's layer 1 would suffice to enable arbitrary smart
> contracts.
>
> It is not yet at the stage where a formal proposal can be made, therefore
> the proposed specs are only for illustrative purposes.
>
> The same content is reformatted below for the mailing list.
>
> Looking forward to hearing about your comments and improvements.
> Salvatore Ingala
>
>
> ==
>
>
> # General smart contracts in bitcoin via covenants
>
> Covenants are UTXOs that are encumbered with restrictions on the outputs
> of the transaction spending the UTXO. More formally, we can define a
> covenant any UTXO such that at least one of its spending conditions is
> valid only if one or more of the outputs’ scriptPubKey satisfies certain
> restrictions.
>
> Generally, covenant proposals also add some form of introspection (that
> is, the ability for Script to access parts of the inputs/outputs, or the
> blockchain history).
>
> In this note, we want to explore the possibilities unleashed by the
> addition of a covenant with the following properties:
>
> - introspection limited to a single hash attached to the UTXO (the
> “covenant data”), and input/output amounts;
> - pre-commitment to every possible future script (but not their data);
> - few simple opcodes operating with the covenant data.
>
> We argue that such a simple covenant construction is enough to extend the
> power of bitcoin’s layer 1 to become a universal settlement layer for
> arbitrary computation.
>
> Moreover, the covenant can elegantly fit within P2TR transactions, without
> any substantial increase for the workload of bitcoin nodes.
>
> A preliminary version of these notes was presented and discussed at the
> BTCAzores Unconference [1], on 23rd September 2022.
>
>
> # Preliminaries
>
> We can think of a smart contract as a “program” that updates a certain
> state according to predetermined rules (which typically include access
> control by authorizing only certain public keys to perform certain
> actions), and that can possibly lock/unlock some coins of the underlying
> blockchain according to the same rules.
>
> The exact definition will be highly dependent on the properties of the
> underlying blockchain.
>
> In bitcoin, the only state upon which all the nodes reach consensus is 

Re: [bitcoin-dev] Merkleize All The Things

2022-11-10 Thread Salvatore Ingala via bitcoin-dev
Hi ZmnSCPxj, Bram, Peter, David,

Thanks for all your comments; replies below.

On Tue, 8 Nov 2022 at 13:01, ZmnSCPxj  wrote:

> Modulo bugs, operator error, misconfigurations, and other irrationalities
> of humans.
>

I agree that making footguns impossible is a much more difficult problem to
solve!

Rather than get taptree from the stack, just use the same taptree as in the
> revelation of the P2TR.
> This removes the need to include quining and similar techniques: just do
> the quining in the SCRIPT interpreter.
>

That's a possibility; I suspect it would be less efficient for many
contracts (in particular, when the total number of states in the FSM is
relatively large, but each of them has only few valid transitions). We
could always allow both variants.

Another reason I preferred to present it in this way is to show that it is
possible to limit the design to covenants where recursion is not allowed /
limited; I don't personally think recursion is bad at this time − but the
covenants (and the protocol for fraud challenges) do not require it in
order to be useful.

Anyway, I suggested some opcodes only as a sketch. I'm not knowledgeable
enough to suggest the best design, and maybe it will be easier to compare
several variants once we implement something on top.


On Wed, 9 Nov 2022 at 00:34, Bram Cohen  wrote:

> Hash chained covenants in general all have about the same plateau of
> functionality, which seems roughly reasonable to add to Bitcoin as it is
> today but suffer from being limited and hence likely only a stepping stone
> to greater functionality and unless whatever's put in now cleanly extends
> to supporting more in the future it's likely to turn into a legacy
> appendage which has to be supported. So my generic suggestion for this sort
> of thing is that it should be proposed along with a plan for how it could
> be extended to support full-blown covenants in the future.
>

I actually struggle to find constructions that are _not_ possible using
such covenants; do you have any concrete example?
That would be very interesting in order to correctly classify the
expressive power of UTXO+Script+covenants when compared to the
"Turing-complete"+stateful models.

Another probably unhelpful bit of feedback I have is that Bitcoin should
> probably be taking verkle trees seriously because those can have
> substantially lower size/cost/weight than merkle trees. That doesn't just
> apply to this proposal, but to Bitcoin in general, which doesn't seem to
> have any serious verkle tree proposals to date.
>

I am not an expert in Verkle trees, but I think the efficiency gain (if
any) is not that interesting for many of the applications I'm suggesting,
as most Merkle trees would be quite small.
Therefore, I agree with Peter that the additional complexity might not be
worth it at this time; if applications requiring large Merkle trees arise
in practice, Verkle trees could always be added in the future as an
optimization.

Moreover, Verkle trees, or even any risky/fancy cryptography, could be used
in layer-2 solutions enabled by the covenant, without impacting any funds
not locked in the covenant in case of disasters.


On Wed, 9 Nov 2022 at 13:07, Peter Todd  wrote:

> Particularly since even having merkle trees in Bitcoin
> is arguably a mistake: they allow for degenerate, weak, security modes
> like SPV
> that aren't clearly good for Bitcoin as a whole.
>

I disagree, as the title of this thread suggests! :)
Thanks to Merkle trees, we'll be able to keep layer 1 extremely light, so
everyone can run a full node − while all the complexity of fancy
constructions is pushed to the application layer.


On Thu, 10 Nov 2022 at 08:39, David A. Harding  wrote:

> > 1. Alice posts the statement “f(x) = y”.
> > 2. After a challenge period, if no challenge occurs, Alice is free to
> > continue and unlock the funds; the statement is true.
> > 3. At any time before the challenge period expires, Bob can start a
> > challenge: “actually, f(x) = z”.
>
> That looks to me very similar to Gregory Maxwell's script from[1]
>

Zero-Knowledge contingent payments do indeed solve the problem more
elegantly in the specific case where swapping Alice's knowledge for x with
a payment from Bob is the entire smart contract.

The covenant adds the ability to carry over some sort of state. For
example, imagine Alice and Bob want to play a game of chess, and the winner
takes all the money [*]. The "state" in the covenant would be the entire
chessboard, and a valid transition is a valid chess move. The covenant
enforces that the game proceeds according to the rules, by only allowing
correct updates to the "state".
Moreover, the parties participating to a covenant don't necessarily need to
be decided in advance, which is crucial for constructions like coinpool [1].

Note that no this does not require any fraud proof, as the rules of chess
are simple enough that each "transition" is a simple enough function. In
fact, many contracts might not 

Re: [bitcoin-dev] Merkleize All The Things

2022-11-09 Thread David A. Harding via bitcoin-dev

On 2022-11-07 23:17, Salvatore Ingala via bitcoin-dev wrote:

Hi list,


Hi Salvatore!,


I have been working on some notes to describe an approach that uses
covenants in order to enable general smart contracts in bitcoin. You
can find them here:

https://merkle.fun


I haven't yet been able to understand everything in your post, but I'm 
wondering if you can describe how your proposal significantly differs in 
application from [1]?  E.g., you write:



1. Alice posts the statement “f(x) = y”.
2. After a challenge period, if no challenge occurs, Alice is free to 
continue and unlock the funds; the statement is true.
3. At any time before the challenge period expires, Bob can start a 
challenge: “actually, f(x) = z”.


That looks to me very similar to Gregory Maxwell's script from[1] 
(comments and variable name changes mine):


# Offchain, Alice posts the statement f(x) = y
# Offchain, Bob provides Ex, an encrypted form of x that can be proven 
in zero knowledge to satisfy both f(x) = y and sha256(x) = Y

OP_SHA256
 OP_EQUAL
OP_IF
  # Bob provided the preimage for Y, that preimage being the solution, 
so he can spend the funds now

  
OP_ELSE
  # The challenge period ended, so Alice can reclaim her funds
   OP_CHECKLOCKTIMEVERIFY OP_DROP
  
OP_ENDIF
OP_CHECKSIG

Thanks and apologies if I'm missing something obvious!,

-Dave

[1] 
https://bitcoincore.org/en/2016/02/26/zero-knowledge-contingent-payments-announcement/

___
bitcoin-dev mailing list
bitcoin-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev


Re: [bitcoin-dev] Merkleize All The Things

2022-11-09 Thread Peter Todd via bitcoin-dev
On Tue, Nov 08, 2022 at 03:34:32PM -0800, Bram Cohen via bitcoin-dev wrote:
> Another probably unhelpful bit of feedback I have is that Bitcoin should
> probably be taking verkle trees seriously because those can have
> substantially lower size/cost/weight than merkle trees. That doesn't just
> apply to this proposal, but to Bitcoin in general, which doesn't seem to
> have any serious verkle tree proposals to date.

Verkle trees only reduce proof sizes by a factor of 6-8, and they introduce
significant implementation complexity and new cryptographic assumptions. Better
to let other crypto-systems get a few more years of experience with them before
adding them to Bitcoin. Particularly since even having merkle trees in Bitcoin
is arguably a mistake: they allow for degenerate, weak, security modes like SPV
that aren't clearly good for Bitcoin as a whole.

-- 
https://petertodd.org 'peter'[:-1]@petertodd.org


signature.asc
Description: PGP signature
___
bitcoin-dev mailing list
bitcoin-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev


Re: [bitcoin-dev] Merkleize All The Things

2022-11-08 Thread Bram Cohen via bitcoin-dev
On Tue, Nov 8, 2022 at 2:13 AM Salvatore Ingala via bitcoin-dev <
bitcoin-dev@lists.linuxfoundation.org> wrote:

>
> I have been working on some notes to describe an approach that uses
> covenants in order to enable general smart contracts in bitcoin. You can
> find them here:
>
> https://merkle.fun/
> 
>

Hash chained covenants in general all have about the same plateau of
functionality, which seems roughly reasonable to add to Bitcoin as it is
today but suffer from being limited and hence likely only a stepping stone
to greater functionality and unless whatever's put in now cleanly extends
to supporting more in the future it's likely to turn into a legacy
appendage which has to be supported. So my generic suggestion for this sort
of thing is that it should be proposed along with a plan for how it could
be extended to support full-blown covenants in the future.

Another probably unhelpful bit of feedback I have is that Bitcoin should
probably be taking verkle trees seriously because those can have
substantially lower size/cost/weight than merkle trees. That doesn't just
apply to this proposal, but to Bitcoin in general, which doesn't seem to
have any serious verkle tree proposals to date.
___
bitcoin-dev mailing list
bitcoin-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev


Re: [bitcoin-dev] Merkleize All The Things

2022-11-08 Thread ZmnSCPxj via bitcoin-dev
Good morning Salvatore,

Interesting idea.

The idea to embed the current state is similar to something I have been musing 
about recently.


> ### Game theory (or why the chain will not see any of this)
> 
> With the right economic incentives, protocol designers can guarantee that 
> playing a losing game always loses money compared to cooperating. Therefore, 
> the challenge game is never expected to be played on-chain. The size of the 
> bonds need to be appropriate to disincentivize griefing attacks.

Modulo bugs, operator error, misconfigurations, and other irrationalities of 
humans.



> - OP_CHECKOUTPUTCOVENANTVERIFY: given a number out_i and three 32-byte hash 
> elements x, d and taptree on top of the stack, verifies that the out_i-th 
> output is a P2TR output with internal key computed as above, and tweaked with 
> taptree. This is the actual covenant opcode.

Rather than get taptree from the stack, just use the same taptree as in the 
revelation of the P2TR.
This removes the need to include quining and similar techniques: just do the 
quining in the SCRIPT interpreter.

The entire SCRIPT that controls the covenant can be defined as a taptree with 
various possible branches as tapleaves.
If the contract is intended to terminate at some point it can have one of the 
tapleaves use `OP_CHECKINPUTCOVENANTVERIFY` and then determine what the output 
"should" be using e.g. `OP_CHECKTEMPLATEVERIFY`.


> - Is it worth adding other introspection opcodes, for example 
> OP_INSPECTVERSION, OP_INSPECTLOCKTIME? See Liquid's Tapscript Opcodes [6].

`OP_CHECKTEMPLATEVERIFY` and some kind of sha256 concatenated hashing should be 
sufficient I think.

> - Is there any malleability issue? Can covenants “run” without signatures, or 
> is a signature always to be expected when using spending conditions with the 
> covenant encumbrance? That might be useful in contracts where no signature is 
> required to proceed with the protocol (for example, any party could feed 
> valid data to the bisection protocol above).

Hmm protocol designer beware?

Regards,
ZmnSCPxj
___
bitcoin-dev mailing list
bitcoin-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev


[bitcoin-dev] Merkleize All The Things

2022-11-08 Thread Salvatore Ingala via bitcoin-dev
Hi list,

I have been working on some notes to describe an approach that uses
covenants in order to enable general smart contracts in bitcoin. You can
find them here:

https://merkle.fun

The approach has a number of desirable features:

- small impact to layer 1;
- not application-specific, very general;
- it fits well into P2TR;
- it does not require new cryptographic assumptions, nor any construction
that has not withstood the test of time.

This content was presented at the BTCAzores unconference, where it received
the name of MATT − short for Merkleize All The Things.
In fact, no other cryptographic primitive is required, other than Merkle
trees.

I believe this construction gets close to answering the question of how
small a change on bitcoin's layer 1 would suffice to enable arbitrary smart
contracts.

It is not yet at the stage where a formal proposal can be made, therefore
the proposed specs are only for illustrative purposes.

The same content is reformatted below for the mailing list.

Looking forward to hearing about your comments and improvements.
Salvatore Ingala


==


# General smart contracts in bitcoin via covenants

Covenants are UTXOs that are encumbered with restrictions on the outputs of
the transaction spending the UTXO. More formally, we can define a covenant
any UTXO such that at least one of its spending conditions is valid only if
one or more of the outputs’ scriptPubKey satisfies certain restrictions.

Generally, covenant proposals also add some form of introspection (that is,
the ability for Script to access parts of the inputs/outputs, or the
blockchain history).

In this note, we want to explore the possibilities unleashed by the
addition of a covenant with the following properties:

- introspection limited to a single hash attached to the UTXO (the
“covenant data”), and input/output amounts;
- pre-commitment to every possible future script (but not their data);
- few simple opcodes operating with the covenant data.

We argue that such a simple covenant construction is enough to extend the
power of bitcoin’s layer 1 to become a universal settlement layer for
arbitrary computation.

Moreover, the covenant can elegantly fit within P2TR transactions, without
any substantial increase for the workload of bitcoin nodes.

A preliminary version of these notes was presented and discussed at the
BTCAzores Unconference [1], on 23rd September 2022.


# Preliminaries

We can think of a smart contract as a “program” that updates a certain
state according to predetermined rules (which typically include access
control by authorizing only certain public keys to perform certain
actions), and that can possibly lock/unlock some coins of the underlying
blockchain according to the same rules.

The exact definition will be highly dependent on the properties of the
underlying blockchain.

In bitcoin, the only state upon which all the nodes reach consensus is the
UTXO set; other blockchains might have other data structures as part of the
consensus, like a key-value store that can be updated as a side effect of
transaction execution.

In this section we explore the following concepts in order to set the
framework for a definition of smart contracts that fits the structure of
bitcoin:

- the contract’s state: the “memory” the smart contract operates on;
- state transitions: the rules to update the contract’s state;
- covenants: the technical means that can allow contracts to function in
the context of a bitcoin UTXO.

In the following, an on-chain smart contract is always represented as a
single UTXO that implicitly embeds the contract’s state and possibly
controls some coins that are “locked” in it. More generally, one could
think of smart contracts that are represented in a set of multiple UTXOs;
we leave the exploration of generalizations of the framework to future
research.

## State

Any interesting “state” of a smart contract can ultimately be encoded as a
list, where each element is either a bit, a fixed-size integers, or an
arbitrary byte string.

Whichever the choice, it does not really affect what kinds of computations
are expressible, as long as one is able to perform some basic computations
on those elements.

In the following, we will assume without loss of generality that
computations happen on a state which is a list of fixed length S = [s_1,
s_2, …, s_n], where each s_i is a byte string.

### Merkleized state

By constructing a Merkle tree that has the (hashes of) the elements of S in
the leaves, we can produce a short commitment h_S to the entire list S with
the following properties (that hold for a verifier that only knows h_S):

- a (log n)-sized proof can prove the value of an element s_i;
- a (log n + |x|)-sized proof can prove the new commitment h_S’, where S’
is a new list obtained by replacing the value of a certain leaf with x.

This allows to compactly commit to a RAM, and to prove correctness of RAM
updates.

In other words, a