@ -429,15 +429,30 @@ wallets--not shared with the network--protecting their privacy
and keeping unnecessary personal data out of the blockchain. For
an example, see <<alice_tx_labels>>.
[[alice_tx_labels]]
.Alice's transaction history with each transaction labeled
[options="header"]
[cols="1,1,1"]
|===
| Date | Label | BTC
| 2023-01-01 | Bought bitcoins from Joe | +0.00100
| 2023-01-02 | Paid Bob for podcast | − 0.00075
|===
++++
<table id="alice_tx_labels">
<caption>Alice’ s transaction history with each transaction labeled</caption>
<thead>
<tr>
<th>Date</th>
<th>Label</th>
<th>BTC</th>
</tr>
</thead>
<tbody>
<tr>
<td><p>2023-01-01</p></td>
<td><p>Bought bitcoins from Joe</p></td>
<td><p>+0.00100</p></td>
</tr>
<tr>
<td><p>2023-01-02</p></td>
<td><p>Paid Bob for podcast</p></td>
<td><p>− 0.00075</p></td>
</tr>
</tbody>
</table>
++++
However, because address and transaction labels are stored only in each
user's wallet database and because they aren't deterministic, they can't
@ -512,17 +527,40 @@ the keys in that path both when it is first started and after a
restoration from a recovery code. We call this solution _implicit
paths_. Several popular implicit paths defined by BIPs are shown in <<bip_implicit_paths>>
[[bip_implicit_paths]]
.Implicit script paths defined by various BIPs
[options="header"]
[cols="1,1,1"]
|===
| Standard | Script | BIP32 path
| BIP44 | P2PKH | +m/44'/0'/0'+
| BIP49 | Nested P2WPKH | +m/49'/1'/0'+
| BIP84 | P2WPKH | +m/84'/0'/0'+
| BIP86 | P2TR Single-key | +m/86'/0'/0'+
|===
++++
<table id="bip_implicit_paths">
<caption>Implicit script paths defined by various BIPs</caption>
<thead>
<tr>
<th>Standard</th>
<th>Script</th>
<th>BIP32 path</th>
</tr>
</thead>
<tbody>
<tr>
<td><p>BIP44</p></td>
<td><p>P2PKH</p></td>
<td><p><code>m/44'/0'/0'</code></p></td>
</tr>
<tr>
<td><p>BIP49</p></td>
<td><p>Nested P2WPKH</p></td>
<td><p><code>m/49'/1'/0'</code></p></td>
</tr>
<tr>
<td><p>BIP84</p></td>
<td><p>P2WPKH</p></td>
<td><p><code>m/84'/0'/0'</code></p></td>
</tr>
<tr>
<td><p>BIP86</p></td>
<td><p>P2TR Single-key</p></td>
<td><p><code>m/86'/0'/0'</code></p></td>
</tr>
</tbody>
</table>
++++
The second solution is to back up the path information with the recovery
code, making it clear which path is used with which scripts. We call
@ -582,21 +620,32 @@ _descriptors_ for short) as specified in BIPs 380, 381, 382, 383, 384,
describe a script and the keys (or key paths) to be used with it.
A few example descriptors are shown in <<sample_descriptors>>.
[[sample_descriptors]]
.Sample descriptors from Bitcoin Core documentation (with elision)
[cols="1,1"]
|===
| Descriptor | Explanation
| +pkh(02c6...9ee5)+
| P2PKH script for the provided public key
| +sh(multi(2,022f...2a01,03ac...ccbe))+
| P2SH multisignature requring two signatures corresponding to these two keys
++++
<table id="sample_descriptors">
<caption>Sample descriptors from Bitcoin Core documentation (with elision)</caption>
<thead>
<tr>
<th>Descriptor</th>
<th>Explanation</th>
</tr>
</thead>
<tbody>
<tr>
<td><p><code>pkh(02c6… 9ee5)</code></p></td>
<td><p>P2PKH script for the provided public key</p></td>
</tr>
<tr>
<td><p><code>sh(multi(2,022f… 2a01,03ac… ccbe))</code></p></td>
<td><p>P2SH multisignature requring two signatures corresponding to these two keys</p></td>
</tr>
<tr>
<td><p><code>pkh([d34db33f/44'/0'/0']xpub6ERA… RcEL/1/*)</code></p></td>
<td><p>P2PKH scripts for the BIP32 <code>d34db33f</code> with the extended public key (xpub) at the path <code>M/44'/0'/0'</code>, which is <code>xpub6ERA… RcEL</code>, using the keys at <code>M/1/*</code> of that xpub</p></td>
</tr>
</tbody>
</table>
++++
| +pkh([d34db33f/44'/0'/0']xpub6ERA...RcEL/1/*)+
| P2PKH scripts for the BIP32 +d34db33f+ with the extended public key (xpub) at the path +M/44'/0'/0'+, which is +xpub6ERA...RcEL+, using the keys at +M/1/*+ of that xpub
|===
It has long been the trend for wallet applications designed only for
single signature scripts to use implicit paths. Wallet applications
@ -690,18 +739,97 @@ image::images/mbc3_0504.png["Generating entropy and encoding as a recovery code"
<<table_4-5>> shows the relationship between the size of the entropy
data and the length of recovery code in words.
[[table_4-5]]
.BIP39: entropy and word length
[options="header"]
[cols="1,1,1,1"]
|=======
|Entropy (bits) | Checksum (bits) | Entropy *+* checksum (bits) | Recovery code words
| 128 | 4 | 132 | 12
| 160 | 5 | 165 | 15
| 192 | 6 | 198 | 18
| 224 | 7 | 231 | 21
| 256 | 8 | 264 | 24
|=======
++++
<table id="table_4-5">
<caption>BIP39: entropy and word length</caption>
<thead>
<tr>
<th>Entropy (bits)</th>
<th>Checksum (bits)</th>
<th>Entropy <strong>+</strong> checksum (bits)</th>
<th>Recovery code words</th>
</tr>
</thead>
<tbody>
<tr>
<td><p>128</p></td>
<td><p>4</p></td>
<td><p>132</p></td>
<td><p>12</p></td>
</tr>
<tr>
<td><p>160</p></td>
<td><p>5</p></td>
<td><p>165</p></td>
<td><p>15</p></td>
</tr>
<tr>
<td><p>192</p></td>
<td><p>6</p></td>
<td><p>198</p></td>
<td><p>18</p></td>
</tr>
<tr>
<td><p>224</p></td>
<td><p>7</p></td>
<td><p>231</p></td>
<td><p>21</p></td>
</tr>
<tr>
<td><p>256</p></td>
<td><p>8</p></td>
<td><p>264</p></td>
<td><p>24</p></td>
</tr>
</tbody>
</table>
++++
++++
<table id="table_4-5">
<caption>BIP39: entropy and word length</caption>
<thead>
<tr>
<th>Entropy (bits)</th>
<th>Checksum (bits)</th>
<th>Entropy <strong>+</strong> checksum (bits)</th>
<th>Recovery code words</th>
</tr>
</thead>
<tbody>
<tr>
<td><p>128</p></td>
<td><p>4</p></td>
<td><p>132</p></td>
<td><p>12</p></td>
</tr>
<tr>
<td><p>160</p></td>
<td><p>5</p></td>
<td><p>165</p></td>
<td><p>15</p></td>
</tr>
<tr>
<td><p>192</p></td>
<td><p>6</p></td>
<td><p>198</p></td>
<td><p>18</p></td>
</tr>
<tr>
<td><p>224</p></td>
<td><p>7</p></td>
<td><p>231</p></td>
<td><p>21</p></td>
</tr>
<tr>
<td><p>256</p></td>
<td><p>8</p></td>
<td><p>264</p></td>
<td><p>24</p></td>
</tr>
</tbody>
</table>
++++
[[recovery_to_seed]]
===== From recovery code to seed
@ -772,40 +900,77 @@ pass:[<a data-type="xref" href="#bip39_256_no_pass"
data-xrefstyle="select: labelnumber">#bip39_256_no_pass</a>] show
some examples of recovery codes and the seeds they produce.
[[bip39_128_no_pass]]
.128-bit entropy BIP39 recovery code, no passphrase, resulting seed
[cols="h,"]
|=======
| *Entropy input (128 bits)*| +0c1e24e5917779d297e14d45f14e1a1a+
| *Recovery Code (12 words)* | +army van defense carry jealous true garbage claim echo media make crunch+
| *Passphrase*| (none)
| *Seed (512 bits)* | +5b56c417303faa3fcba7e57400e120a0ca83ec5a4fc9ffba757fbe63fbd77a89a1a3be4+
+c67196f57c39a88b76373733891bfaba16ed27a813ceed498804c0570+
|=======
[[bip39_128_w_pass]]
.128-bit entropy BIP39 recovery code, with passphrase, resulting seed
[cols="h,"]
|=======
| *Entropy input (128 bits)*| +0c1e24e5917779d297e14d45f14e1a1a+
| *Recovery Code (12 words)* | +army van defense carry jealous true garbage claim echo media make crunch+
| *Passphrase*| SuperDuperSecret
| *Seed (512 bits)* | +3b5df16df2157104cfdd22830162a5e170c0161653e3afe6c88defeefb0818c793dbb28+
+ab3ab091897d0715861dc8a18358f80b79d49acf64142ae57037d1d54+
|=======
[[bip39_256_no_pass]]
.256-bit entropy BIP39 recovery code, no passphrase, resulting seed
[cols="h,"]
|=======
| *Entropy input (256 bits)* | +2041546864449caff939d32d574753fe684d3c947c3346713dd8423e74abcf8c+
| *Recovery Code (24 words)* | +cake apple borrow silk endorse fitness top denial coil riot stay wolf
luggage oxygen faint major edit measure invite love trap field dilemma oblige+
| *Passphrase*| (none)
| *Seed (512 bits)* | +3269bce2674acbd188d4f120072b13b088a0ecf87c6e4cae41657a0bb78f5315b33b3+
+a04356e53d062e55f1e0deaa082df8d487381379df848a6ad7e98798404+
|=======
++++
<table id="bip39_128_no_pass">
<caption>128-bit entropy BIP39 recovery code, no passphrase, resulting seed</caption>
<tbody>
<tr>
<td><p><strong>Entropy input (128 bits)</strong></p></td>
<td><p><code>0c1e24e5917779d297e14d45f14e1a1a</code></p></td>
</tr>
<tr>
<td><p><strong>Recovery Code (12 words)</strong></p></td>
<td><p><code>army van defense carry jealous true garbage claim echo media make crunch</code></p></td>
</tr>
<tr>
<td><p><strong>Passphrase</strong></p></td>
<td><p>(none)</p></td>
</tr>
<tr>
<td><p><strong>Seed (512 bits)</strong></p></td>
<td><p><code>5b56c417303faa3fcba7e57400e120a0ca83ec5a4fc9ffba757fbe63fbd77a89a1a3be4</code>
<code>c67196f57c39a88b76373733891bfaba16ed27a813ceed498804c0570</code></p></td>
</tr>
</tbody>
</table>
<table id="bip39_128_w_pass">
<caption>128-bit entropy BIP39 recovery code, with passphrase, resulting seed</caption>
<tbody>
<tr>
<td><p><strong>Entropy input (128 bits)</strong></p></td>
<td><p><code>0c1e24e5917779d297e14d45f14e1a1a</code></p></td>
</tr>
<tr>
<td><p><strong>Recovery Code (12 words)</strong></p></td>
<td><p><code>army van defense carry jealous true garbage claim echo media make crunch</code></p></td>
</tr>
<tr>
<td><p><strong>Passphrase</strong></p></td>
<td><p>SuperDuperSecret</p></td>
</tr>
<tr>
<td><p><strong>Seed (512 bits)</strong></p></td>
<td><p><code>3b5df16df2157104cfdd22830162a5e170c0161653e3afe6c88defeefb0818c793dbb28</code>
<code>ab3ab091897d0715861dc8a18358f80b79d49acf64142ae57037d1d54</code></p></td>
</tr>
</tbody>
</table>
<table id="bip39_256_no_pass">
<caption><span class="label">Table 5-7. </span>256-bit entropy BIP39 recovery code, no passphrase, resulting seed</caption>
<tbody>
<tr>
<td><p><strong>Entropy input (256 bits)</strong></p></td>
<td><p><code>2041546864449caff939d32d574753fe684d3c947c3346713dd8423e74abcf8c</code></p></td>
</tr>
<tr>
<td><p><strong>Recovery Code (24 words)</strong></p></td>
<td><p><code>cake apple borrow silk endorse fitness top denial coil riot stay wolf
luggage oxygen faint major edit measure invite love trap field dilemma oblige</code></p></td>
</tr>
<tr>
<td><p><strong>Passphrase</strong></p></td>
<td><p>(none)</p></td>
</tr>
<tr>
<td><p><strong>Seed (512 bits)</strong></p></td>
<td><p><code>3269bce2674acbd188d4f120072b13b088a0ecf87c6e4cae41657a0bb78f5315b33b3</code>
<code>a04356e53d062e55f1e0deaa082df8d487381379df848a6ad7e98798404</code></p></td>
</tr>
</tbody>
</table>
++++
.How Much Entropy Do You Need?
****
@ -1283,18 +1448,39 @@ master key from which it was derived. For example, identifier m/x/y/z
describes the key that is the z-th child of key m/x/y, which is the y-th
child of key m/x, which is the x-th child of m.
[[table_4-8]]
.HD wallet path examples
[options="header"]
[cols="1,1"]
|=======
|HD path | Key described
| m/0 | The first (0) child private key from the master private key (m)
| m/0/0 | The first grandchild private key from the first child (m/0)
| m/0'/0 | The first normal grandchild private key from the first _hardened_ child (m/0')
| m/1/0 | The first grandchild private key from the second child (m/1)
| M/23/17/0/0 | The first great-great-grandchild public key from the first great-grandchild from the 18th grandchild from the 24th child
|=======
++++
<table id="table_4-8">
<caption>HD wallet path examples</caption>
<thead>
<tr>
<th>HD path</th>
<th>Key described</th>
</tr>
</thead>
<tbody>
<tr>
<td><p>m/0</p></td>
<td><p>The first (0) child private key from the master private key (m)</p></td>
</tr>
<tr>
<td><p>m/0/0</p></td>
<td><p>The first grandchild private key from the first child (m/0)</p></td>
</tr>
<tr>
<td><p>m/0'/0</p></td>
<td><p>The first normal grandchild private key from the first <em>hardened</em> child (m/0')</p></td>
</tr>
<tr>
<td><p>m/1/0</p></td>
<td><p>The first grandchild private key from the second child (m/1)</p></td>
</tr>
<tr>
<td><p>M/23/17/0/0</p></td>
<td><p>The first great-great-grandchild public key from the first great-grandchild from the 18th grandchild from the 24th child</p></td>
</tr>
</tbody>
</table>
++++
===== Navigating the HD wallet tree structure
@ -1354,16 +1540,31 @@ third receiving address for payments in the primary account
would be M/44++'++/0++'++/0++'++/0/2. <<table_4-9>> shows
a few more examples.
[[table_4-9]]
.BIP44 HD wallet structure examples
[options="header"]
[cols="1,1"]
|=======
|HD path | Key described
| M/44++'++/0++'++/0++'++/0/2 | The third receiving public key for the primary Bitcoin account
| M/44++'++/0++'++/3++'++/1/14 | The fifteenth change-address public key for the fourth Bitcoin account
| m/44++'++/2++'++/0++'++/0/1 | The second private key in the Litecoin main account, for signing transactions
|=======
++++
<table id="table_4-9">
<caption>BIP44 HD wallet structure examples</caption>
<thead>
<tr>
<th>HD path</th>
<th>Key described</th>
</tr>
</thead>
<tbody>
<tr>
<td><p>M/44<code>'</code>/0<code>'</code>/0<code>'</code>/0/2</p></td>
<td><p>The third receiving public key for the primary Bitcoin account</p></td>
</tr>
<tr>
<td><p>M/44<code>'</code>/0<code>'</code>/3<code>'</code>/1/14</p></td>
<td><p>The fifteenth change-address public key for the fourth Bitcoin account</p></td>
</tr>
<tr>
<td><p>m/44<code>'</code>/2<code>'</code>/0<code>'</code>/0/1</p></td>
<td><p>The second private key in the Litecoin main account, for signing transactions</p></td>
</tr>
</tbody>
</table>
++++
Many people focus on securing their bitcoins against theft and other
attacks, but one of the leading causes of lost bitcoins--perhaps _the_