Re: [bitcoin-dev] Vaults in the MATT framework
Hi, It was briefly mentioned in the original post, but wanted to show how simple it is to use COCV as an alternative to CTV, removing that dependency. > In particular, it also inherits the choice of using OP_CTV as a primitive, > building on top of the bitcoin-inquisition's current branch that has already > merged OP_CTV. Reasonable vaults would be possible without CTV, but they > would be less efficient, particularly in the case of sending to many addresses > in a single unvaulting flow. Instead of specifying a CTV hash as embedded data, one could embed the (commitment to the) outputs of the withdrawal transaction. Then instead of a single OP_CTV, one OP_COCV per output to match against the embedded data. Less efficient in case of many outputs as you mention, but simple enough to be interesting. Here's an example how to use MATT as a CTV replacement: https://github.com/halseth/tapsim/blob/b07f29804cf32dce0168ab5bb40558cbb18f2e76/examples/matt/ctv2/README.md Cheers, Johan On Tue, May 2, 2023 at 10:22 AM Salvatore Ingala via bitcoin-dev wrote: > > Hi Michael, > > I can't make any claim of expertise on the field (especially on the > other proposals that you mentioned), so this post necessarily includes > my opinions − and possibly my biases. > > The core functionality of MATT is quite simple, and could be adapted > to any version of the scripting system: basically, COCV allows to > "embed" some data in the next output, and decide its script; CICV > allows "reading" this data. > The design I proposed on taproot is surely not the only possible way, > but it's the most simple/elegant I could come up with. Moreover, it > doesn't seem very useful to spend time trying to get it to work on > pre-taproot Script, due to the obvious advantages of those ideas when > deployed on taproot (like having taptrees, and all the nice properties > of Schnorr signatures). > > CICV/COCV can certainly be considered an additional form of > introspection: you're checking that the script of an input/output > equals a certain value, which is not possible in today's Script. > I think that's generally true for all covenant proposals. > > Unlike some other proposals, MATT is not yet fully formalized, so I > generally call "MATT" the combination of CICV+COCV, plus some other > small set of opcodes that is yet to be defined exactly. I would say it > fits in the same family as APO/OP_CTV/OP_VAULT, per your bucketization. > > The previous posts about MATT, fraud proofs, etc. are an exploration of > the deeper things that are enabled by the MATT opcodes. The claim is > that a set of changes that is (arguably) quite small and easy to analyze > is enough to express general smart contracts − thanks to fraud proofs. > However, fraud proofs themselves are a quite advanced application of > the new opcodes, and are not needed for most/all of the things that > people are trying to build today with the other covenant proposals. > > > Since you mention Simplicity: my current understanding is that its > endeavour of replacing Script with a better language is orthogonal to > the discussion about what features (e.g.: introspection, covenants) > should be in the language. > > All the covenant proposals listed above are technically a lot smaller > and easier to audit than both the SegWit and the Taproot soft forks, > both in terms of code and conceptual complexity. > > Therefore, if we _do_ want the features that they enable, the required > engineering for a soft-fork is relatively straightforward, and there is > not much of a reason to wait for Simplicity. It will be trivial to "port" any > constructions we might create today with covenants to Simplicity scripts. > > If we _do not_ want those features, then the decision would rather be > guided by other considerations, like potential risks to bitcoin caused > by the effect of those features on miners' incentives. These > concerns are not answered by Simplicity, as far as I understand: > you would then want to implement Simplicity _without_ those features. > > Best, > Salvatore > > On Mon, 1 May 2023 at 16:18, Michael Folkson > wrote: >> >> Hi Salvatore >> >> Can you clarify for me which bucket this proposal sits? We have APO, CTV, >> OP_VAULT etc that are proposals to add additional functionality to SegWit >> version 1, Tapleaf version 0 scripts. We have Simplicity that would need a >> new Tapleaf version (e.g. Tapleaf version 1). And then there are CISA like >> proposals that would need a new SegWit version (e.g. SegWit version 2). It >> looks to me like your proposal is in the first bucket (same as APO, CTV etc) >> as it is just introducing new opcode functionality to existing script with >> no deeper introspection needed but previous and current discussion of fraud >> proofs, MATT frameworks etc made me initially think it was going to require >> more than that. >> >> Thanks >> Michael >> >> -- >> Michael Folkson >> Email: michaelfolkson at protonmail.com >> GPG: A2CF5D71603C9201065981
Re: [bitcoin-dev] Vaults in the MATT framework
Hi Michael, I can't make any claim of expertise on the field (especially on the other proposals that you mentioned), so this post necessarily includes my opinions − and possibly my biases. The core functionality of MATT is quite simple, and could be adapted to any version of the scripting system: basically, COCV allows to "embed" some data in the next output, and decide its script; CICV allows "reading" this data. The design I proposed on taproot is surely not the only possible way, but it's the most simple/elegant I could come up with. Moreover, it doesn't seem very useful to spend time trying to get it to work on pre-taproot Script, due to the obvious advantages of those ideas when deployed on taproot (like having taptrees, and all the nice properties of Schnorr signatures). CICV/COCV can certainly be considered an additional form of introspection: you're checking that the script of an input/output equals a certain value, which is not possible in today's Script. I think that's generally true for all covenant proposals. Unlike some other proposals, MATT is not yet fully formalized, so I generally call "MATT" the combination of CICV+COCV, plus some other small set of opcodes that is yet to be defined exactly. I would say it fits in the same family as APO/OP_CTV/OP_VAULT, per your bucketization. The previous posts about MATT, fraud proofs, etc. are an exploration of the deeper things that are enabled by the MATT opcodes. The claim is that a set of changes that is (arguably) quite small and easy to analyze is enough to express general smart contracts − thanks to fraud proofs. However, fraud proofs themselves are a quite advanced application of the new opcodes, and are not needed for most/all of the things that people are trying to build today with the other covenant proposals. Since you mention Simplicity: my current understanding is that its endeavour of replacing Script with a better language is orthogonal to the discussion about what features (e.g.: introspection, covenants) should be in the language. All the covenant proposals listed above are technically a lot smaller and easier to audit than both the SegWit and the Taproot soft forks, both in terms of code and conceptual complexity. Therefore, if we _do_ want the features that they enable, the required engineering for a soft-fork is relatively straightforward, and there is not much of a reason to wait for Simplicity. It will be trivial to "port" any constructions we might create today with covenants to Simplicity scripts. If we _do not_ want those features, then the decision would rather be guided by other considerations, like potential risks to bitcoin caused by the effect of those features on miners' incentives. These concerns are not answered by Simplicity, as far as I understand: you would then want to implement Simplicity _without_ those features. Best, Salvatore On Mon, 1 May 2023 at 16:18, Michael Folkson wrote: > Hi Salvatore > > Can you clarify for me which bucket this proposal sits? We have APO, CTV, > OP_VAULT etc that are proposals to add additional functionality to SegWit > version 1, Tapleaf version 0 scripts. We have Simplicity that would need a > new Tapleaf version (e.g. Tapleaf version 1). And then there are CISA like > proposals that would need a new SegWit version (e.g. SegWit version 2). It > looks to me like your proposal is in the first bucket (same as APO, CTV > etc) as it is just introducing new opcode functionality to existing script > with no deeper introspection needed but previous and current discussion of > fraud proofs, MATT frameworks etc made me initially think it was going to > require more than that. > > Thanks > Michael > > -- > Michael Folkson > Email: michaelfolkson at protonmail.com > GPG: A2CF5D71603C92010659818D2A75D601B23FEE0F > > Learn about Bitcoin: https://www.youtube.com/@portofbitcoin > > --- Original Message --- > On Monday, April 24th, 2023 at 20:37, Salvatore Ingala via bitcoin-dev < > bitcoin-dev@lists.linuxfoundation.org> wrote: > > Hello list, > > TL;DR: the core opcodes of MATT can build vaults with a very similar design > to OP_VAULT. Code example here: > > > https://github.com/bitcoin-inquisition/bitcoin/compare/24.0...bigspider:bitcoin-inquisition:matt-vault > > > In my previous emails about the MATT proposal for smart contracts in > bitcoin [1], I mostly focused on proving its generality; that is, it > allows arbitrary smart contracts thanks to fraud proofs. > > While I still find this "completeness" result compelling, I spent more time > thinking about the framework itself; the construction is not very > interesting > if it turns simple things into complicated ones. Luckily, this is not the > case. > In particular, in this email we will not merkleize anything (other than > taptrees). > > This post describes some progress into formalizing the semantics of the > core > opcodes, and demonstrates how they could be used to create vaults that seem > comparable to the ones built
Re: [bitcoin-dev] Vaults in the MATT framework
Hi Salvatore Can you clarify for me which bucket this proposal sits? We have APO, CTV, OP_VAULT etc that are proposals to add additional functionality to SegWit version 1, Tapleaf version 0 scripts. We have Simplicity that would need a new Tapleaf version (e.g. Tapleaf version 1). And then there are CISA like proposals that would need a new SegWit version (e.g. SegWit version 2). It looks to me like your proposal is in the first bucket (same as APO, CTV etc) as it is just introducing new opcode functionality to existing script with no deeper introspection needed but previous and current discussion of fraud proofs, MATT frameworks etc made me initially think it was going to require more than that. Thanks Michael -- Michael Folkson Email: michaelfolkson at [protonmail.com](http://protonmail.com/) GPG: A2CF5D71603C92010659818D2A75D601B23FEE0F Learn about Bitcoin: https://www.youtube.com/@portofbitcoin --- Original Message --- On Monday, April 24th, 2023 at 20:37, Salvatore Ingala via bitcoin-dev wrote: > Hello list, > > TL;DR: the core opcodes of MATT can build vaults with a very similar design > to OP_VAULT. Code example here: > > https://github.com/bitcoin-inquisition/bitcoin/compare/24.0...bigspider:bitcoin-inquisition:matt-vault > > In my previous emails about the MATT proposal for smart contracts in > bitcoin [1], I mostly focused on proving its generality; that is, it > allows arbitrary smart contracts thanks to fraud proofs. > > While I still find this "completeness" result compelling, I spent more time > thinking about the framework itself; the construction is not very interesting > if it turns simple things into complicated ones. Luckily, this is not the > case. > In particular, in this email we will not merkleize anything (other than > taptrees). > > This post describes some progress into formalizing the semantics of the core > opcodes, and demonstrates how they could be used to create vaults that seem > comparable to the ones built with OP_VAULT [2], despite using general purpose > opcodes. > > An implementation and some minimal tests matching the content of this > e-mail can be found in the link above, using the bitcoin-inquisition as the > base branch. > > Note that the linked code is not well tested and is only intended for > exploratory and demonstrative purposes; therefore, bugs are likely at this > stage. > > ## > # PART 1: MATT's core > ## > > In this section, I will discuss plausible semantics for the core opcodes for > MATT. > > The two core opcodes are defined below as OP_CHECKINPUTCONTRACTVERIFY and > OP_CHECKOUTPUTCONTRACTVERIFY. > > (the initial posts named them OP_CHECK{INPUT,OUTPUT}COVENANTVERIFY) > > They enhance Script with the following capabilities: > - decide the taptree of the output > - embed some (dynamically computed) data in the output > - access the embedded data in the current UTXO (if any) > > The opcodes below are incomplete, as they only control the output's Script and > not the amounts; more on that below. > > Other than that, the semantics should be quite close to the "right" one for > the MATT framework. > > ### The opcodes > > case OP_CHECKINPUTCONTRACTVERIFY: > { > // OP_CHECKINPUTCONTRACTVERIFY is only available in Tapscript > if (sigversion == SigVersion::BASE || sigversion == SigVersion::WITNESS_V0) > return set_error(serror, SCRIPT_ERR_BAD_OPCODE); > // (x d -- ) > if (stack.size() < 2) > return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); > valtype& x = stacktop(-2); > valtype& d = stacktop(-1); > if (x.size() != 32 || d.size() != 32) > return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); > const XOnlyPubKey nakedXOnlyKey{Span{x.data(), x.data() > + 32}}; > const uint256 data(d); > if (!execdata.m_internal_key.has_value()) > return set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR); // TODO > // Verify that tweak(lift_x(x), d) equals the internal pubkey > if (!execdata.m_internal_key.value().CheckDoubleTweak(nakedXOnlyKey, &data, > nullptr)) > return set_error(serror, SCRIPT_ERR_WRONGCONTRACTDATA); > popstack(stack); > popstack(stack); > } > break; > case OP_CHECKOUTPUTCONTRACTVERIFY: > { > // OP_CHECKOUTPUTCONTRACTVERIFY is only available in Tapscript > if (sigversion == SigVersion::BASE || sigversion == SigVersion::WITNESS_V0) > return set_error(serror, SCRIPT_ERR_BAD_OPCODE); > // (out_i x taptree d -- ) > if (stack.size() < 4) > return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); > int out_i = CScriptNum(stacktop(-4), fRequireMinimal).getint(); > valtype& x = stacktop(-3); > valtype& taptree = stacktop(-2); > valtype& d = stacktop(-1); > auto outps = checker.GetTxvOut(); > // Return error if the evaluation context is unavailable > if (!outps) > return set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR); // TODO > if (x.size() != 32 || taptree.size() != 32 || (d.size() != 0 && d.size() != > 32)) > return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); > if
[bitcoin-dev] Vaults in the MATT framework
Hello list, TL;DR: the core opcodes of MATT can build vaults with a very similar design to OP_VAULT. Code example here: https://github.com/bitcoin-inquisition/bitcoin/compare/24.0...bigspider:bitcoin-inquisition:matt-vault In my previous emails about the MATT proposal for smart contracts in bitcoin [1], I mostly focused on proving its generality; that is, it allows arbitrary smart contracts thanks to fraud proofs. While I still find this "completeness" result compelling, I spent more time thinking about the framework itself; the construction is not very interesting if it turns simple things into complicated ones. Luckily, this is not the case. In particular, in this email we will not merkleize anything (other than taptrees). This post describes some progress into formalizing the semantics of the core opcodes, and demonstrates how they could be used to create vaults that seem comparable to the ones built with OP_VAULT [2], despite using general purpose opcodes. An implementation and some minimal tests matching the content of this e-mail can be found in the link above, using the bitcoin-inquisition as the base branch. Note that the linked code is not well tested and is only intended for exploratory and demonstrative purposes; therefore, bugs are likely at this stage. ## #PART 1: MATT's core ## In this section, I will discuss plausible semantics for the core opcodes for MATT. The two core opcodes are defined below as OP_CHECKINPUTCONTRACTVERIFY and OP_CHECKOUTPUTCONTRACTVERIFY. (the initial posts named them OP_CHECK{INPUT,OUTPUT}COVENANTVERIFY) They enhance Script with the following capabilities: - decide the taptree of the output - embed some (dynamically computed) data in the output - access the embedded data in the current UTXO (if any) The opcodes below are incomplete, as they only control the output's Script and not the amounts; more on that below. Other than that, the semantics should be quite close to the "right" one for the MATT framework. ### The opcodes case OP_CHECKINPUTCONTRACTVERIFY: { // OP_CHECKINPUTCONTRACTVERIFY is only available in Tapscript if (sigversion == SigVersion::BASE || sigversion == SigVersion::WITNESS_V0) return set_error(serror, SCRIPT_ERR_BAD_OPCODE); // (x d -- ) if (stack.size() < 2) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); valtype& x = stacktop(-2); valtype& d = stacktop(-1); if (x.size() != 32 || d.size() != 32) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); const XOnlyPubKey nakedXOnlyKey{Span{x.data(), x.data() + 32}}; const uint256 data(d); if (!execdata.m_internal_key.has_value()) return set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR); // TODO // Verify that tweak(lift_x(x), d) equals the internal pubkey if (!execdata.m_internal_key.value().CheckDoubleTweak(nakedXOnlyKey, &data, nullptr)) return set_error(serror, SCRIPT_ERR_WRONGCONTRACTDATA); popstack(stack); popstack(stack); } break; case OP_CHECKOUTPUTCONTRACTVERIFY: { // OP_CHECKOUTPUTCONTRACTVERIFY is only available in Tapscript if (sigversion == SigVersion::BASE || sigversion == SigVersion::WITNESS_V0) return set_error(serror, SCRIPT_ERR_BAD_OPCODE); // (out_i x taptree d -- ) if (stack.size() < 4) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); int out_i = CScriptNum(stacktop(-4), fRequireMinimal).getint(); valtype& x = stacktop(-3); valtype& taptree = stacktop(-2); valtype& d = stacktop(-1); auto outps = checker.GetTxvOut(); // Return error if the evaluation context is unavailable if (!outps) return set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR); // TODO if (x.size() != 32 || taptree.size() != 32 || (d.size() != 0 && d.size() != 32)) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); if (out_i < 0 || out_i >= (int)outps->size()) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); const XOnlyPubKey nakedXOnlyKey{Span{x.data(), x.data() + 32}}; const uint256 data(d); const uint256 *data_ptr = (d.size() == 0 ? nullptr : &data); const uint256 merkle_tree(taptree); CScript scriptPubKey = outps->at(out_i).scriptPubKey; if (scriptPubKey.size() != 1 + 1 + 32 || scriptPubKey[0] != OP_1 || scriptPubKey[1] != 32) return set_error(serror, SCRIPT_ERR_WRONGCONTRACTDATA); const XOnlyPubKey outputXOnlyKey{Span{scriptPubKey.data() + 2, scriptPubKey.data() + 34}}; // Verify that taptweak(tweak(lift_x(x), d), taptree) equals the internal pubkey if (!outputXOnlyKey.CheckDoubleTweak(nakedXOnlyKey, data_ptr, &merkle_tree)) return set_error(serror, SCRIPT_ERR_WRONGCONTRACTDATA); popstack(stack); popstack(stack); popstack(stack); popstack(stack); } break; ### Commentary CheckDoubleTweak function (implemented in the branch) gets an x-only pubkey, optionally so