Added interfaces DescriptorSecretKey and DescriptorPublicKey

This commit is contained in:
dhruvbaliyan 2022-08-09 14:39:15 +05:30
parent 4977cb6d68
commit 58fea6b205
No known key found for this signature in database
GPG Key ID: C0123AC0FAE7CC73
2 changed files with 167 additions and 2 deletions

View File

@ -250,3 +250,26 @@ interface DerivationPath {
[Throws=BdkError]
constructor(string path);
};
interface DescriptorSecretKey {
[Throws=BdkError]
constructor(Network network, string mnemonic, string? password);
[Throws=BdkError]
DescriptorSecretKey derive(DerivationPath path);
DescriptorSecretKey extend(DerivationPath path);
DescriptorPublicKey as_public();
string as_string();
};
interface DescriptorPublicKey {
[Throws=BdkError]
DescriptorPublicKey derive(DerivationPath path);
DescriptorPublicKey extend(DerivationPath path);
string as_string();
};

View File

@ -1,7 +1,7 @@
use bdk::bitcoin::hashes::hex::ToHex;
use bdk::bitcoin::secp256k1::Secp256k1;
use bdk::bitcoin::util::psbt::PartiallySignedTransaction;
use bdk::bitcoin::util::bip32::DerivationPath as BdkDerivationPath;
use bdk::bitcoin::util::psbt::PartiallySignedTransaction;
use bdk::bitcoin::{Address, Network, OutPoint as BdkOutPoint, Script, Txid};
use bdk::blockchain::any::{AnyBlockchain, AnyBlockchainConfig};
use bdk::blockchain::{
@ -10,8 +10,12 @@ use bdk::blockchain::{
use bdk::blockchain::{Blockchain as BdkBlockchain, Progress as BdkProgress};
use bdk::database::any::{AnyDatabase, SledDbConfiguration, SqliteDbConfiguration};
use bdk::database::{AnyDatabaseConfig, ConfigurableDatabase};
use bdk::descriptor::DescriptorXKey;
use bdk::keys::bip39::{Language, Mnemonic, WordCount};
use bdk::keys::{DerivableKey, ExtendedKey, GeneratableKey, GeneratedKey};
use bdk::keys::{
DerivableKey, DescriptorPublicKey as BdkDescriptorPublicKey,
DescriptorSecretKey as BdkDescriptorSecretKey, ExtendedKey, GeneratableKey, GeneratedKey,
};
use bdk::miniscript::BareCtx;
use bdk::wallet::tx_builder::ChangeSpendPolicy;
use bdk::wallet::AddressIndex as BdkAddressIndex;
@ -648,6 +652,144 @@ impl DerivationPath {
}
}
struct DescriptorSecretKey {
descriptor_secret_key_mutex: Mutex<BdkDescriptorSecretKey>,
}
impl DescriptorSecretKey {
fn new(network: Network, mnemonic: String, password: Option<String>) -> Result<Self, BdkError> {
let mnemonic = Mnemonic::parse_in(Language::English, mnemonic)
.map_err(|e| BdkError::Generic(e.to_string()))?;
let xkey: ExtendedKey = (mnemonic, password).into_extended_key()?;
let descriptor_secret_key = BdkDescriptorSecretKey::XPrv(DescriptorXKey {
origin: None,
xkey: xkey.into_xprv(network).unwrap(),
derivation_path: BdkDerivationPath::master(),
wildcard: bdk::descriptor::Wildcard::Unhardened,
});
Ok(Self {
descriptor_secret_key_mutex: Mutex::new(descriptor_secret_key),
})
}
fn derive(&self, path: Arc<DerivationPath>) -> Result<Arc<Self>, BdkError> {
let secp = Secp256k1::new();
let descriptor_secret_key = self.descriptor_secret_key_mutex.lock().unwrap();
let path = path.derivation_path_mutex.lock().unwrap().deref().clone();
let descriptor_x_key = match descriptor_secret_key.deref() {
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => Some(descriptor_x_key),
_ => None,
}
.unwrap();
let derived_xprv = descriptor_x_key.xkey.derive_priv(&secp, &path)?;
let key_source = match descriptor_x_key.origin.clone() {
Some((fingerprint, origin_path)) => (fingerprint, origin_path.extend(path)),
None => (descriptor_x_key.xkey.fingerprint(&secp), path),
};
let derived_descriptor_secret_key = BdkDescriptorSecretKey::XPrv(DescriptorXKey {
origin: Some(key_source),
xkey: derived_xprv,
derivation_path: BdkDerivationPath::default(),
wildcard: descriptor_x_key.wildcard,
});
Ok(Arc::new(Self {
descriptor_secret_key_mutex: Mutex::new(derived_descriptor_secret_key),
}))
}
fn extend(&self, path: Arc<DerivationPath>) -> Arc<Self> {
let descriptor_secret_key = self.descriptor_secret_key_mutex.lock().unwrap();
let path = path.derivation_path_mutex.lock().unwrap().deref().clone();
let descriptor_x_key = match descriptor_secret_key.deref() {
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => Some(descriptor_x_key),
_ => None,
}
.unwrap();
let extended_path = descriptor_x_key.derivation_path.extend(path);
let extended_descriptor_secret_key = BdkDescriptorSecretKey::XPrv(DescriptorXKey {
origin: descriptor_x_key.origin.clone(),
xkey: descriptor_x_key.xkey,
derivation_path: extended_path,
wildcard: descriptor_x_key.wildcard,
});
Arc::new(Self {
descriptor_secret_key_mutex: Mutex::new(extended_descriptor_secret_key),
})
}
fn as_public(&self) -> Arc<DescriptorPublicKey> {
let secp = Secp256k1::new();
let descriptor_public_key = self
.descriptor_secret_key_mutex
.lock()
.unwrap()
.as_public(&secp)
.unwrap();
Arc::new(DescriptorPublicKey {
descriptor_public_key_mutex: Mutex::new(descriptor_public_key),
})
}
fn as_string(&self) -> String {
self.descriptor_secret_key_mutex.lock().unwrap().to_string()
}
}
struct DescriptorPublicKey {
descriptor_public_key_mutex: Mutex<BdkDescriptorPublicKey>,
}
impl DescriptorPublicKey {
fn derive(&self, path: Arc<DerivationPath>) -> Result<Arc<Self>, BdkError> {
let secp = Secp256k1::new();
let descriptor_public_key = self.descriptor_public_key_mutex.lock().unwrap();
let path = path.derivation_path_mutex.lock().unwrap().deref().clone();
let descriptor_x_key = match descriptor_public_key.deref() {
BdkDescriptorPublicKey::XPub(descriptor_x_key) => Some(descriptor_x_key),
_ => None,
}
.unwrap();
let derived_xpub = descriptor_x_key.xkey.derive_pub(&secp, &path)?;
let key_source = match descriptor_x_key.origin.clone() {
Some((fingerprint, origin_path)) => (fingerprint, origin_path.extend(path)),
None => (descriptor_x_key.xkey.fingerprint(), path),
};
let derived_descriptor_public_key = BdkDescriptorPublicKey::XPub(DescriptorXKey {
origin: Some(key_source),
xkey: derived_xpub,
derivation_path: BdkDerivationPath::default(),
wildcard: descriptor_x_key.wildcard,
});
Ok(Arc::new(Self {
descriptor_public_key_mutex: Mutex::new(derived_descriptor_public_key),
}))
}
fn extend(&self, path: Arc<DerivationPath>) -> Arc<Self> {
let descriptor_secret_key = self.descriptor_public_key_mutex.lock().unwrap();
let path = path.derivation_path_mutex.lock().unwrap().deref().clone();
let descriptor_x_key = match descriptor_secret_key.deref() {
BdkDescriptorPublicKey::XPub(descriptor_x_key) => Some(descriptor_x_key),
_ => None,
}
.unwrap();
let extended_path = descriptor_x_key.derivation_path.extend(path);
let extended_descriptor_public_key = BdkDescriptorPublicKey::XPub(DescriptorXKey {
origin: descriptor_x_key.origin.clone(),
xkey: descriptor_x_key.xkey,
derivation_path: extended_path,
wildcard: descriptor_x_key.wildcard,
});
Arc::new(Self {
descriptor_public_key_mutex: Mutex::new(extended_descriptor_public_key),
})
}
fn as_string(&self) -> String {
self.descriptor_public_key_mutex.lock().unwrap().to_string()
}
}
uniffi::deps::static_assertions::assert_impl_all!(Wallet: Sync, Send);
// The goal of these tests to to ensure `bdk-ffi` intermediate code correctly calls `bdk` APIs.