From bf2eb4f680f537e344370f7bc92cc234b5ca5083 Mon Sep 17 00:00:00 2001 From: chris-belcher Date: Sat, 2 Jul 2022 18:43:09 +0100 Subject: [PATCH 01/24] Specify BIP-fidelity-bonds For storing fidelity bonds in HD wallets --- bip-fidelity-bonds.mediawiki | 167 +++++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 bip-fidelity-bonds.mediawiki diff --git a/bip-fidelity-bonds.mediawiki b/bip-fidelity-bonds.mediawiki new file mode 100644 index 00000000..571eca2e --- /dev/null +++ b/bip-fidelity-bonds.mediawiki @@ -0,0 +1,167 @@ +
+  BIP: TBD. Preferably a two-digit number to match the bip44, bip49, bip84, bip86 family of bips
+  Layer: Applications
+  Title: Derivation scheme for timelocked address fidelity bond based accounts
+  Author: Chris Belcher 
+  Status: Draft
+  Type: Standards Track
+  Comments-Summary: No comments yet.
+  Created: 2022-04-01
+  License: CC0-1.0
+  Post-History: 2022-5-1: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2022-May/020389.html
+
+ +== Abstract == + +This BIP defines the derivation scheme for HD wallets 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 HD seed 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. + +It would be useful to be able to keep the private keys of fidelity bonds in cold storage. This would allow the sybil resistance of a system to increase without hot wallet risk. + +== 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 === + +To allow for holding fidelity bonds in cold storage, there is an intermediate keypair called the certificate. + + UTXO key ---signs---> certificate ---signs---> endpoint + +Where the endpoint might be a 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 change set to 2. + +
+m / 84' / 0' / 0' / 2 / index
+
+ +A key derived with this derivation path pattern will be referred to as derived_key further +in this document. + +For index, 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 959 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 index. The timelock is a unix time. It is always the first of the month at midnight. The index 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. + +
+year = 2020 + index // 12
+month = 1 + index % 12
+
+ + +=== Address derivation === + +To derive the address from the above calculated public key and timelock, we create a redeemScript which locks the funds until the timelock, and then checks the signature of the derived_key. The redeemScript is hashed with SHA256 to produce a 32-byte hash value that forms the scriptPubKey of the P2WSH address. + + redeemScript: OP_CHECKLOCKTIMEVERIFY OP_DROP OP_CHECKSIG + witness: + scriptSig: (empty) + scriptPubKey: 0 <32-byte-hash> + (0x0020{32-byte-hash}) + +=== Message signing === + +In order to support signing of certificates, implementors should support signing ascii messages. + +A certificate message can be created by another application external to this standard. It 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 derived_key. 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 == + +
+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 = 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
+
+ +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|BIP65 - 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]] + From 05e2c0c12f1e37dbe031994e74d8deb390868dc7 Mon Sep 17 00:00:00 2001 From: theborakompanioni Date: Thu, 23 May 2024 14:16:38 +0200 Subject: [PATCH 02/24] chore(bip-0046): rename bip-fidelity-bonds to bip-0046 --- bip-fidelity-bonds.mediawiki => bip-0046.mediawiki | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename bip-fidelity-bonds.mediawiki => bip-0046.mediawiki (100%) diff --git a/bip-fidelity-bonds.mediawiki b/bip-0046.mediawiki similarity index 100% rename from bip-fidelity-bonds.mediawiki rename to bip-0046.mediawiki From 8e109f98de1dcbc8395d138f693ed42114eeefca Mon Sep 17 00:00:00 2001 From: theborakompanioni Date: Thu, 23 May 2024 14:18:08 +0200 Subject: [PATCH 03/24] docs(bip-0046): add bip number to header section --- bip-0046.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-0046.mediawiki b/bip-0046.mediawiki index 571eca2e..b5088fcf 100644 --- a/bip-0046.mediawiki +++ b/bip-0046.mediawiki @@ -1,5 +1,5 @@
-  BIP: TBD. Preferably a two-digit number to match the bip44, bip49, bip84, bip86 family of bips
+  BIP: 46
   Layer: Applications
   Title: Derivation scheme for timelocked address fidelity bond based accounts
   Author: Chris Belcher 

