From ba719510306c826e4f8b7186051932f6b9858023 Mon Sep 17 00:00:00 2001 From: Hunter Beast Date: Tue, 16 Jan 2024 02:31:14 -0700 Subject: [PATCH] Add segwit key derivation as a feature (#447) * Add segwit key derivation as a feature * Segwit build script * Fix descriptor * Fix descriptor syntax * Fix xpub * Undo package rename --- Cargo.lock | 2 +- Cargo.toml | 1 + build-segwit.sh | 10 ++++++++++ lib/web/package-lock.json | 4 ++-- lib/web/yarn.lock | 20 ++++++++++++++++++++ src/bitcoin/keys.rs | 34 +++++++++++++++++++++++++++++----- src/constants.rs | 7 +++++++ 7 files changed, 70 insertions(+), 8 deletions(-) create mode 100755 build-segwit.sh create mode 100644 lib/web/yarn.lock diff --git a/Cargo.lock b/Cargo.lock index f9597f0f..b3ab1932 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -659,7 +659,7 @@ dependencies = [ [[package]] name = "bitmask-core" -version = "0.7.0-beta.10" +version = "0.7.0-beta.11" dependencies = [ "amplify", "anyhow", diff --git a/Cargo.toml b/Cargo.toml index 94596af3..18bb118b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,7 @@ required-features = ["server"] all = [] default = [] web = [] +segwit = [] server = ["tokio/full", "tower-http/cors"] [dependencies] diff --git a/build-segwit.sh b/build-segwit.sh new file mode 100755 index 00000000..5796d916 --- /dev/null +++ b/build-segwit.sh @@ -0,0 +1,10 @@ +#!/bin/sh +wasm-pack build --release --target web --features segwit +cp pkg/*.ts lib/web +cp pkg/*.js lib/web +cp pkg/*.wasm lib/web +cp pkg/README.md lib/web +cp pkg/LICENSE* lib/web +cd lib/web +npm install +npm run prepare diff --git a/lib/web/package-lock.json b/lib/web/package-lock.json index bcacd74c..5f19dfce 100644 --- a/lib/web/package-lock.json +++ b/lib/web/package-lock.json @@ -1,11 +1,11 @@ { - "name": "bitmask-core", + "name": "bitmask-segwit", "version": "0.7.0-beta.10", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "bitmask-core", + "name": "bitmask-segwit", "version": "0.7.0-beta.10", "license": "MIT", "devDependencies": { diff --git a/lib/web/yarn.lock b/lib/web/yarn.lock new file mode 100644 index 00000000..7040d96b --- /dev/null +++ b/lib/web/yarn.lock @@ -0,0 +1,20 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@types/node@^20.8.2": + version "20.11.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.0.tgz#8e0b99e70c0c1ade1a86c4a282f7b7ef87c9552f" + integrity sha512-o9bjXmDNcF7GbM4CNQpmi+TutCgap/K3w1JyKgxAjqx41zp9qlIAVFi0IhCNsJcXolEqLWhbFbEeL0PvYm4pcQ== + dependencies: + undici-types "~5.26.4" + +typescript@^5.2.2: + version "5.3.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37" + integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw== + +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== diff --git a/src/bitcoin/keys.rs b/src/bitcoin/keys.rs index 3eafcb61..da342620 100644 --- a/src/bitcoin/keys.rs +++ b/src/bitcoin/keys.rs @@ -1,12 +1,16 @@ use std::str::FromStr; +#[cfg(feature = "segwit")] +use bdk::miniscript::Segwitv0; +#[cfg(not(feature = "segwit"))] +use bdk::miniscript::Tap; use bdk::{ bitcoin::{ secp256k1::Secp256k1, util::bip32::{ChildNumber, DerivationPath, ExtendedPrivKey, ExtendedPubKey, KeySource}, }, keys::{DerivableKey, DescriptorKey, DescriptorKey::Secret as SecretDesc, DescriptorSecretKey}, - miniscript::{descriptor::DescriptorKeyParseError, Tap}, + miniscript::descriptor::DescriptorKeyParseError, }; use bip39::{Language, Mnemonic}; use bitcoin::{KeyPair, Network}; @@ -70,10 +74,16 @@ fn get_descriptor( let deriv_descriptor = DerivationPath::from_str(path)?; let derived_xprv = &xprv.derive_priv(&secp, &deriv_descriptor)?; let origin: KeySource = (xprv.fingerprint(&secp), deriv_descriptor); + #[cfg(not(feature = "segwit"))] let derived_xprv_desc_key: DescriptorKey = derived_xprv.into_descriptor_key( Some(origin), DerivationPath::default().child(ChildNumber::from_normal_idx(change)?), )?; + #[cfg(feature = "segwit")] + let derived_xprv_desc_key: DescriptorKey = derived_xprv.into_descriptor_key( + Some(origin), + DerivationPath::default().child(ChildNumber::from_normal_idx(change)?), + )?; if let SecretDesc(desc_seckey, _, _) = derived_xprv_desc_key { Ok(desc_seckey) @@ -85,7 +95,12 @@ fn get_descriptor( fn xprv_desc(xprv: &ExtendedPrivKey, path: &str, change: u32) -> Result { let xprv = get_descriptor(xprv, path, change)?; - Ok(format!("tr({xprv})")) + #[cfg(not(feature = "segwit"))] + let desc = format!("tr({xprv})"); + #[cfg(feature = "segwit")] + let desc = format!("wpkh({xprv})"); + + Ok(desc) } fn xpub_desc(xprv: &ExtendedPrivKey, path: &str, change: u32) -> Result { @@ -93,7 +108,12 @@ fn xpub_desc(xprv: &ExtendedPrivKey, path: &str, change: u32) -> Result Result, Bitcoi }; let desc_xpub = DescriptorPublicKey::XPub(desc).to_string(); - let tap = format!("tr({desc_xpub}/*)"); - Ok(Some(SecretString(tap))) + #[cfg(not(feature = "segwit"))] + let desc_str = format!("tr({desc_xpub}/*)"); + #[cfg(feature = "segwit")] + let desc_str = format!("wpkh({desc_xpub}/*)"); + + Ok(Some(SecretString(desc_str))) } diff --git a/src/constants.rs b/src/constants.rs index c9e593be..03b6b4a3 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -90,8 +90,15 @@ pub async fn get_udas_utxo() -> String { } // Descriptor strings +#[cfg(not(feature = "segwit"))] pub const BTC_MAINNET_PATH: &str = "m/86h/0h/0h"; +#[cfg(not(feature = "segwit"))] pub const BTC_TESTNET_PATH: &str = "m/86h/1h/0h"; +#[cfg(feature = "segwit")] +pub const BTC_MAINNET_PATH: &str = "m/84h/0h/0h"; +#[cfg(feature = "segwit")] +pub const BTC_TESTNET_PATH: &str = "m/84h/1h/0h"; + pub static BTC_PATH: Lazy> = Lazy::new(|| { RwLock::new(if dot_env("BITCOIN_NETWORK") == "bitcoin" { BTC_MAINNET_PATH.to_owned()