Compare commits

...

23 Commits

Author SHA1 Message Date
Shannon Appelcline
133094de92
Update TODO.md 2026-02-05 15:37:57 -10:00
Shannon Appelcline
3fb9c62394
Update 03_4_Understanding_the_Descriptor.md 2026-02-05 15:33:28 -10:00
Shannon Appelcline
3521f105a4
Update TODO.md 2026-02-05 15:10:38 -10:00
Shannon Appelcline
a93ce2f546
full draft 2026-02-05 15:07:54 -10:00
Shannon Appelcline
7747673850
Update TODO.md 2026-02-05 14:33:24 -10:00
Shannon Appelcline
351684632c
updated objectives for updated text 2026-02-05 14:31:55 -10:00
Shannon Appelcline
6d80242649
Update 03_4_Understanding_the_Descriptor.md 2026-02-05 14:30:14 -10:00
Shannon Appelcline
35881cecba
wrote listdescriptors section 2026-02-05 14:11:00 -10:00
Shannon Appelcline
dbdad26ecc
added some addresses 2026-02-05 13:38:57 -10:00
Shannon Appelcline
979bdc0076
wrote/revised early sections on HD and Descriptor Wallets 2026-02-05 13:25:07 -10:00
Shannon Appelcline
e281e38800
moving BIP info 2026-02-05 12:58:32 -10:00
Shannon Appelcline
f47ed04e78
minor edits 2026-02-05 12:28:34 -10:00
Shannon Appelcline
20793e23da
Update 03_3a_Interlude_Using_Command-Line_Variables.md 2026-02-05 12:24:26 -10:00
Shannon Appelcline
c8b93a8069
Update 03_3a_Interlude_Using_Command-Line_Variables.md 2026-02-05 12:24:01 -10:00
Shannon Appelcline
db881b6742
Update 03_3a_Interlude_Using_Command-Line_Variables.md 2026-02-05 12:22:19 -10:00
Shannon Appelcline
ec2367b8ac
Update 03_3a_Interlude_Using_Command-Line_Variables.md 2026-02-05 12:21:37 -10:00
Shannon Appelcline
e524305d07
Update 03_3a_Interlude_Using_Command-Line_Variables.md 2026-02-05 12:21:23 -10:00
Shannon Appelcline
1030a1030e
Update TODO.md 2026-02-05 12:06:21 -10:00
Shannon Appelcline
d0dc6fc78a
address for (final) wallet 2026-02-05 12:05:50 -10:00
Shannon Appelcline
2d2a74b120
content on multiple wallets 2026-02-05 12:04:36 -10:00
Shannon Appelcline
6130e2061e
Update 03_3_Setting_Up_Your_Wallet.md 2026-02-05 11:37:28 -10:00
Shannon Appelcline
cee1dfe1de
added encryption 2026-02-05 11:01:10 -10:00
Shannon Appelcline
47c2d59354
Update 03_4_Understanding_the_Descriptor.md 2026-02-05 10:22:48 -10:00
6 changed files with 425 additions and 179 deletions

View File

@ -9,8 +9,9 @@ For this and future chapters, we presume that you have a VPS with Bitcoin instal
After working through this chapter, a developer will be able to:
* Demonstrate that Their Bitcoin Node is Installed and Up-to-date
* Create an Address to Receive Bitcoin Funds
* Create Bitcoin Wallets
* Use Basic Wallet Commands
* Create an Address to Receive Bitcoin Funds
* Create an Address from a Descriptor
Supporting objectives include the ability to:
@ -19,7 +20,7 @@ Supporting objectives include the ability to:
* Use Basic Informational Commands
* Understand What a Bitcoin Address Is
* Understand What a Wallet Is
* Understand How to Import Addresses
* Recognize Common Types of Bitcoin Wallets
## Table of Contents

View File

