Return-Path: Received: from smtp4.osuosl.org (smtp4.osuosl.org [140.211.166.137]) by lists.linuxfoundation.org (Postfix) with ESMTP id E672DC000B for ; Mon, 7 Mar 2022 17:26:35 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id C7C56410D1 for ; Mon, 7 Mar 2022 17:26:35 +0000 (UTC) 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 Authentication-Results: smtp4.osuosl.org (amavisd-new); dkim=pass (2048-bit key) header.d=gmail.com Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id TUgD9Ux59kPR for ; Mon, 7 Mar 2022 17:26:32 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.8.0 Received: from mail-ej1-x632.google.com (mail-ej1-x632.google.com [IPv6:2a00:1450:4864:20::632]) by smtp4.osuosl.org (Postfix) with ESMTPS id 642AB410B3 for ; Mon, 7 Mar 2022 17:26:32 +0000 (UTC) Received: by mail-ej1-x632.google.com with SMTP id qa43so33457937ejc.12 for ; Mon, 07 Mar 2022 09:26:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=89Ke4B72bFC7UTUGikTWCRwIpP4CZr11JV6vD91QXdQ=; b=kpahSjnG41YSZUsqNC0Rs8/NUwLpNblQIZZHYGi+WZU0/Bk/ThfzfvIe22F6RnF99L YNlWZ/8FfHYh5JydvGjkeq6rYuxwaXBiqA98+mBT01biTYpKpQLKYpYF53JJrvNEpmIF AJiEd0jHPssOjFUjeC5/sSvQ108SnL4PpsJCGyErl4RItOgpD5XtnhFZ3IFo9tC2Mumu FBtyFPQtxIsKRgOz1sjjza5ZKlvdtIXByshbpVAr0xBHZIt8OHqQ9FBkjeBmXNZTq6DZ ufWkZLmdOcZvH6+4NBrzT1yB5DxuT3fiWry/rxLfJ39PHrKfNNGWgTdbUkf0F6/6z70r 4E7A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=89Ke4B72bFC7UTUGikTWCRwIpP4CZr11JV6vD91QXdQ=; b=Nwu7AcN/NYgiYSSzB7phh+cPe/6YYqxUcb/5Ku/vR7u+91APR50TiV82m+2kWImOJU uLTANsH/Ys1xv+BnABKtcZ12OzQSSwzDr5U2qaUqWYB428REFTWJvVZ/Mqi+tB+xAG7M RYv6h3STR496UZLLgaFMENwqgeej82aY4/nHlQ/vX+mXVsvBBESgDmF/QF3D670YLAgP DOYQ8HbKnyN1i79XT49bfdPOl4+3A3tIAgxWrJbrK/mwR5f7Vt2iHuOdLfHl9wb8B/yD hOsleiyjrzDbe4QkSwKZGAh4wl5WFMtp3/PThpIV8m2XA5ANzKBD0aza2fbvR6okZuUR nnxg== X-Gm-Message-State: AOAM532ThKrX/mP3wXG14Nkcs1Pn/HyraTK2tE/snOpFoNqAc7+NYTYt IZb7athEPHkZ7zOuF4ZOvqHOODNhrIpUnCtkLOEhT+q7 X-Google-Smtp-Source: ABdhPJy91psC0LLQefoLX53dUu628Brao3k4jN1UgjBemlxbYPz2YBnDq5vgkra9g5b7ScIEVfqdOWySTLhs/hksviY= X-Received: by 2002:a17:907:206a:b0:6da:b2d9:5e32 with SMTP id qp10-20020a170907206a00b006dab2d95e32mr10111280ejb.176.1646673990170; Mon, 07 Mar 2022 09:26:30 -0800 (PST) MIME-Version: 1.0 References: <1zAD-_yaVAjRfYOQmNn_lh1cIQ9yxtR_TpLpHfl3A8TbtTpHEpduMloN72b-zI8U4HjrXRCHBBee16Ly89OAZJohfJuewWNCCHuacBN5TE8=@protonmail.com> <-3inEV9Skl4K8wQefM7I0EbYzQc-zWV4QPgJSXKNxx0X_2EbwyTRmVjwooU1a8wFRNU41Cr41hb-Ajno_nV39U9rOge1oaUg9MvKmQ7-v30=@protonmail.com> In-Reply-To: <-3inEV9Skl4K8wQefM7I0EbYzQc-zWV4QPgJSXKNxx0X_2EbwyTRmVjwooU1a8wFRNU41Cr41hb-Ajno_nV39U9rOge1oaUg9MvKmQ7-v30=@protonmail.com> From: Billy Tetrud Date: Mon, 7 Mar 2022 11:26:13 -0600 Message-ID: To: ZmnSCPxj Content-Type: multipart/alternative; boundary="0000000000003ec01305d9a42ae7" X-Mailman-Approved-At: Mon, 07 Mar 2022 17:42:31 +0000 Cc: Bitcoin Protocol Discussion Subject: Re: [bitcoin-dev] `OP_FOLD`: A Looping Construct For Bitcoin SCRIPT X-BeenThere: bitcoin-dev@lists.linuxfoundation.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Bitcoin Protocol Discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 07 Mar 2022 17:26:36 -0000 --0000000000003ec01305d9a42ae7 Content-Type: text/plain; charset="UTF-8" Let me organize my thoughts on this a little more clearly. There's a couple possibilities I can think of for a jet-like system: A. We could implement jets now without a consensus change, and without requiring all nodes to upgrade to new relay rules. Probably. This would give upgraded nodes improved validation performance and many upgraded nodes relay savings (transmitting/receiving fewer bytes). Transactions would be weighted the same as without the use of jets tho. B. We could implement the above + lighter weighting by using a soft fork to put the jets in a part of the blockchain hidden from unupgraded nodes, as you mentioned. C. We could implement the above + the jet registration idea in a soft fork. For A: * Upgraded nodes query each connection for support of jets in general, and which specific jets they support. * For a connection to another upgraded node that supports the jet(s) that a transaction contains, the transaction is sent verbatim with the jet included in the script (eg as some fake opcode line like 23 OP_JET, indicating to insert standard jet 23 in its place). When validation happens, or when a miner includes it in a block, the jet opcode call is replaced with the script it represents so hashing happens in a way that is recognizable to unupgraded nodes. * For a connection to a non-upgraded node that doesn't support jets, or an upgraded node that doesn't support the particular jet included in the script, the jet opcode call is replaced as above before sending to that node. In addition, some data is added to the transaction that unupgraded nodes propagate along but otherwise ignore. Maybe this is extra witness data, maybe this is some kind of "annex", or something else. But that data would contain the original jet opcode (in this example "23 OP_JET") so that when that transaction data reaches an upgraded node that recognizes that jet again, it can swap that back in, in place of the script fragment it represents. I'm not 100% sure the required mechanism I mentioned of "extra ignored data" exists, and if it doesn't, then all nodes would at least need to be upgraded to support that before this mechanism could fully work. But even if such a mechanism doesn't exist, a jet script could still be used, but it would be clobbered by the first nonupgraded node it is relayed to, and can't then be converted back (without using a potentially expensive lookup table as you mentioned). > If the script does not weigh less if it uses a jet, then there is no incentive for end-users to use a jet That's a good point. However, I'd point out that nodes do lots of things that there's no individual incentive for, and this might be one where people either altruistically use jets to be lighter on the network, or use them in the hopes that the jet is accepted as a standard, reducing the cost of their scripts. But certainly a direct incentive to use them is better. Honest nodes can favor connecting to those that support jets. >if a jet would allow SCRIPT weights to decrease, upgraded nodes need to hide them from unupgraded nodes > we have to do that by telling unupgraded nodes "this script will always succeed and has weight 0" Right. It doesn't have to be weight zero, but that would work fine enough. > if everybody else has not upgraded, a user of a new jet has no security. For case A, no security is lost. For case B you're right. For case C, once nodes upgrade to the initial soft fork, new registered jets can take advantage of relay-cost weight savings (defined by the soft fork) without requiring any nodes to do any upgrading, and nodes could be further upgraded to optimize the validation of various of those registered jets, but those processing savings couldn't change the weighting of transactions without an additional soft fork. > Consider an attack where I feed you a SCRIPT that validates trivially but is filled with almost-but-not-quite-jettable code I agree a pattern-matching lookup table is probably not a great design. But a lookup table like that is not needed for the jet registration idea. After the necessary soft fork, there would be standard rules for which registered jets nodes are required to keep an index of, and so the lookup table would be a straightforward jet hash lookup rather than a pattern-matching lookup, which wouldn't have the same DOS problems. A node would simply find a jet opcode call like "ab38cd39e OP_JET" and just lookup ab38cd39e in its index. On Sun, Mar 6, 2022 at 2:38 PM ZmnSCPxj wrote: > Good morning Billy, > > > Even changing the weight of a transaction using jets (ie making a script > weigh less if it uses a jet) could be done in a similar way to how segwit > separated the witness out. > > The way we did this in SegWit was to *hide* the witness from unupgraded > nodes, who are then unable to validate using the upgraded rules (because > you are hiding the data from them!), which is why I bring up: > > > > If a new jet is released but nobody else has upgraded, how bad is my > security if I use the new jet? > > > > Security wouldn't be directly affected, only (potentially) cost. If your > security depends on cost (eg if it depends on pre-signed transactions and > is for some reason not easily CPFPable or RBFable), then security might be > affected if the unjetted scripts costs substantially more to mine. > > So if we make a script weigh less if it uses a jet, we have to do that by > telling unupgraded nodes "this script will always succeed and has weight > 0", just like `scriptPubKey`s with `<0> ` are, to pre-SegWit > nodes, spendable with an empty `scriptSig`. > At least, that is how I always thought SegWit worked. > > Otherwise, a jet would never allow SCRIPT weights to decrease, as > unupgraded nodes who do not recognize the jet will have to be fed the > entire code of the jet and would consider the weight to be the expanded, > uncompressed code. > And weight is a consensus parameter, blocks are restricted to 4Mweight. > > So if a jet would allow SCRIPT weights to decrease, upgraded nodes need to > hide them from unupgraded nodes (else the weight calculations of unupgraded > nodes will hit consensus checks), then if everybody else has not upgraded, > a user of a new jet has no security. > > Not even the `softfork` form of chialisp that AJ is proposing in the other > thread would help --- unupgraded nodes will simply skip over validation of > the `softfork` form. > > If the script does not weigh less if it uses a jet, then there is no > incentive for end-users to use a jet, as they would still pay the same > price anyway. > > Now you might say "okay even if no end-users use a jet, we could have > fullnodes recognize jettable code and insert them automatically on > transport". > But the lookup table for that could potentially be large once we have a > few hundred jets (and I think Simplicity already *has* a few hundred jets, > so additional common jets would just add to that?), jettable code could > start at arbitrary offsets of the original SCRIPT, and jettable code would > likely have varying size, that makes for a difficult lookup table. > In particular that lookup table has to be robust against me feeding it > some section of code that is *almost* jettable but suddenly has a different > opcode at the last byte, *and* handle jettable code of varying sizes > (because of course some jets are going to e more compressible than others). > Consider an attack where I feed you a SCRIPT that validates trivially but > is filled with almost-but-not-quite-jettable code (and again, note that > expanded forms of jets are varying sizes), your node has to look up all > those jets but then fails the last byte of the > almost-but-not-quite-jettable code, so it ends up not doing any jetting. > And since the SCRIPT validated your node feels obligated to propagate it > too, so now you are helping my DDoS. > > > > I suppose the point would be --- how often *can* we add new jets? > > > > A simple jet would be something that's just added to bitcoin software > and used by nodes that recognize it. This would of course require some > debate and review to add it to bitcoin core or whichever bitcoin software > you want to add it to. However, the idea I proposed in my last email would > allow anyone to add a new jet. Then each node can have their own policy to > determine which jets of the ones registered it wants to keep an index of > and use. On its own, it wouldn't give any processing power optimization, > but it would be able to do the same kind of script compression you're > talking about op_fold allowing. And a list of registered jets could inform > what jets would be worth building an optimized function for. This would > require a consensus change to implement this mechanism, but thereafter any > jet could be registered in userspace. > > Certainly a neat idea. > Again, lookup table tho. > > Regards, > ZmnSCPxj > --0000000000003ec01305d9a42ae7 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Let me organize my thoughts on this a little more cle= arly. There's a couple possibilities I can think of for a jet-like syst= em:

