Skip to content

Commit b4ea29d

Browse files
committed
update
1 parent f58cd2c commit b4ea29d

File tree

2 files changed

+128
-31
lines changed

2 files changed

+128
-31
lines changed

src/commands.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
//! All subcommands are defined in the below enums.
1414
1515
#![allow(clippy::large_enum_variant)]
16-
1716
use bdk_wallet::bitcoin::{
1817
bip32::{DerivationPath, Xpriv},
1918
Address, Network, OutPoint, ScriptBuf,
@@ -132,23 +131,22 @@ pub enum CliSubCommand {
132131
}
133132
#[derive(Debug, Clone, PartialEq, Args)]
134133
pub struct GenerateDescriptorArgs {
135-
/// Script type: BIP44 (Legacy), BIP49 (Nested), BIP84 (Native SegWit), or BIP86 (Taproot)
136-
#[clap(value_enum)]
137-
pub script_type: ScriptType,
134+
#[clap(long)]
135+
pub network: Network,
136+
137+
#[clap(long, value_parser = clap::value_parser!(u8).range(44..=86))]
138+
pub r#type: u8, // 44, 49, 84, 86
138139

139-
/// Use multipath derivation (e.g. m/44'/0'/0'/*/*)
140140
#[clap(long)]
141141
pub multipath: bool,
142142

143-
/// Use weak key string instead of a fingerprinted xpub
144143
#[clap(long)]
145-
pub weak_keys: bool,
144+
pub weak: Option<String>, // If present, user supplied a weak string
146145

147-
/// Specify the network: bitcoin, testnet, regtest, signet
148-
#[clap(long, default_value = "testnet")]
149-
pub network: Network,
146+
pub key: Option<String>, // Positional argument (tprv/tpub/xprv/xpub)
150147
}
151148

149+
152150
#[derive(Debug, Clone, PartialEq, ValueEnum)]
153151
pub enum ScriptType {
154152
Bip44,

src/descriptor_handler.rs

Lines changed: 120 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,41 @@
1-
use crate::commands::{GenerateDescriptorArgs, ScriptType};
1+
use serde_json::Value;
2+
use serde_json::json;
3+
use crate::commands::GenerateDescriptorArgs;
24
use anyhow::{anyhow, Result};
35
use bdk_wallet::bitcoin::bip32::Xpriv;
46
use bdk_wallet::bitcoin::secp256k1::Secp256k1;
5-
use bdk_wallet::bitcoin::Network as BdkNetwork;
67
use bdk_wallet::bitcoin::Network;
78
use bdk_wallet::descriptor::Segwitv0;
89
use bdk_wallet::keys::bip39::{Language, Mnemonic, WordCount};
910
use bdk_wallet::keys::{GeneratableKey, GeneratedKey};
1011
use bdk_wallet::miniscript::{Descriptor, DescriptorPublicKey};
1112

12-
pub fn generate_descriptor_from_args(
13-
args: GenerateDescriptorArgs,
14-
) -> Result<serde_json::Value, anyhow::Error> {
15-
// Convert CLI network to BDK network
16-
let bdk_network = match args.network {
17-
Network::Bitcoin => BdkNetwork::Bitcoin,
18-
Network::Testnet => BdkNetwork::Testnet,
19-
Network::Testnet4 => BdkNetwork::Testnet4,
20-
Network::Regtest => BdkNetwork::Regtest,
21-
Network::Signet => BdkNetwork::Signet,
22-
_ => todo!(),
23-
};
24-
25-
match args.script_type {
26-
ScriptType::Bip84 => {
27-
let json = generate_bip84_descriptor(bdk_network)?;
28-
Ok(json)
13+
pub fn generate_descriptor_from_args(args: GenerateDescriptorArgs) -> Result<Value, anyhow::Error> {
14+
match (args.weak.as_ref(), args.multipath, args.key.as_ref()) {
15+
(Some(weak_str), _, _) => {
16+
generate_descriptor_from_weak_string(&args.network, args.r#type, weak_str)
2917
}
30-
_ => Err(anyhow!("Script type not supported yet")),
18+
(None, true, Some(key)) => {
19+
generate_multipath_descriptor(&args.network, args.r#type, key)
20+
}
21+
(None, false, Some(key)) => {
22+
generate_standard_descriptor(&args.network, args.r#type, key)
23+
}
24+
(None, false, None) => {
25+
// New default: generate descriptor from fresh mnemonic (for script_type 84 only maybe)
26+
if args.r#type == 84 {
27+
generate_new_bip84_descriptor_with_mnemonic(args.network)
28+
} else {
29+
Err(anyhow!("Only script type 84 is supported for mnemonic-based generation"))
30+
}
31+
}
32+
_ => Err(anyhow!("Invalid arguments: please provide a key or a weak string")),
3133
}
34+
3235
}
3336

34-
pub fn generate_bip84_descriptor(network: Network) -> Result<serde_json::Value> {
37+
38+
pub fn generate_new_bip84_descriptor_with_mnemonic(network: Network) -> Result<serde_json::Value> {
3539
let secp = Secp256k1::new();
3640

3741
let mnemonic: GeneratedKey<Mnemonic, Segwitv0> =
@@ -67,3 +71,98 @@ pub fn generate_bip84_descriptor(network: Network) -> Result<serde_json::Value>
6771
}
6872
}))
6973
}
74+
75+
fn generate_descriptor_from_weak_string(
76+
network: &Network,
77+
script_type: u8,
78+
weak_str: &str,
79+
) -> Result<Value, anyhow::Error> {
80+
// TODO: replace with real weak key generation logic
81+
let fake_xprv = format!("xprv-from-{}", weak_str);
82+
generate_standard_descriptor(network, script_type, &fake_xprv)
83+
}
84+
85+
fn generate_multipath_descriptor(
86+
_network: &Network,
87+
script_type: u8,
88+
key: &str,
89+
) -> Result<Value, anyhow::Error> {
90+
// TODO: Implement multipath logic
91+
Ok(json!({ "multipath": true, "key": key, "type": script_type }))
92+
}
93+
94+
fn generate_standard_descriptor(
95+
network: &Network,
96+
script_type: u8,
97+
key: &str,
98+
) -> Result<Value, anyhow::Error> {
99+
match script_type {
100+
84 => generate_bip84_descriptor_from_key(network, key),
101+
86 => generate_bip86_descriptor_from_key(network, key),
102+
49 => generate_bip49_descriptor_from_key(network, key),
103+
44 => generate_bip44_descriptor_from_key(network, key),
104+
_ => Err(anyhow!("Unsupported script type")),
105+
}
106+
}
107+
108+
pub fn generate_bip84_descriptor_from_key(
109+
network: &Network,
110+
key: &str,
111+
) -> Result<Value, anyhow::Error> {
112+
// Adjust derivation paths according to BIP84
113+
let external = format!("wpkh([{fingerprint}/84'/1'/0']{key}/0/*)", fingerprint = "00000000");
114+
let internal = format!("wpkh([{fingerprint}/84'/1'/0']{key}/1/*)", fingerprint = "00000000");
115+
116+
Ok(json!({
117+
"type": "bip84",
118+
"external": external,
119+
"internal": internal,
120+
"network": network.to_string()
121+
}))
122+
}
123+
124+
pub fn generate_bip86_descriptor_from_key(
125+
network: &Network,
126+
key: &str,
127+
) -> Result<Value, anyhow::Error> {
128+
let external = format!("tr([{}/86'/1'/0']{}/0/*)", "00000000", key);
129+
let internal = format!("tr([{}/86'/1'/0']{}/1/*)", "00000000", key);
130+
131+
Ok(json!({
132+
"type": "bip86",
133+
"external": external,
134+
"internal": internal,
135+
"network": network.to_string()
136+
}))
137+
}
138+
139+
140+
pub fn generate_bip49_descriptor_from_key(
141+
network: &Network,
142+
key: &str,
143+
) -> Result<Value, anyhow::Error> {
144+
let external = format!("sh(wpkh([{}/49'/1'/0']{}/0/*))", "00000000", key);
145+
let internal = format!("sh(wpkh([{}/49'/1'/0']{}/1/*))", "00000000", key);
146+
147+
Ok(json!({
148+
"type": "bip49",
149+
"external": external,
150+
"internal": internal,
151+
"network": network.to_string()
152+
}))
153+
}
154+
155+
pub fn generate_bip44_descriptor_from_key(
156+
network: &Network,
157+
key: &str,
158+
) -> Result<Value, anyhow::Error> {
159+
let external = format!("pkh([{}/44'/1'/0']{}/0/*)", "00000000", key);
160+
let internal = format!("pkh([{}/44'/1'/0']{}/1/*)", "00000000", key);
161+
162+
Ok(json!({
163+
"type": "bip44",
164+
"external": external,
165+
"internal": internal,
166+
"network": network.to_string()
167+
}))
168+
}

0 commit comments

Comments
 (0)