From 64f93a239d24f6abbaa0345b190585bbaa8aa595 Mon Sep 17 00:00:00 2001
From: theborakompanioni 
Date: Thu, 23 May 2024 14:21:40 +0200
Subject: [PATCH 04/24] chore(bip-0046): fix typos and grammar

---
 bip-0046.mediawiki | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/bip-0046.mediawiki b/bip-0046.mediawiki
index b5088fcf..e4566042 100644
--- a/bip-0046.mediawiki
+++ b/bip-0046.mediawiki
@@ -23,7 +23,7 @@ It would be useful to have a common derivation scheme so that users of wallet so
 
 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.
+This standard is already implemented and deployed in JoinMarket. As most changes would require 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.
 
 It would be useful to be able to keep the private keys of fidelity bonds in cold storage. This would allow the sybil resistance of a system to increase without hot wallet risk.
 
@@ -52,7 +52,7 @@ It would be useful for the user to avoid having to keep a record of the timelock
 
 == 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.
+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 that can be signed by the deterministic address key.
 
 === Public key derivation ===
 
@@ -79,9 +79,9 @@ month = 1 + index % 12
 
 === Address derivation ===
 
-To derive the address from the above calculated public key and timelock, we create a redeemScript which locks the funds until the timelock, and then checks the signature of the derived_key. The redeemScript is hashed with SHA256 to produce a 32-byte hash value that forms the scriptPubKey of the P2WSH address.
+To derive the address from the above calculated public key and timelock, we create a witness script which locks the funds until the timelock, and then checks the signature of the derived_key. The witness script is hashed with SHA256 to produce a 32-byte hash value that forms the scriptPubKey of the P2WSH address.
 
-    redeemScript:  OP_CHECKLOCKTIMEVERIFY OP_DROP  OP_CHECKSIG
+    witnessScript:  OP_CHECKLOCKTIMEVERIFY OP_DROP  OP_CHECKSIG
     witness:       
     scriptSig:    (empty)
     scriptPubKey: 0 <32-byte-hash>
@@ -89,11 +89,11 @@ To derive the address from the above calculated public key and timelock, we crea
 
 === Message signing ===
 
-In order to support signing of certificates, implementors should support signing ascii messages.
+In order to support signing of certificates, implementors should support signing ASCII messages.
 
 A certificate message can be created by another application external to this standard. It 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 derived_key. 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.
+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.
 

From 03a679958aedf1e152b96286571724c0199a1fc5 Mon Sep 17 00:00:00 2001
From: theborakompanioni 
Date: Thu, 23 May 2024 14:23:44 +0200
Subject: [PATCH 05/24] docs(bip-0046): change title to 'Address Scheme for
 Timelocked Fidelity Bonds'

---
 bip-0046.mediawiki | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/bip-0046.mediawiki b/bip-0046.mediawiki
index e4566042..1b85dccb 100644
--- a/bip-0046.mediawiki
+++ b/bip-0046.mediawiki
@@ -1,7 +1,7 @@
 
   BIP: 46
   Layer: Applications
-  Title: Derivation scheme for timelocked address fidelity bond based accounts
+  Title: Address Scheme for Timelocked Fidelity Bonds
   Author: Chris Belcher 
   Status: Draft
   Type: Standards Track

From 57f1fe3f4bc902e828041ad329ecd025d847ae7d Mon Sep 17 00:00:00 2001
From: theborakompanioni 
Date: Thu, 23 May 2024 14:24:42 +0200
Subject: [PATCH 06/24] chore(bip-0046): remove (optional) Comments-Summary
 header

---
 bip-0046.mediawiki | 1 -
 1 file changed, 1 deletion(-)