A. We could implement jets now without a c= onsensus change, and without=C2=A0requiring all nodes to upgrade to new rel= ay rules. Probably. This would give upgraded nodes improved=C2=A0validation= performance and many upgraded nodes relay savings (transmitting/receiving = fewer bytes). Transactions would be weighted the same as without the use of= jets tho.
B. We could implement the above=C2=A0+ lighter weighting by u= sing a soft fork to put the jets in a part of the blockchain hidden from un= upgraded nodes, as you mentioned.=C2=A0
C. We could implement the= above=C2=A0+ the jet registration idea in a soft fork.=C2=A0
For A:

* Upgraded nodes query each con= nection for support of jets in general, and which specific jets they suppor= t.
* For a connection to another upgraded node that supports the = jet(s) that a transaction contains, the transaction is sent verbatim=C2=A0w= ith the jet included in the script (eg as some fake opcode line like 23 OP_= JET, indicating to insert standard jet 23 in its place). When validation ha= ppens, or when a miner includes it in a block, the jet opcode call is repla= ced with the script it represents so hashing happens in a way that is recog= nizable to unupgraded nodes.
* For a connection to a non-upgraded= node that doesn't support jets, or an upgraded node that doesn't s= upport the particular jet included in the script, the jet opcode call is re= placed as above before sending to that node. In addition, some data is adde= d to the transaction that unupgraded nodes propagate along but otherwise ig= nore. Maybe this is extra witness data, maybe this is some kind of "an= nex", or something else. But that data would contain the original jet = opcode (in this example "23 OP_JET") so that when that transactio= n data reaches an upgraded node that recognizes that jet again, it can swap= that back in, in place of the script fragment it represents.=C2=A0

