summaryrefslogtreecommitdiff
path: root/20/c8b2abebf0fd613200cdcfb2aef972c8b3e595
blob: 28c0b10a97c372203e0c216f615032a4525dab67 (plain)
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
Return-Path: <belcher@riseup.net>
Received: from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137])
 by lists.linuxfoundation.org (Postfix) with ESMTP id 4F1DEC002D
 for <bitcoin-dev@lists.linuxfoundation.org>;
 Sun,  1 May 2022 08:57:33 +0000 (UTC)
Received: from localhost (localhost [127.0.0.1])
 by smtp4.osuosl.org (Postfix) with ESMTP id 3C2A4404A3
 for <bitcoin-dev@lists.linuxfoundation.org>;
 Sun,  1 May 2022 08:57:33 +0000 (UTC)
X-Virus-Scanned: amavisd-new at osuosl.org
X-Spam-Flag: NO
X-Spam-Score: -0.265
X-Spam-Level: 
X-Spam-Status: No, score=-0.265 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, FILL_THIS_FORM=0.001,
 LONGWORDS=2.035, PDS_BTC_ID=0.499, RCVD_IN_DNSWL_LOW=-0.7,
 RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001,
 SPF_HELO_PASS=-0.001, SPF_PASS=-0.001] autolearn=no autolearn_force=no
Authentication-Results: smtp4.osuosl.org (amavisd-new);
 dkim=pass (1024-bit key) header.d=riseup.net
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 oYmF9KD2cDr6
 for <bitcoin-dev@lists.linuxfoundation.org>;
 Sun,  1 May 2022 08:57:30 +0000 (UTC)
X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0
Received: from mx1.riseup.net (mx1.riseup.net [198.252.153.129])
 by smtp4.osuosl.org (Postfix) with ESMTPS id 74153408A5
 for <bitcoin-dev@lists.linuxfoundation.org>;
 Sun,  1 May 2022 08:57:30 +0000 (UTC)
Received: from fews2.riseup.net (fews2-pn.riseup.net [10.0.1.84])
 (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
 key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256
 client-signature RSA-PSS (2048 bits) client-digest SHA256)
 (Client CN "mail.riseup.net", Issuer "R3" (not verified))
 by mx1.riseup.net (Postfix) with ESMTPS id 4Krg8n49SpzDqKr
 for <bitcoin-dev@lists.linuxfoundation.org>;
 Sun,  1 May 2022 01:57:29 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=riseup.net; s=squak;
 t=1651395449; bh=vapfWrCQI6Zal2FR80sOzBDYLvy0BWcfiXRZpzcD7Dw=;
 h=Date:To:From:Subject:From;
 b=GP9FIgrHdrXxWXYFEKGJHOFkOJzEq0cwmgXLclU2NIo4fbsWDvu9/vmkbaTnKKLMI
 ro5NR8q4apGpQ2hHy/cXt1mLBFswDfUZZM0T1rng2GcUKoc1AvCbjUfEVCuRM9Vea/
 Q76QdoRRRsx7+/bx7wbNsK3KSGNsAHcjGqVuUO64=
X-Riseup-User-ID: 7831ACE43BB11BBB9976A0E1BAD71BB286B39DB5B3D9D6B4C9AD6B4AF858FB1C
Received: from [127.0.0.1] (localhost [127.0.0.1])
 by fews2.riseup.net (Postfix) with ESMTPSA id 4Krg8n0y45z214N
 for <bitcoin-dev@lists.linuxfoundation.org>;
 Sun,  1 May 2022 01:57:28 -0700 (PDT)
Message-ID: <22c80504-e648-e021-866e-ca5a5db3b247@riseup.net>
Date: Sun, 1 May 2022 09:57:25 +0100
MIME-Version: 1.0
Content-Language: en-US
To: bitcoin-dev@lists.linuxfoundation.org
From: Chris Belcher <belcher@riseup.net>
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Subject: [bitcoin-dev] BIP proposal: Timelocked address fidelity bond for
	BIP39 seeds
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, 01 May 2022 08:57:33 -0000

See 
https://gist.github.com/chris-belcher/7257763cedcc014de2cd4239857cd36e 
for the latest version of this BIP.

<pre>
   BIP: TBD. Preferably a two-digit number to match the bip44, bip49, 
bip84, bip86 family of bips
   Layer: Applications
   Title: Derivation scheme for storing timelocked address fidelity 
