diff options
author | sommerfeld <sommerfeld@sommerfeld.dev> | 2024-04-30 11:21:44 +0100 |
---|---|---|
committer | sommerfeld <sommerfeld@sommerfeld.dev> | 2024-04-30 11:21:44 +0100 |
commit | 39df428117484b447258cf697b1ea3fb48082e42 (patch) | |
tree | ec150fd0303239e34e548150bd844e73d60888a5 | |
parent | 93326aa3f96963415bc1950eadda471b6bf326f4 (diff) | |
download | sentrum-39df428117484b447258cf697b1ea3fb48082e42.tar.gz sentrum-39df428117484b447258cf697b1ea3fb48082e42.tar.bz2 sentrum-39df428117484b447258cf697b1ea3fb48082e42.zip |
Improve wallet descriptor support
-rw-r--r-- | README.md | 25 | ||||
-rw-r--r-- | src/wallets.rs | 37 |
2 files changed, 50 insertions, 12 deletions
@@ -93,8 +93,27 @@ It assumes a BIP84 (native segwit, `bc1` style addresses) wallet. If your wallet has a different script kind add the field `kind = "legacy"` (or `nested_segwit`, or `taproot`). -More complex wallet types are supported by providing `primary = "<desc>"` and -`change = "<desc>"` wallet descriptors instead of `xpub =` and `kind = `. +### Multisig and friends + +More complex wallet types are supported by providing `descriptor = "<desc>"` and +`change_descriptor = "<desc>"` wallet descriptors instead of `xpub =` and +`kind = `. You don't need to provide `change_descriptor`, it's optional, and +many times the main descriptor already includes it. Example: + +```toml +[[wallets]] +name = "charlie" +descriptor = "wsh(sortedmulti(2,[bbc5fee8/48h/1h/0h/2h]tpubDEuo3nCajorgHFrA5unQB3dSR3Mh7EPfedyU36GC2wVLwB32PsDuiPcsw5RobqNRfQyjas3cxeEraxs6HYJvQPcNX5neut2jRvZijyxLiqT/<0;1>/*,[3f007faa/48h/1h/0h/2h]tpubDEgyzFTDNEUcy674okNRZFuV1Q3P3RNdhd5FwncHBZ9DpZNHR3FGm5c4n8co1Efg3Xv6cUCPuPraJ85j8CV2QXqhLdXn38uyNoSX3rVMpbC/<0;1>/*,[c478c82d/48h/1h/0h/2h]tpubDFKmAnxyJKb7LLQ2UDU4ytFZ1Lx5R7C9op23Ew7zxDwCHDMUhqWfmgMi7d6YNSfKnsW3wp9QEU4TuNJxcPCcAi4ddCYsVL9ken6tWGPD9jz/<0;1>/*))#3l992dql" +``` + +You can retrieve the wallet descriptor for practically any wallet using Sparrow +Wallet by opening the wallet, going to +`Settings >> Script Policy >> Descriptor Edit`. A window will pop-up where you +can copy the wallet descriptor string and paste it as the `descriptor =` value +of the `sentrum.toml`. + +Not all scripts are supported. `sentrum` depends on bdk which only supports +[these scripts](https://bitcoindevkit.org/descriptors/). ## Actions @@ -326,7 +345,7 @@ extracted release archive): 1. Copy systemd files to appropriate places: ```bash -sudo cp contrib/systemd/sentrum.service +sudo cp contrib/systemd/sentrum.service /etc/systemd/system sudo cp contrib/systemd/sentrum.sysusers /etc/sysusers.d/sentrum.conf sudo cp contrib/systemd/sentrum.tmpfiles /etc/tmpfiles.d/sentrum.conf ``` diff --git a/src/wallets.rs b/src/wallets.rs index 9ee702c..b7b6886 100644 --- a/src/wallets.rs +++ b/src/wallets.rs @@ -14,6 +14,7 @@ use bdk::{ KeychainKind, SyncOptions, TransactionDetails, Wallet, }; use log::{debug, error, warn}; +use regex::Regex; use serde::Deserialize; use crate::blockchain::{get_blockchain, ElectrumConfig}; @@ -48,11 +49,11 @@ impl XpubSpec { } } -#[derive(Deserialize, Debug, Hash)] +#[derive(Deserialize, Debug, Hash, Clone)] pub struct DescriptorsSpec { name: String, - primary: String, - change: Option<String>, + descriptor: String, + change_descriptor: Option<String>, } impl DescriptorsSpec { @@ -62,12 +63,12 @@ impl DescriptorsSpec { s.finish().to_string() } - pub fn primary(&self) -> &str { - &self.primary + pub fn descriptor(&self) -> &str { + &self.descriptor } - pub fn change(&self) -> Option<&String> { - self.change.as_ref() + pub fn change_descriptor(&self) -> Option<&str> { + self.change_descriptor.as_deref() } pub fn name(&self) -> &str { @@ -75,6 +76,23 @@ impl DescriptorsSpec { } } +fn handle_multipart_descritor(desc_spec: &DescriptorsSpec) -> Result<DescriptorsSpec> { + if !desc_spec.descriptor().contains("<0;1>") { + return Ok(desc_spec.clone()); + } + + let desc_no_checksum = Regex::new("#[A-Za-z0-9]+$")?.replace(desc_spec.descriptor(), ""); + + let desc = desc_no_checksum.replace("<0;1>", "0"); + let change_desc = desc_no_checksum.replace("<0;1>", "1"); + + Ok(DescriptorsSpec { + name: desc_spec.name().to_string(), + descriptor: desc, + change_descriptor: Some(change_desc), + }) +} + #[derive(Deserialize, Debug)] #[serde(untagged)] pub enum WalletConfig { @@ -136,9 +154,10 @@ fn get_descriptors_wallet( network: Network, ) -> Result<Wallet<sled::Tree>> { let sled = sled::open(get_cache_dir(&descriptors_spec.get_hash()))?.open_tree("wallet")?; + let desc_spec_no_multi = handle_multipart_descritor(descriptors_spec)?; Wallet::new( - descriptors_spec.primary(), - descriptors_spec.change().map(String::as_ref), + desc_spec_no_multi.descriptor(), + desc_spec_no_multi.change_descriptor(), network, sled, ) |