I'm not 100% sure the required mechanism I mentioned = of "extra ignored data" exists, and if it doesn't, then all n= odes would at least need to be upgraded to support that before this mechani= sm could fully work. But even if such a mechanism doesn't exist, a jet = script could still be used, but it would be clobbered by the first nonupgra= ded node it is relayed to, and can't then be converted back (without us= ing a potentially expensive lookup table as you mentioned).=C2=A0

> If the script does not weigh less if it uses a jet, th= en there is no incentive for end-users to use a jet

That's a good point. However, I'd point out that nodes do lot= s of things that there's no individual incentive for, and this might be= one where people either altruistically use jets to be lighter on the netwo= rk, or use them in the hopes that the jet is accepted as a standard, reduci= ng the cost of their scripts. But certainly a direct incentive to use them = is better. Honest nodes can favor connecting to those that support jets.

>if a jet would allow SCRIPT weights to decrease,= upgraded nodes need to hide them from unupgraded nodes
> we h= ave to do that by telling unupgraded nodes "this script will always su= cceed and has weight 0"

Right. It doesn&#= 39;t have to be weight zero, but that would work fine enough.=C2=A0

> if everybody else has not upgraded, a user of a new = jet has no security.

For case A, no security is lo= st. For case B you're right. For case C, once nodes upgrade to the init= ial soft fork, new registered jets can take advantage of relay-cost weight = savings (defined by the soft fork) without requiring any nodes to do any up= grading, and nodes could be further upgraded to optimize the validation of = various of those registered jets, but those processing savings couldn't= change the weighting of transactions without an additional soft fork.