bonds in BIP39 phrases
   Author: Chris Belcher <belcher at riseup dot net>
   Status: Draft
   Type: Standards Track
   Comments-Summary: No comments yet.
   Created: 2022-04-01
   License: CC0-1.0
</pre>

== Abstract ==

This BIP defines the derivation scheme for BIP39 seed phrases which 
create timelocked addresses used for creating fidelity bonds. It also 
defines how to sign fidelity bond certificates, which are needed when 
using fidelity bonds that are stored offline.

== Motivation ==

Fidelity bonds are used to resist sybil attacks in certain decentralized 
anonymous protocols. They are created by locking up bitcoins using the 
`OP_CHECKLOCKTIMEVERIFY` opcode.

It would be useful to have a common derivation scheme so that users of 
wallet software can have a backup of their fidelity bonds by storing 
only the BIP39 seed phrase and a reference to this BIP. Importantly the 
user does not need to backup any timelock values.

We largely use the same approach used in BIPs 49, 84 and 86 for ease of 
implementation.

This standard is already implemented and deployed in JoinMarket. As most 
changes would requires a protocol change of a live system, there is 
limited scope for changing this standard in review. This BIP is more 
about documenting something which already exists, warts and all.

== Background ==

=== Fidelity bonds ===

A fidelity bond is a mechanism where bitcoin value is deliberately 
sacrificed to make a cryptographic identity expensive to obtain. A way 
to create a fidelity bond is to lock up bitcoins by sending them to a 
timelocked address. The valuable thing being sacrificed is the 
time-value-of-money.

The sacrifice must be done in a way that can be proven to a third party. 
This proof can be made by showing the UTXO outpoint, the address 
redeemscript and a signature which signs a message using the private key 
corresponding to the public key in the redeemscript.

The sacrificed value is an objective measurement that can't be faked and 
which can be verified by anybody (just like, for example PoW mining). 
Sybil attacks can be made very expensive by forcing a hypothetical sybil 
attacker to lock up many bitcoins for a long time. JoinMarket implements 
fidelity bonds for protection from sybil attackers. At the time of 
writing over 600 BTC in total have been locked up with some for many 
years. Their UTXOs and signatures have been advertised to the world as 
proof. We can calculate that for a sybil attacker to succeed in unmixing 
all the CoinJoins, they would have to lock up over 100k BTC for several 
years.

=== Fidelity bonds in cold storage ===

It would be useful to be able to keep the private keys of timelocked 
addresses in cold storage. This would allow the sybil resistance of a 
system to increase without hot wallet risk. For this reason there is an 
intermediate keypair called the certificate.

     UTXO key ---signs---> certificate ---signs---> endpoint (e.g. IRC 
nickname or tor .onion hostname)

The certificate keypair can be kept online and used to prove ownership 
of the fidelity bond. Even if the hot wallet private keys are stolen, 
the coins in the timelocked address will still be safe, although the 
thief will be able to impersonate the fidelity bond until the expiry.

=== Fixed timelock values ===

It would be useful for the user to avoid having to keep a record of the 
timelocks in the time-locked addresses. So only a limited small set of 
timelocks are defined by this BIP. This way the user must only store 
their seed phrase, and knowledge that they have coins stored using this 
BIP standard. The user doesn't need to remember or store any dates.


== Specifications ==

This BIP defines the two needed steps to derive multiple deterministic 
addresses based on a [[bip-0032.mediawiki|BIP 32]] master private key. 
It also defines the format of the certificate can be signed by the 
deterministic address key.

=== Public key derivation ===

To derive a public key from the root account, this BIP uses a similar 
account-structure as defined in BIP [[bip-0084.mediawiki|44]] but with 
<tt>change</tt> set to <tt>2</tt>.

<pre>
m / 84' / 0' / 0' / 2 / index
</pre>

A key derived with this derivation path pattern will be referred to as 
<tt>derived_key</tt> further
in this document.

For <tt>index</tt>, addresses are numbered from 0 in a sequentially 
increasing manner, but index does not increase forever like in other 
similar standards. The index only goes up to <tt>959</tt> inclusive. 
Only 960 addresses can be derived for a given BIP32 master key. 
Furthermore there is no concept of a gap limit, instead wallets must 
always generate all 960 addresses and check all of them if they have a 
balance and history.

=== Timelock derivation ===