diff --git a/bip-0046.mediawiki b/bip-0046.mediawiki
index 1b85dccb..e179d937 100644
--- a/bip-0046.mediawiki
+++ b/bip-0046.mediawiki
@@ -5,7 +5,6 @@
   Author: Chris Belcher 
   Status: Draft
   Type: Standards Track
-  Comments-Summary: No comments yet.
   Created: 2022-04-01
   License: CC0-1.0
   Post-History: 2022-5-1: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2022-May/020389.html

From 5209a28c1a25a853b0d5afbd90136a446484715d Mon Sep 17 00:00:00 2001
From: theborakompanioni 
Date: Thu, 23 May 2024 14:27:20 +0200
Subject: [PATCH 07/24] docs(bip-0046): add Comments-URI header

---
 bip-0046.mediawiki | 1 +
 1 file changed, 1 insertion(+)

diff --git a/bip-0046.mediawiki b/bip-0046.mediawiki
index e179d937..0766796d 100644
--- a/bip-0046.mediawiki
+++ b/bip-0046.mediawiki
@@ -3,6 +3,7 @@
   Layer: Applications
   Title: Address Scheme for Timelocked Fidelity Bonds
   Author: Chris Belcher 
+  Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0046
   Status: Draft
   Type: Standards Track
   Created: 2022-04-01

From 164412d08b7c67cf5a9b7282a4aa2a15863fa40d Mon Sep 17 00:00:00 2001
From: theborakompanioni 
Date: Thu, 23 May 2024 14:30:48 +0200
Subject: [PATCH 08/24] docs(bip-0046): add Copyright section

---
 bip-0046.mediawiki | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/bip-0046.mediawiki b/bip-0046.mediawiki
index 0766796d..190c9caf 100644
--- a/bip-0046.mediawiki
+++ b/bip-0046.mediawiki
@@ -15,6 +15,10 @@
 
 This BIP defines the derivation scheme for HD wallets 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.
 
+== Copyright ==
+
+This document is placed in the public domain.
+
 == 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.

From 00c7d0b8151046bd4058deaabf67fbc48b8c05a3 Mon Sep 17 00:00:00 2001
From: theborakompanioni 
Date: Thu, 23 May 2024 15:48:23 +0200
Subject: [PATCH 09/24] fix(bip-0046): change license from Public Domain to
 CC0-1.0

---
 bip-0046.mediawiki | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/bip-0046.mediawiki b/bip-0046.mediawiki
index 190c9caf..ea006664 100644
--- a/bip-0046.mediawiki
+++ b/bip-0046.mediawiki
@@ -17,7 +17,7 @@ This BIP defines the derivation scheme for HD wallets which create timelocked ad
 
 == Copyright ==
 
-This document is placed in the public domain.
+This document is licensed under the Creative Commons CC0 1.0 Universal license.
 
 == Motivation ==
 

From f9d370d3da35a242a6568179aee8d7ab66b37e69 Mon Sep 17 00:00:00 2001
From: theborakompanioni 
Date: Thu, 23 May 2024 15:52:46 +0200
Subject: [PATCH 10/24] chore(bip-0046): scriptPubKey -> witness programm

---
 bip-0046.mediawiki | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/bip-0046.mediawiki b/bip-0046.mediawiki
index ea006664..7f2ef5e6 100644
--- a/bip-0046.mediawiki
+++ b/bip-0046.mediawiki
@@ -83,7 +83,7 @@ month = 1 + index % 12
 
 === Address derivation ===
 
-To derive the address from the above calculated public key and timelock, we create a witness script which locks the funds until the timelock, and then checks the signature of the derived_key. The witness script is hashed with SHA256 to produce a 32-byte hash value that forms the scriptPubKey of the P2WSH address.
+To derive the address from the above calculated public key and timelock, we create a witness script which locks the funds until the timelock, and then checks the signature of the derived_key. The witness script is hashed with SHA256 to produce a 32-byte hash value that forms the witness program in the output script of the P2WSH address.
 
     witnessScript:  OP_CHECKLOCKTIMEVERIFY OP_DROP  OP_CHECKSIG
     witness:       

