1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
|
Return-Path: <fresheneesz@gmail.com>
Received: from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137])
by lists.linuxfoundation.org (Postfix) with ESMTP id 40F61C000B
for <bitcoin-dev@lists.linuxfoundation.org>;
Fri, 11 Mar 2022 14:11:58 +0000 (UTC)
Received: from localhost (localhost [127.0.0.1])
by smtp4.osuosl.org (Postfix) with ESMTP id 3106341959
for <bitcoin-dev@lists.linuxfoundation.org>;
Fri, 11 Mar 2022 14:11:58 +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 eylJidm2J4sm
for <bitcoin-dev@lists.linuxfoundation.org>;
Fri, 11 Mar 2022 14:11:54 +0000 (UTC)
X-Greylist: whitelisted by SQLgrey-1.8.0
Received: from mail-ed1-x52f.google.com (mail-ed1-x52f.google.com
[IPv6:2a00:1450:4864:20::52f])
by smtp4.osuosl.org (Postfix) with ESMTPS id 1ADFE4195C
for <bitcoin-dev@lists.linuxfoundation.org>;
Fri, 11 Mar 2022 14:11:54 +0000 (UTC)
Received: by mail-ed1-x52f.google.com with SMTP id h13so11061246ede.5
for <bitcoin-dev@lists.linuxfoundation.org>;
Fri, 11 Mar 2022 06:11:53 -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=jevb2hjZTTz6KyWSztUgewuImFF9M3pYutUZwImJD1s=;
b=UxpYhI6b/u9Sh4TNX0fxcBk+Knbs5Io7MwNxswwOioXMKuQXEoJtVYZUwj0ezM1ZB5
nzCWYL2ylo4sCYhYIJlW7f3Rs2PkFxxSB1FyZoE835tLniwg/FVict4USi2/EeubZEqV
M3VPkcbt5wwmJVizkmz6ZFWdjlt3+BFW5EC8r/niBSzghro3DeV1MGpAIfS2H6NKC2rX
eaYNnXsuD/gFAgFSxe/ZuDQeg+2VmLBS97nXwLH8AbR2+tPJWnw33De44hgMnbZMb94M
TrpH0WU/VQ9ARBvebbCM9Z45NG8096XxC+SBS2ms6bI83RdyHNBldLuq/Q7o0bUBaxr/
Le7Q==
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=jevb2hjZTTz6KyWSztUgewuImFF9M3pYutUZwImJD1s=;
b=E3iqH+TERj2ZDi6iGTSbWi/cwWdY3fFdzj4PFLDNqL1k3eaozFgxE2EpJKnU/mCql/
ghPMn2wAwTzo+BdkEA7kPo1hPDRG6XbRA+cKbUjmf2zj705smDSnulnmDf9etMuYC7PU
Mzrkzkx9Z4ilgxeHvvk2FOwMysj3Etfl7pArlVFBINp/b4Q5MVGNsaSwyCIcxfX82N2m
Ni2BgPhKiiey4PYMQlfLvzSN+QtdOWtTcol/tpY18YQpi6dbVhPBL1K3cDwDAVqvs8xf
xj1xJgPvnAJtFFjDG2iRrjPdLII6SbhtPdZEtUtWlC2nXDUc3sAwAZgFAmfnPGJHOX26
xh6g==
X-Gm-Message-State: AOAM533tQ7uSVMzbbOlzJzcsJLoV776uJswTIYQWMXR0SRq341PgJQzb
fhS9u/zgRHKK+dAV7fj1RmiHrGnvnztDaD2UtneDUg3lST8=
X-Google-Smtp-Source: ABdhPJwZrKmOttE7Ap7f+RyKWuLUs/dPzZlhsRnPDSwX7ha65evjyMelnMxh+OZHiD/cOL9/73t4FpwDxvZJ+9eHNOo=
X-Received: by 2002:a05:6402:5144:b0:416:3513:8c1f with SMTP id
n4-20020a056402514400b0041635138c1fmr8975880edd.355.1647007911952; Fri, 11
Mar 2022 06:11:51 -0800 (PST)
MIME-Version: 1.0
References: <EIwjydT0d68Z7Jv8_JlrCbQW6NHSSnIU5sWwE8eX2rm9K3djfzU3nQqUrmt44U8-L9sObegelHCV6Sk7h2nwq_HS1d26FophzjNU7xC_6SE=@protonmail.com>
<CAGpPWDafWGcZJOUs4wSEt0DzFP8OXB4nrbx+9sUtTe5JfdwE_w@mail.gmail.com>
<8R8D_XAaz7xYHmgWXR-pc3_GVFRzBCNdRT6s3PdKblrnnZPirB0orzLpEUvynBZHNBTiqOM_EteDdUjdqXQ5ZmrGbdlgnnfjIihgFZIXpUM=@protonmail.com>
In-Reply-To: <8R8D_XAaz7xYHmgWXR-pc3_GVFRzBCNdRT6s3PdKblrnnZPirB0orzLpEUvynBZHNBTiqOM_EteDdUjdqXQ5ZmrGbdlgnnfjIihgFZIXpUM=@protonmail.com>
From: Billy Tetrud <billy.tetrud@gmail.com>
Date: Fri, 11 Mar 2022 08:11:33 -0600
Message-ID: <CAGpPWDZwYE__YifZ0h7Bkftas6zN6Q7yOhB4rUAAwT0dcgYk7w@mail.gmail.com>
To: ZmnSCPxj <ZmnSCPxj@protonmail.com>
Content-Type: multipart/alternative; boundary="00000000000088c5b805d9f1e9e2"
X-Mailman-Approved-At: Fri, 11 Mar 2022 16:03:55 +0000
Cc: Bitcoin Protocol Discussion <bitcoin-dev@lists.linuxfoundation.org>
Subject: Re: [bitcoin-dev] Jets (Was: `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 <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, 11 Mar 2022 14:11:58 -0000
--00000000000088c5b805d9f1e9e2
Content-Type: text/plain; charset="UTF-8"
> I think we would want to have a cleanstack rule at some point
Ah is this a rule where a script shouldn't validate if more than just a
true is left on the stack? I can see how that would prevent the
non-soft-fork version of what I'm proposing.
> How large is the critical mass needed?
Well it seems we've agreed that were we going to do this, we would want to
at least do a soft-fork to make known jet scripts lighter weight (and
unknown jet scripts not-heavier) than their non-jet counterparts. So given
a situation where this soft fork happens, and someone wants to implement a
new jet, how much critical mass would be needed for the network to get some
benefit from the jet? Well, the absolute minimum for some benefit to happen
is that two nodes that support that jet are connected. In such a case, one
node can send that jet scripted transaction along without sending the data
of what the jet stands for. The jet itself is pretty small, like 2 or so
bytes. So that does impose a small additional cost on nodes that don't
support a jet. For 100,000 nodes, that means 200,000 bytes of transmission
would need to be saved for a jet to break even. So if the jet stands for a
22 byte script, it would break even when 10% of the network supported it.
If the jet stood for a 102 byte script, it would break even when 2% of the
network supported it. So how much critical mass is necessary for it to be
worth it depends on what the script is.
> Than using a dynamic lookup table, which is how I understood your
previous email about "scripts in the 1000 past blocks".
Ah, I didn't mean using a dynamic lookup. This was about the idea of jet
registration, where registered jets would be kept a count of for some
number of blocks (eg 1000) and dropped if they don't reach a threshold rate
of usage. A static lookup table would work for this, I agree.
> It would have to validate as well that the SCRIPT sub-section matches the
jet
Seems like a good idea.
> Adler32 seems a bit short though
You might be right. Certainly some more care would need to be taken in an
actual implementation than I've taken writing my back of the napkin idea
out ; )
> nothing prevents anyone from using a different SCRIPT subsection for a
particular Adler32 hash if they find a collision and can somehow convince
people to run their modified software.
Someone that can convince people to run their modified software can
*always* cause those people to chainsplit from the main chain, so I don't
think the above ideas are special in this regard.
>> it might not be worth doing it this way without a soft fork
> Which is why I pointed out that each individual jet may very well require
a softfork, or enough buy-in that you might as well just softfork.
I'm saying something rather different actually. I don't think each
individual jet requires a softfork to be quite useful. What I meant by "it
might not be worth doing it this way without a soft fork" is that we
probably want to implement a soft fork to allow all jet scripts to have
reduced blockweight. However, once most nodes support that soft fork, new
individual jets do not need a softfork for the network to take advantage of
them. As I mused about above, even 10% of the network supporting a jet
standin for a medium length script could result in significant network
bandwidth savings. Different sections of the network could decide
individually what jets they want to support without needing the usual chaos
of a soft fork for each one, but of course the more the better for a
popular jet. There would be benefits for eventually soft forking such jets
in (to make them weigh even less based on implementation of optimized
validation functions), and real life usage of those jets could inform the
decisions around them. They could already be well tested in the wild before
being upgraded in a softfork.
> Yes, but that implies additional operations (and execution overhead),
increasing the costs to use jets, which makes it even less palatable to use
jets, *in addition to* the witness hack disincentivizing jets.
For the use of a single jet, this can be completely solved by that jet. All
the additional operations you're talking about only need to happen in a
general bitcoin script evaluator. But a jet evaluator can be hand optimized
for that jet, which could operate in exactly the the function-like way you
suggested, because it would actually be a function, under the hood.
> this helps jets compose more easily; if we want a SCRIPT that
incorporates an existing jet, we do not have to manipulate the stack in a
way that the existing jet expects, we just load the proper data into the
constants table.
I think I see what you're saying about multiple jets composing together
easily. I think your idea about loading constants from their initial
positions has merit - basically function arguments that you can reference
by position rather than needing to arrange them in the right order on the
stack. Such is the existence of a stack-based language. I like the idea of
eg `c1` to `c26` paralleling the pushdata opcodes. The question I have is:
where would the constants table come from? Would it reference the original
positions of items on the witness stack?
On Thu, Mar 10, 2022 at 12:44 AM ZmnSCPxj <ZmnSCPxj@protonmail.com> wrote:
> Good morning Billy,
>
> > Hi ZmnSCPxj,
> >
> > > Just ask a bunch of fullnodes to add this 1Mb of extra ignored data
> in this tiny 1-input-1-output transaction so I pay only a small fee
> >
> > I'm not suggesting that you wouldn't have to pay a fee for it. You'd pay
> a fee for it as normal, so there's no DOS vector. Doesn't adding
> extra witness data do what would be needed here? Eg simply adding extra
> data onto the witness script that will remain unconsumed after successful
> execution of the script?
>
> I think we would want to have a cleanstack rule at some point (do not
> remember out-of-hand if Taproot already enforces one).
>
> So now being nice to the network is *more* costly?
> That just *dis*incentivizes jet usage.
>
> > > how do new jets get introduced?
> >
> > In scenario A, new jets get introduced by being added to bitcoin
> software as basically relay rules.
> >
> > > If a new jet requires coordinated deployment over the network, then
> you might as well just softfork and be done with it.
> >
> > It would not need a coordinated deployment. However, the more nodes that
> supported that jet, the more efficient using it would be for the network.
> >
> > > If a new jet can just be entered into some configuration file, how do
> you coordinate those between multiple users so that there *is* some benefit
> for relay?
> >
> > When a new version of bitcoin comes out, people generally upgrade to it
> eventually. No coordination is needed. 100% of the network need not support
> a jet. Just some critical mass to get some benefit.
>
> How large is the critical mass needed?
>
> If you use witness to transport jet information across non-upgraded nodes,
> then that disincentivizes use of jets and you can only incentivize jets by
> softfork, so you might as well just get a softfork.
>
> If you have no way to transport jet information from an upgraded through a
> non-upgraded back to an upgraded node, then I think you need a fairly large
> buy-in from users before non-upgraded nodes are rare enough that relay is
> not much affected, and if the required buy-in is large enough, you might as
> well softfork.
>
> > > Having a static lookup table is better since you can pattern-match on
> strings of specific, static length
> >
> > Sorry, better than what exactly?
>
> Than using a dynamic lookup table, which is how I understood your previous
> email about "scripts in the 1000 past blocks".
>
> > > How does the unupgraded-to-upgraded boundary work?
> > <snip>
> > When the non-jet aware node sends this to a jet-aware node, that node
> would see the extra items on the stack after script execution, and would
> interpret them as an OP_JET call specifying that OP_JET should replace the
> witness items starting at index 0 with `1b5f03cf OP_JET`. It does this and
> then sends that along to the next hop.
>
> It would have to validate as well that the SCRIPT sub-section matches the
> jet, else I could pretend to be a non-jet-aware node and give you a SCRIPT
> sub-section that does not match the jet and would cause your validation to
> diverge from other nodes.
>
> Adler32 seems a bit short though, it seems to me that it may lead to two
> different SCRIPT subsections hashing to the same hash.
>
> Suppose I have two different node softwares.
> One uses a particular interpretation for a particular Adler32 hash.
> The other uses a different interpretation.
> If we are not careful, if these two jet-aware software talk to each other,
> they will ban each other from the network and cause a chainsplit.
> Since the Bitcoin software is open source, nothing prevents anyone from
> using a different SCRIPT subsection for a particular Adler32 hash if they
> find a collision and can somehow convince people to run their modified
> software.
>
> > In order to support this without a soft fork, this extra otherwise
> unnecessary data would be needed, but for jets that represent long scripts,
> the extra witness data could be well worth it (for the network).
> >
> > However, this extra data would be a disincentive to do transactions this
> way, even when its better for the network. So it might not be worth doing
> it this way without a soft fork. But with a soft fork to upgrade nodes to
> support an OP_JET opcode, the extra witness data can be removed (replaced
> with out-of-band script fragment transmission for nodes that don't support
> a particular jet).
>
> Which is why I pointed out that each individual jet may very well require
> a softfork, or enough buy-in that you might as well just softfork.
>
> > One interesting additional thing that could be done with this mechanism
> is to add higher-order function ability to jets, which could allow nodes to
> add OP_FOLD or similar functions as a jet without requiring additional soft
> forks. Hypothetically, you could imagine a jet script that uses an OP_LOOP
> jet be written as follows:
> >
> > 5 # Loop 5 times
> > 1 # Loop the next 1 operation
> > 3c1g14ad
> > OP_JET
> > OP_ADD # The 1 operation to loop
> >
> > The above would sum up 5 numbers from the stack. And while this
> summation jet can't be represented in bitcoin script on its own (since
> bitcoin script can't manipulate opcode calls), the jet *call* can still be
> represented as:
> >
> > OP_ADD
> > OP_ADD
> > OP_ADD
> > OP_ADD
> > OP_ADD
> >
> > which means all of the above replacement functionality would work just
> as well.
> >
> > So my point here is that jets implemented in a way similar to this would
> give a much wider range of "code as compression" possibilities than
> implementing a single opcode like op_fold.
>
> Yes, that is certainly the case, and nothing really prevents us bringing
> "programming as compression" to its logical conclusion.
>
> > > To make jets more useful, we should redesign the language so that
> `OP_PUSH` is not in the opcode stream, but instead, we have a separate
> table of constants that is attached / concatenated to the actual SCRIPT.
> >
> > This can already be done, right? You just have to redesign the script to
> consume and swap/rot around the data in the right way to separate them out
> from the main script body.
>
> Yes, but that implies additional operations (and execution overhead),
> increasing the costs to use jets, which makes it even less palatable to use
> jets, *in addition to* the witness hack disincentivizing jets.
>
> So I would suggest that, if we were to seriously pursue jets, we should
> really replace most of the `OP_PUSH` opcodes with variants that look up in
> a static table at the start, before the executable script body.
> I.e. opcodes 0x01 to 0x4e instead mean "push contents of `c1` to `c78`
> from the constants table", and have aliases `a` through `z` for `c1` to
> `c26`, etc.
> That way, replacing the `OP_PUSH` is shorter in the actual SCRIPT (instead
> of a bunch of stack manipulations) and hopefully the overhead of the
> constants table can be kept low.
>
> In particular, this helps jets compose more easily; if we want a SCRIPT
> that incorporates an existing jet, we do not have to manipulate the stack
> in a way that the existing jet expects, we just load the proper data into
> the constants table.
>
> Or something, anyway.
> This seems a fair amount of complexity here.
>
> Regards,
> ZmnSCPxj
>
--00000000000088c5b805d9f1e9e2
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>> I think we would want to have a cleanstack rule =
at some point</div><div><br></div><div>Ah is this a rule where a script sho=
uldn't validate if more than just a true is left on the stack? I can se=
e how that would prevent the non-soft-fork version of what I'm proposin=
g.=C2=A0</div><div><br></div><div>> How large is the critical mass neede=
d?</div><div><br></div><div>Well it seems we've agreed that were we goi=
ng to do this, we would want to at least do a soft-fork to make known jet s=
cripts lighter weight (and unknown jet scripts not-heavier) than their=C2=
=A0non-jet counterparts. So given a situation where this soft fork happens,=
and someone wants to implement a new jet, how much critical mass would be =
needed for the network to get some benefit from the jet? Well, the absolute=
minimum for some benefit to happen is that two nodes that support that jet=
are connected. In such a case, one node can send that jet scripted transac=
tion along without sending the data of what the jet stands for. The jet its=
elf is pretty small, like 2 or so bytes. So that does impose a small additi=
onal cost on nodes that don't support a jet. For 100,000 nodes, that me=
ans 200,000 bytes of transmission would need to be saved for a jet to break=
even. So if the jet stands for a 22 byte script, it would break even when =
10% of the network supported it. If the jet stood for a 102 byte script, it=
would break even when 2% of the network supported it. So=20
how much critical mass is necessary for it to be worth it depends on what t=
he script is.=C2=A0</div><div><br></div>>=C2=A0
Than using a dynamic lookup table, which is how I understood your previous =
email about "scripts in the 1000 past blocks".<div><br></div><div=
>Ah, I didn't mean using a dynamic lookup. This was about the idea of j=
et registration, where registered jets would be kept a count of for some nu=
mber of blocks (eg 1000) and dropped if they don't reach a threshold ra=
te of usage. A static lookup table would work for this,=C2=A0I agree.=C2=A0=
</div><div><br></div><div>> It would have to validate as well that the S=
CRIPT sub-section matches the jet</div><div><br></div><div>Seems like a goo=
d idea.</div><div><br></div><div>> Adler32 seems a bit short though</div=
><div><br></div><div>You might be right. Certainly some more care would nee=
d to be taken in an actual implementation than I've taken writing my ba=
ck of the napkin idea out ; )</div><div><br></div><div>> nothing prevent=
s anyone from using a different SCRIPT subsection for a particular Adler32 =
hash if they find a collision and can somehow convince people to run their =
modified software.</div><div><br></div><div>Someone that can convince peopl=
e to run their modified software can *always* cause those people to chainsp=
lit=C2=A0from the main chain, so I don't think the above ideas are spec=
ial in this regard.</div><div><br></div><div>>>=C2=A0<span style=3D"c=
olor:rgb(80,0,80)">it might not be worth doing it this way without a soft f=
ork</span></div><div>> Which is why I pointed out that each individual j=
et may very well require a softfork, or enough buy-in that you might as wel=
l just softfork.</div><div><br></div><div>I'm saying something rather d=
ifferent actually. I don't think each individual jet requires a softfor=
k to be quite useful. What I meant by "<span style=3D"color:rgb(80,0,8=
0)">it might not be worth doing it this way without a soft fork" </spa=
n>is that we probably want to implement a soft fork to allow all jet script=
s to have reduced blockweight. However, once most nodes support that soft f=
ork, new individual jets do not need a softfork=C2=A0for the network to tak=
e advantage of them. As I mused about above, even 10% of the network suppor=
ting a jet standin=C2=A0for a medium length script could result in signific=
ant network bandwidth savings. Different sections of the network could deci=
de individually what jets they want to support without needing the usual ch=
aos of a soft fork for each one, but of course the more the better for a po=
pular jet. There would be benefits for eventually soft forking such jets in=
(to make them weigh even less based on implementation of optimized validat=
ion functions), and real life usage of those jets could inform the decision=
s around them. They could already be well tested in the wild before being u=
pgraded in a softfork.</div><div><br></div><div>> Yes, but that implies =
additional operations (and execution overhead), increasing the costs to use=
jets, which makes it even less palatable to use jets, *in addition to* the=
witness hack disincentivizing jets.</div><div><br></div><div>For the use o=
f a single jet, this can be completely solved by that jet. All the addition=
al operations you're talking about only need to happen in a general bit=
coin script evaluator. But a jet evaluator can be hand optimized for that j=
et, which could operate in exactly the the function-like way you suggested,=
because it would actually be a function, under the hood.=C2=A0</div><div><=
br></div><div>> this helps jets compose more easily; if we want a SCRIPT=
that incorporates an existing jet, we do not have to manipulate the stack =
in a way that the existing jet expects, we just load the proper data into t=
he constants table.</div><div><br></div><div>I think I see what you're =
saying about multiple jets composing together easily. I think your idea abo=
ut loading constants from their initial positions has merit - basically fun=
ction arguments that you can reference by position rather than needing to a=
rrange them in the right order on the stack. Such is the existence of a sta=
ck-based language. I like the idea of eg `c1` to `c26` paralleling the push=
data opcodes. The question I have is: where would the constants table come =
from? Would it reference the original positions of items on the witness sta=
ck?=C2=A0</div><div><br></div><div><br></div><div><br></div><div><br></div>=
<div><br></div><div><br></div></div><br><div class=3D"gmail_quote"><div dir=
=3D"ltr" class=3D"gmail_attr">On Thu, Mar 10, 2022 at 12:44 AM ZmnSCPxj <=
;<a href=3D"mailto:ZmnSCPxj@protonmail.com" target=3D"_blank">ZmnSCPxj@prot=
onmail.com</a>> wrote:<br></div><blockquote class=3D"gmail_quote" style=
=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding=
-left:1ex">Good morning Billy,<br>
<br>
> Hi=C2=A0ZmnSCPxj,<br>
><br>
> >=C2=A0 Just ask a bunch of fullnodes to add this 1Mb of extra igno=
red data in this tiny 1-input-1-output transaction so I pay only a small fe=
e<br>
><br>
> I'm not suggesting that you wouldn't have to pay a fee for it.=
You'd pay a fee for it as normal, so there's no DOS vector. Doesn&=
#39;t adding extra=C2=A0witness data do what would be needed here? Eg simpl=
y adding extra data onto the witness script that will remain unconsumed aft=
er successful execution of the script?<br>
<br>
I think we would want to have a cleanstack rule at some point (do not remem=
ber out-of-hand if Taproot already enforces one).<br>
<br>
So now being nice to the network is *more* costly?<br>
That just *dis*incentivizes jet usage.<br>
<br>
> > how do new jets get introduced?<br>
><br>
> In scenario A, new jets get introduced by being added to bitcoin softw=
are as basically relay rules.=C2=A0<br>
><br>
> > If a new jet requires coordinated deployment over the network, th=
en you might as well just softfork and be done with it.<br>
><br>
> It would not need a coordinated deployment. However, the more nodes th=
at supported that jet, the more efficient using it would be for the network=
.=C2=A0<br>
><br>
> > If a new jet can just be entered into some configuration file, ho=
w do you coordinate those between multiple users so that there *is* some be=
nefit for relay?<br>
><br>
> When a new version of bitcoin comes out, people generally upgrade to i=
t eventually. No coordination is needed. 100% of the network need not suppo=
rt a jet. Just some critical mass to=C2=A0get some benefit.=C2=A0<br>
<br>
How large is the critical mass needed?<br>
<br>
If you use witness to transport jet information across non-upgraded nodes, =
then that disincentivizes use of jets and you can only incentivize jets by =
softfork, so you might as well just get a softfork.<br>
<br>
If you have no way to transport jet information from an upgraded through a =
non-upgraded back to an upgraded node, then I think you need a fairly large=
buy-in from users before non-upgraded nodes are rare enough that relay is =
not much affected, and if the required buy-in is large enough, you might as=
well softfork.<br>
<br>
> > Having a static lookup table is better since you can pattern-matc=
h on strings of specific, static length<br>
><br>
> Sorry, better than what exactly?=C2=A0<br>
<br>
Than using a dynamic lookup table, which is how I understood your previous =
email about "scripts in the 1000 past blocks".<br>
<br>
> > How does the unupgraded-to-upgraded boundary work?<br>
> <snip><br>
> When the non-jet aware node sends this to a jet-aware node, that node =
would see the extra items on the stack after script execution, and would in=
terpret them as an OP_JET call specifying that OP_JET should replace the wi=
tness items starting at index 0 with `1b5f03cf=C2=A0=C2=A0OP_JET`. It does =
this and then sends that along to the next hop.<br>
<br>
It would have to validate as well that the SCRIPT sub-section matches the j=
et, else I could pretend to be a non-jet-aware node and give you a SCRIPT s=
ub-section that does not match the jet and would cause your validation to d=
iverge from other nodes.<br>
<br>
Adler32 seems a bit short though, it seems to me that it may lead to two di=
fferent SCRIPT subsections hashing to the same hash.<br>
<br>
Suppose I have two different node softwares.<br>
One uses a particular interpretation for a particular Adler32 hash.<br>
The other uses a different interpretation.<br>
If we are not careful, if these two jet-aware software talk to each other, =
they will ban each other from the network and cause a chainsplit.<br>
Since the Bitcoin software is open source, nothing prevents anyone from usi=
ng a different SCRIPT subsection for a particular Adler32 hash if they find=
a collision and can somehow convince people to run their modified software=
.<br>
<br>
> In order to support this without a soft fork, this extra otherwise unn=
ecessary=C2=A0data would be needed, but for jets that represent long script=
s, the extra witness data could be well worth it (for the network).=C2=A0<b=
r>
><br>
> However, this extra data would be a disincentive to do transactions th=
is way, even when its=C2=A0better for the network. So it might not be worth=
doing it this way without a soft fork. But with a soft fork to upgrade nod=
es to support an OP_JET opcode, the extra witness data can be removed (repl=
aced with out-of-band script fragment transmission for nodes that don't=
support a particular jet).=C2=A0<br>
<br>
Which is why I pointed out that each individual jet may very well require a=
softfork, or enough buy-in that you might as well just softfork.<br>
<br>
> One interesting additional thing that could be done with this mechanis=
m is to add higher-order function ability to jets, which could allow nodes =
to add OP_FOLD or similar functions as a jet without requiring additional s=
oft forks.=C2=A0 Hypothetically, you could imagine a jet script that uses a=
n OP_LOOP jet be written as follows:<br>
><br>
> 5=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0# Loop 5 times<br>
> 1=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0# Loop the next 1 ope=
ration<br>
> 3c1g14ad=C2=A0<br>
> OP_JET<br>
> OP_ADD=C2=A0 # The 1 operation to loop<br>
><br>
> The above would sum up 5 numbers from the stack. And while this summat=
ion jet can't be represented in bitcoin script on its own (since bitcoi=
n script can't manipulate opcode calls), the jet *call* can still be re=
presented as:<br>
><br>
> OP_ADD=C2=A0=C2=A0<br>
> OP_ADD=C2=A0=C2=A0<br>
> OP_ADD=C2=A0=C2=A0<br>
> OP_ADD=C2=A0=C2=A0<br>
> OP_ADD=C2=A0=C2=A0<br>
><br>
> which means all of the above replacement functionality would work just=
as well.=C2=A0<br>
><br>
> So my point here is that jets implemented in a way similar to this wou=
ld give a much wider range of "code as compression" possibilities=
than implementing a single opcode like op_fold.=C2=A0<br>
<br>
Yes, that is certainly the case, and nothing really prevents us bringing &q=
uot;programming as compression" to its logical conclusion.<br>
<br>
> > To make jets more useful, we should redesign the language so that=
`OP_PUSH` is not in the opcode stream, but instead, we have a separate tab=
le of constants that is attached / concatenated to the actual SCRIPT.<br>
><br>
> This can already be done, right? You just have to redesign the script =
to consume and swap/rot around the data in the right way to separate them o=
ut from the main script body.=C2=A0<br>
<br>
Yes, but that implies additional operations (and execution overhead), incre=
asing the costs to use jets, which makes it even less palatable to use jets=
, *in addition to* the witness hack disincentivizing jets.<br>
<br>
So I would suggest that, if we were to seriously pursue jets, we should rea=
lly replace most of the `OP_PUSH` opcodes with variants that look up in a s=
tatic table at the start, before the executable script body.<br>
I.e. opcodes 0x01 to 0x4e instead mean "push contents of `c1` to `c78`=
from the constants table", and have aliases `a` through `z` for `c1` =
to `c26`, etc.<br>
That way, replacing the `OP_PUSH` is shorter in the actual SCRIPT (instead =
of a bunch of stack manipulations) and hopefully the overhead of the consta=
nts table can be kept low.<br>
<br>
In particular, this helps jets compose more easily; if we want a SCRIPT tha=
t incorporates an existing jet, we do not have to manipulate the stack in a=
way that the existing jet expects, we just load the proper data into the c=
onstants table.<br>
<br>
Or something, anyway.<br>
This seems a fair amount of complexity here.<br>
<br>
Regards,<br>
ZmnSCPxj<br>
</blockquote></div>
--00000000000088c5b805d9f1e9e2--
|