The timelock used in the time-locked address is derived from the 
<tt>index</tt>. The timelock is a unix time. It is always the first of 
the month at midnight. The <tt>index</tt> counts upwards the months from 
January 2020, ending in December 2099. At 12 months per year for 80 
years this totals 960 timelocks. Note that care must be taken with the 
year 2038 problem on 32-bit systems.

<pre>
year = 2020 + index // 12
month = 1 + index % 12
</pre>


=== Address derivation ===

To derive the address from the above calculated public key and timelock, 
we create a <tt>redeemScript</tt> which locks the funds until the 
<tt>timelock</tt>, and then checks the signature of the 
<tt>derived_key</tt>. The <tt>redeemScript</tt> is hashed with SHA256 to 
produce a 32-byte hash value that forms the <tt>scriptPubKey</tt> of the 
P2WSH address.

     redeemScript: <timelock> OP_CHECKLOCKTIMEVERIFY OP_DROP 
<derived_key> OP_CHECKSIG
     witness:      <signature> <pubkey>
     scriptSig:    (empty)
     scriptPubKey: 0 <32-byte-hash>
                   (0x0020{32-byte-hash})

=== Certificate message derivation ===

To create a certificate needed for using fidelity bonds in cold storage, 
another application external to this standard will create a ECDSA 
keypair. The public key of this keypair and an integer called the 
`expiry` will be used to create a certificate message.

The certificate message is defined as:

    'fidelity-bond-cert|' + cert_pubkey + '|' + cert_expiry

where + denotes concatenation. `cert_pubkey` is encoded as a hex string, 
and `cert_expiry` is encoded as an ascii string of the integer.

This certificate message is then prepended with the string `\x18Bitcoin 
Signed Message:\n` and a byte denoting the length of the certificate 
message. The whole thing is then signed with the private key of the 
<tt>derived_key</tt>. This part is identical to the "Sign Message" 
function which many wallets already implement.

Almost all wallets implementing this standard can use their 
already-existing "Sign Message" function to sign the certificate 
message. As the certificate message itself is always an ascii string, 
the wallet may not need to specially implement this section at all but 
just rely on users copypasting their certificate message into the 
already-existing "Sign Message" user interface. This works as long as 
the wallet knows how to use the private key of the timelocked address 
for signing messages.

It is most important for wallet implementions of this standard to 
support creating the certificate signature. Verifying the certificate 
signature is less important.


== Test vectors ==

<pre>
mnemonic = abandon abandon abandon abandon abandon abandon abandon 
abandon abandon abandon abandon about
rootpriv = 
xprv9s21ZrQH143K3GJpoapnV8SFfukcVBSfeCficPSGfubmSFDxo1kuHnLisriDvSnRRuL2Qrg5ggqHKNVpxR86QEC8w35uxmGoggxtQTPvfUu
rootpub  = 
xpub661MyMwAqRbcFkPHucMnrGNzDwb6teAX1RbKQmqtEF8kK3Z7LZ59qafCjB9eCRLiTVG3uxBxgKvRgbubRhqSKXnGGb1aoaqLrpMBDrVxga8

// First timelocked address = m/84'/0'/0'/2/0
derived private_key = L2tQBEdhC48YLeEWNg3e4msk94iKfyVa9hdfzRwUERabZ53TfH3d
derived public_key  = 
02a1b09f93073c63f205086440898141c0c3c6d24f69a18db608224bcf143fa011
unix locktime       = 1577836800
string locktime     = 2020-01-01 00:00:00
redeemscript        = 
0400e10b5eb1752102a1b09f93073c63f205086440898141c0c3c6d24f69a18db608224bcf143fa011ac
scriptPubKey        = 
0020bdee9515359fc9df912318523b4cd22f1c0b5410232dc943be73f9f4f07e39ad
address             = 
bc1qhhhf29f4nlyalyfrrpfrknxj9uwqk4qsyvkujsa7w0ulfur78xkspsqn84