From 0b353bc7dbede1a8637f9074484b8a257ed2d575 Mon Sep 17 00:00:00 2001
From: theborakompanioni 
Date: Mon, 27 May 2024 10:10:22 +0200
Subject: [PATCH 11/24] docs(bip-0046): add Backwards Compatibility section

---
 bip-0046.mediawiki | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/bip-0046.mediawiki b/bip-0046.mediawiki
index 7f2ef5e6..b793a1a2 100644
--- a/bip-0046.mediawiki
+++ b/bip-0046.mediawiki
@@ -31,6 +31,10 @@ This standard is already implemented and deployed in JoinMarket. As most changes
 
 It would be useful to be able to keep the private keys of fidelity bonds in cold storage. This would allow the sybil resistance of a system to increase without hot wallet risk.
 
+== Backwards Compatibility ==
+
+This BIP is not backwards compatible by design as described in the Considerations section of [[bip-0049.mediawiki|BIP 49]]. An incompatible wallet will not discover fidelity bonds at all and the user will notice that something is wrong.
+
 == Background ==
 
 === Fidelity bonds ===

From 722a388ae3e400db6e1928bcd90d8c9ece324c31 Mon Sep 17 00:00:00 2001
From: theborakompanioni 
Date: Mon, 27 May 2024 10:13:28 +0200
Subject: [PATCH 12/24] chore(bip-0046): fix date format in Post-History header

---
 bip-0046.mediawiki | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/bip-0046.mediawiki b/bip-0046.mediawiki
index b793a1a2..f1fe01d3 100644
--- a/bip-0046.mediawiki
+++ b/bip-0046.mediawiki
@@ -8,7 +8,7 @@
   Type: Standards Track
   Created: 2022-04-01
   License: CC0-1.0
-  Post-History: 2022-5-1: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2022-May/020389.html
+  Post-History: 2022-05-01: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2022-May/020389.html
 