@ -30,15 +30,22 @@ $ ls ~/.bitcoin/signet/wallets
$
```
That's because Bitcoin Core doesn't create a wallet by default, but creating one is quite simple. You just run `bitcoin-cli createwallet` and choose a name for your wallet, such as `"mainwallet"`.
That's because Bitcoin Core doesn't create a wallet by default, but creating one is quite simple. You just run `bitcoin-cli createwallet` and choose a name for your wallet. If you choose no name (`""`) you're creating a wallet that will be loaded by default (which is helpful!). But you could also choose a real name like `"mainwallet"` if you plan to run multiple wallets. (We suggest the use of a no-name wallet for this tutorial, for reasons of simplicity, as we'll discuss later.)
Here's what the creation looks like:
```
$ bitcoin-cli createwallet "mainwallet"
$ bitcoin-cli createwallet ""
{
"name": "mainwallet"
"name": ""
}
```
Now, your `wallets` directory should be populated.
If you created a `""` wallet, your `wallets` directory will have files in it:
```
wallet.dat wallet.dat-journal
```
If you created a named wallet, the `wallets` directory will instead have a subdirectory by that name, and the subdirectory will have the files.
```
$ ls ~/.bitcoin/signet/wallets
mainwallet
@ -46,8 +53,36 @@ $ ls ~/.bitcoin/signet/wallets/mainwallet
wallet.dat wallet.dat-journal
```
As this indicates, each wallet will have its own directory. (The main directory is used if you choose `""` for your wallet name.) Each directory will then have a `wallet.dat` file (which is a SQLite database) and a `wallet.dat-journal` file (which is an SQLite rollback journal).
Each wallet will have a `wallet.dat` file (which is a SQLite database) and a `wallet.dat-journal` file (which is an SQLite rollback journal).
You can see details on your wallet with the `bitcoin-cli getwalletinfo` command:
```
$ bitcoin-cli getwalletinfo
{
"walletname": "",
"walletversion": 169900,
"format": "sqlite",
"txcount": 0,
"keypoolsize": 4000,
"keypoolsize_hd_internal": 4000,
"paytxfee": 0.00000000,
"private_keys_enabled": true,
"avoid_reuse": false,
"scanning": false,
"descriptors": true,
"external_signer": false,
"blank": false,
"birthtime": 1770328126,
"flags": [
"last_hardened_xpub_cached",
"descriptor_wallet"
],
"lastprocessedblock": {
"hash": "0000000bd5046d28c2c02a60be14f2d3f1909277e574fa01279190dbe468a6e0",
"height": 290283
}
}
```
> :book: ***What is a Bitcoin wallet?*** A Bitcoin wallet is the digital equivalent of a physical wallet. It stores information on the amount of bitcoins you have and where it's located (addresses), as well as the ways you can use to spend it. Spending physical money is intuitive, but to spend Bitcoin, users need to provide the correct _private key_. We will explain this in more detail throughout the course, but what you should know for now is that this public-private key dynamic is part of what makes Bitcoin secure and trustless. Your key pair information is saved in the `wallet.dat` file, in addition to data about preferences and transactions. For the most part, you won't have to worry about that private key: `bitcoind` will use it when it's needed. However, this makes the `wallet.dat` file extremely important: if you lose it, you lose your private keys, and if you lose your private keys, you lose your funds!
You now have a Bitcoin wallet. But you can't receive funds with a wallet. For that you need an address, which is a specific repository for funds, derived from the private key information in your wallet: its one private key can generate many addresses.
@ -58,7 +93,29 @@ The next thing you need to do is create an address for receiving payments. This
```
$ bitcoin-cli getnewaddress
tb1qmuqycfqfffvkys2h8rwqpgw6n0v6s0uhd235sj
tb1q05ua6g7njnjrtsjc0t9w3jc6g2leeznasf4ny9
```
You can keep typing the command you'll get a different address each time:
```
$ bitcoin-cli getnewaddress
tb1q0psqqqgy0fv5928wmk86ntu7hlax8dva7nl82p
$ bitcoin-cli getnewaddress
tb1q9f8j03uywqsxuxjefz68g7x4kduer2ky6shsf4
```
You can later look up the addresses you've generated with `bitcoin-cli getaddressesbylabel`, with the label being `""` unless you set one:
```
$ bitcoin-cli getaddressesbylabel ""
{
"tb1q9f8j03uywqsxuxjefz68g7x4kduer2ky6shsf4": {
"purpose": "receive"
},
"tb1q0psqqqgy0fv5928wmk86ntu7hlax8dva7nl82p": {
"purpose": "receive"
},
"tb1q05ua6g7njnjrtsjc0t9w3jc6g2leeznasf4ny9": {
"purpose": "receive"
}
}
```
Note that this address begins with an "tb1", which [means](https://en.bitcoin.it/wiki/List_of_address_prefixes) that it's a Bech32 address on either signet or testnet. The discussion of different address types in §4.1 will also talk about all of their identifying prefixes.
@ -68,83 +125,118 @@ Take careful note of the address. You'll need to give it to whomever will be sen
> :book: ***What is a Bitcoin address?*** A Bitcoin address is literally where you receive money. It's like an email address, but for funds. It's based on a public key, though different address schemes adjust that in different ways. However unlike an email address, a Bitcoin address should be considered single use: use it to receive funds just _once_. When you want to receive funds from someone else or at some other time, generate a new address. This is suggested in large part to improve your privacy. The whole blockchain is immutable, which means that explorers can look at long chains of transactions over time, making it possible to statistically determine who you and your contacts are, no matter how careful you are. If you keep reusing the same address, then this becomes even easier.
By creating your first Bitcoin address, you've also begun to fill in your Bitcoin wallet. More precisely, you've begun to fill the `wallet.dat` file in your `~/.bitcoin/signet /wallets/{walletname}` directory. With a single address in hand, you could jump straight [§3.5: Receiving a Transaction](03_5_Receiving_a_Transaction.md) and begin receiving funds. However, before we get there, we're going to briefly discuss a few optional wallet commands that you might want to use in the future.
By creating your first Bitcoin address, you've also begun to fill in your Bitcoin wallet. More precisely, you've begun to fill the `wallet.dat` file in the appropriate `~/.bitcoin/signet /wallets/` directory. With a single address in hand, you could jump straight [§3.5: Receiving a Transaction](03_5_Receiving_a_Transaction.md) and begin receiving funds. However, before we get there, we're going to briefly discuss backing up your wallet and a few optional wallet commands that you might want to use in the future.
## Optional: Sign a Message
## Backup Your Wallet
Sometimes you'll need to prove that you control a Bitcoin address (or rather, that you control its private key). This is important because it lets people know that they're sending funds to the right person. This can be done by creating a signature with the `bitcoin-cli signmessage` command, in the form `bitcoin-cli signmessage [address] [message]`. For example:
You can backup your wallet with the `bitcoin-cli backupwallet` command:
```
$ bitcoin-cli signmessage "moKVV6XEhfrBCE3QCYq6ppT7AaMF8KsZ1B" "Hello, World"
HyIP0nzdcH12aNbQ2s2rUxLwzG832HxiO1vt8S/jw+W4Ia29lw6hyyaqYOsliYdxne70C6SZ5Utma6QY/trHZBI=
$ mkdir ~/backups
$ bitcoin-cli backupwallet ~/backups/mainwallet.dat
```
You'll get the signature as a return.
This will create a backup of the SQLite file that you can later restore from with the `bitcoin-cli restorewallet` command. It's probably best used if you'll be backing up your wallet to a secure (encrypted) storage area.
> :book: ***What is a signature?*** A digital signature is a combination of a message and a private key that can then be unlocked with a public key. Since there's a one-to-one correspendence between the elements of a keypair, unlocking with a public key proves that the signer controlled the corresponding private key.
Just having a single backup will be enough to recover your wallet, because it'll contain the seed used to generate the wallet (more on that next chapter). However, it's good to regularly backup your wallet so that you don't lose data about your transactions.
Another person can then use the `bitcoin-cli verifymessage` command to verify the signature. He inputs the address in question, the signature, and the message:
```
$ bitcoin-cli verifymessage "moKVV6XEhfrBCE3QCYq6ppT7AaMF8KsZ1B" "HyIP0nzdcH12aNbQ2s2rUxLwzG832HxiO1vt8S/jw+W4Ia29lw6hyyaqYOsliYdxne70C6SZ5Utma6QY/trHZBI=" "Hello, World"
true
```
If they all match up, then the other person knows that he can safely transfer funds to the person who signed the message by sending to the address.
## Optional: Encrypt Your Wallet
If some black hat was making up signatures, this would instead produce a negative result:
You can choose to encrypt your wallet. (It actually just encrypts the private information in your wallet, such as your private keys.) This is done with the `bitcoin-cli encryptwallet` command.
```
$ bitcoin-cli verifymessage "FAKEV6XEhfrBCE3QCYq6ppT7AaMF8KsZ1B" "HyIP0nzdcH12aNbQ2s2rUxLwzG832HxiO1vt8S/jw+W4Ia29lw6hyyaqYOsliYdxne70C6SZ5Utma6QY/trHZBI=" "Hello, World"
error code: -3
error message:
Invalid address
$ bitcoin-cli encryptwallet "your-great-password"
wallet encrypted; The keypool has been flushed and a new HD seed was generated. You need to make a new backup with the backupwallet RPC.
```
You should _definitely_ encrypt your wallet if you are using `bitcoin-cli` to deal with real money, but you probably shouldn't do it for this course (or any other use of test networks) because it'll just add new hoops to jump through test out funds.
Once you have encrypted your wallet, you'll be required to enter a passphrase in order to do many commands:
```
$ bitcoin-cli walletpassphrase "your-great-password" 3600
```
This will unlock your wallet for a set number of seconds (here, 3600 seconds, which is an hour), after which you'll again be required to enter your passphrase.
If you want to lock your wallet back up earlier than that, you can use `bitcoin-cli walletlock`:
```
$ bitcoin-cli walletlock
```
## Optional: Dump Your Wallet
## Optional: Reload Named Wallets
It might seem dangerous having all of your irreplaceable private keys in a single file. That's what `bitcoin-cli dumpwallet` is for. It lets you make a copy of your wallet.dat:
If you created a no-name (`""`) wallet, it will automatically load when you restart `bitcoind`. However, if you instead created a named wallet, it will not reload, forcing you to (initially) reload it by hand when you restart.
```
$ bitcoin-cli dumpwallet ~/mywallet.txt
```
The `mywallet.txt` file in your home directory will have a long list of private keys, addresses, and other information. Mind you, you'd never want to put this data out in a plain text file on a Bitcoin setup with real funds!
You can then recover it with `bitcoin-cli importwallet`.
```
$ bitcoin-cli importwallet ~/mywallet.txt
```
But note this requires an unpruned node!
```
$ bitcoin-cli importwallet ~/mywallet.txt
error code: -4
error message:
Importing wallets is disabled when blocks are pruned
```
## Optional: View Your Private Keys
Sometimes, you might want to actually look at the private keys associated with your Bitcoin addresses. Perhaps you want to be able to sign a message or spend bitcoins from a different machine. Perhaps you just want to back up certain important private keys. You can also do this with your dump file, since it's human readable.
```
$ bitcoin-cli dumpwallet ~/mywallet.txt
$ bitcoin-cli loadwallet mainwallet
{
"filename": "/home/standup/mywallet.txt"
"name": "mainwallet"
}
```
More likely, you just want to look at the private key associated with a specific address. This can be done with the `bitcoin-cli dumpprivkey` command.
But you can also make your named wallet load on start by adding a `true` to the end of the `bitcoin-cli loadwallet` command:
```
$ bitcoin-cli dumpprivkey "moKVV6XEhfrBCE3QCYq6ppT7AaMF8KsZ1B"
cTv75T4B3NsG92tdSxSfzhuaGrzrmc1rJjLKscoQZXqNRs5tpYhH
$ bitcoin-cli loadwallet mainwallet true
{
"name": "mainwallet"
}
```
You can then save that key somewhere safe, preferably somewhere not connected to the internet.
Afterward, the wallet that you must recently flagged in this way should always be the one that appaers at startup.
You can also import any private key, from a wallet dump or an individual key dump, as follows:
```
$ bitcoin-cli importprivkey cW4s4MdW7BkUmqiKgYzSJdmvnzq8QDrf6gszPMC7eLmfcdoRHtHh
```
Again, expect this to require an unpruned node. Expect this to take a while, as `bitcoind` needs to reread all past transactions, to see if there are any new ones that it should pay attention to.
## Optional: Create Multiple Wallets
> :information_source: **NOTE:** Many modern wallets prefer [mnemonic codes](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) to generate the seeds necessary to create the private keys. This methodology is not used `bitcoin-cli`, so you won't be able to generate handy word lists to remember your private keys.
You can create multiple wallets if it's helpful for separating funds or separating different sorts of expenses:
```
$ bitcoin-cli createwallet "gamingfunds"
{
"name": "gamingfunds"
}
```
bitcoin-cli listwallets` will list out all of the wallets currently "loaded", which will include your newly created one(s).
```
$ bitcoin-cli listwallets
[
"mainwallet",
"gamingfunds"
]
```
For commands that relate to the wallet (which is most of the ones you'll regularly use), you can specify which loaded wallet to use with the `-rpcwallet=` flag:
```
$ bitcoin-cli -rpcwallet=mainwallet getnewaddress
tb1qdve6cqp05acjpm77d7le5d07haplhkcc3ucr3k
```
If you try to run a wallet-related command when you have multiple wallets loaded without using the `-rpcwallet=` flag, you'll get an error:
```
Multiple wallets are loaded. Please select which wallet to use by requesting the RPC through the /wallet/<walletname> URI path. Or for the CLI, specify the "-rpcwallet=<walletname>" option before the command (run "bitcoin-cli -h" for help or "bitcoin-cli listwallets" to see which wallets are currently loaded).
```
Rather than flagging every command, it's easier to use `bitcoin-cli unloadwallet` to unload the wallets that you're not currently using:
```
$ bitcoin-cli unloadwallet mainwallet
{
}
$ bitcoin-cli listwallets
[
"gamingfunds"
]
```
You can then use the `bitcoin-cli loadwallet` to bring a wallet back into active use, and use both commands to swap around what you're using:
```
$ bitcoin-cli loadwallet mainwallet
{
"name": "mainwallet"
}
$ bitcoin-cli unloadwallet gamingfunds
{
}
$ bitcoin-cli listwallets
[
"mainwallet"
]
```
As discussed above, named wallets will not load by default unless you use `loadwallet` with `true` as the second argument. In this example of `mainwallet` and `gamingfunds`, nothing would load when you restarted `bitcoind` unless you specified otherwise.
_You've been typing that Bitcoin address you generated a _lot_, while you were signing messages and now dumping keys. If you think it's a pain, we agree. It's also prone to errors, a topic that we'll address in the very next section._
## Optional: Prove Control
In previous versions of Bitcoin Core, you were able to prove control of an address with the `bicoin-cli signmessage` command. This is generally a nice feature because it allows you to assure someone sending you funds that they're sending to a place where you will definitely be able to retrieve the funds (or at least where you can currently). Because of the advent of descriptor wallets, which we'll talk about in the next section, this is no longer possible. You still _can_ prove control of an address by deriving a WIF-format private key from the descriptor for a particular address and then using `bitcoin-cli signmessagewithprivkey` with that specific key, but that's a complex process that goes beyond the scope of this course.
Just keep in mind for the moment that proof of control is a nice feature if you can manage it.
## Summary: Setting Up Your Wallet
You need to create an address to receive funds. Your address is stored in a wallet, which you can back up. You can also do lots more with an address, like dumping its private key or using it to sign messages. But really, creating that address is _all_ you need to do in order to receive Bitcoin funds.
You need to create an address to receive funds. That address is stored in a wallet, which you can backup. But, there's more to both the wallet and the address: they're supported by an interoperable description system called descriptors. Understanding that will be the topic of the next chapter, before we finally get some funds. We'll also be seeing lots more wallet commands in the future, but they'll be things like checking your balance, which require you to have those funds!
## What's Next?

View File

@ -10,25 +10,18 @@ That's a simple command substitution, the equivalent to ``VARIABLE=`command` ``.
To create a new address would then look like this:
```
$ unset NEW_ADDRESS_1
$ NEW_ADDRESS_1=$(bitcoin-cli getnewaddress "" legacy)
$ NEW_ADDRESS_1=$(bitcoin-cli getnewaddress)
```
These commands clear the NEW_ADDRESS_1 variable, just to be sure, then fill it with the results of the `bitcoin-cli getnewaddress` command.
This commands fills the NEW_ADDRESS_1 variable with the results of the `bitcoin-cli getnewaddress` command.
You can then use your shell's `echo` command to look at your (new) address:
```
$ echo $NEW_ADDRESS_1
mi25UrzHnvn3bpEfFCNqJhPWJn5b77a5NE
tb1q0psqqqgy0fv5928wmk86ntu7hlax8dva7nl82p
```
Because you have your address in a variable, you can now easily sign a message for that address, without worrying about mistyping the address. You'll of course save that signature into a variable too!
```
$ NEW_SIG_1=$(bitcoin-cli signmessage $NEW_ADDRESS_1 "Hello, World")
$ echo $NEW_SIG_1
IPYIzgj+Rg4bxDwCyoPiFiNNcxWHYxgVcklhmN8aB2XRRJqV731Xu9XkfZ6oxj+QGCRmTe80X81EpXtmGUpXOM4=
```
The rest of this tutorial will use this style of saving information to variables when it's practical.
You can then use this variable in other commands which require the address (or do similar for any other complex output). The rest of this tutorial will use this style of saving information to variables when it's practical.
> :book: ***When is it not practical to use command-line variables?*** Command-line variables aren't practical if you need to use the information somewhere other than on the command line. For example, saving your signature may not actually be useful if you're just going to have to send it to someone else in an email. In addition, some future commands will output JSON objects instead of simple information, and variables can't be used to capture that information ... at least not without a _little_ more work.
> :book: ***When is it not practical to use command-line variables?*** Command-line variables aren't practical if you need to use the information somewhere other than on the command line. For example, saving an address may not actually be useful if you're just going to have to send it to someone else in an email. In addition, some future commands will output JSON objects instead of simple information, and variables can't be used to capture that information ... at least not without a _little_ more work.
## Summary: Using Command-Line Variables
@ -36,4 +29,4 @@ Shell variables can be used to hold long Bitcoin strings, minimizing the chances
## What's Next?
Continue "Understanding Your Bitcoin Setup" with [§3.4: Receiving a Transaction](03_4_Receiving_a_Transaction.md).
See how to store information in a different way with [Interlude: Creating QR Codes](03_3b_Interlude_Creating_QR_Codes.md).

View File

@ -1,154 +1,303 @@
TODO:
# 3.4: Understanding the Descriptor
1. Revise Section: Understanding the Descriptor (3.5)
* New Content: Descriptor Wallets
* New Content: Complex Descriptors
* Consider: Breaking into Two Sections
You've got your wallet set up, but before we go further we're going to take a moment to really understand it.
# 3.5: Understanding the Descriptor
## Know about HD Wallets
> :information_source: **NOTE:** This section has been recently added to the course and is an early draft that may still be awaiting review. Caveat reader.
Private keys are what make the Bitcoin world go round. They're used to generate public keys, which are the foundation of addresses, and they're also used to control those addresses. One private key creates one public key which creates one address. Once upon a time, the Bitcoin Core wallet managed this by holding on to a "bag of keys". A new, unrelated private key would be created every time a new address was desired. But a bag of keys can be big, inefficient, and prone to loss. That's where the HD wallet came in.
You may have noticed a weird `desc:` field in the `listunspent` command of the previous section. Here's what's all about (and how it can be used to transfer addresses).
The HD wallet, which is short for the Hierarchical Deterministic Wallet, was defined in [BIP-32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki). It's a hierarchical design where a single "seed" generates an extended private key, which includes not just the private key but also a "chain code" that can be used to create descendents of that key. The key and chain code can be used to deterministically generate chains of keys (and therefore addresses) for a variety of purposes. A Bitcoin HD wallet will typically have individual chains of keys (and addresses) for a variety of different address types. But, they can all be restored from that seed (or from that master extended private key) because of their determinism: the addresses are always created in the same way provided that you have the same starting points (your master extended private key and a specific index [0,1,...,n] for a specific type of address).
## Know about Transferring Addresses
> :book: ***What is a BIP?*** A BIP is a Bitcoin Improvement Proposal. It's an in-depth suggestion for a change to the Bitcoin Core code. Often, when a BIP has been sufficiently discussed and updated, it will become an actual part of the Bitcoin Core code. BIP-32 is one of many examples.
## Know about Descriptor Wallets
Most of this course presumes that you're working entirely from a single node where you manage your own wallet, sending and receiving payments with the addresses created by that wallet. However, that's not necessarily how the larger Bitcoin ecosystem works. There, you're more likely to be moving addresses between wallets and even setting up wallets to watch over funds controlled by different wallets.
That's where descriptors come in. They're most useful if you're interacting with software _other_ than Bitcoin Core, and really need to lean on this sort of compatibility function: see [§6.1](https://github.com/BlockchainCommons/Learning-Bitcoin-from-the-Command-Line/blob/master/06_1_Sending_a_Transaction_to_a_Multisig.md) for a real-world example of how having the capability of descriptors is critical.
HD wallets offered a big step forward for managing this sort of interoperability, because they allowed you to load a single seed (or master extended private key) into a new wallet rather than having to move over a whole bag of keys. Seed phrases and the `xpub` and `xprv` formats were introduced to define these master secrets. But they quickly proved inadequate. The `xprv` (and `xpub`) defined the root of an HD tree, but they were very specific to a certain type of address. When a new address type was created, a new format was needed, resulting in the `yprv` and `ypub` formats. Then a third address type resulted in the creation of `zprv` and `zpub`. The system was quickly growing unmanageable. A new system was needed that described not just the extended keys, but also which address types they would be used to create. Because if you didn't have that, a new wallet would have to test a master extended public key against _every possible type of address_ and that was going to be very inefficient and time-consuming and still introduced the likelihood of losing funds.
Moving addresses between wallets used to focus on `xpub` and `xprv`, and those are still supported.
> :book: **What is a seed phase?** A collection of words that define a seed. The seed is in turn used to generate an extended private key. Seed phrases are not currently used by Bitcoin Core, but they are in wide use in the larger Bitcoin ecosystem.
> :book: ***What is xprv?*** An extended private key. This is the combination of a private key and a chain code. It's a private key that a whole sequence of children private keys can be derived from.
> :book: ***What is xpub?*** An extended public key. This is the combination of a public key and a chain code. It's a public key that a whole sequence of children public keys can be derived from.
The fact that you can have a "whole sequence of children ... keys" reveals the fact that "xpub" and "xprv" aren't standard keys like we've been talking about so far. They're instead hierarchical keys that can be used to create whole families of keys, built on the idea of HD Wallets.
Enter, at last, the descriptor wallet. A descriptor wallet collects together "output descriptors" (sometimes called "wallet descriptors") which each either define one address or for a special "ranged descriptor" a whole array of addresses, each at a separate index. They do so through the specification of a specific format that includes: a function (which defines how to unlock the Bitcoin at the address), a derivation path (which defines the purpose of an address, which mostly links it to a specific standard), either the master extended public key or the master extended private key, and a checksum to make sure that nothing has been corrupted.
> :book: ***What is an HD Wallet?*** Most modern wallets are built on [BIP32: Hierarchical Deterministic Wallets](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki). This is a hierarchical design where a single seed can be used to generate a whole sequence of keys. The entire wallet may then be restored from that seed, rather than requiring the restoring of every single private key.
> :book: ***What is a Derivation Path?*** When you have hierarchical keys, you need to be able to define individual keys as descendents of the master key. For example `[0]` is the 0th key of the master key, `[0/1]` is the first son of the 0th key, `[0/1/1]` is the first grandson of the first son of the 0th key. Some keys also contain a `'` or `h` after the number, to show they're hardened, which protects them from a specific attack that could otherwise be used to derive a private key from a public key. You don't need to worry about the specifics, other than the fact that a derivation path like `[0/1/1/0/0]` depicts a path down through a hierarchy tree and that descriptor wallets run specific calculations to deterministically determine the right address for a specific position in a tree. A derivation path defines a key, which means that a key represents a derivation path. They're equivalent.
> :book: ***What is a Derivation Path?*** When you have hierarchical keys, you need to be able to define individual keys as descendents of a seed. For example `[0]` is the 0th key, `[0/1]` is the first son of the 0th key, `[1/0/1]` is the first grandson of the zeroth son of the 1st key. Some keys also contain a `'` after the number, to show they're hardened, which protects them from a specific attack that can be used to derive an `xprv` from an `xpub`. You don't need to worry about the specifics, other than the fact that those `'`s will cause you formatting troubles when working from the command line.
The derivation path allows you to calculate the right key from the master extended key, but it's the introduction of functions into descriptors that makes them particularly powerful, because it allows descriptors to serve a number of different types of past, present, and future addresses (which we'll meet in the next chapter).
> :information_source: **NOTE:** a derivation path defines a key, which means that a key represents a derivation path. They're equivalent. In the case of a descriptor, the derivation path lets `bitcoind` know where the key that follows in the descriptor came from!
> :warning: **VERSION WARNING:** Modern Bitcoin wallets use descriptor wallets stored in SQLite. Older, "classic" wallets were instead bags of keys, stored in BDB (Berkeley Database) format. The classic files can currently still be opened by `bitcoin-cli` but you wouldn't want to create something new in that format.
>
## Examine Your Wallet's Descriptors
`xpubs` and `xprvs` proved insufficient when the types of public keys multiplied under the [SegWit expansion](https://github.com/BlockchainCommons/Learning-Bitcoin-from-the-Command-Line/blob/master/04_6_Creating_a_Segwit_Transaction.md), thus the need for "output descriptors".
> :book: ***What is an output descriptor?*** A precise description of how to derive a Bitcoin address from a combination of a function and one or more inputs to that function.
The introduction of functions into descriptors is what makes them powerful, because they can be used to transfer all sorts of addresses, from the Legacy addresses that we're working with now to the Segwit and multisig addresses that we'll meet down the road. An individual function matches a particular type of address and correlates with specific rules to generate that address.
## Capture a Descriptor
Descriptors are visible in several commands such as `listunspent` and `getaddressinfo`:
You can look at all of the descriptors contained in your wallet with `bitcoin-cli listdescriptors`:
```
$ bitcoin-cli getaddressinfo ms7ruzvL4atCu77n47dStMb3of6iScS8kZ
$ bitcoin-cli listdescriptors
{
"address": "ms7ruzvL4atCu77n47dStMb3of6iScS8kZ",
"scriptPubKey": "76a9147f437379bcc66c40745edc1891ea6b3830e1975d88ac",
"wallet_name": "",
"descriptors": [
{
"desc": "pkh([e18dae20/44h/1h/0h]tpubDCsocyjrtJLXKJ3atFwKf6FiPheuVNV27B1swsGiNvk4cuPhVTsCDvusSNcH8thnS68FPFotgHqo9FHNGrvhtx6ZqdbWBQTWrCgK9xous17/0/*)#5q6np9at",
"timestamp": 1770329126,
"active": true,
"internal": false,
"range": [
0,
999
],
"next": 0,
"next_index": 0
},
{
"desc": "pkh([e18dae20/44h/1h/0h]tpubDCsocyjrtJLXKJ3atFwKf6FiPheuVNV27B1swsGiNvk4cuPhVTsCDvusSNcH8thnS68FPFotgHqo9FHNGrvhtx6ZqdbWBQTWrCgK9xous17/1/*)#95ljusdn",
"timestamp": 1770329126,
"active": true,
"internal": true,
"range": [
0,
999
],
"next": 0,
"next_index": 0
},
{
"desc": "sh(wpkh([e18dae20/49h/1h/0h]tpubDCmuiGVie2yYNXiwi6ymC2qamb7RdEXKeo8HZtkLAtaCcLHFGvHBY4W3Fx9rTjxYdxkb1kvkLp86oDvdxmYjvrVXpcVG2XptmYu8rYsAirP/0/*))#jdj8slnk",
"timestamp": 1770329126,
"active": true,
"internal": false,
"range": [
0,
999
],
"next": 0,
"next_index": 0
},
{
"desc": "sh(wpkh([e18dae20/49h/1h/0h]tpubDCmuiGVie2yYNXiwi6ymC2qamb7RdEXKeo8HZtkLAtaCcLHFGvHBY4W3Fx9rTjxYdxkb1kvkLp86oDvdxmYjvrVXpcVG2XptmYu8rYsAirP/1/*))#8vu3gqxf",
"timestamp": 1770329127,
"active": true,
"internal": true,
"range": [
0,
999
],
"next": 0,
"next_index": 0
},
{
"desc": "tr([e18dae20/86h/1h/0h]tpubDC5ZrtRv5CURANE3oWS1cK7mE9t93KnZfUApDs3dg8xxDuGMsuSejCLeh4yKeqkvHknRboWEctS2BSGQxXhsCx1dgPCTCwjF4a9mgq999Af/0/*)#h4xmum5n",
"timestamp": 1770329126,
"active": true,
"internal": false,
"range": [
0,
999
],
"next": 0,
"next_index": 0
},
{
"desc": "tr([e18dae20/86h/1h/0h]tpubDC5ZrtRv5CURANE3oWS1cK7mE9t93KnZfUApDs3dg8xxDuGMsuSejCLeh4yKeqkvHknRboWEctS2BSGQxXhsCx1dgPCTCwjF4a9mgq999Af/1/*)#xpr6pwyt",
"timestamp": 1770329127,
"active": true,
"internal": true,
"range": [
0,
999
],
"next": 0,
"next_index": 0
},
{
"desc": "wpkh([e18dae20/84h/1h/0h]tpubDC4ujMbsd9REzpGk3gnTjkrfJFw1NnvCpx6QBbLj3CHBzcLmVzssTVP8meRAM1WW4pZnK6SCCPGyzi9eMfzSXoeFMNprqtgxG71VRXTmetu/0/*)#3658f8sn",
"timestamp": 1770329126,
"active": true,
"internal": false,
"range": [
0,
1001
],
"next": 3,
"next_index": 3
},
{
"desc": "wpkh([e18dae20/84h/1h/0h]tpubDC4ujMbsd9REzpGk3gnTjkrfJFw1NnvCpx6QBbLj3CHBzcLmVzssTVP8meRAM1WW4pZnK6SCCPGyzi9eMfzSXoeFMNprqtgxG71VRXTmetu/1/*)#qw3x5jqt",
"timestamp": 1770329127,
"active": true,
"internal": true,
"range": [
0,
999
],
"next": 0,
"next_index": 0
}
]
}
```
Wow, that's a lot! But it's really just a listing of eight descriptors (`desc`) with a bunch of additional information on each. As it happens, that's descriptors for four different types of addresses (which we'll meet in chapter 4), with both an external address (for receiving funds from other wallets) and an internal address (for sending change back to this wallet). (And we'll talk about change in chapter 4 too!)
With that understood, we can look more closely at one of the descriptors:
```
{
"desc": "wpkh([e18dae20/84h/1h/0h]tpubDC4ujMbsd9REzpGk3gnTjkrfJFw1NnvCpx6QBbLj3CHBzcLmVzssTVP8meRAM1WW4pZnK6SCCPGyzi9eMfzSXoeFMNprqtgxG71VRXTmetu/0/*)#3658f8sn",
"timestamp": 1770329126,
"active": true,
"internal": false,
"range": [
0,
1001
],
"next": 3,
"next_index": 3
},
```
This contains:
* **`desc`:** The descriptor.
* **`timestamp`:** When the descriptor was created.
* **`active`:** Is the descriptor still in use for creating new addresses? (It could have been superseded by a new master extended key, for example when encrypting the wallet.)
* **`internal`:** Is this a descriptor for internal addresses (for change).
* **`range`:** For ranged descriptors, what's the range?
* **`next`, `next_index`:** What is the next address to create for this descriptor? In this example, the next one is `3` because we already created three addresses from this descriptor (`0`, `1`, and `2`) in [§3.3](3_3_Setting_Up_Your_Wallet.md).
As for the descriptor itself, let's break that down further:
* **Function: `wpkh`.** The function that is used to create an address from that key. In this cases it's `wpkh`. That stands for "Witness Public Key Hash," which is one of the methods used to unlock a Bech32 address.
* **Fingerprint: `e18dae20`.** This is a fingerprint of the master extended public key. It tells you which secret was used to generate this address. The fingerprint is *not* necessary to generate the keys and addresses for a derivation, it's just helpful for you need to go back and find the secret that generated your extended keys.
* **Derivation Path: `/84h/1h/0h`.** This describes what part of an HD wallet is being exported. This is the 0th child key of the 1st child of the 84th child in the HD tree. The various levels in the derivation path have very specific meanings as defined in [BIP-44](https://en.bitcoin.it/wiki/BIP_0044): `/purpose/ coin_type/ account/`. The purpose of this derivation path is "84", which means that it follows [BIP-84](https://github.com/bitcoin/bips/blob/master/bip-0084.mediawiki), which describes WPKH derivation. The coin type is "1", which means that it's a testnet or signet coin. (A mainnet coin could would be "0") The account is "0", as it's the only account in our wallet.
* **Key: `tpubDC4ujMbsd9REzpGk3gnTjkrfJFw1NnvCpx6QBbLj3CHBzcLmVzssTVP8meRAM1WW4pZnK6SCCPGyzi9eMfzSXoeFMNprqtgxG71VRXTmetu`.** This is the signet or testnet extended master public key that was used to generate this derived key. (A private key could be here instead. A public key would demonstrate how to watch this series of addresses, while a private key would show to control them)
* **Range: `/0/*`.** These are actually the final two parts of the derivation path, which are defined as `change / address_index`. The "0" says it's an external address. (An internal or change address would be "1".) The `*` says it's a ranged address, which means that it's defining a whole set of WPKH addresses that could be created.
* **`#3658f8sn"`.** This is a checksum showing the descriptor isn't corrupted.
So that's what everything means in a descriptor. Though they might seem somewhat complex, keep in mind that a descriptor takes the place of a potentially infinite number of addresses. With this one descriptor, or these eight descriptors as the case might be, you can regenerate every key and addresse that you might have used for these four address types. That's a huge boon for backups (when you want to protect your funds) and for moving control of your funds from one wallet-app to another.
> :information_source: **NOTE:** You could instead run `bitcoin-cli listdescriptors true` if you want your descriptor list to include the private keys instead of the public keys.
## Examine an Address' Descriptor
You can look at the descriptor for an individual address with `bitcoin-cli getaddressinfo`:
```
$ bitcoin-cli getaddressinfo tb1q9f8j03uywqsxuxjefz68g7x4kduer2ky6shsf4
{
"address": "tb1q9f8j03uywqsxuxjefz68g7x4kduer2ky6shsf4",
"scriptPubKey": "00142a4f27c78470206e1a5948b47478d5b37991aac4",
"ismine": true,
"solvable": true,
"desc": "pkh([d6043800/0'/0'/18']03efdee34c0009fd175f3b20b5e5a5517fd5d16746f2e635b44617adafeaebc388)#4ahsl9pk",
"desc": "wpkh([e18dae20/84h/1h/0h/0/2]02040bf9b12e48bbbcbf72ef5197bc18067db378411ae6220f1d0a77da2ee7dbba)#dqt0983r",
"parent_desc": "wpkh([e18dae20/84h/1h/0h]tpubDC4ujMbsd9REzpGk3gnTjkrfJFw1NnvCpx6QBbLj3CHBzcLmVzssTVP8meRAM1WW4pZnK6SCCPGyzi9eMfzSXoeFMNprqtgxG71VRXTmetu/0/*)#3658f8sn",
"iswatchonly": false,
"isscript": false,
"iswitness": false,
"pubkey": "03efdee34c0009fd175f3b20b5e5a5517fd5d16746f2e635b44617adafeaebc388",
"iscompressed": true,
"iswitness": true,
"witness_version": 0,
"witness_program": "2a4f27c78470206e1a5948b47478d5b37991aac4",
"pubkey": "02040bf9b12e48bbbcbf72ef5197bc18067db378411ae6220f1d0a77da2ee7dbba",
"ischange": false,
"timestamp": 1592335136,
"hdkeypath": "m/0'/0'/18'",
"hdseedid": "fdea8e2630f00d29a9d6ff2af7bf5b358d061078",
"hdmasterfingerprint": "d6043800",
"timestamp": 1770329126,
"hdkeypath": "m/84h/1h/0h/0/2",
"hdseedid": "0000000000000000000000000000000000000000",
"hdmasterfingerprint": "e18dae20",
"labels": [
""
]
}
```
Here the descriptor is `pkh([d6043800/0'/0'/18']03efdee34c0009fd175f3b20b5e5a5517fd5d16746f2e635b44617adafeaebc388)#4ahsl9pk`.
## Understand a Descriptor
A descriptor is broken into several parts:
That reveals:
```
function([derivation-path]key)#checksum
"desc": "wpkh([e18dae20/84h/1h/0h/0/2]02040bf9b12e48bbbcbf72ef5197bc18067db378411ae6220f1d0a77da2ee7dbba)#dqt0983r",
```
Here's what that all means:
* **Function.** The function that is used to create an address from that key. In this cases it's `pkh`, which is the standard P2PKH legacy address that you met in [§3.3: Setting Up Your Wallet](03_3_Setting_Up_Your_Wallet.md). Similarly, a P2WSH SegWit address would use `wsh` and a P2WPKH address would use `wpkh`.
* **Derivation Path.** This describes what part of an HD wallet is being exported. In this case it's a seed with the fingerprint `d6043800` and then the 18th child of the 0th child of the 0th child (`0'/0'/18'`) of that seed. There may also be a further derivation after the key: `function([derivation-path]key/more-derivation)#checksum`
* It's worth noting here that if you ever get a derivation path without a fingerprint, you can make it up. It's just that if there's an existing one, you should match it, because if you ever go back to the device that created the fingerprint, you'll need to have the same one.
* **Key**. The key or keys that are being transferred. This could be something traditional like an `xpub` or `xprv`, it could just be a public key for an address as in this case, it could be a set of addresses for a multi-signature, or it could be something else. This is the core data: the function explains what to do with it.
* **Checksum**. Descriptors are meant to be human transferrable. This checksum makes sure you got it right.
See [Bitcoin Core's Info on Descriptor Support](https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md) for more information.
## Examine a Descriptor
You can look at a descriptor with the `getdescriptorinfo` RPC:
Which you can compare to the ranged descriptor we just looked at:
```
$ bitcoin-cli getdescriptorinfo "pkh([d6043800/0'/0'/18']03efdee34c0009fd175f3b20b5e5a5517fd5d16746f2e635b44617adafeaebc388)#4ahsl9pk"
"desc": "wpkh([e18dae20/84h/1h/0h]tpubDC4ujMbsd9REzpGk3gnTjkrfJFw1NnvCpx6QBbLj3CHBzcLmVzssTVP8meRAM1WW4pZnK6SCCPGyzi9eMfzSXoeFMNprqtgxG71VRXTmetu/0/*)#3658f8sn",
```
They're in slightly different formats as the non-ranged address has the derivation path all together. But other than that, there are just two changes:
* The wallet has a ranged of addresses `0/*`, while the address is one specific index in that range `0/2`.
* The checksums are different, as you'd expect due to the differences in the index number.
That's the only difference between a descriptor in the wallet and a descriptor for a specific address!
You will see descriptors throughout Bitcoin commands. They're a vital element of not just the wallet, but of each address that is used to transfer funds and therefore of each transaction.
## Examine Descriptors Again
Descriptors can be also be examined with another command, `bitcoin-cli getdescriptorinfo`:
```
$ bitcoin-cli getdescriptorinfo "wpkh([e18dae20/84h/1h/0h]tpubDC4ujMbsd9REzpGk3gnTjkrfJFw1NnvCpx6QBbLj3CHBzcLmVzssTVP8meRAM1WW4pZnK6SCCPGyzi9eMfzSXoeFMNprqtgxG71VRXTmetu/0/*)#3658f8sn"
{
"descriptor": "pkh([d6043800/0'/0'/18']03efdee34c0009fd175f3b20b5e5a5517fd5d16746f2e635b44617adafeaebc388)#4ahsl9pk",
"checksum": "4ahsl9pk",
"isrange": false,
"descriptor": "wpkh([e18dae20/84h/1h/0h]tpubDC4ujMbsd9REzpGk3gnTjkrfJFw1NnvCpx6QBbLj3CHBzcLmVzssTVP8meRAM1WW4pZnK6SCCPGyzi9eMfzSXoeFMNprqtgxG71VRXTmetu/0/*)#3658f8sn",
"checksum": "3658f8sn",
"isrange": true,
"issolvable": true,
"hasprivatekeys": false
}
```
Note that it returns a checksum. If you're ever given a descriptor without a checksum, you can learn it with this command:
This is a pretty sparse description that includes the `descriptor` and its `checksum` and confirms that it's a ranged descriptor (`isrange`), that our wallet has the private key (`issolvable`), and that the private key isn't included in the descriptor and that there's instead a public key (`hasprivatekeys`). Beyond that information, `getdescriptorinfo` serves two other purposes:
1. If you don't have the checksum (which is required for other descriptor-related `bitcoin-cli` commands), you can enter the descriptor into `getdescriptorinfo` without it, and it'll be calculated for you.
```
$ bitcoin-cli getdescriptorinfo "pkh([d6043800/0'/0'/18']03efdee34c0009fd175f3b20b5e5a5517fd5d16746f2e635b44617adafeaebc388)"
$ bitcoin-cli getdescriptorinfo "wpkh([e18dae20/84h/1h/0h]tpubDC4ujMbsd9REzpGk3gnTjkrfJFw1NnvCpx6QBbLj3CHBzcLmVzssTVP8meRAM1WW4pZnK6SCCPGyzi9eMfzSXoeFMNprqtgxG71VRXTmetu/0/*)"
{
"descriptor": "pkh([d6043800/0'/0'/18']03efdee34c0009fd175f3b20b5e5a5517fd5d16746f2e635b44617adafeaebc388)#4ahsl9pk",
"checksum": "4ahsl9pk",
"isrange": false,
"descriptor": "wpkh([e18dae20/84h/1h/0h]tpubDC4ujMbsd9REzpGk3gnTjkrfJFw1NnvCpx6QBbLj3CHBzcLmVzssTVP8meRAM1WW4pZnK6SCCPGyzi9eMfzSXoeFMNprqtgxG71VRXTmetu/0/*)#3658f8sn",
"checksum": "3658f8sn",
"isrange": true,
"issolvable": true,
"hasprivatekeys": false
}
```
Besides giving you the checksum, this command also verifies the validity of the descriptor and provides useful information like whether a descriptor contains private keys.
One of the powers of a descriptor is being able to derive an address in a regular way. This is done with the `deriveaddresses` RPC.
2. If your descriptor is invalid, `getdescriptorinfo` will tell you:
```
$ bitcoin-cli deriveaddresses "pkh([d6043800/0'/0'/18']03efdee34c0009fd175f3b20b5e5a5517fd5d16746f2e635b44617adafeaebc388)#4ahsl9pk"
$ bitcoin-cli getdescriptorinfo "cow([e18dae20/84h/1h/0h]tpubDC4ujMbsd9REzpGk3gnTjkrfJFw1NnvCpx6QBbLj3CHBzcLmVzssTVP8meRAM1WW4pZnK6SCCPGyzi9eMfzSXoeFMNprqtgxG71VRXTmetu/0/*)"
error code: -5
error message:
'cow([e18dae20/84h/1h/0h]tpubDC4ujMbsd9REzpGk3gnTjkrfJFw1NnvCpx6QBbLj3CHBzcLmVzssTVP8meRAM1WW4pZnK6SCCPGyzi9eMfzSXoeFMNprqtgxG71VRXTmetu/0/*)' is not a valid descriptor function
```
## Derive Addresses by Hand
One of the powers of a descriptor is being able to derive an address in a regular way. `bitcoin-cli` takes care of that for you automatically whenever you request a new address, but you can also do it by hand with the `deriveaddresses` command.
```
$ bitcoin-cli deriveaddresses "wpkh([e18dae20/84h/1h/0h]tpubDC4ujMbsd9REzpGk3gnTjkrfJFw1NnvCpx6QBbLj3CHBzcLmVzssTVP8meRAM1WW4pZnK6SCCPGyzi9eMfzSXoeFMNprqtgxG71VRXTmetu/0/*)#3658f8sn" 2
[
"ms7ruzvL4atCu77n47dStMb3of6iScS8kZ"
"tb1q05ua6g7njnjrtsjc0t9w3jc6g2leeznasf4ny9",
"tb1q0psqqqgy0fv5928wmk86ntu7hlax8dva7nl82p",
"tb1q9f8j03uywqsxuxjefz68g7x4kduer2ky6shsf4"
]
```
You'll note it loops back to the address we started with (as it should).
This example shows the derivation of addresses from the BIP-84 ranged descriptor up through index "2". If you check this against the addresses created in [§3.3](03_3_Setting_Up_Your_Wallet.md), you'll see they're just the same. Which is of course the whole point of descriptors! They are deterministically derived in the same way every time. The main purpose of this function would be to export addresses to other services (for example, if you wanted to export watch-only addresses to another wallet-app).
> :book: ***What is a watch-only address?*** A watch-only address allows you to watch for transactions related to an address (or to a whole family of addresses if you used a ranged descriptor), but not to spend funds on those addresses.
## Import a Descriptor
But, the really important thing about a descriptor is that you can take it to another (remote) machine and import it. This is done with the `importmulti` RPC using the `desc` option:
The really important feature of descriptors is that you can take them to another (remote) machine and import them. This is done with the `importdescriptors` command. The following example shows the import of the private-key version of our BIP-84 ranged descriptor into another wallet:
```
remote$ bitcoin-cli importmulti '[{"desc": "pkh([d6043800/0'"'"'/0'"'"'/18'"'"']03efdee34c0009fd175f3b20b5e5a5517fd5d16746f2e635b44617adafeaebc388)#4ahsl9pk", "timestamp": "now", "watchonly": true}]'
$ bitcoin-cli importdescriptors '[{ "desc": "wpkh(tprv8ZgxMBicQKsPd1dP4NpsFDpsLUCnZ7oyn4UEbYLw7if1EDVCxMgfSzAwP3aCr1YeRvX9GtGvHsCLdrM7zaDyh33jEj7joQoEeNEyJaSYm5p/84h/1h/0h/0/*)#grdqnase", "timestamp":1770329126, "active": true, "range": [0,10] }]'
[
{
"success": true
}
]
```
First, you'll note our first really ugly use of quotes. Every `'` in the derivation path had to be replaced with `'"'"'`. Just expect to have to do that if you're manipulating a descriptor that contains a derivation path. (The other option is to exchange the `'` with a `h` for hardened, but that will change you checksum, so if you prefer that for its ease of use, you'll need to get a new checksum with `getdescriptorinfo`.)
Second, you'll note that we flagged this as `watchonly`. That's because we know that it's a public key, so we can't spend with it. If we'd failed to enter this flag, `importmulti` would helpfully have told us something like: `Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag.`.
> :book: ***What is a watch-only address?*** A watch-only address allows you to watch for transactions related to an address (or to a whole family of addresses if you used an `xpub`), but not to spend funds on those addresses.
Using `getaddressesbylabel`, we can now see that our address has correctly been imported into our remote machine!
You'll note that this is a much more complex `bitcoin-cli` command than anything we've used before. It requires the input of a JSON array with a variety of different variables. (Which is a pain.) The `desc` is that private-key descriptor, the `timestamp` says how much of the blockchain to rescan, the `range` says how much of the range to import, and the `active` says that this descriptor can be used to create new addresses. After importing it, if you create three new addresses, they'll all look familiar, as they should:
```
remote$ bitcoin-cli getaddressesbylabel ""
{
"ms7ruzvL4atCu77n47dStMb3of6iScS8kZ": {
"purpose": "receive"
}
}
$ bitcoin-cli getnewaddress
tb1q05ua6g7njnjrtsjc0t9w3jc6g2leeznasf4ny9
$ bitcoin-cli getnewaddress
tb1q0psqqqgy0fv5928wmk86ntu7hlax8dva7nl82p
$ bitcoin-cli getnewaddress
tb1q9f8j03uywqsxuxjefz68g7x4kduer2ky6shsf4
```
We've now unlocked the full power of descriptors by both importing and exporting addresses!
## Summary: Understanding the Descriptor
Descriptors let you pass public keys and private keys among wallets, but more than that, they allow you to precisely and correctly to define addresses and to derive addresses of a lot of different sorts from a standardized description format.
Descriptors let you pass public keys and private keys among wallets, but more than that, they allow you to precisely and correctly define addresses and derive addresses of a lot of different sorts from a standardized description format. They're the heart of Bitcoin Core's descriptor wallets.
> :fire: ***What is the power of descriptors?*** Descriptors allow you to import and export seeds and keys. That's great if you want to move between different wallets. As a developer, they also allow you to build up the precise sort of addresses that you're interested in creating. For example, we use it in [FullyNoded 2](https://github.com/BlockchainCommons/FullyNoded-2/blob/master/Docs/How-it-works.md) to generate a multi-sig from three seeds.
We'll make real use of descriptors in [§7.3](07_3_Integrating_with_Hardware_Wallets.md), when we're importing addresses from a hardware wallet.
> :fire: ***What is the power of descriptors?*** Descriptors allow you to import and export keys and addresses. That's great if you want to move between different wallets. As a developer, they also allow you to build up the precise sort of addresses that you're interested in creating.
## What's Next?
Advance through "bitcoin-cli" with [Chapter Four: Sending Bitcoin Transactions](04_0_Sending_Bitcoin_Transactions.md).
Continue "Understanding Your Bitcoin Setup" with [§3.5: Receiving a Transaction](03_5_Receiving_a_Transaction.md).

View File

@ -61,8 +61,6 @@ This means that the sequence number must be set to less than 0xffffffff-1. (4294
> 4. The replacement transaction must pay for its own bandwidth in addition to the amount paid by the original transactions at or above the rate set by the node's minimum relay fee setting. For example, if the minimum relay fee is 1 satoshi/byte and the replacement transaction is 500 bytes total, then the replacement must pay a fee at least 500 satoshis higher than the sum of the originals.
> 5. The number of original transactions to be replaced and their descendant transactions which will be evicted from the mempool must not exceed a total of 100 transactions.
> :book: ***What is a BIP?*** A BIP is a Bitcoin Improvement Proposal. It's an in-depth suggestion for a change to the Bitcoin Core code. Often, when a BIP has been sufficiently discussed and updated, it will become an actual part of the Bitcoin Core code. For example, BIP 125 was implemented in Bitcoin Core 0.12.0.
The other thing to understand about RBF is that in order to use it, you must double-spend, reusing one or more the same UTXOs. Just sending another transaction with a different UTXO to the same recipient won't do the trick (and will likely result in your losing money). Instead, you must purposefully create a conflict, where the same UTXO is used in two different transactions.
Faced with this conflict, the miners will know to use the one with the higher fee, and they'll be incentivized to do so by that higher fee.

41
TODO.md
View File

@ -2,23 +2,15 @@
The following TODO items are intended for a 3.0 version of Learning Bitcoin from the Command Line
## Immediate TODO (for 2/5): Descriptor Wallets
1. <strike>Edit §3.1-3.2, esp. for any references to legacy addresses</strike> (Still need to update `bitcoin-cli -getinfo` command)
2. Update §3.3 to use a descriptor wallet
3. Update any mentions of classic wallets
4. Thoroughly rewrite §3.4 for new focus on descriptors, possibly expanding to two sections.
5. Update §3.5 to fit into new flow
6. <strike>Remove all references to things appearing at certain versions (they're all pretty standardized now)</strike>
7. <strike>But write a note early on about potential missing features</strike>
## Immediate TODO (for 2/19): Segwit
1. Change §4.1-4.5 to use Bech32 (incorporate existing §4.6)
2. Create a new chapter §4.6
1. Update §3.5 to fit into new flow
2. Write QR Code Interlude (§3.3b)
3. Change §4.1-4.5 to use Bech32 (incorporate existing §4.6)
4. Create a new chapter §4.6 (4.1?)
* Lay out new table of all the address types
* Demonstrate how to send legacy & wrapped Segwit transactions
3. Remove legacy address references from the rest of the course
5. Remove legacy address references from the rest of the course
## Longer-Term TODO (Small Tasks)
@ -28,7 +20,7 @@ The following updates involve updates or the creation of new chapters, but their
* <strike>Signet</strike>
* SEGWIT
* Talk about address types: https://www.unchained.com/blog/bitcoin-address-types-compared
* Descriptor Wallets
* <strike>Descriptor Wallets</strike>
1. Revise 4.4
* freezing coins
1. New Interlude: Creating Animated QR Codes (after 7.1)
@ -103,6 +95,9 @@ The following updates involve the large-scale work done on Schnorr and Taproot i
The following updates could be part of v3.0 or could be further future, depending on how long the above takes. My guess is that they'll get incorporated come late spring or summer.
1. New Graphics
* Mermaid or Mermaid-like diagrams.
* For example in §3.4 could diagram HD keys, derivation of seed phrase to seed to key, etc
1. New Graphics: Animated GIFs for key demos.
* Reference: https://github.com/faressoft/terminalizer
1. New Chapter: Using Other Command-Line Tools (between 8+9)
@ -241,6 +236,17 @@ See [release notes](https://bitcoincore.org/en/releases/0.21.0/).
---
# Progress Log
## Immediate TODO (for 2/5): Descriptor Wallets
1. <strike>Edit §3.1-3.2, esp. for any references to legacy addresses</strike> (Still need to update `bitcoin-cli -getinfo` command)
2. <strike>Update §3.3 to use a descriptor wallet</strike>
3. <strike>Update any mentions of classic wallets</strike> (done for this section, need to watch in other sections)
4. <strike>Thoroughly rewrite §3.4 for new focus on descriptors, possibly expanding to two sections.</strike>
6. <strike>Remove all references to things appearing at certain versions (they're all pretty standardized now)</strike>
7. <strike>But write a note early on about potential missing features</strike>
## Immediate TODO (for 1/22): Signet
@ -249,3 +255,10 @@ See [release notes](https://bitcoincore.org/en/releases/0.21.0/).
3. <strike>Revise §2.1 for newest Stackscript</strike>
4. <strike>Puzzle out organization for overall project (largely based on updates below and remaining Issues)</strike>
5. <strike>Change testnet to signet + list out network options</strike>
## Initial TODO (for 1/15): Setup
1. <strike>Update Standup Script for BTC 30.2 & Debian 13</strike>
2. <strike>Work through PRs & Issues</strike>
3. <strike>Tag 2.2.1 and Branched 3.0</strike>
4. <strike>Log relevant updates for Bitcoin Core up to 30.2</strike>