Skip to content

Commit 1f77842

Browse files
committed
fix descriptors generation
1 parent 6c9c3a1 commit 1f77842

File tree

4 files changed

+125
-387
lines changed

4 files changed

+125
-387
lines changed

src/commands.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@ use bdk_wallet::bitcoin::{
1717
Address, Network, OutPoint, ScriptBuf,
1818
bip32::{DerivationPath, Xpriv},
1919
};
20-
use clap::{Args, Parser, Subcommand, ValueEnum, builder::TypedValueParser, value_parser};
20+
use clap::{
21+
Args, Parser, Subcommand, ValueEnum,
22+
builder::{PossibleValuesParser, TypedValueParser},
23+
value_parser,
24+
};
2125

2226
#[cfg(any(feature = "electrum", feature = "esplora", feature = "rpc"))]
2327
use crate::utils::parse_proxy_auth;
@@ -488,7 +492,7 @@ pub enum DescriptorSubCommand {
488492
#[arg(
489493
long = "type",
490494
short = 't',
491-
value_parser = clap::builder::PossibleValuesParser::new(["44", "49", "84", "86"])
495+
value_parser = PossibleValuesParser::new(["44", "49", "84", "86"])
492496
.map(|s| s.parse::<u8>().unwrap()),
493497
default_value = "84"
494498
)]
@@ -499,7 +503,4 @@ pub enum DescriptorSubCommand {
499503
/// Optional key input
500504
key: Option<String>,
501505
},
502-
503-
/// Show info about a given descriptor
504-
Info { descriptor: String },
505506
}

src/error.rs

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ use thiserror::Error;
55