== Abstract == From a6f1cf3e0d391fdc7c6d8eb1291868d35e293c09 Mon Sep 17 00:00:00 2001 From: theborakompanioni Date: Mon, 27 May 2024 10:25:14 +0200 Subject: [PATCH 13/24] chore(bip-0046): improve timelock point in time explanation --- bip-0046.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-0046.mediawiki b/bip-0046.mediawiki index f1fe01d3..fa4dd5c0 100644 --- a/bip-0046.mediawiki +++ b/bip-0046.mediawiki @@ -77,7 +77,7 @@ For index, addresses are numbered from 0 in a sequentially increasing m === Timelock derivation === -The timelock used in the time-locked address is derived from the index. The timelock is a unix time. It is always the first of the month at midnight. The index 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. +The timelock used in the time-locked address is derived from the index. The timelock is a unix time. It is always at the start of the first second at the beginning of the month (see [[#Test vectors|Test vectors]]). The index 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.
 year = 2020 + index // 12

From 25361d28ed534d06da89b92257aae47cb08db5b4 Mon Sep 17 00:00:00 2001
From: theborakompanioni 
Date: Mon, 27 May 2024 10:33:17 +0200
Subject: [PATCH 14/24] chore(bip-0046): add tbk to Author header

---
 bip-0046.mediawiki | 1 +
 1 file changed, 1 insertion(+)

diff --git a/bip-0046.mediawiki b/bip-0046.mediawiki
index fa4dd5c0..3576345a 100644
--- a/bip-0046.mediawiki
+++ b/bip-0046.mediawiki
@@ -3,6 +3,7 @@
   Layer: Applications
   Title: Address Scheme for Timelocked Fidelity Bonds
   Author: Chris Belcher 
+          Thebora Kompanioni 
   Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0046
   Status: Draft
   Type: Standards Track

From 2bc326e6afc6d976b22cc8cf68ecc45d35761bb1 Mon Sep 17 00:00:00 2001
From: theborakompanioni 
Date: Mon, 27 May 2024 10:33:48 +0200
Subject: [PATCH 15/24] docs(bip-0046): add Rationale section

---
 bip-0046.mediawiki | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/bip-0046.mediawiki b/bip-0046.mediawiki
index 3576345a..7bb80449 100644
--- a/bip-0046.mediawiki
+++ b/bip-0046.mediawiki
@@ -28,8 +28,6 @@ It would be useful to have a common derivation scheme so that users of wallet so
 
 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 require 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.
-
 It would be useful to be able to keep the private keys of fidelity bonds in cold storage. This would allow the sybil resistance of a system to increase without hot wallet risk.
 
 == Backwards Compatibility ==
@@ -54,10 +52,11 @@ To allow for holding fidelity bonds in cold storage, there is an intermediate ke
 
 Where the endpoint might be a 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 ===
+== Rationale ==
 
 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.
 
+This standard is already implemented and deployed in JoinMarket. As most changes would require 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.
 
 == Specifications ==
 

From 87bbc4aeb6d7da736de63e86f3cb43cf87e39554 Mon Sep 17 00:00:00 2001
From: theborakompanioni 
Date: Thu, 6 Jun 2024 12:51:44 +0200
Subject: [PATCH 16/24] docs(bip-0046): add bip-0046 to readme

---
 README.mediawiki | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/README.mediawiki b/README.mediawiki
index 47d3822a..f84fcf0d 100644
--- a/README.mediawiki
+++ b/README.mediawiki
@@ -252,6 +252,13 @@ Those proposing changes should consider that ultimately consent may rest with th
 | Standard
 | Proposed
 |-
+| [[bip-0046.mediawiki|46]]
+| Applications
+| Address Scheme for Timelocked Fidelity Bonds
+| Chris Belcher, Thebora Kompanioni
+| Standard
+| Draft
+|-
 | [[bip-0047.mediawiki|47]]
 | Applications
 | Reusable Payment Codes for Hierarchical Deterministic Wallets

From 0a12bf8572c64f8b3217b58d005aba05cd4f66fe Mon Sep 17 00:00:00 2001
From: theborakompanioni 
Date: Thu, 6 Jun 2024 14:20:22 +0200
Subject: [PATCH 17/24] docs(bip-0046): apply minor wording improvement
 suggestions

by @AdamISZ
---
 bip-0046.mediawiki | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/bip-0046.mediawiki b/bip-0046.mediawiki
index 7bb80449..70bc703e 100644
--- a/bip-0046.mediawiki
+++ b/bip-0046.mediawiki
@@ -14,7 +14,7 @@
 
 == Abstract ==
 
-This BIP defines the derivation scheme for HD wallets 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.
+This BIP defines the derivation scheme for HD wallets which create timelocked addresses used for creating fidelity bonds. It also gives advice to wallet developers on how to use fidelity bonds to sign over messages, such as certificates, which are needed when using fidelity bonds that are stored offline.
 
 == Copyright ==
 
@@ -24,11 +24,11 @@ This document is licensed under the Creative Commons CC0 1.0 Universal license.
 
 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 HD seed and a reference to this BIP. Importantly the user does not need to backup any timelock values.
+Having a common derivation scheme allows users of wallet software to have a backup of their fidelity bonds by storing only the HD seed 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.
 
-It would be useful to be able to keep the private keys of fidelity bonds in cold storage. This would allow the sybil resistance of a system to increase without hot wallet risk.
+This allows keeping the private keys of fidelity bonds in cold storage, which increases the sybil resistance of a system without hot wallet risk.
 
 == Backwards Compatibility ==
 
@@ -54,7 +54,7 @@ Where the endpoint might be a IRC nickname or Tor onion hostname. The certificat
 
 == Rationale ==
 
-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.
+It is 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.
 
 This standard is already implemented and deployed in JoinMarket. As most changes would require 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.
 

From 821fb900f8c550b7414403a59cfd5a2dd11a6050 Mon Sep 17 00:00:00 2001
From: theborakompanioni 
Date: Fri, 7 Jun 2024 12:04:30 +0200
Subject: [PATCH 18/24] chore(bip-0046): less ambiguous message prefix style

by @AdamISZ
---
 bip-0046.mediawiki | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/bip-0046.mediawiki b/bip-0046.mediawiki
index 70bc703e..a6bc1809 100644
--- a/bip-0046.mediawiki
+++ b/bip-0046.mediawiki
@@ -99,7 +99,7 @@ To derive the address from the above calculated public key and timelock, we crea
 
 In order to support signing of certificates, implementors should support signing ASCII messages.
 
-A certificate message can be created by another application external to this standard. It 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 derived_key. This part is identical to the "Sign Message" function which many wallets already implement.
+A certificate message can be created by another application external to this standard. It is then prepended with the string `0x18 || "Bitcoin 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 derived_key. 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.
 

From 8f0962a1ba1168a81b185593e82dfb4c1c9bbcb8 Mon Sep 17 00:00:00 2001
From: theborakompanioni 
Date: Fri, 7 Jun 2024 12:05:20 +0200
Subject: [PATCH 19/24] chore(bip-0046): remove superfluous newline

---
 bip-0046.mediawiki | 1 -
 1 file changed, 1 deletion(-)

diff --git a/bip-0046.mediawiki b/bip-0046.mediawiki
index a6bc1809..5e5ab437 100644
--- a/bip-0046.mediawiki
+++ b/bip-0046.mediawiki
@@ -172,4 +172,3 @@ Code generating these test vectors can be found here: https://github.com/chris-b
 * [[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]]
-

From b7a5f9ce60188e96364d54a85784f04630542aec Mon Sep 17 00:00:00 2001
From: theborakompanioni 
Date: Wed, 19 Jun 2024 14:06:41 +0200
Subject: [PATCH 20/24] docs(bip-0046): apply minor wording improvement
 suggestions

by @murchandamus
---
 bip-0046.mediawiki | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/bip-0046.mediawiki b/bip-0046.mediawiki
index 5e5ab437..84fd2e2d 100644
--- a/bip-0046.mediawiki
+++ b/bip-0046.mediawiki
@@ -73,7 +73,7 @@ m / 84' / 0' / 0' / 2 / index
 A key derived with this derivation path pattern will be referred to as derived_key further
 in this document.
 
-For index, 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 959 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.
+For index, 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 959 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 for all of them if they have a balance and history.
 
 === Timelock derivation ===
 
@@ -162,7 +162,7 @@ address             = bc1qsqex3czzqzrn0n6rjayvhddygj0rz8df4fj2uwk9dkzdqkt9f7zs5c
 
 Code generating these test vectors can be found here: https://github.com/chris-belcher/timelocked-addresses-fidelity-bond-bip-testvectors
 
-==Reference==
+== 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]]

From 0f1eba2a607e84d85c1787b127c14333adf358ee Mon Sep 17 00:00:00 2001
From: theborakompanioni 
Date: Thu, 20 Jun 2024 17:29:37 +0200
Subject: [PATCH 21/24] docs(bip-0046): add test certificate for the 960th
 timelocked address

---
 bip-0046.mediawiki | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/bip-0046.mediawiki b/bip-0046.mediawiki
index 84fd2e2d..1dc124ef 100644
--- a/bip-0046.mediawiki
+++ b/bip-0046.mediawiki
@@ -122,7 +122,7 @@ redeemscript        = 0400e10b5eb1752102a1b09f93073c63f205086440898141c0c3c6d24f
 scriptPubKey        = 0020bdee9515359fc9df912318523b4cd22f1c0b5410232dc943be73f9f4f07e39ad
 address             = bc1qhhhf29f4nlyalyfrrpfrknxj9uwqk4qsyvkujsa7w0ulfur78xkspsqn84
 
-// Test certificate using first timelocked address
+// Test certificate using the 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.
@@ -158,6 +158,12 @@ string locktime     = 2099-12-01 00:00:00
 redeemscript        = 0580785df400b175210308c5751121b1ae5c973cdc7071312f6fc10ab864262f0cbd8134f056166e50f3ac
 scriptPubKey        = 0020803268e042008737cf439748cbb5a4449e311da9aa64ae3ac56d84d059654f85
 address             = bc1qsqex3czzqzrn0n6rjayvhddygj0rz8df4fj2uwk9dkzdqkt9f7zs5c493u
+
+// Test certificate using the 960th timelocked address
+Message       = fidelity-bond-cert|020000000000000000000000000000000000000000000000000000000000000001|750
+Address       = bc1qsqex3czzqzrn0n6rjayvhddygj0rz8df4fj2uwk9dkzdqkt9f7zs5c493u
+p2pkh address = 1JmTqEXY9pHwrao9XXPo1MeiQerMETmwP3
+Signature     = H9LWcv9PXjOLdGmA6s6jRKnPP9bKeOSUGN7ZF80dphKOUrLQnoIJx8NtHraTq5o6BbRBoNjKHuo4Mnok3/JXGBY=
 
Code generating these test vectors can be found here: https://github.com/chris-belcher/timelocked-addresses-fidelity-bond-bip-testvectors From 0cdb745ee001b11fe4b1da55ec1fb4f2351b6451 Mon Sep 17 00:00:00 2001 From: theborakompanioni Date: Mon, 8 Jul 2024 10:48:53 +0200 Subject: [PATCH 22/24] docs(bip-0046): apply minor wording improvement suggestions by @AdamISZ --- bip-0046.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-0046.mediawiki b/bip-0046.mediawiki index 1dc124ef..83ddd5eb 100644 --- a/bip-0046.mediawiki +++ b/bip-0046.mediawiki @@ -73,7 +73,7 @@ m / 84' / 0' / 0' / 2 / index A key derived with this derivation path pattern will be referred to as derived_key further in this document. -For index, 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 959 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 for all of them if they have a balance and history. +For index, addresses are numbered from 0 in a sequentially increasing manner with a fixed upper bound: The index only goes up to 959 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 for all of them if they have a balance and history. === Timelock derivation === From b916adebae2606edf4934eb6f4a1d056425abf05 Mon Sep 17 00:00:00 2001 From: theborakompanioni Date: Mon, 8 Jul 2024 11:01:26 +0200 Subject: [PATCH 23/24] docs(bip-0046): add cert format and clarify expiry param --- bip-0046.mediawiki | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bip-0046.mediawiki b/bip-0046.mediawiki index 83ddd5eb..7eb5d990 100644 --- a/bip-0046.mediawiki +++ b/bip-0046.mediawiki @@ -99,6 +99,10 @@ To derive the address from the above calculated public key and timelock, we crea In order to support signing of certificates, implementors should support signing ASCII messages. +The certificate message is defined as `"fidelity-bond-cert" || "|" || cert_pubkey || "|" || cert_expiry`. + +The certificate expiry `cert_expiry` is the number of the 2016-block period after which the certificate is no longer valid. For example, if `cert_expiry` is 330 then the certificate will become invalid after block height 665280 (:=330x2016). The purpose of the expiry parameter is so that in case the certificate keypair is compromised, the attacker can only impersonate the fidelity bond for a limited amount of time. + A certificate message can be created by another application external to this standard. It is then prepended with the string `0x18 || "Bitcoin 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 derived_key. 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. From 4f788d69f501d26f6c88db7fe0cf19696b608059 Mon Sep 17 00:00:00 2001 From: theborakompanioni Date: Mon, 8 Jul 2024 12:25:37 +0200 Subject: [PATCH 24/24] docs(bip-0046): add endpoint signing example --- bip-0046.mediawiki | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/bip-0046.mediawiki b/bip-0046.mediawiki index 7eb5d990..e3ad5750 100644 --- a/bip-0046.mediawiki +++ b/bip-0046.mediawiki @@ -131,10 +131,10 @@ address = bc1qhhhf29f4nlyalyfrrpfrknxj9uwqk4qsyvkujsa7w0ulfur78xksps // 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 +message = fidelity-bond-cert|020000000000000000000000000000000000000000000000000000000000000001|375 +address = bc1qhhhf29f4nlyalyfrrpfrknxj9uwqk4qsyvkujsa7w0ulfur78xkspsqn84 p2pkh address = 16vmiGpY1rEaYnpGgtG7FZgr2uFCpeDgV6 -Signature = H2b/90XcKnIU/D1nSCPhk8OcxrHebMCr4Ok2d2yDnbKDTSThNsNKA64CT4v2kt+xA1JmGRG/dMnUUH1kKqCVSHo= +signature = H2b/90XcKnIU/D1nSCPhk8OcxrHebMCr4Ok2d2yDnbKDTSThNsNKA64CT4v2kt+xA1JmGRG/dMnUUH1kKqCVSHo= // 2nd timelocked address = m/84'/0'/0'/2/1 derived private_key = KxctaFBzetyc9KXeUr6jxESCZiCEXRuwnQMw7h7hroP6MqnWN6Pf @@ -163,11 +163,20 @@ redeemscript = 0580785df400b175210308c5751121b1ae5c973cdc7071312f6fc10ab8 scriptPubKey = 0020803268e042008737cf439748cbb5a4449e311da9aa64ae3ac56d84d059654f85 address = bc1qsqex3czzqzrn0n6rjayvhddygj0rz8df4fj2uwk9dkzdqkt9f7zs5c493u -// Test certificate using the 960th timelocked address -Message = fidelity-bond-cert|020000000000000000000000000000000000000000000000000000000000000001|750 -Address = bc1qsqex3czzqzrn0n6rjayvhddygj0rz8df4fj2uwk9dkzdqkt9f7zs5c493u -p2pkh address = 1JmTqEXY9pHwrao9XXPo1MeiQerMETmwP3 -Signature = H9LWcv9PXjOLdGmA6s6jRKnPP9bKeOSUGN7ZF80dphKOUrLQnoIJx8NtHraTq5o6BbRBoNjKHuo4Mnok3/JXGBY= +// Test certificate and endpoint signing using the first timelocked address = m/84'/0'/0'/2/0 (see above) +bond private_key = L2tQBEdhC48YLeEWNg3e4msk94iKfyVa9hdfzRwUERabZ53TfH3d +bond p2pkh address = 16vmiGpY1rEaYnpGgtG7FZgr2uFCpeDgV6 + +certificate private_key = KyZpNDKnfs94vbrwhJneDi77V6jF64PWPF8x5cdJb8ifgg2DUc9d +certificate public_key = 0330d54fd0dd420a6e5f8d3624f5f3482cae350f79d5f0753bf5beef9c2d91af3c +certificate p2pkh address = 1JaUQDVNRdhfNsVncGkXedaPSM5Gc54Hso + +certificate message = fidelity-bond-cert|0330d54fd0dd420a6e5f8d3624f5f3482cae350f79d5f0753bf5beef9c2d91af3c|375 +certificate signature = INOP3cB9UW7F1e1Aglj8rI9QhnyxmgWDEPt+nOMvl7hJJne7rH/KCNDYvLiqNuB9qWaWUojutjRsgPJrvyDQ+0Y= + +// example endpoint signing two IRC nicknames (used in JoinMarket) +endpoint message = J54LS6YyJPoseqFS|J55VZ6U6ZyFDNeuv +endpoint signature = H18WE4MugDNoWZIf9jU0njhQptdUyBDUf7lToG9bpMKmeJK0lOoABaDs5bKnohSuZ0e9gnSco5OL9lXdKU7gP5E=
Code generating these test vectors can be found here: https://github.com/chris-belcher/timelocked-addresses-fidelity-bond-bip-testvectors