> Consider an attack where I feed you a SCRIPT that= validates trivially but is filled with almost-but-not-quite-jettable code<= /div>

I agree a pattern-matching lookup table is probabl= y not a great design. But a lookup table like that is not needed for the je= t registration idea. After the necessary soft fork, there would be standard= rules for which registered jets nodes are required to keep an index of, an= d so the lookup table would be a straightforward jet hash lookup rather tha= n a pattern-matching lookup, which wouldn't have the same DOS problems.= A node would simply find a jet opcode call like "ab38cd39e OP_JET&quo= t; and just lookup ab38cd39e in its index.=C2=A0

=
On Sun= , Mar 6, 2022 at 2:38 PM ZmnSCPxj <ZmnSCPxj@protonmail.com> wrote:
Good morning Billy,

> Even changing the weight of a transaction using jets (ie making a scri= pt weigh less if it uses a jet) could be done in a similar=C2=A0way to how = segwit separated=C2=A0the witness out.

The way we did this in SegWit was to *hide* the witness from unupgraded nod= es, who are then unable to validate using the upgraded rules (because you a= re hiding the data from them!), which is why I bring up:

> > If a new jet is released but nobody else has upgraded, how bad is= my security if I use the new jet?
>
> Security wouldn't be directly affected, only (potentially) cost. I= f your security depends on cost (eg if it depends on pre-signed transaction= s and is for some reason not easily CPFPable or RBFable), then security mig= ht be affected if the unjetted=C2=A0scripts costs substantially more to min= e.=C2=A0