66
#[derive(Debug, Error)]
77
pub enum BDKCliError {
8-
#[error("BIP39 error: {0}")]
9-
BIP39Error(#[from] bdk_wallet::bip39::Error),
8+
#[error("BIP39 error: {0:?}")]
9+
BIP39Error(#[from] Option<bdk_wallet::bip39::Error>),
1010

1111
#[error("BIP32 error: {0}")]
1212
BIP32Error(#[from] bdk_wallet::bitcoin::bip32::Error),
@@ -103,30 +103,6 @@ pub enum BDKCliError {
103103
#[cfg(feature = "cbf")]
104104
#[error("BDK-Kyoto update error: {0}")]
105105
KyotoUpdateError(#[from] bdk_kyoto::UpdateError),
106-
107-
#[error("Mnemonic generation failed: {0}")]
108-
MnemonicGenerationError(String),
109-
110-
#[error("Xpriv creation failed: {0}")]
111-
XprivCreationError(String),
112-
113-
#[error("Descriptor parsing failed: {0}")]
114-
DescriptorParsingError(String),
115-
116-
#[error("Invalid extended key (xpub): {0}")]
117-
InvalidKey(String),
118-
119-
#[error("Invalid derivation path: {0}")]
120-
InvalidDerivationPath(String),
121-
122-
#[error("Unsupported script type: {0}")]
123-
UnsupportedScriptType(u8),
124-
125-
#[error("Descriptor key conversion failed: {0}")]
126-
DescriptorKeyError(String),
127-
128-
#[error("Invalid arguments: {0}")]
129-
InvalidArguments(String),
130106
}
131107

132108
impl From<ExtractTxError> for BDKCliError {

src/handlers.rs

Lines changed: 31 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ use crate::commands::*;
1515
use crate::error::BDKCliError as Error;
1616
#[cfg(any(feature = "sqlite", feature = "redb"))]
1717
use crate::persister::Persister;
18-
#[cfg(feature = "cbf")]
19-
use crate::utils::BlockchainClient::KyotoClient;
2018
use crate::utils::*;
2119
#[cfg(feature = "redb")]
2220
use bdk_redb::Store as RedbStore;
@@ -35,27 +33,25 @@ use bdk_wallet::keys::{
3533
bip39::WordCount,
3634
};
3735
use bdk_wallet::miniscript::miniscript;
38-
use bdk_wallet::bitcoin::bip32::{DerivationPath, KeySource};
39-
use bdk_wallet::bitcoin::consensus::encode::serialize_hex;
40-
use bdk_wallet::bitcoin::script::PushBytesBuf;
41-
use bdk_wallet::bitcoin::Network;
42-
use bdk_wallet::bitcoin::{secp256k1::Secp256k1, Txid};
43-
use bdk_wallet::bitcoin::{Amount, FeeRate, Psbt, Sequence};
44-
use bdk_wallet::descriptor::{Descriptor, Segwitv0};
45-
use bdk_wallet::keys::bip39::WordCount;
4636
#[cfg(feature = "sqlite")]
4737
use bdk_wallet::rusqlite::Connection;
4838
use bdk_wallet::{KeychainKind, SignOptions, Wallet};
4939
#[cfg(feature = "compiler")]
5040
use bdk_wallet::{
41+
bitcoin::XOnlyPublicKey,
5142
descriptor::{Descriptor, Legacy, Miniscript},
52-
miniscript::{Tap, descriptor::TapTree, policy::Concrete},
5343
descriptor::{Legacy, Miniscript},
5444
miniscript::policy::Concrete,
45+
miniscript::{Tap, descriptor::TapTree, policy::Concrete},
5546
};
5647
use cli_table::{Cell, CellStruct, Style, Table, format::Justify};
5748
use serde_json::json;
58-
use bdk_wallet::{KeychainKind, SignOptions, Wallet};
49+
#[cfg(feature = "cbf")]
50+
use {
51+
crate::utils::BlockchainClient::KyotoClient,
52+
bdk_kyoto::{Info, LightClient},
53+
tokio::select,
54+
};
5955

6056
#[cfg(feature = "electrum")]
6157
use crate::utils::BlockchainClient::Electrum;
@@ -64,29 +60,16 @@ use bdk_kyoto::LightClient;
6460
#[cfg(feature = "compiler")]
6561
use bdk_wallet::bitcoin::XOnlyPublicKey;
6662
use bdk_wallet::bitcoin::base64::prelude::*;
67-
use bdk_wallet::keys::DescriptorKey::Secret;
68-
use bdk_wallet::keys::{
69-
DerivableKey, DescriptorKey, DescriptorKey::Secret, DescriptorPublicKey, ExtendedKey,
70-
GeneratableKey, GeneratedKey, bip39::WordCount,
71-
};
72-
use bdk_wallet::miniscript::miniscript;
73-
use serde_json::{Value, json};
63+
use serde_json::Value;
7464
use std::collections::BTreeMap;
7565
#[cfg(any(feature = "electrum", feature = "esplora"))]
7666
use std::collections::HashSet;
7767
use std::convert::TryFrom;
78-
use std::fmt;
7968
#[cfg(any(feature = "repl", feature = "electrum", feature = "esplora"))]
8069
use std::io::Write;
8170
use std::str::FromStr;
82-
83-
#[cfg(feature = "electrum")]
84-
use crate::utils::BlockchainClient::Electrum;
85-
#[cfg(feature = "cbf")]
86-
use bdk_kyoto::{Info, LightClient};
87-
use bdk_wallet::bitcoin::base64::prelude::*;
88-
#[cfg(feature = "cbf")]
89-
use tokio::select;
71+
#[cfg(any(feature = "redb", feature = "compiler"))]
72+
use std::sync::Arc;
9073
#[cfg(any(
9174
feature = "electrum",
9275
feature = "esplora",
@@ -95,7 +78,7 @@ use tokio::select;
9578
))]
9679
use {
9780
crate::commands::OnlineWalletSubCommand::*,
98-
bdk_wallet::bitcoin::{consensus::Decodable, hex::FromHex, Transaction},
81+
bdk_wallet::bitcoin::{Transaction, consensus::Decodable, hex::FromHex},
9982
};
10083
#[cfg(feature = "esplora")]
10184
use {crate::utils::BlockchainClient::Esplora, bdk_esplora::EsploraAsyncExt};
@@ -1287,8 +1270,7 @@ pub(crate) async fn handle_command(cli_opts: CliOpts) -> Result<String, Error> {
12871270
subcommand: descriptor_subcommand,
12881271
} => {
12891272
let network = cli_opts.network;
1290-
let descriptor = handle_descriptor_subcommand(network, descriptor_subcommand)
1291-
.map_err(|e| Error::Generic(e.to_string()))?;
1273+
let descriptor = handle_descriptor_subcommand(network, descriptor_subcommand)?;
12921274
let json = serde_json::to_string_pretty(&descriptor)?;
12931275
Ok(json)
12941276
}
@@ -1375,84 +1357,35 @@ pub fn handle_descriptor_subcommand(
13751357
multipath,
13761358
key,
13771359
} => {
1378-
let (descriptor_type, derivation_path_str) = match r#type {
1379-
44 => (DescriptorType::Bip44, "m/44h/1h/0h"),
1380-
49 => (DescriptorType::Bip49, "m/49h/1h/0h"),
1381-
84 => (DescriptorType::Bip84, "m/84h/1h/0h"),
1382-
86 => (DescriptorType::Bip86, "m/86h/1h/0h"),
1383-
_ => return Err(Error::UnsupportedScriptType(r#type)),
1360+
let descriptor_type = match r#type {
1361+
44 => DescriptorType::Bip44,
1362+
49 => DescriptorType::Bip49,
1363+
84 => DescriptorType::Bip84,
1364+
86 => DescriptorType::Bip86,
1365+
_ => {
1366+
return Err(Error::Generic(
1367+
"Unsupported script type: {r#type}".to_string(),
1368+
));
1369+
}
13841370
};
13851371

13861372
match (multipath, key.as_ref()) {
1387-
(true, Some(k)) => generate_multipath_descriptor(&network, r#type, k),
1373+
// generate multipath descriptors
1374+
(true, Some(k)) => generate_descriptors(&network, descriptor_type, k, true),
13881375
(false, Some(k)) => {
13891376
if is_mnemonic(k) {
1390-
generate_descriptor_from_mnemonic_string(
1391-
k,
1392-
network,
1393-
derivation_path_str,
1394-
descriptor_type,
1395-
)
1377+
// generate descriptors from given mnemonic string
1378+
generate_descriptor_from_mnemonic_string(k, network, descriptor_type)
13961379
} else {
1397-
generate_standard_descriptor(&network, r#type, k)
1380+
// generate descriptors from key
1381+
generate_descriptors(&network, descriptor_type, k, false)
13981382
}
13991383
}
1384+
// generate mnemonic and descriptors
14001385
(false, None) => generate_new_descriptor_with_mnemonic(network, descriptor_type),
1401-
_ => Err(Error::InvalidArguments(
1402-
"Provide a key or weak string".to_string(),
1403-
)),
1386+
_ => Err(Error::Generic("Provide a key or string".to_string())),
14041387
}
14051388
}
1406-
DescriptorSubCommand::Info { descriptor } => {
1407-
let parsed: Descriptor<DescriptorPublicKey> = descriptor
1408-
.parse()
1409-
.map_err(|e| Error::Generic(format!("Failed to parse descriptor: {}", e)))?;
1410-
1411-
let checksum = parsed.to_string();
1412-
let script_type = match parsed {
1413-
Descriptor::Wpkh(_) => "wpkh",
1414-
Descriptor::Pkh(_) => "pkh",
1415-
Descriptor::Sh(_) => "sh",
1416-
Descriptor::Tr(_) => "tr",
1417-
_ => "other",
1418-
};
1419-
1420-
let json = json!({
1421-
"descriptor": checksum,
1422-
"type": script_type,
1423-
"is_multipath": descriptor.contains("/*"),
1424-
});
1425-
1426-
Ok(json)
1427-
}
1428-
}
1429-
}
1430-
1431-
pub fn generate_standard_descriptor(
1432-
network: &Network,
1433-
script_type: u8,
1434-
key: &str,
1435-
) -> Result<Value, Error> {
1436-
let descriptor_type = match script_type {
1437-
44 => DescriptorType::Bip44,
1438-
49 => DescriptorType::Bip49,
1439-
84 => DescriptorType::Bip84,
1440-
86 => DescriptorType::Bip86,
1441-
_ => return Err(Error::UnsupportedScriptType(script_type)),
1442-
};
1443-
1444-
generate_descriptor_from_key_by_type(network, key, descriptor_type)
1445-
}
1446-
1447-
impl fmt::Display for DescriptorType {
1448-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1449-
let s = match self {
1450-
DescriptorType::Bip44 => "bip44",
1451-
DescriptorType::Bip49 => "bip49",
1452-
DescriptorType::Bip84 => "bip84",
1453-
DescriptorType::Bip86 => "bip86",
1454-
};
1455-
write!(f, "{}", s)
14561389
}
14571390
}
14581391

0 commit comments

Comments
 (0)