// Test certificate using first timelocked address
// Note that as signatures contains a random nonce, it might not be 
exactly the same when your code generates it
// p2pkh address is the p2pkh address corresponding to the derived 
public key, it can be used to verify the message
//  signature in any wallet that supports Verify Message.
// As mentioned before, it is more important for implementors of this 
standard to support signing such messages, not verifying them
Message       = 
fidelity-bond-cert|020000000000000000000000000000000000000000000000000000000000000001|375
Address       = 
bc1qhhhf29f4nlyalyfrrpfrknxj9uwqk4qsyvkujsa7w0ulfur78xkspsqn84
p2pkh address = 16vmiGpY1rEaYnpGgtG7FZgr2uFCpeDgV6
Signature     = 
H2b/90XcKnIU/D1nSCPhk8OcxrHebMCr4Ok2d2yDnbKDTSThNsNKA64CT4v2kt+xA1JmGRG/dMnUUH1kKqCVSHo=

// 2nd timelocked address = m/84'/0'/0'/2/1
derived private_key = KxctaFBzetyc9KXeUr6jxESCZiCEXRuwnQMw7h7hroP6MqnWN6Pf
derived public_key  = 
02599f6db8b33265a44200fef0be79c927398ed0b46c6a82fa6ddaa5be2714002d
unix locktime       = 1580515200
string locktime     = 2020-02-01 00:00:00
redeemscript        = 
0480bf345eb1752102599f6db8b33265a44200fef0be79c927398ed0b46c6a82fa6ddaa5be2714002dac
scriptPubKey        = 
0020b8f898643991608524ed04e0c6779f632a57f1ffa3a3a306cd81432c5533e9ae
address             = 
bc1qhrufsepej9sg2f8dqnsvvaulvv490u0l5w36xpkds9pjc4fnaxhq7pcm4h

// timelocked address after the year 2038 problem = m/84'/0'/0'/2/240
derived private_key = L3SYqae23ZoDDcyEA8rRBK83h1MDqxaDG57imMc9FUx1J8o9anQe
derived public_key  = 
03ec8067418537bbb52d5d3e64e2868e67635c33cfeadeb9a46199f89ebfaab226
unix locktime       = 2208988800
string locktime     = 2040-01-01 00:00:00
redeemscript        = 
05807eaa8300b1752103ec8067418537bbb52d5d3e64e2868e67635c33cfeadeb9a46199f89ebfaab226ac
scriptPubKey        = 
0020e7de0ad2720ae1d6cc9b6ad91af57eb74646762cf594c91c18f6d5e7a873635a
address             = 
bc1qul0q45njptsadnymdtv34at7karyva3v7k2vj8qc7m2702rnvddq0z20u5

// last timelocked address = m/84'/0'/0'/2/959
derived private_key = L5Z9DDMnj5RZMyyPiQLCvN48Xt7GGmev6cjvJXD8uz5EqiY8trNJ
derived public_key  = 
0308c5751121b1ae5c973cdc7071312f6fc10ab864262f0cbd8134f056166e50f3
unix locktime       = 4099766400
string locktime     = 2099-12-01 00:00:00
redeemscript        = 
0580785df400b175210308c5751121b1ae5c973cdc7071312f6fc10ab864262f0cbd8134f056166e50f3ac
scriptPubKey        = 
0020803268e042008737cf439748cbb5a4449e311da9aa64ae3ac56d84d059654f85
address             = 
bc1qsqex3czzqzrn0n6rjayvhddygj0rz8df4fj2uwk9dkzdqkt9f7zs5c493u
</pre>

Code generating these test vectors can be found here: 
https://github.com/chris-belcher/timelocked-addresses-fidelity-bond-bip-testvectors

==Reference==

* 
[[https://gist.github.com/chris-belcher/18ea0e6acdb885a2bfbdee43dcd6b5af/|Design 
for improving JoinMarket's resistance to sybil attacks using fidelity 
bonds]]
* 
[[https://github.com/JoinMarket-Org/joinmarket-clientserver/blob/master/docs/fidelity-bonds.md|JoinMarket 
fidelity bonds doc page]]
* [[bip-0065.mediawiki|BIP86 - OP_CHECKLOCKTIMEVERIFY]]
* [[bip-0032.mediawiki|BIP32 - Hierarchical Deterministic Wallets]]
* [[bip-0044.mediawiki|BIP44 - Multi-Account Hierarchy for Deterministic 
Wallets]]
* [[bip-0049.mediawiki|BIP49 - Derivation scheme for 
P2WPKH-nested-in-P2SH based accounts]]
* [[bip-0084.mediawiki|BIP84 - Derivation scheme for P2WPKH based accounts]]
* [[bip-0086.mediawiki|BIP86 - Key Derivation for Single Key P2TR Outputs]]