aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLibravatar sommerfeld <sommerfeld@sommerfeld.dev>2024-04-30 11:21:44 +0100
committerLibravatar sommerfeld <sommerfeld@sommerfeld.dev>2024-04-30 11:21:44 +0100
commit39df428117484b447258cf697b1ea3fb48082e42 (patch)
treeec150fd0303239e34e548150bd844e73d60888a5
parent93326aa3f96963415bc1950eadda471b6bf326f4 (diff)
downloadsentrum-39df428117484b447258cf697b1ea3fb48082e42.tar.gz
sentrum-39df428117484b447258cf697b1ea3fb48082e42.tar.bz2
sentrum-39df428117484b447258cf697b1ea3fb48082e42.zip
Improve wallet descriptor support
-rw-r--r--README.md25
-rw-r--r--src/wallets.rs37
2 files changed, 50 insertions, 12 deletions
diff --git a/README.md b/README.md
index 766c375..cff420e 100644
--- a/README.md
+++ b/README.md
@@ -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,
)