# Multi-Keychain Wallet [#318](https://github.com/bitcoindevkit/bdk_wallet/pull/318) <br> ## Todo - [ ] 1. `Wallet::create_with_params` allowed to create a wallet with a custom genesis block. Should this come in the keyring? - [x] 2. On `Wallet::create_with_params`, the docs say `The genesis_hash (if not specified) will be inferred from keyring.network`. What if it's specified but conflicts with the keyring's network? It might be better to have this defined and checked in one place. - [ ] 3. The `Wallet::load` and `Wallet::create_with_params` are still kind of messy. They achieve similar goals to the keyring. Needs cleanup on the design. Can `CreateParams` be made free of the generic? - [ ] 4. Handle all `// TODO PR #318: ...` comments. - [x] 5. Remove `KeyRingError` variants corresponding to default. Same for `LoadError`. Remove default keychain field of `LoadParams` too. - [ ] 6. `KeyRing::new_with_descriptors` may not be needed now. - [ ] 7. `wallet_name_from_desc` should be fixed? - [ ] 8. Add a helper function to revert back to 2.3.0 wallet from multi-keychain wallet and use this in migration examples. <br> ## Old PR Todo List - [ ] Fix up the `Wallet` API docs (`K` needs to be `Ord` for example) - [ ] Should the create_with_params take a struct of params? - [x] `Wallet::new` should call `Wallet::create_with_params` - [x] Wallet persistence - [ ] Customizing genesis hash: throw if KeyRing is on Mainnet, ok otherwise. - [x] Fix up the wallet `ChangeSet`. - [x] Add persistence example. - [ ] Restore tests if applicable - [ ] Add wallet migration example from a 2.3.0 wallet <br> ## Design Questions/Decisions 1. Should `KeyRing::new` take in a descriptor? 2. Should mismatch/missing load errors reside in `LoadError`? 3. Should `LoadMismatch` be removed? 4. `KeyRing` should have a minimal public API <br> ## Impact on Public API 72 functions are part of the public API. This is how they are impacted by this PR. | # | Current Wallet Impacted Methods | Changes | | --- | ----------------------------------------- | ------------------------------------------------------------------------------------------------ | | 1 | `Wallet::create_single` | Removed | | 2 | `Wallet::create_from_two_path_descriptor` | Removed | | 3 | `Wallet::create` | Now takes a `KeyRing`. | | 4 | `Wallet::create_with_params` | The `CreateParams` type is a bit different. | | 5 | `Wallet::load` | The `LoadParams` type is a bit different. | | 6 | `Wallet::load_with_params` | The `LoadParams` type is a bit different. | | 7 | `Wallet::keychains` | Very similar but now returns a map of keychains. | | 8 | `Wallet::peek_address` | Now takes generic `K` and returns an `Option`. | | 9 | `Wallet::reveal_next_address` | Now takes generic `K` and returns an `Option`. | | 10 | `Wallet::reveal_addresses_to` | Now takes generic `K` and returns an `Option`. | | 11 | `Wallet::next_unused_address` | Now takes generic `K` and returns an `Option`. | | 12 | `Wallet::mark_used` | Now takes generic `K`. Needs work. | | 13 | `Wallet::unmark_used` | Now takes generic `K`. Needs work. | | 14 | `Wallet::list_unused_addresses` | Now takes generic `K` and returns an `Option`. Needs work. | | 15 | `Wallet::derivation_of_spk` | Now returns the generic `K` keychain. | | 16 | `Wallet::all_unbounded_spk_iters` | The keys on the map are now the generic `K`. | | 17 | `Wallet::unbounded_spk_iters` | Now takes generic `K` and returns an `Option`. | | 18 | `Wallet::public_descriptor` | Replaced by the `Wallet::keychains` method which returns a Map<K, PubDescriptor> | | 19 | `Wallet::derivation_index` | Now takes generic `K`. | | 20 | `Wallet::next_derivation_index` | Now takes generic `K` and returns an `Option`. | | 21 | `Wallet::descriptor_checksum` | Now takes generic `K` and returns an `Option`. | <br> | # | Unimpacted Methods | | --- | ------------------------------------------ | | 1 | `Wallet::network` | | 2 | `Wallet::is_mine` | | 3 | `Wallet::list_unspent` | | 4 | `Wallet::tx_details` | | 5 | `Wallet::list_output` | | 6 | `Wallet::checkpoints` | | 7 | `Wallet::latest_checkpoint` | | 8 | `Wallet::get_utxo` | | 9 | `Wallet::insert_txout` | | 10 | `Wallet::calculate_fee` | | 11 | `Wallet::calculate_fee_rate` | | 12 | `Wallet::sent_and_received` | | 13 | `Wallet::get_tx` | | 14 | `Wallet::transactions` | | 15 | `Wallet::transactions_sort_by` | | 16 | `Wallet::balance` | | 17 | `Wallet::finalize_psbt` | | 18 | `Wallet::cancel_tx` | | 19 | `Wallet::get_psbt_input` | | 20 | `Wallet::apply_update` | | 21 | `Wallet::apply_update_events` | | 22 | `Wallet::staged` | | 23 | `Wallet::staged_mut` | | 24 | `Wallet::take_staged` | | 25 | `Wallet::tx_graph` | | 26 | `Wallet::spk_index` | | 27 | `Wallet::local_chain` | | 28 | `Wallet::list_locked_outpoints` | | 29 | `Wallet::list_locked_unspent` | | 30 | `Wallet::is_outpoint_locked` | | 31 | `Wallet::lock_outpoint` | | 32 | `Wallet::unlock_outpoint` | | 33 | `Wallet::apply_block` | | 34 | `Wallet::apply_block_events` | | 35 | `Wallet::apply_block_connected_to` | | 36 | `Wallet::apply_block_connected_to_events` | | 37 | `Wallet::apply_unconfirmed_txs` | | 38 | `Wallet::apply_evicted_txs` | | 39 | `Wallet::start_sync_with_revealed_spks_at` | | 40 | `Wallet::start_sync_with_revealed_spks` | | 41 | `Wallet::start_full_scan` | | 42 | `Wallet::start_full_scan_at` | <br> | # | Will Be Removed Before Multi-Keychain | | --- | ------------------------------------- | | 1 | `Wallet::add_signer` | | 2 | `Wallet::set_keymap` | | 3 | `Wallet::set_keymaps` | | 4 | `Wallet::get_signers` | | 5 | `Wallet::build_tx` | | 6 | `Wallet::build_fee_bump` | | 7 | `Wallet::sign` | | 8 | `Wallet::policies` | | 9 | `Wallet::secp_ctx` | ## Follow-Ups 1. Example showcasing maintaining a default keychain? 2. Example emulating wallet creation in bitcoin-cli. 3. 2-Keychain wrapper around wallet?