So if we make a script weigh less if it uses a jet, we have to do that by t= elling unupgraded nodes "this script will always succeed and has weigh= t 0", just like `scriptPubKey`s with `<0> <P2WKH hash>` ar= e, to pre-SegWit nodes, spendable with an empty `scriptSig`.
At least, that is how I always thought SegWit worked.

Otherwise, a jet would never allow SCRIPT weights to decrease, as unupgrade= d nodes who do not recognize the jet will have to be fed the entire code of= the jet and would consider the weight to be the expanded, uncompressed cod= e.
And weight is a consensus parameter, blocks are restricted to 4Mweight.

So if a jet would allow SCRIPT weights to decrease, upgraded nodes need to = hide them from unupgraded nodes (else the weight calculations of unupgraded= nodes will hit consensus checks), then if everybody else has not upgraded,= a user of a new jet has no security.

Not even the `softfork` form of chialisp that AJ is proposing in the other = thread would help --- unupgraded nodes will simply skip over validation of = the `softfork` form.

If the script does not weigh less if it uses a jet, then there is no incent= ive for end-users to use a jet, as they would still pay the same price anyw= ay.

Now you might say "okay even if no end-users use a jet, we could have = fullnodes recognize jettable code and insert them automatically on transpor= t".
But the lookup table for that could potentially be large once we have a few= hundred jets (and I think Simplicity already *has* a few hundred jets, so = additional common jets would just add to that?), jettable code could start = at arbitrary offsets of the original SCRIPT, and jettable code would likely= have varying size, that makes for a difficult lookup table.
In particular that lookup table has to be robust against me feeding it some= section of code that is *almost* jettable but suddenly has a different opc= ode at the last byte, *and* handle jettable code of varying sizes (because = of course some jets are going to e more compressible than others).
Consider an attack where I feed you a SCRIPT that validates trivially but i= s filled with almost-but-not-quite-jettable code (and again, note that expa= nded forms of jets are varying sizes), your node has to look up all those j= ets but then fails the last byte of the almost-but-not-quite-jettable code,= so it ends up not doing any jetting.
And since the SCRIPT validated your node feels obligated to propagate it to= o, so now you are helping my DDoS.

> >=C2=A0 I suppose the point would be --- how often *can* we add new= jets?
>
> A simple jet would be something that's just added to bitcoin softw= are and used by nodes that recognize it. This would of course require some = debate and review to add it to bitcoin core or whichever bitcoin software y= ou want to add it to. However, the idea I proposed in my last email would a= llow anyone to add a new jet. Then each node can have their own policy to d= etermine which jets of the ones registered it wants to keep an index of and= use. On its own, it wouldn't give any processing power optimization, b= ut it would be able to do the same kind of script compression you're ta= lking about op_fold allowing. And a list of registered jets could inform wh= at jets would be worth building an optimized function for.=C2=A0This would = require a consensus change to implement this mechanism, but thereafter any = jet could be registered in userspace.

Certainly a neat idea.
Again, lookup table tho.

Regards,
ZmnSCPxj
--0000000000003ec01305d9a42ae7--