Return-Path: <antoine.riard@gmail.com> Received: from smtp3.osuosl.org (smtp3.osuosl.org [IPv6:2605:bc80:3010::136]) by lists.linuxfoundation.org (Postfix) with ESMTP id D980DC002D for <bitcoin-dev@lists.linuxfoundation.org>; Fri, 30 Sep 2022 02:00:47 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id AB75C61207 for <bitcoin-dev@lists.linuxfoundation.org>; Fri, 30 Sep 2022 02:00:47 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org AB75C61207 Authentication-Results: smtp3.osuosl.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20210112 header.b=R5gnA5Jp X-Virus-Scanned: amavisd-new at osuosl.org X-Spam-Flag: NO X-Spam-Score: -2.098 X-Spam-Level: X-Spam-Status: No, score=-2.098 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001] autolearn=ham autolearn_force=no Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id gBmDUHTxZdCE for <bitcoin-dev@lists.linuxfoundation.org>; Fri, 30 Sep 2022 02:00:45 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.8.0 DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org 3E40961206 Received: from mail-il1-x12a.google.com (mail-il1-x12a.google.com [IPv6:2607:f8b0:4864:20::12a]) by smtp3.osuosl.org (Postfix) with ESMTPS id 3E40961206 for <bitcoin-dev@lists.linuxfoundation.org>; Fri, 30 Sep 2022 02:00:43 +0000 (UTC) Received: by mail-il1-x12a.google.com with SMTP id i9so1329639ilv.9 for <bitcoin-dev@lists.linuxfoundation.org>; Thu, 29 Sep 2022 19:00:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :from:to:cc:subject:date; bh=avcU9keNmwPPKOsRN69fD8Qcqmw0e8VYvM1gsnk/UKs=; b=R5gnA5JpcRqyiNPwDxc5nTMJCzyosw0HQNdqfk1sOfo3dpllKQG1JSI+Ye3HWPYmF8 CiYtCm/xdB/MKanijjs4qJD7sdwEAJF0IDBI3AMPXO6L06Tgh+u3fV/dVE+uBV+aBFZT kOw7u6RW97AAuBDXuykQZECgA4iIuJ/elz7Ffq0Kl4k0SrxH4T8QmWB18JWdYG3wHtn9 Si3cKgCtr1fnNBkiTT2107aOVFCd96YOeW2CUbXQ+spBUZ4bK4TR8xNxIHGnC+F96WNp slDiNVp9RgfO6V8qPb1dqtch4v9fGUSeDkcBX9PrGma3FRPC39C+AHpzOppDzNYKixG1 uB6Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :x-gm-message-state:from:to:cc:subject:date; bh=avcU9keNmwPPKOsRN69fD8Qcqmw0e8VYvM1gsnk/UKs=; b=xh9Scr3Pn4axUBye4nAdASiFv26lmGKDuUCiw5oYjbkQEMUaf0kdTEr1yneoxfeqIb vS/Rht2HXbrzt14mo3EOguGX1MlL9YGhxnydpiJaalbr3+GZ6nLjDp+73/Qek1NnomFX rw5pNzrqdf/0TCzfq59S23z3B/k1xWxZ0yAUPRdvfyf1Kkx80mktLvkA8Pw3Ia6EqVEP /3z2gaYE4PF3hs/qkMCFqmpIixKSu4Xp5/g54R/EkxTMC+VROaFEZU6yidq+LFfsdiwC UjiuicmaUuxui/gThII4mSPe+6Ey2s5xeoBB6582vK0vWW6Cq7pbpxbIyCn3WLqpKfkI iH1Q== X-Gm-Message-State: ACrzQf1fj67Ha0XL+vnmetTIGsgFLl6e44RgLyjj+wGm/+PAvNXjBqTD RsofkwVzej383sBz8cSObnq15qV5Skr3USQwcDeIugjzsoEvmA== X-Google-Smtp-Source: AMsMyM4lw0S8cbupCFdIlDeLY1RQ4JBsOAvGYm4n3IjbDoeMDyp3gUTFAP3aRZUMgBWNvh60SxG7bgqchcPCGZhGxfw= X-Received: by 2002:a92:3652:0:b0:2df:4133:787 with SMTP id d18-20020a923652000000b002df41330787mr3188715ilf.39.1664503242260; Thu, 29 Sep 2022 19:00:42 -0700 (PDT) MIME-Version: 1.0 References: <CAD5xwhgKGMx79+RLpb-hjd3Gc=EKxTVzkpME-=KuM_C5+d7mRQ@mail.gmail.com> In-Reply-To: <CAD5xwhgKGMx79+RLpb-hjd3Gc=EKxTVzkpME-=KuM_C5+d7mRQ@mail.gmail.com> From: Antoine Riard <antoine.riard@gmail.com> Date: Thu, 29 Sep 2022 22:00:30 -0400 Message-ID: <CALZpt+E6KeyvAp-nBUdO3J79dKRKHEZJkUpcSasJ4TH9h=sU7g@mail.gmail.com> To: Jeremy Rubin <jeremy.l.rubin@gmail.com>, Bitcoin Protocol Discussion <bitcoin-dev@lists.linuxfoundation.org> Content-Type: multipart/alternative; boundary="0000000000007b864205e9db5c7b" X-Mailman-Approved-At: Fri, 30 Sep 2022 02:18:09 +0000 Subject: Re: [bitcoin-dev] Spookchains: Drivechain Analog with One-Time Trusted Setup & APO X-BeenThere: bitcoin-dev@lists.linuxfoundation.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Bitcoin Protocol Discussion <bitcoin-dev.lists.linuxfoundation.org> List-Unsubscribe: <https://lists.linuxfoundation.org/mailman/options/bitcoin-dev>, <mailto:bitcoin-dev-request@lists.linuxfoundation.org?subject=unsubscribe> List-Archive: <http://lists.linuxfoundation.org/pipermail/bitcoin-dev/> List-Post: <mailto:bitcoin-dev@lists.linuxfoundation.org> List-Help: <mailto:bitcoin-dev-request@lists.linuxfoundation.org?subject=help> List-Subscribe: <https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev>, <mailto:bitcoin-dev-request@lists.linuxfoundation.org?subject=subscribe> X-List-Received-Date: Fri, 30 Sep 2022 02:00:48 -0000 --0000000000007b864205e9db5c7b Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hi Jeremy, Thanks for bringing back to awareness covenant-based drivechain designs again! I'm not super familiar with the thousands shades of sidechains, and especially how the variants of pegging mechanisms influence the soundness of the game-theory backing up the functionaries execution. However it could be interesting to give security bounds to the defect of any trusted component, such as the one-time trusted setup, and the impacts on funds. If it's a full-blown loss, a timevalue loss, a privacy leak, etc... Started at least an entry for the ZmnSCPxj design: https://github.com/ariard/bitcoin-contracting-primitives-wg/pull/9 One interesting point from the OG post: > The recursive covenant could, with the help of `OP_CAT` and > `OP_CTV`, check that every transaction spending the UTXO has a > second output that is an `OP_RETURN` with a commitment to the > sidechain block. > We can ensure that only one such transaction exists in each > mainchain block by adding a `<1> OP_CSV`, ensuring that only one > sidechain-commitment transaction can occur on each mainchain > block. Such recursive-covenant "embedded" sidechains could be used as solution to the double-spend of payment pools and channel factories partitions, as an instantiation of a "on-chain authoritative board" for partitions statement, as described earlier this year, in a quest to solve the high interactivity issue affecting those constructions [0]. Best, Antoine [0] https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2022-April/020370.h= tml Le mer. 14 sept. 2022 =C3=A0 14:32, Jeremy Rubin via bitcoin-dev < bitcoin-dev@lists.linuxfoundation.org> a =C3=A9crit : > *also available here on my blog with nicer > formatting: https://rubin.io/bitcoin/2022/09/14/drivechain-apo/ > <https://rubin.io/bitcoin/2022/09/14/drivechain-apo/>* > > This post draws heavily from Zmnscpxj's fantastic post showing how to > make drivechains with recursive covenants. In this post, I will show > similar tricks that can accomplish something similar using ANYPREVOUT > with a one time trusted setup ceremony. > > This post presents general techniques that could be applied to many > different types of covenant. > > # Peano Counters > > The first component we need to build is a Peano counter graph. Instead > of using sha-256, like in Zmnscpxj's scheme, we will use a key and > build a simple 1 to 5 counter that has inc / dec. > > Assume a key K1...K5, and a point NUMS which is e.g. > HashToCurve("Spookchains"). > > Generate scripts as follows: > > ``` > <1 || K1> CHECKSIG > ... > <1 || K5> CHECKSIG > ``` > > Now generate 2 signatures under Ki with flags `SIGHASH_SINGLE | > SIGHASH_ANYONECANPAY | SIGHASH_ANYPREVOUT`. > > > ## Rule Increment > For each Ki, when `i < 5`, create a signature that covers a > transaction described as: > > ``` > Amount: 1 satoshi > Key: Tr(NUMS, {<1 || K{i+1}> CHECKSIG}) > ``` > > ## Rule Decrement > For each Ki, when `i > 1` The second signature should cover: > ``` > Amount: 1 satoshi > Key: Tr(NUMS, {<1 || K{i-1}> CHECKSIG}) > ``` > > > > _Are these really Peano?_ Sort of. While a traditional Peano numeral > is defined as a structural type, e.g. `Succ(Succ(Zero))`, here we > define them via a Inc / Dec transaction operator, and we have to > explicitly bound these Peano numbers since we need a unique key per > element. They're at least spiritually similar. > > ## Instantiation > Publish a booklet of all the signatures for the Increment and > Decrement rules. > > Honest parties should destroy the secret key sets `k`. > > > To create a counter, simply spend to output C: > > ``` > Amount: 1 satoshi > Key: Tr(NUMS, {<1 || K1> CHECKSIG}) > ``` > > > The signature from K1 can be bound to C to 'transition' it to (+1): > > ``` > Amount: 1 satoshi > Key: Tr(NUMS, {<1 || K2> CHECKSIG}) > ``` > > Which can then transition to (+1): > > ``` > Amount: 1 satoshi > Key: Tr(NUMS, {<1 || K3> CHECKSIG}) > ``` > > Which can then transition (-1) to: > > ``` > Amount: 1 satoshi > Key: Tr(NUMS, {<1 || K2> CHECKSIG}) > ``` > > This can repeat indefinitely. > > > We can generalize this technique from `1...5` to `1...N`. > > > > # Handling Arbitrary Deposits / Withdrawals > > > One issue with the design presented previously is that it does not > handle arbitrary deposits well. > > One simple way to handle this is to instantiate the protocol for every > amount you'd like to support. > > This is not particularly efficient and requires a lot of storage > space. > > Alternatively, divide (using base 2 or another base) the deposit > amount into a counter utxo per bit. > > For each bit, instead of creating outputs with 1 satoshi, create > outputs with 2^i satoshis. > > Instead of using keys `K1...KN`, create keys `K^i_j`, where i > represents the number of sats, and j represents the counter. Multiple > keys are required per amount otherwise the signatures would be valid > for burning funds. > > ## Splitting and Joining > > For each `K^i_j`, it may also be desirable to allow splitting or > joining. > > Splitting can be accomplished by pre-signing, for every `K^i_j`, where > `i!=3D0`, with `SIGHASH_ALL | SIGHASH_ANYPREVOUT`: > > ``` > Input: 2^i sats with key K^i_j > Outputs: > - 2^i-1 sats to key K^{i-1}_j > - 2^i-1 sats to key K^{i-1}_j > ``` > > Joining can be accomplished by pre-signing, for every `K^i_j`, where > `i!=3DMAX`, with `SIGHASH_ALL | SIGHASH_ANYPREVOUT`: > > ``` > Inputs: > - 2^i sats with key K^i_j > - 2^i sats with key K^i_j > Outputs: > - 2^i+1 sats to key K^{i+1}_j > ``` > > N.B.: Joining allows for third parties to deposit money in externally, > that is not a part of the covenant. > > > The splitting and joining behavior means that spookchain operators > would be empowered to consolidate UTXOs to a smaller number, while > allowing arbitrary deposits. > > > # One Vote Per Block > > To enforce that only one vote per block mined is allowed, ensure that > all signatures set the input sequence to 1 block. No CSV is required > because nSequence is in the signatures already. > > # Terminal States / Thresholds > > When a counter reaches the Nth state, it represents a certain amount > of accumulated work over a period where progress was agreed on for > some outcome. > > There should be some viable state transition at this point. > > One solution would be to have the money at this point sent to an > `OP_TRUE` output, which the miner incrementing that state is > responsible for following the rules of the spookchain. Or, it could be > specified to be some administrator key / federation for convenience, > with a N block timeout that degrades it to fewer signers (eventually > 0) if the federation is dead to allow recovery. > > This would look like, from any `K^i_j`, a signature for a transaction > putting it into an `OP_TRUE` and immediately spending it. Other > spookchain miners would be expected to orphan that miner otherwise. > > > # Open States / Proposals > > From a state `K^i_1`, the transaction transitioning to `K^i_2` can be > treated as 'special' and the `OP_RETURN` output type can be used to > commit to, e.g., the outputs that must be created in when the Terminal > State is reached. This clarifies the issue of "what is being voted > on". > > This method does not *lock in* at a consensus layer what Terminal > State is being voted on. > > In certain circumstances, without violating the one-time-setup > constraint, if a fixed list of withdrawer's addresses is known in > advance, the Open States could cover withdrawals to specific > participants, which then must collect a certain number of votes from > miners. However, it seems impossible, without new primitives, for an > arbitrary transaction proposal to be voted on. > > # Setup Variants > > ## xpubs > > Instead of using randomly generated keys for each state, define each > to be an xpub and derive a path where it is k/i/j for each > state/satoshi amount. This saves some data, and also requires less > entropy. > > ### Trustless Data Commit: > > commit to the hash of the entire program spec as a tweak to the xpub, > so that someone can quickly verify if they have all the signatures you > are expected to generate if honest. > > One way to do this is to convert a hash to a list of HD Child Numbers > (9 of them) deterministically, and tweak the xpub by that. This is a > convenient, yet inefficient, way to tweak an xpub because the child > has a normal derivation path for signing devices. > > ## Single Party > > A single party pre-signs all the transactions for the spookchain, and > then deletes their xpriv. > > You trust them to have deleted the key, and signed properly, but you > do not trust whoever served you the spookchain blob to have given you > all the state transitions because of the trustless data commitment. > > ## MuSig Multi-Party > > Define a MuSig among all participants in the setup ceremony, N-of-N. > > Now you simply trust that any one person in the one-time-setup was > honest! Very good. > > ## Unaggregated Multi-Party > > > Allow for unaggregated multi-sig keys in the spec. This grows with > O(signers), however, it means that a-la-carte you can aggregate setups > from random participants who never interacted / performed setup > ceremonies independently if they signed the same specs. > > Can also combine multiple MuSig Multi-Parties in this way. > > This is nice because MuSig inherently implies the parties colluded at > one point to do a MuSig setup, whereas unaggregated multi-sig could be > performed with no connectivity between parties. > > ## Soft Forking Away Trust > > Suppose a spookchain becomes popular. You could configure your client > to reject invalid state transitions, or restrict the spookchain keys > to only sign with the known signatures. This soft fork would smoothly > upgrade the trust assumption. > > ## Symmetry of State Transition Rules & DAG Covenants > > We could have our increment state transitions be done via a trustless > covenant, and our backwards state transitions be done via the setup. > > This would look something like the following for state i: > > ``` > Tr(NUMS, { > `<sig for state K_{i+1}> <1 || PK_nonsecret> CHECKSIG`, > `<1 || Ki> CHECKSIG` > }) > ``` > > The advantage of such an optimization is theoretically nice because it > means that *only* the non-destructuring recursive part of the > computation is subject to the one-time-setup trust assumption, which > might be of use in various other protocols, where recursivity might > only be unlocked e.g. after a timeout (but for spookchains it is used > at each step). > > A compiler writer might perform this task by starting with an > arbitrary abstract graph, and then removing edges selectively (a > number of heuristics may make sense, e.g., to minimize reliance on > one-time-setup or minimize costs) until the graph is a Directed > Acyclic Graph, consisting of one or more components, compiling those > with committed covenants, and then adding the removed edges back using > the one-time-setup key materials. > > > # Commentary on Trust and Covenantiness > > Is this a covenant? I would say "yes". When I defined covenants in my > _Calculus of Covenants_ post, it was with a particular set of > assumptions per covenant. > > Under that model, you could, e.g., call a 7-10 multi-sig with specific > committed instructions as 4-10 honest (requires 4 signatories to be > honest to do invalid state transition) and 4-10 killable (requires 4 > signatories to die to have no way of recovering). > > For emulations that are pre-signed, like the varieties used to emulate > CTV, it is a different model because if your program is correct and > you've pre-gotten the signatures for N-N it is 1-N honest (only 1 > party must be honest to prevent an invalid state transition) and > unkillable (all parties can safely delete keys). > > I model these types of assumptions around liveness and honesty as > different 'complexity classes' than one another. > > What I would point out is that with the counter model presented above, > this is entirely a pre-signed 1-N honest and unkillable covenant that > requires no liveness from signers. Further, with APO, new instances of > the covenant do not require a new set of signers, the setup is truly > one-time. Therefore this type of covenant exists in an even lower > trust-complexity class than CTV emulation via presigneds, which > requires a new federation to sign off on each contract instance. > > > With that preface, let us analyze this covenant: > > > 1) A set of sets of transaction intents (a family), potentially > recursive or co-recursive (e.g., the types of state transitions that > can be generated). These intents can also be represented by a > language that generates the transactions, rather than the literal > transactions themselves. We do the family rather than just sets at > this level because to instantiate a covenant we must pick a member of > the family to use. > > > The set of sets of transaction intents is to increment / decrement to > a successor or predecessor, or to halve into two instances or double > value by adding funds. Each successor or predecessor is the same type > of covenant, with the excetion of the first and last, which have some > special rules. > > > 2) A verifier generator function that generates a function that > accepts an intent that is any element of one member of the family of > intents and a proof for it and rejects others. > > The verifier generator is the simple APO CHECKSIG script. > > 3) A prover generator function that generates a function that takes an > intent that is any element of one member of the family and some extra > data and returns either a new prover function, a finished proof, or a > rejection (if not a valid intent). > > The prover generator is the selection of the correct signature from a > table for a given script. > > Run the prover generator with the private keys present *once* to > initialize over all reachable states, and cache the signatures, then > the keys may be deleted for future runs. > > 4) A set of proofs that the Prover, Verifier, and a set of intents are > "impedance matched", that is, all statements the prover can prove and > all statements the verifier can verify are one-to-one and onto (or > something similar), and that this also is one-to-one and onto with one > element of the intents (a set of transactions) and no other. > > At a given key state the only things that may happen are signed > transactions, no other data is interpreted off of the stack. Therefore > there is perfect impedance match. > > > 5) A set of assumptions under which the covenant is verified (e.g., a > multi-sig covenant with at least 1-n honesty, a multisig covenant with > any 3-n honesty required, Sha256 collision resistance, Discrete Log > Hardness, a SGX module being correct). > > Uniquely, that during the setup phase at least one of the keys > were faithfully deleted. > > The usual suspects for any bitcoin transaction are also assumed for > security. > > > 6) Composability: > > The Terminal State can pay out into a pre-specified covenant if > desired from any other family of covenants. > -- > @JeremyRubin <https://twitter.com/JeremyRubin> > _______________________________________________ > bitcoin-dev mailing list > bitcoin-dev@lists.linuxfoundation.org > https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev > --0000000000007b864205e9db5c7b Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">Hi Jeremy,<br><br>Thanks for bringing back to awareness co= venant-based drivechain designs again!<br><br>I'm not super familiar wi= th the thousands shades of sidechains, and especially how the variants of p= egging mechanisms influence the soundness of the game-theory backing up the= functionaries execution. However it could be interesting to give security = bounds to the defect of any trusted component, such as the one-time trusted= setup, and the impacts on funds. If it's a full-blown loss, a timevalu= e loss, a privacy leak, etc...<br><br>Started at least an entry for the Zmn= SCPxj design:<br><a href=3D"https://github.com/ariard/bitcoin-contracting-p= rimitives-wg/pull/9">https://github.com/ariard/bitcoin-contracting-primitiv= es-wg/pull/9</a><br><br>One interesting point from the OG post:<br>> The= recursive covenant could, with the help of `OP_CAT` and<br>> `OP_CTV`, = check that every transaction spending the UTXO has a<br>> second output = that is an `OP_RETURN` with a commitment to the<br>> sidechain block.<br= >> We can ensure that only one such transaction exists in each<br>> m= ainchain block by adding a `<1> OP_CSV`, ensuring that only one<br>&g= t; sidechain-commitment transaction can occur on each mainchain<br>> blo= ck.<br><br>Such recursive-covenant "embedded" sidechains could be= used as solution to the double-spend of payment pools and channel factorie= s partitions, as an instantiation of a "on-chain authoritative board&q= uot; for partitions statement, as described earlier this year, in a quest t= o solve the high interactivity issue affecting those constructions [0].<br>= <br>Best,<br>Antoine<br><br>[0] <a href=3D"https://lists.linuxfoundation.or= g/pipermail/bitcoin-dev/2022-April/020370.html">https://lists.linuxfoundati= on.org/pipermail/bitcoin-dev/2022-April/020370.html</a><br></div><br><div c= lass=3D"gmail_quote"><div dir=3D"ltr" class=3D"gmail_attr">Le=C2=A0mer. 14 = sept. 2022 =C3=A0=C2=A014:32, Jeremy Rubin via bitcoin-dev <<a href=3D"m= ailto:bitcoin-dev@lists.linuxfoundation.org">bitcoin-dev@lists.linuxfoundat= ion.org</a>> a =C3=A9crit=C2=A0:<br></div><blockquote class=3D"gmail_quo= te" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204= );padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_default" style=3D"= font-family:arial,helvetica,sans-serif;font-size:small;color:rgb(0,0,0)"><b= ><span style=3D"font-family:Arial,Helvetica,sans-serif;color:rgb(34,34,34)"= >also available here on my blog with nicer formatting:=C2=A0</span><span st= yle=3D"font-family:Arial,Helvetica,sans-serif;color:rgb(34,34,34)"><a href= =3D"https://rubin.io/bitcoin/2022/09/14/drivechain-apo/" target=3D"_blank">= https://rubin.io/bitcoin/2022/09/14/drivechain-apo/</a></span></b></div><di= v class=3D"gmail_default" style=3D"font-family:arial,helvetica,sans-serif;f= ont-size:small;color:rgb(0,0,0)"><span style=3D"font-family:Arial,Helvetica= ,sans-serif;color:rgb(34,34,34)"><br></span></div><div class=3D"gmail_defau= lt" style=3D"font-family:arial,helvetica,sans-serif;font-size:small;color:r= gb(0,0,0)"><span style=3D"font-family:Arial,Helvetica,sans-serif;color:rgb(= 34,34,34)">This post draws heavily from Zmnscpxj's fantastic post showi= ng how to</span><br></div>make drivechains with recursive covenants. In thi= s post, I will show<br>similar tricks that can accomplish something similar= using ANYPREVOUT<br>with a one time trusted setup ceremony.<br><br>This po= st presents general techniques that could be applied to many<br>different t= ypes of covenant.<br><br># Peano Counters<br><br>The first component we nee= d to build is a Peano counter graph. Instead<br>of using sha-256, like in Z= mnscpxj's scheme, we will use a key and<br>build a simple 1 to 5 counte= r that has inc / dec.<br><br>Assume a key K1...K5, and a point NUMS which i= s e.g.<br>HashToCurve("Spookchains").<br><br>Generate scripts as = follows:<br><br>```<br><1 || K1> CHECKSIG<br>...<br><1 || K5> C= HECKSIG<br>```<br><br>Now generate 2 signatures under Ki with flags `SIGHAS= H_SINGLE |<br>SIGHASH_ANYONECANPAY | SIGHASH_ANYPREVOUT`.<br><br><br>## Rul= e Increment<br>For each Ki, when `i < 5`, create a signature that covers= a<br>transaction described as:<br><br>```<br>Amount: 1 satoshi<br>Key: Tr(= NUMS, {<1 || K{i+1}> CHECKSIG})<br>```<br><br>## Rule Decrement<br>Fo= r each Ki, when `i > 1` The second signature should cover:<br>```<br>Amo= unt: 1 satoshi<br>Key: Tr(NUMS, {<1 || K{i-1}> CHECKSIG})<br>```<br><= br><br><br>_Are these really Peano?_ Sort of. While a traditional Peano num= eral<br>is defined as a structural type, e.g. `Succ(Succ(Zero))`, here we<b= r>define them via a Inc / Dec transaction operator, and we have to<br>expli= citly bound these Peano numbers since we need a unique key per<br>element. = They're at least spiritually similar.<br><br>## Instantiation<br>Publis= h a booklet of all the signatures for the Increment and<br>Decrement rules.= <br><br>Honest parties should destroy the secret key sets `k`.<br><br><br>T= o create a counter, simply spend to output C:<br><br>```<br>Amount: 1 satos= hi<br>Key: Tr(NUMS, {<1 || K1> CHECKSIG})<br>```<br><br><br>The signa= ture from K1 can be bound to C to 'transition' it to (+1):<br><br>`= ``<br>Amount: 1 satoshi<br>Key: Tr(NUMS, {<1 || K2> CHECKSIG})<br>```= <br><br>Which can then transition to (+1):<br><br>```<br>Amount: 1 satoshi<= br>Key: Tr(NUMS, {<1 || K3> CHECKSIG})<br>```<br><br>Which can then t= ransition (-1) to:<br><br>```<br>Amount: 1 satoshi<br>Key: Tr(NUMS, {<1 = || K2> CHECKSIG})<br>```<br><br>This can repeat indefinitely.<br><br><br= >We can generalize this technique from `1...5` to `1...N`.<br><br><br><br>#= Handling Arbitrary Deposits / Withdrawals<br><br><br>One issue with the de= sign presented previously is that it does not<br>handle arbitrary deposits = well.<br><br>One simple way to handle this is to instantiate the protocol f= or every<br>amount you'd like to support.<br><br>This is not particular= ly efficient and requires a lot of storage<br>space.<br><br>Alternatively, = divide (using base 2 or another base) the deposit<br>amount into a counter = utxo per bit.<br><br>For each bit, instead of creating outputs with 1 satos= hi, create<br>outputs with 2^i satoshis.<br><br>Instead of using keys `K1..= .KN`, create keys `K^i_j`, where i<br>represents the number of sats, and j = represents the counter. Multiple<br>keys are required per amount otherwise = the signatures would be valid<br>for burning funds.<br><br>## Splitting and= Joining<br><br>For each `K^i_j`, it may also be desirable to allow splitti= ng or<br>joining.<br><br>Splitting can be accomplished by pre-signing, for = every `K^i_j`, where<br>`i!=3D0`, with `SIGHASH_ALL | SIGHASH_ANYPREVOUT`:<= br><br>```<br>Input: 2^i sats with key K^i_j<br>Outputs:<br>=C2=A0 =C2=A0 -= 2^i-1 sats to key K^{i-1}_j<br>=C2=A0 =C2=A0 - 2^i-1 sats to key K^{i-1}_j= <br>```<br><br>Joining can be accomplished by pre-signing, for every `K^i_j= `, where<br>`i!=3DMAX`, with `SIGHASH_ALL | SIGHASH_ANYPREVOUT`:<br><br>```= <br>Inputs:<br>=C2=A0 =C2=A0 - 2^i sats with key K^i_j<br>=C2=A0 =C2=A0 - 2= ^i sats with key K^i_j<br>Outputs:<br>=C2=A0 =C2=A0 - 2^i+1 sats to key K^{= i+1}_j<br>```<br><br>N.B.: Joining allows for third parties to deposit mone= y in externally,<br>that is not a part of the covenant.<br><br><br>The spli= tting and joining behavior means that spookchain operators<br>would be empo= wered to consolidate UTXOs to a smaller number, while<br>allowing arbitrary= deposits.<br><br><br># One Vote Per Block<br><br>To enforce that only one = vote per block mined is allowed, ensure that<br>all signatures set the inpu= t sequence to 1 block. No CSV is required<br>because nSequence is in the si= gnatures already.<br><br># Terminal States / Thresholds<br><br>When a count= er reaches the Nth state, it represents a certain amount<br>of accumulated = work over a period where progress was agreed on for<br>some outcome.<br><br= >There should be some viable state transition at this point.<br><br>One sol= ution would be to have the money at this point sent to an<br>`OP_TRUE` outp= ut, which the miner incrementing that state is<br>responsible for following= the rules of the spookchain. Or, it could be<br>specified to be some admin= istrator key / federation for convenience,<br>with a N block timeout that d= egrades it to fewer signers (eventually<br>0) if the federation is dead to = allow recovery.<br><br>This would look like, from any `K^i_j`, a signature = for a transaction<br>putting it into an `OP_TRUE` and immediately spending = it. Other<br>spookchain miners would be expected to orphan that miner other= wise.<br><br><br># Open States / Proposals<br><br>From a state `K^i_1`, the= transaction transitioning to `K^i_2` can be<br>treated as 'special'= ; and the `OP_RETURN` output type can be used to<br>commit to, e.g., the ou= tputs that must be created in when the Terminal<br>State is reached. This c= larifies the issue of "what is being voted<br>on".<br><br>This me= thod does not *lock in* at a consensus layer what Terminal<br>State is bein= g voted on.<br><br>In certain circumstances, without violating the one-time= -setup<br>constraint, if a fixed list of withdrawer's addresses is know= n in<br>advance, the Open States could cover withdrawals to specific<br>par= ticipants, which then must collect a certain number of votes from<br>miners= .=C2=A0 However, it seems impossible, without new primitives, for an<br>arb= itrary transaction proposal to be voted on.<br><br># Setup Variants<br><br>= ## xpubs<br><br>Instead of using randomly generated keys for each state, de= fine each<br>to be an xpub and derive a path where it is k/i/j for each<br>= state/satoshi amount. This saves some data, and also requires less<br>entro= py.<br><br>### Trustless Data Commit:<br><br>commit to the hash of the enti= re program spec as a tweak to the xpub,<br>so that someone can quickly veri= fy if they have all the signatures you<br>are expected to generate if hones= t.<br><br>One way to do this is to convert a hash to a list of HD Child Num= bers<br>(9 of them) deterministically, and tweak the xpub by that. This is = a<br>convenient, yet inefficient, way to tweak an xpub because the child<br= >has a normal derivation path for signing devices.<br><br>## Single Party<b= r><br>A single party pre-signs all the transactions for the spookchain, and= <br>then deletes their xpriv.<br><br>You trust them to have deleted the key= , and signed properly, but you<br>do not trust whoever served you the spook= chain blob to have given you<br>all the state transitions because of the tr= ustless data commitment.<br><br>## MuSig Multi-Party<br><br>Define a MuSig = among all participants in the setup ceremony, N-of-N.<br><br>Now you simply= trust that any one person in the one-time-setup was<br>honest! Very good.<= br><br>## Unaggregated Multi-Party<br><br><br>Allow for unaggregated multi-= sig keys in the spec. This grows with<br>O(signers), however, it means that= a-la-carte you can aggregate setups<br>from random participants who never = interacted / performed setup<br>ceremonies independently if they signed the= same specs.<br><br>Can also combine multiple MuSig Multi-Parties in this w= ay.<br><br>This is nice because MuSig inherently implies the parties collud= ed at<br>one point to do a MuSig setup, whereas unaggregated multi-sig coul= d be<br>performed with no connectivity between parties.<br><br>## Soft Fork= ing Away Trust<br><br>Suppose a spookchain becomes popular. You could confi= gure your client<br>to reject invalid state transitions, or restrict the sp= ookchain keys<br>to only sign with the known signatures. This soft fork wou= ld smoothly<br>upgrade the trust assumption.<br><br>## Symmetry of State Tr= ansition Rules & DAG Covenants<br><br>We could have our increment state= transitions be done via a trustless<br>covenant, and our backwards state t= ransitions be done via the setup.<br><br>This would look something like the= following for state i:<br><br>```<br>Tr(NUMS, {<br>=C2=A0 =C2=A0 `<sig = for state K_{i+1}> <1 || PK_nonsecret> CHECKSIG`,<br>=C2=A0 =C2=A0= `<1 || Ki> CHECKSIG`<br>})<br>```<br><br>The advantage of such an op= timization is theoretically nice because it<br>means that *only* the non-de= structuring recursive part of the<br>computation is subject to the one-time= -setup trust assumption, which<br>might be of use in various other protocol= s, where recursivity might<br>only be unlocked e.g. after a timeout (but fo= r spookchains it is used<br>at each step).<br><br>A compiler writer might p= erform this task by starting with an<br>arbitrary abstract graph, and then = removing edges selectively (a<br>number of heuristics may make sense, e.g.,= to minimize reliance on<br>one-time-setup or minimize costs) until the gra= ph is a Directed<br>Acyclic Graph, consisting of one or more components, co= mpiling those<div>with committed covenants, and then<span class=3D"gmail_de= fault" style=3D"font-family:arial,helvetica,sans-serif;font-size:small;colo= r:rgb(0,0,0)"> </span>adding the removed edges back using</div><div>the one= -time-setup key materials.<br><br><br># Commentary on Trust and Covenantine= ss<br><br>Is this a covenant? I would say "yes". When I defined c= ovenants in my<br>_Calculus of Covenants_ post, it was with a particular se= t of<br>assumptions per covenant.<br><br>Under that model, you could, e.g.,= call a 7-10 multi-sig with specific<br>committed instructions as 4-10 hone= st (requires 4 signatories to be<br>honest to do invalid state transition) = and 4-10 killable (requires 4<br>signatories to die to have no way of recov= ering).<br><br>For emulations that are pre-signed, like the varieties used = to emulate<br>CTV, it is a different model because if your program is corre= ct and<br>you've pre-gotten the signatures for N-N it is 1-N honest (on= ly 1<br>party must be honest to prevent an invalid state transition) and<br= >unkillable (all parties can safely delete keys).<br><br>I model these type= s of assumptions around liveness and honesty as<br>different 'complexit= y classes' than one another.<br><br>What I would point out is that with= the counter model presented above,<br>this is entirely a pre-signed 1-N ho= nest and unkillable covenant that<br>requires no liveness from signers. Fur= ther, with APO, new instances of<br>the covenant do not require a new set o= f signers, the setup is truly<br>one-time. Therefore this type of covenant = exists in an even lower<br>trust-complexity class than CTV emulation via pr= esigneds, which<br>requires a new federation to sign off on each contract i= nstance.<br><br><br>With that preface, let us analyze this covenant:<br><br= ><br>1) A set of sets of transaction intents (a family), potentially<br>rec= ursive or co-recursive (e.g., the types of state transitions that<br>can be= generated).=C2=A0 These intents can also be represented by a<br>language t= hat generates the transactions, rather than the literal<br>transactions the= mselves. We do the family rather than just sets at<br>this level because to= instantiate a covenant we must pick a member of<br>the family to use.<br><= br><br>The set of sets of transaction intents is to increment / decrement t= o<br>a successor or predecessor, or to halve into two instances or double<b= r>value by adding funds. Each successor or predecessor is the same type<br>= of covenant, with the excetion of the first and last, which have some<br>sp= ecial rules.<br><br><br>2) A verifier generator function that generates a f= unction that<br>accepts an intent that is any element of one member of the = family of<br>intents and a proof for it and rejects others.<br><br>The veri= fier generator is the simple APO CHECKSIG script.<br><br>3) A prover genera= tor function that generates a function that takes an<br>intent that is any = element of one member of the family and some extra<br>data and returns eith= er a new prover function, a finished proof, or a<br>rejection (if not a val= id intent).<br><br>The prover generator is the selection of the correct sig= nature from a<br>table for a given script.<br><br>Run the prover generator = with the private keys present *once* to<br>initialize over all reachable st= ates, and cache the signatures, then<br>the keys may be deleted for future = runs.<br><br>4) A set of proofs that the Prover, Verifier, and a set of int= ents are<br>"impedance matched", that is, all statements the prov= er can prove and<br>all statements the verifier can verify are one-to-one a= nd onto (or<br>something similar), and that this also is one-to-one and ont= o with one<br>element of the intents (a set of transactions) and no other.<= br><br>At a given key state the only things that may happen are signed<br>t= ransactions, no other data is interpreted off of the stack. Therefore<br>th= ere is perfect impedance match.<br><br><br>5) A set of assumptions under wh= ich the covenant is verified (e.g., a<br>multi-sig covenant with at least 1= -n honesty, a multisig covenant with<br>any 3-n honesty required, Sha256 co= llision resistance, Discrete Log<br>Hardness, a SGX module being correct).<= br><br>Uniquely, that during the setup phase at least one of the keys<br>we= re faithfully deleted.<br><br>The usual suspects for any bitcoin transactio= n are also assumed for<br>security.<br><br><br>6) Composability:<br><br>The= Terminal State can pay out into a pre-specified covenant if<br>desired fro= m any other family of covenants.<br clear=3D"all"><div><div dir=3D"ltr"><di= v dir=3D"ltr">--<br><a href=3D"https://twitter.com/JeremyRubin" target=3D"_= blank">@JeremyRubin</a><br></div></div></div></div></div> _______________________________________________<br> bitcoin-dev mailing list<br> <a href=3D"mailto:bitcoin-dev@lists.linuxfoundation.org" target=3D"_blank">= bitcoin-dev@lists.linuxfoundation.org</a><br> <a href=3D"https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev" = rel=3D"noreferrer" target=3D"_blank">https://lists.linuxfoundation.org/mail= man/listinfo/bitcoin-dev</a><br> </blockquote></div> --0000000000007b864205e9db5c7b--