Refactor: separate keys from lib.rs
This commit is contained in:
parent
6fcb8985f1
commit
46bd9a1f15
@ -1,5 +1,5 @@
|
|||||||
// use crate::BlockchainConfig;
|
// use crate::BlockchainConfig;
|
||||||
use crate::{PartiallySignedTransaction, BdkError};
|
use crate::{BdkError, PartiallySignedTransaction};
|
||||||
use bdk::bitcoin::Network;
|
use bdk::bitcoin::Network;
|
||||||
use bdk::blockchain::any::{AnyBlockchain, AnyBlockchainConfig};
|
use bdk::blockchain::any::{AnyBlockchain, AnyBlockchainConfig};
|
||||||
use bdk::blockchain::rpc::Auth as BdkAuth;
|
use bdk::blockchain::rpc::Auth as BdkAuth;
|
||||||
|
@ -1,17 +1,18 @@
|
|||||||
|
use crate::{BdkError, DescriptorPublicKey, DescriptorSecretKey};
|
||||||
|
use bdk::bitcoin::secp256k1::Secp256k1;
|
||||||
|
use bdk::bitcoin::util::bip32::Fingerprint;
|
||||||
|
use bdk::bitcoin::Network;
|
||||||
|
use bdk::descriptor::{ExtendedDescriptor, IntoWalletDescriptor, KeyMap};
|
||||||
|
use bdk::keys::{
|
||||||
|
DescriptorPublicKey as BdkDescriptorPublicKey, DescriptorSecretKey as BdkDescriptorSecretKey,
|
||||||
|
};
|
||||||
|
use bdk::template::{
|
||||||
|
Bip44, Bip44Public, Bip49, Bip49Public, Bip84, Bip84Public, DescriptorTemplate,
|
||||||
|
};
|
||||||
|
use bdk::KeychainKind;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use bdk::bitcoin::Network;
|
|
||||||
use bdk::bitcoin::secp256k1::Secp256k1;
|
|
||||||
use bdk::bitcoin::util::bip32::Fingerprint;
|
|
||||||
use bdk::descriptor::{ExtendedDescriptor, IntoWalletDescriptor, KeyMap};
|
|
||||||
use bdk::KeychainKind;
|
|
||||||
use bdk::template::{Bip44, Bip44Public, Bip49, Bip49Public, Bip84, Bip84Public, DescriptorTemplate};
|
|
||||||
use bdk::keys::{
|
|
||||||
DescriptorPublicKey as BdkDescriptorPublicKey,
|
|
||||||
DescriptorSecretKey as BdkDescriptorSecretKey,
|
|
||||||
};
|
|
||||||
use crate::{DescriptorPublicKey, DescriptorSecretKey, BdkError};
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct Descriptor {
|
pub(crate) struct Descriptor {
|
||||||
|
244
bdk-ffi/src/keys.rs
Normal file
244
bdk-ffi/src/keys.rs
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
use crate::BdkError;
|
||||||
|
|
||||||
|
use bdk::bitcoin::secp256k1::Secp256k1;
|
||||||
|
use bdk::bitcoin::util::bip32::DerivationPath as BdkDerivationPath;
|
||||||
|
use bdk::bitcoin::Network;
|
||||||
|
use bdk::descriptor::DescriptorXKey;
|
||||||
|
use bdk::keys::bip39::{Language, Mnemonic as BdkMnemonic, WordCount};
|
||||||
|
use bdk::keys::{
|
||||||
|
DerivableKey, DescriptorPublicKey as BdkDescriptorPublicKey,
|
||||||
|
DescriptorSecretKey as BdkDescriptorSecretKey, ExtendedKey, GeneratableKey, GeneratedKey,
|
||||||
|
};
|
||||||
|
use bdk::miniscript::BareCtx;
|
||||||
|
use std::ops::Deref;
|
||||||
|
use std::str::FromStr;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
|
/// Mnemonic phrases are a human-readable version of the private keys.
|
||||||
|
/// Supported number of words are 12, 15, 18, 21 and 24.
|
||||||
|
pub(crate) struct Mnemonic {
|
||||||
|
internal: BdkMnemonic,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mnemonic {
|
||||||
|
/// Generates Mnemonic with a random entropy
|
||||||
|
pub(crate) fn new(word_count: WordCount) -> Self {
|
||||||
|
let generated_key: GeneratedKey<_, BareCtx> =
|
||||||
|
BdkMnemonic::generate((word_count, Language::English)).unwrap();
|
||||||
|
let mnemonic = BdkMnemonic::parse_in(Language::English, generated_key.to_string()).unwrap();
|
||||||
|
Mnemonic { internal: mnemonic }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse a Mnemonic with given string
|
||||||
|
pub(crate) fn from_string(mnemonic: String) -> Result<Self, BdkError> {
|
||||||
|
BdkMnemonic::from_str(&mnemonic)
|
||||||
|
.map(|m| Mnemonic { internal: m })
|
||||||
|
.map_err(|e| BdkError::Generic(e.to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new Mnemonic in the specified language from the given entropy.
|
||||||
|
/// Entropy must be a multiple of 32 bits (4 bytes) and 128-256 bits in length.
|
||||||
|
pub(crate) fn from_entropy(entropy: Vec<u8>) -> Result<Self, BdkError> {
|
||||||
|
BdkMnemonic::from_entropy(entropy.as_slice())
|
||||||
|
.map(|m| Mnemonic { internal: m })
|
||||||
|
.map_err(|e| BdkError::Generic(e.to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns Mnemonic as string
|
||||||
|
pub(crate) fn as_string(&self) -> String {
|
||||||
|
self.internal.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) struct DerivationPath {
|
||||||
|
derivation_path_mutex: Mutex<BdkDerivationPath>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DerivationPath {
|
||||||
|
pub(crate) fn new(path: String) -> Result<Self, BdkError> {
|
||||||
|
BdkDerivationPath::from_str(&path)
|
||||||
|
.map(|x| DerivationPath {
|
||||||
|
derivation_path_mutex: Mutex::new(x),
|
||||||
|
})
|
||||||
|
.map_err(|e| BdkError::Generic(e.to_string()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub(crate) struct DescriptorSecretKey {
|
||||||
|
pub(crate) descriptor_secret_key_mutex: Mutex<BdkDescriptorSecretKey>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DescriptorSecretKey {
|
||||||
|
pub(crate) fn new(network: Network, mnemonic: Arc<Mnemonic>, password: Option<String>) -> Self {
|
||||||
|
let mnemonic = mnemonic.internal.clone();
|
||||||
|
let xkey: ExtendedKey = (mnemonic, password).into_extended_key().unwrap();
|
||||||
|
let descriptor_secret_key = BdkDescriptorSecretKey::XPrv(DescriptorXKey {
|
||||||
|
origin: None,
|
||||||
|
xkey: xkey.into_xprv(network).unwrap(),
|
||||||
|
derivation_path: BdkDerivationPath::master(),
|
||||||
|
wildcard: bdk::descriptor::Wildcard::Unhardened,
|
||||||
|
});
|
||||||
|
Self {
|
||||||
|
descriptor_secret_key_mutex: Mutex::new(descriptor_secret_key),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn from_string(private_key: String) -> Result<Self, BdkError> {
|
||||||
|
let descriptor_secret_key = BdkDescriptorSecretKey::from_str(private_key.as_str())
|
||||||
|
.map_err(|e| BdkError::Generic(e.to_string()))?;
|
||||||
|
Ok(Self {
|
||||||
|
descriptor_secret_key_mutex: Mutex::new(descriptor_secret_key),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) 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();
|
||||||
|
match descriptor_secret_key.deref() {
|
||||||
|
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
|
||||||
|
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),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
BdkDescriptorSecretKey::Single(_) => Err(BdkError::Generic(
|
||||||
|
"Cannot derive from a single key".to_string(),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn extend(&self, path: Arc<DerivationPath>) -> Result<Arc<Self>, BdkError> {
|
||||||
|
let descriptor_secret_key = self.descriptor_secret_key_mutex.lock().unwrap();
|
||||||
|
let path = path.derivation_path_mutex.lock().unwrap().deref().clone();
|
||||||
|
match descriptor_secret_key.deref() {
|
||||||
|
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
|
||||||
|
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,
|
||||||
|
});
|
||||||
|
Ok(Arc::new(Self {
|
||||||
|
descriptor_secret_key_mutex: Mutex::new(extended_descriptor_secret_key),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
BdkDescriptorSecretKey::Single(_) => Err(BdkError::Generic(
|
||||||
|
"Cannot extend from a single key".to_string(),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn as_public(&self) -> Arc<DescriptorPublicKey> {
|
||||||
|
let secp = Secp256k1::new();
|
||||||
|
let descriptor_public_key = self
|
||||||
|
.descriptor_secret_key_mutex
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.to_public(&secp)
|
||||||
|
.unwrap();
|
||||||
|
Arc::new(DescriptorPublicKey {
|
||||||
|
descriptor_public_key_mutex: Mutex::new(descriptor_public_key),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the private key as bytes.
|
||||||
|
pub(crate) fn secret_bytes(&self) -> Vec<u8> {
|
||||||
|
let descriptor_secret_key = self.descriptor_secret_key_mutex.lock().unwrap();
|
||||||
|
let secret_bytes: Vec<u8> = match descriptor_secret_key.deref() {
|
||||||
|
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
|
||||||
|
descriptor_x_key.xkey.private_key.secret_bytes().to_vec()
|
||||||
|
}
|
||||||
|
BdkDescriptorSecretKey::Single(_) => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
secret_bytes
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn as_string(&self) -> String {
|
||||||
|
self.descriptor_secret_key_mutex.lock().unwrap().to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub(crate) struct DescriptorPublicKey {
|
||||||
|
pub(crate) descriptor_public_key_mutex: Mutex<BdkDescriptorPublicKey>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DescriptorPublicKey {
|
||||||
|
pub(crate) fn from_string(public_key: String) -> Result<Self, BdkError> {
|
||||||
|
let descriptor_public_key = BdkDescriptorPublicKey::from_str(public_key.as_str())
|
||||||
|
.map_err(|e| BdkError::Generic(e.to_string()))?;
|
||||||
|
Ok(Self {
|
||||||
|
descriptor_public_key_mutex: Mutex::new(descriptor_public_key),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) 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();
|
||||||
|
|
||||||
|
match descriptor_public_key.deref() {
|
||||||
|
BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
|
||||||
|
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),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
BdkDescriptorPublicKey::Single(_) => Err(BdkError::Generic(
|
||||||
|
"Cannot derive from a single key".to_string(),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn extend(&self, path: Arc<DerivationPath>) -> Result<Arc<Self>, BdkError> {
|
||||||
|
let descriptor_public_key = self.descriptor_public_key_mutex.lock().unwrap();
|
||||||
|
let path = path.derivation_path_mutex.lock().unwrap().deref().clone();
|
||||||
|
match descriptor_public_key.deref() {
|
||||||
|
BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
|
||||||
|
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,
|
||||||
|
});
|
||||||
|
Ok(Arc::new(Self {
|
||||||
|
descriptor_public_key_mutex: Mutex::new(extended_descriptor_public_key),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
BdkDescriptorPublicKey::Single(_) => Err(BdkError::Generic(
|
||||||
|
"Cannot extend from a single key".to_string(),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn as_string(&self) -> String {
|
||||||
|
self.descriptor_public_key_mutex.lock().unwrap().to_string()
|
||||||
|
}
|
||||||
|
}
|
@ -1,24 +1,26 @@
|
|||||||
mod blockchain;
|
mod blockchain;
|
||||||
|
mod descriptor;
|
||||||
|
mod keys;
|
||||||
mod psbt;
|
mod psbt;
|
||||||
mod wallet;
|
mod wallet;
|
||||||
|
|
||||||
use crate::blockchain::{
|
use crate::blockchain::{
|
||||||
Auth, Blockchain, BlockchainConfig, ElectrumConfig, EsploraConfig, RpcConfig, RpcSyncParams,
|
Auth, Blockchain, BlockchainConfig, ElectrumConfig, EsploraConfig, RpcConfig, RpcSyncParams,
|
||||||
};
|
};
|
||||||
|
use crate::descriptor::Descriptor;
|
||||||
|
use crate::keys::DerivationPath;
|
||||||
|
use crate::keys::{DescriptorPublicKey, DescriptorSecretKey, Mnemonic};
|
||||||
use crate::psbt::PartiallySignedTransaction;
|
use crate::psbt::PartiallySignedTransaction;
|
||||||
use crate::wallet::{BumpFeeTxBuilder, TxBuilder, Wallet};
|
use crate::wallet::{BumpFeeTxBuilder, TxBuilder, Wallet};
|
||||||
use crate::descriptor::Descriptor;
|
|
||||||
use bdk::bitcoin::blockdata::script::Script as BdkScript;
|
use bdk::bitcoin::blockdata::script::Script as BdkScript;
|
||||||
use bdk::bitcoin::secp256k1::Secp256k1;
|
use bdk::bitcoin::secp256k1::Secp256k1;
|
||||||
use bdk::bitcoin::util::bip32::{DerivationPath as BdkDerivationPath};
|
|
||||||
use bdk::bitcoin::{Address as BdkAddress, Network, OutPoint as BdkOutPoint, Txid};
|
use bdk::bitcoin::{Address as BdkAddress, Network, OutPoint as BdkOutPoint, Txid};
|
||||||
use bdk::blockchain::Progress as BdkProgress;
|
use bdk::blockchain::Progress as BdkProgress;
|
||||||
use bdk::database::any::{SledDbConfiguration, SqliteDbConfiguration};
|
use bdk::database::any::{SledDbConfiguration, SqliteDbConfiguration};
|
||||||
use bdk::descriptor::{DescriptorXKey};
|
use bdk::descriptor::{DescriptorXKey};
|
||||||
use bdk::keys::bip39::{Language, Mnemonic as BdkMnemonic, WordCount};
|
use bdk::keys::bip39::{Language, WordCount};
|
||||||
use bdk::keys::{
|
use bdk::keys::{
|
||||||
DerivableKey, DescriptorPublicKey as BdkDescriptorPublicKey,
|
DerivableKey, ExtendedKey, GeneratableKey, GeneratedKey,
|
||||||
DescriptorSecretKey as BdkDescriptorSecretKey, ExtendedKey, GeneratableKey, GeneratedKey,
|
|
||||||
};
|
};
|
||||||
use bdk::miniscript::BareCtx;
|
use bdk::miniscript::BareCtx;
|
||||||
use bdk::wallet::AddressIndex as BdkAddressIndex;
|
use bdk::wallet::AddressIndex as BdkAddressIndex;
|
||||||
@ -124,72 +126,6 @@ impl From<&bdk::TransactionDetails> for TransactionDetails {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// struct Blockchain {
|
|
||||||
// blockchain_mutex: Mutex<AnyBlockchain>,
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// impl Blockchain {
|
|
||||||
// fn new(blockchain_config: BlockchainConfig) -> Result<Self, BdkError> {
|
|
||||||
// let any_blockchain_config = match blockchain_config {
|
|
||||||
// BlockchainConfig::Electrum { config } => {
|
|
||||||
// AnyBlockchainConfig::Electrum(ElectrumBlockchainConfig {
|
|
||||||
// retry: config.retry,
|
|
||||||
// socks5: config.socks5,
|
|
||||||
// timeout: config.timeout,
|
|
||||||
// url: config.url,
|
|
||||||
// stop_gap: usize::try_from(config.stop_gap).unwrap(),
|
|
||||||
// validate_domain: config.validate_domain,
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// BlockchainConfig::Esplora { config } => {
|
|
||||||
// AnyBlockchainConfig::Esplora(EsploraBlockchainConfig {
|
|
||||||
// base_url: config.base_url,
|
|
||||||
// proxy: config.proxy,
|
|
||||||
// concurrency: config.concurrency,
|
|
||||||
// stop_gap: usize::try_from(config.stop_gap).unwrap(),
|
|
||||||
// timeout: config.timeout,
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// BlockchainConfig::Rpc { config } => AnyBlockchainConfig::Rpc(BdkRpcConfig {
|
|
||||||
// url: config.url,
|
|
||||||
// auth: config.auth.into(),
|
|
||||||
// network: config.network,
|
|
||||||
// wallet_name: config.wallet_name,
|
|
||||||
// sync_params: config.sync_params.map(|p| p.into()),
|
|
||||||
// }),
|
|
||||||
// };
|
|
||||||
// let blockchain = AnyBlockchain::from_config(&any_blockchain_config)?;
|
|
||||||
// Ok(Self {
|
|
||||||
// blockchain_mutex: Mutex::new(blockchain),
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fn get_blockchain(&self) -> MutexGuard<AnyBlockchain> {
|
|
||||||
// self.blockchain_mutex.lock().expect("blockchain")
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fn broadcast(&self, psbt: &PartiallySignedTransaction) -> Result<(), BdkError> {
|
|
||||||
// let tx = psbt.internal.lock().unwrap().clone().extract_tx();
|
|
||||||
// self.get_blockchain().broadcast(&tx)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fn estimate_fee(&self, target: u64) -> Result<Arc<FeeRate>, BdkError> {
|
|
||||||
// let result: Result<FeeRate, bdk::Error> =
|
|
||||||
// self.get_blockchain().estimate_fee(target as usize);
|
|
||||||
// result.map(Arc::new)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fn get_height(&self) -> Result<u32, BdkError> {
|
|
||||||
// self.get_blockchain().get_height()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fn get_block_hash(&self, height: u32) -> Result<String, BdkError> {
|
|
||||||
// self.get_blockchain()
|
|
||||||
// .get_block_hash(u64::from(height))
|
|
||||||
// .map(|hash| hash.to_string())
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
/// A reference to a transaction output.
|
/// A reference to a transaction output.
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct OutPoint {
|
pub struct OutPoint {
|
||||||
@ -345,235 +281,6 @@ pub struct TxBuilderResult {
|
|||||||
pub transaction_details: TransactionDetails,
|
pub transaction_details: TransactionDetails,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mnemonic phrases are a human-readable version of the private keys.
|
|
||||||
/// Supported number of words are 12, 15, 18, 21 and 24.
|
|
||||||
struct Mnemonic {
|
|
||||||
internal: BdkMnemonic,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Mnemonic {
|
|
||||||
/// Generates Mnemonic with a random entropy
|
|
||||||
fn new(word_count: WordCount) -> Self {
|
|
||||||
let generated_key: GeneratedKey<_, BareCtx> =
|
|
||||||
BdkMnemonic::generate((word_count, Language::English)).unwrap();
|
|
||||||
let mnemonic = BdkMnemonic::parse_in(Language::English, generated_key.to_string()).unwrap();
|
|
||||||
Mnemonic { internal: mnemonic }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parse a Mnemonic with given string
|
|
||||||
fn from_string(mnemonic: String) -> Result<Self, BdkError> {
|
|
||||||
BdkMnemonic::from_str(&mnemonic)
|
|
||||||
.map(|m| Mnemonic { internal: m })
|
|
||||||
.map_err(|e| BdkError::Generic(e.to_string()))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a new Mnemonic in the specified language from the given entropy.
|
|
||||||
/// Entropy must be a multiple of 32 bits (4 bytes) and 128-256 bits in length.
|
|
||||||
fn from_entropy(entropy: Vec<u8>) -> Result<Self, BdkError> {
|
|
||||||
BdkMnemonic::from_entropy(entropy.as_slice())
|
|
||||||
.map(|m| Mnemonic { internal: m })
|
|
||||||
.map_err(|e| BdkError::Generic(e.to_string()))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns Mnemonic as string
|
|
||||||
fn as_string(&self) -> String {
|
|
||||||
self.internal.to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct DerivationPath {
|
|
||||||
derivation_path_mutex: Mutex<BdkDerivationPath>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DerivationPath {
|
|
||||||
fn new(path: String) -> Result<Self, BdkError> {
|
|
||||||
BdkDerivationPath::from_str(&path)
|
|
||||||
.map(|x| DerivationPath {
|
|
||||||
derivation_path_mutex: Mutex::new(x),
|
|
||||||
})
|
|
||||||
.map_err(|e| BdkError::Generic(e.to_string()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct DescriptorSecretKey {
|
|
||||||
descriptor_secret_key_mutex: Mutex<BdkDescriptorSecretKey>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DescriptorSecretKey {
|
|
||||||
fn new(network: Network, mnemonic: Arc<Mnemonic>, password: Option<String>) -> Self {
|
|
||||||
let mnemonic = mnemonic.internal.clone();
|
|
||||||
let xkey: ExtendedKey = (mnemonic, password).into_extended_key().unwrap();
|
|
||||||
let descriptor_secret_key = BdkDescriptorSecretKey::XPrv(DescriptorXKey {
|
|
||||||
origin: None,
|
|
||||||
xkey: xkey.into_xprv(network).unwrap(),
|
|
||||||
derivation_path: BdkDerivationPath::master(),
|
|
||||||
wildcard: bdk::descriptor::Wildcard::Unhardened,
|
|
||||||
});
|
|
||||||
Self {
|
|
||||||
descriptor_secret_key_mutex: Mutex::new(descriptor_secret_key),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn from_string(private_key: String) -> Result<Self, BdkError> {
|
|
||||||
let descriptor_secret_key = BdkDescriptorSecretKey::from_str(private_key.as_str())
|
|
||||||
.map_err(|e| BdkError::Generic(e.to_string()))?;
|
|
||||||
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();
|
|
||||||
match descriptor_secret_key.deref() {
|
|
||||||
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
|
|
||||||
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),
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
BdkDescriptorSecretKey::Single(_) => Err(BdkError::Generic(
|
|
||||||
"Cannot derive from a single key".to_string(),
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn extend(&self, path: Arc<DerivationPath>) -> Result<Arc<Self>, BdkError> {
|
|
||||||
let descriptor_secret_key = self.descriptor_secret_key_mutex.lock().unwrap();
|
|
||||||
let path = path.derivation_path_mutex.lock().unwrap().deref().clone();
|
|
||||||
match descriptor_secret_key.deref() {
|
|
||||||
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
|
|
||||||
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,
|
|
||||||
});
|
|
||||||
Ok(Arc::new(Self {
|
|
||||||
descriptor_secret_key_mutex: Mutex::new(extended_descriptor_secret_key),
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
BdkDescriptorSecretKey::Single(_) => Err(BdkError::Generic(
|
|
||||||
"Cannot extend from a single key".to_string(),
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_public(&self) -> Arc<DescriptorPublicKey> {
|
|
||||||
let secp = Secp256k1::new();
|
|
||||||
let descriptor_public_key = self
|
|
||||||
.descriptor_secret_key_mutex
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.to_public(&secp)
|
|
||||||
.unwrap();
|
|
||||||
Arc::new(DescriptorPublicKey {
|
|
||||||
descriptor_public_key_mutex: Mutex::new(descriptor_public_key),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the private key as bytes.
|
|
||||||
fn secret_bytes(&self) -> Vec<u8> {
|
|
||||||
let descriptor_secret_key = self.descriptor_secret_key_mutex.lock().unwrap();
|
|
||||||
let secret_bytes: Vec<u8> = match descriptor_secret_key.deref() {
|
|
||||||
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
|
|
||||||
descriptor_x_key.xkey.private_key.secret_bytes().to_vec()
|
|
||||||
}
|
|
||||||
BdkDescriptorSecretKey::Single(_) => {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
secret_bytes
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_string(&self) -> String {
|
|
||||||
self.descriptor_secret_key_mutex.lock().unwrap().to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct DescriptorPublicKey {
|
|
||||||
descriptor_public_key_mutex: Mutex<BdkDescriptorPublicKey>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DescriptorPublicKey {
|
|
||||||
fn from_string(public_key: String) -> Result<Self, BdkError> {
|
|
||||||
let descriptor_public_key = BdkDescriptorPublicKey::from_str(public_key.as_str())
|
|
||||||
.map_err(|e| BdkError::Generic(e.to_string()))?;
|
|
||||||
Ok(Self {
|
|
||||||
descriptor_public_key_mutex: Mutex::new(descriptor_public_key),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
|
|
||||||
match descriptor_public_key.deref() {
|
|
||||||
BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
|
|
||||||
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),
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
BdkDescriptorPublicKey::Single(_) => Err(BdkError::Generic(
|
|
||||||
"Cannot derive from a single key".to_string(),
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn extend(&self, path: Arc<DerivationPath>) -> Result<Arc<Self>, BdkError> {
|
|
||||||
let descriptor_public_key = self.descriptor_public_key_mutex.lock().unwrap();
|
|
||||||
let path = path.derivation_path_mutex.lock().unwrap().deref().clone();
|
|
||||||
match descriptor_public_key.deref() {
|
|
||||||
BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
|
|
||||||
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,
|
|
||||||
});
|
|
||||||
Ok(Arc::new(Self {
|
|
||||||
descriptor_public_key_mutex: Mutex::new(extended_descriptor_public_key),
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
BdkDescriptorPublicKey::Single(_) => Err(BdkError::Generic(
|
|
||||||
"Cannot extend from a single key".to_string(),
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_string(&self) -> String {
|
|
||||||
self.descriptor_public_key_mutex.lock().unwrap().to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uniffi::deps::static_assertions::assert_impl_all!(Wallet: Sync, Send);
|
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.
|
// The goal of these tests to to ensure `bdk-ffi` intermediate code correctly calls `bdk` APIs.
|
||||||
|
@ -5,7 +5,7 @@ use bdk::psbt::PsbtUtils;
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use crate::{FeeRate, BdkError};
|
use crate::{BdkError, FeeRate};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct PartiallySignedTransaction {
|
pub(crate) struct PartiallySignedTransaction {
|
||||||
|
@ -3,21 +3,19 @@ use bdk::bitcoin::{Address as BdkAddress, Network, OutPoint as BdkOutPoint, Sequ
|
|||||||
use bdk::database::any::AnyDatabase;
|
use bdk::database::any::AnyDatabase;
|
||||||
use bdk::database::{AnyDatabaseConfig, ConfigurableDatabase};
|
use bdk::database::{AnyDatabaseConfig, ConfigurableDatabase};
|
||||||
use bdk::wallet::tx_builder::ChangeSpendPolicy;
|
use bdk::wallet::tx_builder::ChangeSpendPolicy;
|
||||||
use bdk::{
|
use bdk::{FeeRate, SignOptions, SyncOptions as BdkSyncOptions, Wallet as BdkWallet};
|
||||||
FeeRate, SignOptions, SyncOptions as BdkSyncOptions, Wallet as BdkWallet,
|
|
||||||
};
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::{Arc, Mutex, MutexGuard};
|
use std::sync::{Arc, Mutex, MutexGuard};
|
||||||
|
|
||||||
use crate::blockchain::Blockchain;
|
use crate::blockchain::Blockchain;
|
||||||
use crate::psbt::PartiallySignedTransaction;
|
|
||||||
use crate::descriptor::Descriptor;
|
use crate::descriptor::Descriptor;
|
||||||
|
use crate::psbt::PartiallySignedTransaction;
|
||||||
use crate::{
|
use crate::{
|
||||||
AddressIndex, AddressInfo, Balance, DatabaseConfig, LocalUtxo, NetworkLocalUtxo,
|
AddressIndex, AddressInfo, Balance, BdkError, DatabaseConfig, LocalUtxo, NetworkLocalUtxo,
|
||||||
OutPoint, Progress, ProgressHolder, RbfValue, Script, ScriptAmount, TransactionDetails,
|
OutPoint, Progress, ProgressHolder, RbfValue, Script, ScriptAmount, TransactionDetails,
|
||||||
TxBuilderResult, BdkError,
|
TxBuilderResult,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user