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
|
Return-Path: <vjudeu@gazeta.pl>
Received: from smtp3.osuosl.org (smtp3.osuosl.org [140.211.166.136])
by lists.linuxfoundation.org (Postfix) with ESMTP id B572EC0032;
Sun, 22 Oct 2023 08:40:12 +0000 (UTC)
Received: from localhost (localhost [127.0.0.1])
by smtp3.osuosl.org (Postfix) with ESMTP id 9E5DA70999;
Sun, 22 Oct 2023 08:40:12 +0000 (UTC)
DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org 9E5DA70999
Authentication-Results: smtp3.osuosl.org;
dkim=pass (1024-bit key) header.d=gazeta.pl header.i=@gazeta.pl
header.a=rsa-sha256 header.s=2013 header.b=daHv5UFN
X-Virus-Scanned: amavisd-new at osuosl.org
X-Spam-Flag: NO
X-Spam-Score: -2.096
X-Spam-Level:
X-Spam-Status: No, score=-2.096 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,
RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, 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 Sh5uQA-Y7Y0S; Sun, 22 Oct 2023 08:40:11 +0000 (UTC)
X-Greylist: delayed 600 seconds by postgrey-1.37 at util1.osuosl.org;
Sun, 22 Oct 2023 08:40:10 UTC
DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org 05E6170998
Received: from smtpo93.poczta.onet.pl (smtpo93.poczta.onet.pl
[213.180.149.146])
by smtp3.osuosl.org (Postfix) with ESMTPS id 05E6170998;
Sun, 22 Oct 2023 08:40:09 +0000 (UTC)
Received: from pmq5v.m5r2.onet (pmq5v.m5r2.onet [10.174.35.25])
by smtp.poczta.onet.pl (Onet) with ESMTP id 4SCs2L68x3zlks;
Sun, 22 Oct 2023 10:30:02 +0200 (CEST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gazeta.pl; s=2013;
t=1697963403; bh=YhEzA5n+k0tcEVVQ+3imp/3cGcRllK38KTEL1UNQoUQ=;
h=From:Cc:To:In-Reply-To:Date:Subject:From;
b=daHv5UFNPd3+5AG9fxuzEAI83XFfiaetfIa//VGlRwMno513B8N0w6OkoQrcWbbWo
BenMZa/GJmy6adWzf1SkOfFf3i6qXZCs0BWOo4bSXt46Y4/zwNskZSLiHDIeZq400l
e2XYRhT9tDfmXbHqrHxlAouoODFiFcDlB0uar4eQ=
Content-Type: multipart/alternative;
boundary="===============0333453674442322640=="
MIME-Version: 1.0
Received: from [5.173.249.56] by pmq5v.m5r2.onet via HTTP id ;
Sun, 22 Oct 2023 10:30:02 +0200
From: vjudeu@gazeta.pl
X-Priority: 3
To: "Peter Todd <pete@petertodd.org>,
Bitcoin Protocol Discussion" <bitcoin-dev@lists.linuxfoundation.org>,
Antoine Riard <antoine.riard@gmail.com>,
Bitcoin Protocol Discussion <bitcoin-dev@lists.linuxfoundation.org>
In-Reply-To: <ZTMWrJ6DjxtslJBn@petertodd.org>
Date: Sun, 22 Oct 2023 10:30:01 +0200
Message-Id: <193770517-370d11da072c35721a528135516153d7@pmq5v.m5r2.onet>
X-Mailer: onet.poczta
X-Onet-PMQ: <vjudeu@gazeta.pl>;5.173.249.56;PL;4
X-Mailman-Approved-At: Sun, 22 Oct 2023 09:07:58 +0000
Cc: security@ariard.me, "lightning-dev\\\\@lists.linuxfoundation.org"
<lightning-dev@lists.linuxfoundation.org>
Subject: Re: [bitcoin-dev] OP_Expire and Coinbase-Like Behavior: Making
HTLCs Safer by Letting Transactions Expire Safely
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: Sun, 22 Oct 2023 08:40:14 -0000
This is a multi-part message in MIME format.
--===============0333453674442322640==
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: quoted-printable
> By redefining a bit of the nVersion field, eg the most significant bit, w=
e can apply coinbase-like txout handling to arbitrary transactions.
=C2=A0
We already have that in OP_CHECKSEQUENCEVERIFY. You can have a system with =
no coinbase transactions at all, and use only OP_CHECKSEQUENCEVERIFY on the=
first transaction, and set sequence numbers to put a relative locktime of =
100 blocks. Also, if you think some soft-fork is needed anyway, then I reco=
mmend building it around already existing OP_CHECKSEQUENCEVERIFY, than rein=
vent the wheel.
=C2=A0
> Redefining an existing OP_Nop opcode, OP_Expire would terminate script ev=
aluation with an error
=C2=A0
This one is also already there. We have reserved opcodes, like OP_RESERVED.=
You can do something like "<condition> OP_IF OP_RESERVED OP_ENDIF", and th=
en, if "<condition>" is triggered in the Script, the whole transaction is m=
arked as invalid. But if that condition is false, then everything is fine, =
and you can continue executing next opcodes. Again, the situation is the sa=
me as in previous case: build it around OP_RESERVED, that is just "OP_EXPIR=
E" with a different name than you want, and then the only thing you need, i=
s soft-forking a proper condition on the stack.
=C2=A0
On 2023-10-21 02:09:55 user Peter Todd via bitcoin-dev <bitcoin-dev@lists.l=
inuxfoundation.org> wrote:
On Mon, Oct 16, 2023 at 05:57:36PM +0100, Antoine Riard via bitcoin-dev wro=
te: > Here enter a replacement cycling attack. A malicious channel counterp=
arty > can broadcast its HTLC-preimage transaction with a higher absolute f=
ee and > higher feerate than the honest HTLC-timeout of the victim lightnin=
g node > and triggers a replacement. Both for legacy and anchor output chan=
nels, a > HTLC-preimage on a counterparty commitment transaction is malleab=
le, i.e > additional inputs or outputs can be added. The HTLC-preimage spen=
ds an > unconfirmed and unrelated to the channel parent transaction M and c=
onflicts > its child. The basic problem here is after the HTLC-timeout path=
becomes spendable, the HTLC-preimage path remains spendable. That's bad, b=
ecause in this case we want spending the HTLC-preimage - if possible - to h=
ave an urgency attached to it to ensure that it happens before the previous=
HTLC-timeout is mined. So, why can't we make the HTLC-preimage path expire=
? Traditionally, we've tried to ensure that transactions - once valid - rem=
ain valid forever. We do this because we don't want transactions to become =
impossible to mine in the event of a large reorganization. A notable exampl=
e of this design philosophy is seen in Bitcoin's rules around coinbase outp=
uts: they only become spendable after 100 more blocks have been found; a 10=
0 block reorg is quite unlikely. Enter the OP_Expire and the Coinbase Bit s=
oft-fork upgrade. # Coinbase Bit By redefining a bit of the nVersion field,=
eg the most significant bit, we can apply coinbase-like txout handling to =
arbitrary transactions. Such a transaction's outputs would be treated simil=
arly to a coinbase transaction, and would be spendable only after 100 more =
blocks had been mined. Due to this requirement, these transactions will pos=
e no greater risk to reorg safety than the existing hazard of coinbase tran=
sactions themselves becoming invalid. Note how such a transaction is non-st=
andard right now, ensuring compatibility with existing nodes in a soft-fork=
upgrade. # OP_Expire Redefining an existing OP_Nop opcode, OP_Expire would=
terminate script evaluation with an error if: 1) the Coinbase Bit was not =
set; or 2) the stack is empty; or 3) the top item on the stack was >=3D the=
block height of the containing block This is conceptually an AntiCheckLock=
TimeVerify: where CLTV _allows_ a txout to become spendable in a particular=
way in the future, Expire _prevents_ a txout from being spent in a particu=
lar way. Since OP_Expire requires the Coinbase Bit to be set, the reorg sec=
urity of OP_Expire-using transactions is no worse than transactions spendin=
g miner coinbases. # How HTLC's Would Use OP_Expire Whenever revealing the =
preimage on-chain is necessary to the secure functioning of the HTLC-using =
protocol, we simply add an appropriate OP_Expire to the pre-image branch of=
the script along the lines of: If Expire Drop Hash EqualVerify CheckSig El=
seIf # HTLC Expiration conditions ... EndIf Now the party receiving the pre=
-image has a deadline. Either they get a transaction spending the preimage =
mined, notifying the other party via the blockchain itself, or they fail to=
get the preimage mined in time, reverting control to the other party who c=
an spend the HTLC output at their leisure, without strict time constraints.=
Since the HTLC-expired branch does *not* execute OP_Expire, the transactio=
n spending the HTLC-expired branch does *not* need to set the Coinbase Bit.=
Thus it can be spent in a perfectly normal transaction, without restrictio=
ns. # Delta Encoding Expiration Rather than having a specific Coinbase Bit,=
it may also be feasible to encode the expiration height as a delta against=
a block-height nLockTime. In this variant, OP_Expire would work similarly =
to OP_CheckLockTimeVerify, by checking that the absolute expiration height =
was <=3D the requested expiration, allowing multiple HTLC preimage outputs =
to be spent in one transaction. If the top 16-bits were used, the maximum p=
eriod a transaction could be valid would be: 2^16 blocks / 144 blocks/day =
=3D 455 days In this variant, a non-zero expiration delta would enable expi=
ration behavior, as well as the coinbase-like output spending restriction. =
The remaining 16-bits of nVersion would remain available for other meanings=
. Similar to how CLTV and CSV verified nLockTime and nSequence respectively=
, verifying an expiration height encoded in the nVersion has the advantage =
of making an expiration height easy to detect without validating scripts. W=
hile Lightning's HTLC-success transactions currently use nLockTime=3D0, AFA=
IK there is no reason why they could not set nLockTime to be valid in the n=
ext block, allowing delta encoding to be used. ## Reusing Time-Based nLockT=
ime Reusing time-based nLockTime's prior to some pre-2009 genesis point for=
expiration is another possibility (similar to how Lightning makes use of t=
ime-based nLockTime for signalling). However I believe this is not as desir=
able as delta encoding or a coinbase bit, as it would prevent transactions =
from using block nLockTime and expiration at the same time. It would also s=
till require a coinbase bit or nVersion increase to ensure expiration-using=
transactions are non-standard. # Mempool Behavior Obviously, mempool logic=
will need to handle transactions that can expire differently than non-expi=
ring transactions. One notable consideration is that nodes should require h=
igher minimum relay fees for transactions close to their expiration height =
to ensure we don't waste bandwidth on transactions that have no potential t=
o be mined. Considering the primary use-case, it is probably acceptable to =
always require a fee rate high enough to be mined in the next block. -- htt=
ps://petertodd.org 'peter'[:-1]@petertodd.org _____________________________=
__________________ bitcoin-dev mailing list bitcoin-dev@lists.linuxfoundati=
on.org https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
--===============0333453674442322640==
Content-Type: text/html; charset="utf-8"
Content-Transfer-Encoding: quoted-printable
<div>
<div>> By redefining a bit of the nVersion field, eg the most significan=
t bit, we can apply coinbase-like txout handling to arbitrary transactions.=
</div>
<div> </div>
<div>We already have that in OP_CHECKSEQUENCEVERIFY. You can have a system =
with no coinbase transactions at all, and use only OP_CHECKSEQUENCEVERIFY o=
n the first transaction, and set sequence numbers to put a relative locktim=
e of 100 blocks. Also, if you think some soft-fork is needed anyway, then I=
recommend building it around already existing OP_CHECKSEQUENCEVERIFY, than=
reinvent the wheel.</div>
<div> </div>
<div>> Redefining an existing OP_Nop opcode, OP_Expire would terminate s=
cript evaluation with an error</div>
<div> </div>
<div>This one is also already there. We have reserved opcodes, like OP_RESE=
RVED. You can do something like "<condition> OP_IF OP_RESERVED OP_END=
IF", and then, if "<condition>" is triggered in the Script, the whole=
transaction is marked as invalid. But if that condition is false, then eve=
rything is fine, and you can continue executing next opcodes. Again, the si=
tuation is the same as in previous case: build it around OP_RESERVED, that =
is just "OP_EXPIRE" with a different name than you want, and then the only =
thing you need, is soft-forking a proper condition on the stack.</div>
<br /><br /></div>
<div> </div>
<div>On 2023-10-21 02:09:55 user Peter Todd via bitcoin-dev <bitcoin-dev=
@lists.linuxfoundation.org> wrote:</div>
<blockquote style=3D"margin-right: 0; margin-left: 7px; border-left: 2px so=
lid orange; padding-left: 8px;">
<pre>On Mon, Oct 16, 2023 at 05:57:36PM +0100, Antoine Riard via bitcoin-de=
v wrote:
> Here enter a replacement cycling attack. A malicious channel counterpa=
rty
> can broadcast its HTLC-preimage transaction with a higher absolute fee=
and
> higher feerate than the honest HTLC-timeout of the victim lightning no=
de
> and triggers a replacement. Both for legacy and anchor output channels=
, a
> HTLC-preimage on a counterparty commitment transaction is malleable, i=
.e
> additional inputs or outputs can be added. The HTLC-preimage spends an
> unconfirmed and unrelated to the channel parent transaction M and conf=
licts
> its child.
The basic problem here is after the HTLC-timeout path becomes spendable, the
HTLC-preimage path remains spendable. That's bad, because in this case we w=
ant
spending the HTLC-preimage - if possible - to have an urgency attached to i=
t to
ensure that it happens before the previous HTLC-timeout is mined.
So, why can't we make the HTLC-preimage path expire? Traditionally, we've t=
ried
to ensure that transactions - once valid - remain valid forever. We do this
because we don't want transactions to become impossible to mine in the even=
t of
a large reorganization.
A notable example of this design philosophy is seen in Bitcoin's rules arou=
nd
coinbase outputs: they only become spendable after 100 more blocks have been
found; a 100 block reorg is quite unlikely.
Enter the OP_Expire and the Coinbase Bit soft-fork upgrade.
# Coinbase Bit
By redefining a bit of the nVersion field, eg the most significant bit, we =
can
apply coinbase-like txout handling to arbitrary transactions. Such a
transaction's outputs would be treated similarly to a coinbase transaction,=
and
would be spendable only after 100 more blocks had been mined. Due to this
requirement, these transactions will pose no greater risk to reorg safety t=
han
the existing hazard of coinbase transactions themselves becoming invalid.
Note how such a transaction is non-standard right now, ensuring compatibili=
ty
with existing nodes in a soft-fork upgrade.
# OP_Expire
Redefining an existing OP_Nop opcode, OP_Expire would terminate script
evaluation with an error if:
1) the Coinbase Bit was not set; or
2) the stack is empty; or
3) the top item on the stack was >=3D the block height of the containing=
block
This is conceptually an AntiCheckLockTimeVerify: where CLTV _allows_ a txou=
t to
become spendable in a particular way in the future, Expire _prevents_ a txo=
ut
from being spent in a particular way.
Since OP_Expire requires the Coinbase Bit to be set, the reorg security of
OP_Expire-using transactions is no worse than transactions spending miner
coinbases.
# How HTLC's Would Use OP_Expire
Whenever revealing the preimage on-chain is necessary to the secure functio=
ning
of the HTLC-using protocol, we simply add an appropriate OP_Expire to the
pre-image branch of the script along the lines of:
If
Expire Drop
Hash EqualVerify
CheckSig
ElseIf
# HTLC Expiration conditions
...
EndIf
Now the party receiving the pre-image has a deadline. Either they get a
transaction spending the preimage mined, notifying the other party via the
blockchain itself, or they fail to get the preimage mined in time, reverting
control to the other party who can spend the HTLC output at their leisure,
without strict time constraints.
Since the HTLC-expired branch does *not* execute OP_Expire, the transaction
spending the HTLC-expired branch does *not* need to set the Coinbase Bit. T=
hus
it can be spent in a perfectly normal transaction, without restrictions.
# Delta Encoding Expiration
Rather than having a specific Coinbase Bit, it may also be feasible to enco=
de
the expiration height as a delta against a block-height nLockTime. In this
variant, OP_Expire would work similarly to OP_CheckLockTimeVerify, by check=
ing
that the absolute expiration height was <=3D the requested expiration, a=
llowing
multiple HTLC preimage outputs to be spent in one transaction.
If the top 16-bits were used, the maximum period a transaction could be val=
id
would be:
2^16 blocks / 144 blocks/day =3D 455 days
In this variant, a non-zero expiration delta would enable expiration behavi=
or,
as well as the coinbase-like output spending restriction. The remaining 16-=
bits
of nVersion would remain available for other meanings.
Similar to how CLTV and CSV verified nLockTime and nSequence respectively,
verifying an expiration height encoded in the nVersion has the advantage of
making an expiration height easy to detect without validating scripts.
While Lightning's HTLC-success transactions currently use nLockTime=3D0, AF=
AIK
there is no reason why they could not set nLockTime to be valid in the next
block, allowing delta encoding to be used.
## Reusing Time-Based nLockTime
Reusing time-based nLockTime's prior to some pre-2009 genesis point for
expiration is another possibility (similar to how Lightning makes use of
time-based nLockTime for signalling). However I believe this is not as
desirable as delta encoding or a coinbase bit, as it would prevent transact=
ions
from using block nLockTime and expiration at the same time. It would also s=
till
require a coinbase bit or nVersion increase to ensure expiration-using
transactions are non-standard.
# Mempool Behavior
Obviously, mempool logic will need to handle transactions that can expire
differently than non-expiring transactions. One notable consideration is th=
at
nodes should require higher minimum relay fees for transactions close to th=
eir
expiration height to ensure we don't waste bandwidth on transactions that h=
ave
no potential to be mined. Considering the primary use-case, it is probably
acceptable to always require a fee rate high enough to be mined in the next
block.
-- =
https://petertodd.org 'peter'[:-1]@petertodd.org
_______________________________________________
bitcoin-dev mailing list
bitcoin-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
</pre>
</blockquote>
--===============0333453674442322640==--
|