Convert upper-case acronyms as suggested by CamelCase convention
see https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms
This commit is contained in:
parent
745be7bea8
commit
192965413c
@ -13,7 +13,7 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use bdk::bitcoin;
|
use bdk::bitcoin;
|
||||||
use bdk::database::MemoryDatabase;
|
use bdk::database::MemoryDatabase;
|
||||||
use bdk::descriptor::HDKeyPaths;
|
use bdk::descriptor::HdKeyPaths;
|
||||||
use bdk::wallet::address_validator::{AddressValidator, AddressValidatorError};
|
use bdk::wallet::address_validator::{AddressValidator, AddressValidatorError};
|
||||||
use bdk::KeychainKind;
|
use bdk::KeychainKind;
|
||||||
use bdk::Wallet;
|
use bdk::Wallet;
|
||||||
@ -29,7 +29,7 @@ impl AddressValidator for DummyValidator {
|
|||||||
fn validate(
|
fn validate(
|
||||||
&self,
|
&self,
|
||||||
keychain: KeychainKind,
|
keychain: KeychainKind,
|
||||||
hd_keypaths: &HDKeyPaths,
|
hd_keypaths: &HdKeyPaths,
|
||||||
script: &Script,
|
script: &Script,
|
||||||
) -> Result<(), AddressValidatorError> {
|
) -> Result<(), AddressValidatorError> {
|
||||||
let (_, path) = hd_keypaths
|
let (_, path) = hd_keypaths
|
||||||
|
@ -237,7 +237,7 @@ impl Blockchain for CompactFiltersBlockchain {
|
|||||||
|
|
||||||
let skip_blocks = self.skip_blocks.unwrap_or(0);
|
let skip_blocks = self.skip_blocks.unwrap_or(0);
|
||||||
|
|
||||||
let cf_sync = Arc::new(CFSync::new(Arc::clone(&self.headers), skip_blocks, 0x00)?);
|
let cf_sync = Arc::new(CfSync::new(Arc::clone(&self.headers), skip_blocks, 0x00)?);
|
||||||
|
|
||||||
let initial_height = self.headers.get_height()?;
|
let initial_height = self.headers.get_height()?;
|
||||||
let total_bundles = (first_peer.get_version().start_height as usize)
|
let total_bundles = (first_peer.get_version().start_height as usize)
|
||||||
@ -537,11 +537,11 @@ pub enum CompactFiltersError {
|
|||||||
NoPeers,
|
NoPeers,
|
||||||
|
|
||||||
/// Internal database error
|
/// Internal database error
|
||||||
DB(rocksdb::Error),
|
Db(rocksdb::Error),
|
||||||
/// Internal I/O error
|
/// Internal I/O error
|
||||||
IO(std::io::Error),
|
Io(std::io::Error),
|
||||||
/// Invalid BIP158 filter
|
/// Invalid BIP158 filter
|
||||||
BIP158(bitcoin::util::bip158::Error),
|
Bip158(bitcoin::util::bip158::Error),
|
||||||
/// Internal system time error
|
/// Internal system time error
|
||||||
Time(std::time::SystemTimeError),
|
Time(std::time::SystemTimeError),
|
||||||
|
|
||||||
@ -557,9 +557,9 @@ impl fmt::Display for CompactFiltersError {
|
|||||||
|
|
||||||
impl std::error::Error for CompactFiltersError {}
|
impl std::error::Error for CompactFiltersError {}
|
||||||
|
|
||||||
impl_error!(rocksdb::Error, DB, CompactFiltersError);
|
impl_error!(rocksdb::Error, Db, CompactFiltersError);
|
||||||
impl_error!(std::io::Error, IO, CompactFiltersError);
|
impl_error!(std::io::Error, Io, CompactFiltersError);
|
||||||
impl_error!(bitcoin::util::bip158::Error, BIP158, CompactFiltersError);
|
impl_error!(bitcoin::util::bip158::Error, Bip158, CompactFiltersError);
|
||||||
impl_error!(std::time::SystemTimeError, Time, CompactFiltersError);
|
impl_error!(std::time::SystemTimeError, Time, CompactFiltersError);
|
||||||
|
|
||||||
impl From<crate::error::Error> for CompactFiltersError {
|
impl From<crate::error::Error> for CompactFiltersError {
|
||||||
|
@ -120,7 +120,7 @@ impl Encodable for BundleStatus {
|
|||||||
BundleStatus::Init => {
|
BundleStatus::Init => {
|
||||||
written += 0x00u8.consensus_encode(&mut e)?;
|
written += 0x00u8.consensus_encode(&mut e)?;
|
||||||
}
|
}
|
||||||
BundleStatus::CFHeaders { cf_headers } => {
|
BundleStatus::CfHeaders { cf_headers } => {
|
||||||
written += 0x01u8.consensus_encode(&mut e)?;
|
written += 0x01u8.consensus_encode(&mut e)?;
|
||||||
written += VarInt(cf_headers.len() as u64).consensus_encode(&mut e)?;
|
written += VarInt(cf_headers.len() as u64).consensus_encode(&mut e)?;
|
||||||
for header in cf_headers {
|
for header in cf_headers {
|
||||||
@ -171,7 +171,7 @@ impl Decodable for BundleStatus {
|
|||||||
cf_headers.push(FilterHeader::consensus_decode(&mut d)?);
|
cf_headers.push(FilterHeader::consensus_decode(&mut d)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(BundleStatus::CFHeaders { cf_headers })
|
Ok(BundleStatus::CfHeaders { cf_headers })
|
||||||
}
|
}
|
||||||
0x02 => {
|
0x02 => {
|
||||||
let num = VarInt::consensus_decode(&mut d)?;
|
let num = VarInt::consensus_decode(&mut d)?;
|
||||||
@ -623,26 +623,26 @@ impl<T: StoreType> fmt::Debug for ChainStore<T> {
|
|||||||
|
|
||||||
pub enum BundleStatus {
|
pub enum BundleStatus {
|
||||||
Init,
|
Init,
|
||||||
CFHeaders { cf_headers: Vec<FilterHeader> },
|
CfHeaders { cf_headers: Vec<FilterHeader> },
|
||||||
CFilters { cf_filters: Vec<Vec<u8>> },
|
CFilters { cf_filters: Vec<Vec<u8>> },
|
||||||
Processed { cf_filters: Vec<Vec<u8>> },
|
Processed { cf_filters: Vec<Vec<u8>> },
|
||||||
Tip { cf_filters: Vec<Vec<u8>> },
|
Tip { cf_filters: Vec<Vec<u8>> },
|
||||||
Pruned,
|
Pruned,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CFStore {
|
pub struct CfStore {
|
||||||
store: Arc<RwLock<DB>>,
|
store: Arc<RwLock<DB>>,
|
||||||
filter_type: u8,
|
filter_type: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
type BundleEntry = (BundleStatus, FilterHeader);
|
type BundleEntry = (BundleStatus, FilterHeader);
|
||||||
|
|
||||||
impl CFStore {
|
impl CfStore {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
headers_store: &ChainStore<Full>,
|
headers_store: &ChainStore<Full>,
|
||||||
filter_type: u8,
|
filter_type: u8,
|
||||||
) -> Result<Self, CompactFiltersError> {
|
) -> Result<Self, CompactFiltersError> {
|
||||||
let cf_store = CFStore {
|
let cf_store = CfStore {
|
||||||
store: Arc::clone(&headers_store.store),
|
store: Arc::clone(&headers_store.store),
|
||||||
filter_type,
|
filter_type,
|
||||||
};
|
};
|
||||||
@ -782,7 +782,7 @@ impl CFStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
|
let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
|
||||||
let value = (BundleStatus::CFHeaders { cf_headers }, checkpoint);
|
let value = (BundleStatus::CfHeaders { cf_headers }, checkpoint);
|
||||||
|
|
||||||
read_store.put(key, value.serialize())?;
|
read_store.put(key, value.serialize())?;
|
||||||
|
|
||||||
|
@ -25,22 +25,22 @@ use crate::error::Error;
|
|||||||
|
|
||||||
pub(crate) const BURIED_CONFIRMATIONS: usize = 100;
|
pub(crate) const BURIED_CONFIRMATIONS: usize = 100;
|
||||||
|
|
||||||
pub struct CFSync {
|
pub struct CfSync {
|
||||||
headers_store: Arc<ChainStore<Full>>,
|
headers_store: Arc<ChainStore<Full>>,
|
||||||
cf_store: Arc<CFStore>,
|
cf_store: Arc<CfStore>,
|
||||||
skip_blocks: usize,
|
skip_blocks: usize,
|
||||||
bundles: Mutex<VecDeque<(BundleStatus, FilterHeader, usize)>>,
|
bundles: Mutex<VecDeque<(BundleStatus, FilterHeader, usize)>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CFSync {
|
impl CfSync {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
headers_store: Arc<ChainStore<Full>>,
|
headers_store: Arc<ChainStore<Full>>,
|
||||||
skip_blocks: usize,
|
skip_blocks: usize,
|
||||||
filter_type: u8,
|
filter_type: u8,
|
||||||
) -> Result<Self, CompactFiltersError> {
|
) -> Result<Self, CompactFiltersError> {
|
||||||
let cf_store = Arc::new(CFStore::new(&headers_store, filter_type)?);
|
let cf_store = Arc::new(CfStore::new(&headers_store, filter_type)?);
|
||||||
|
|
||||||
Ok(CFSync {
|
Ok(CfSync {
|
||||||
headers_store,
|
headers_store,
|
||||||
cf_store,
|
cf_store,
|
||||||
skip_blocks,
|
skip_blocks,
|
||||||
@ -151,7 +151,7 @@ impl CFSync {
|
|||||||
checkpoint,
|
checkpoint,
|
||||||
headers_resp.filter_hashes,
|
headers_resp.filter_hashes,
|
||||||
)? {
|
)? {
|
||||||
BundleStatus::CFHeaders { cf_headers } => cf_headers,
|
BundleStatus::CfHeaders { cf_headers } => cf_headers,
|
||||||
_ => return Err(CompactFiltersError::InvalidResponse),
|
_ => return Err(CompactFiltersError::InvalidResponse),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -171,7 +171,7 @@ impl CFSync {
|
|||||||
.cf_store
|
.cf_store
|
||||||
.advance_to_cf_filters(index, checkpoint, cf_headers, filters)?;
|
.advance_to_cf_filters(index, checkpoint, cf_headers, filters)?;
|
||||||
}
|
}
|
||||||
if let BundleStatus::CFHeaders { cf_headers } = status {
|
if let BundleStatus::CfHeaders { cf_headers } = status {
|
||||||
log::trace!("status: CFHeaders");
|
log::trace!("status: CFHeaders");
|
||||||
|
|
||||||
peer.get_cf_filters(
|
peer.get_cf_filters(
|
||||||
|
@ -33,7 +33,7 @@ use bitcoin::{BlockHeader, Script, Transaction, Txid};
|
|||||||
|
|
||||||
use electrum_client::{Client, ConfigBuilder, ElectrumApi, Socks5Config};
|
use electrum_client::{Client, ConfigBuilder, ElectrumApi, Socks5Config};
|
||||||
|
|
||||||
use self::utils::{ELSGetHistoryRes, ElectrumLikeSync};
|
use self::utils::{ElectrumLikeSync, ElsGetHistoryRes};
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::database::BatchDatabase;
|
use crate::database::BatchDatabase;
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
@ -107,7 +107,7 @@ impl ElectrumLikeSync for Client {
|
|||||||
fn els_batch_script_get_history<'s, I: IntoIterator<Item = &'s Script> + Clone>(
|
fn els_batch_script_get_history<'s, I: IntoIterator<Item = &'s Script> + Clone>(
|
||||||
&self,
|
&self,
|
||||||
scripts: I,
|
scripts: I,
|
||||||
) -> Result<Vec<Vec<ELSGetHistoryRes>>, Error> {
|
) -> Result<Vec<Vec<ElsGetHistoryRes>>, Error> {
|
||||||
self.batch_script_get_history(scripts)
|
self.batch_script_get_history(scripts)
|
||||||
.map(|v| {
|
.map(|v| {
|
||||||
v.into_iter()
|
v.into_iter()
|
||||||
@ -116,7 +116,7 @@ impl ElectrumLikeSync for Client {
|
|||||||
.map(
|
.map(
|
||||||
|electrum_client::GetHistoryRes {
|
|electrum_client::GetHistoryRes {
|
||||||
height, tx_hash, ..
|
height, tx_hash, ..
|
||||||
}| ELSGetHistoryRes {
|
}| ElsGetHistoryRes {
|
||||||
height,
|
height,
|
||||||
tx_hash,
|
tx_hash,
|
||||||
},
|
},
|
||||||
|
@ -39,7 +39,7 @@ use bitcoin::hashes::hex::{FromHex, ToHex};
|
|||||||
use bitcoin::hashes::{sha256, Hash};
|
use bitcoin::hashes::{sha256, Hash};
|
||||||
use bitcoin::{BlockHash, BlockHeader, Script, Transaction, Txid};
|
use bitcoin::{BlockHash, BlockHeader, Script, Transaction, Txid};
|
||||||
|
|
||||||
use self::utils::{ELSGetHistoryRes, ElectrumLikeSync};
|
use self::utils::{ElectrumLikeSync, ElsGetHistoryRes};
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::database::BatchDatabase;
|
use crate::database::BatchDatabase;
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
@ -210,7 +210,7 @@ impl UrlClient {
|
|||||||
async fn _script_get_history(
|
async fn _script_get_history(
|
||||||
&self,
|
&self,
|
||||||
script: &Script,
|
script: &Script,
|
||||||
) -> Result<Vec<ELSGetHistoryRes>, EsploraError> {
|
) -> Result<Vec<ElsGetHistoryRes>, EsploraError> {
|
||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
let scripthash = Self::script_to_scripthash(script);
|
let scripthash = Self::script_to_scripthash(script);
|
||||||
|
|
||||||
@ -227,7 +227,7 @@ impl UrlClient {
|
|||||||
.json::<Vec<EsploraGetHistory>>()
|
.json::<Vec<EsploraGetHistory>>()
|
||||||
.await?
|
.await?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|x| ELSGetHistoryRes {
|
.map(|x| ElsGetHistoryRes {
|
||||||
tx_hash: x.txid,
|
tx_hash: x.txid,
|
||||||
height: x.status.block_height.unwrap_or(0) as i32,
|
height: x.status.block_height.unwrap_or(0) as i32,
|
||||||
}),
|
}),
|
||||||
@ -261,7 +261,7 @@ impl UrlClient {
|
|||||||
|
|
||||||
debug!("... adding {} confirmed transactions", len);
|
debug!("... adding {} confirmed transactions", len);
|
||||||
|
|
||||||
result.extend(response.into_iter().map(|x| ELSGetHistoryRes {
|
result.extend(response.into_iter().map(|x| ElsGetHistoryRes {
|
||||||
tx_hash: x.txid,
|
tx_hash: x.txid,
|
||||||
height: x.status.block_height.unwrap_or(0) as i32,
|
height: x.status.block_height.unwrap_or(0) as i32,
|
||||||
}));
|
}));
|
||||||
@ -291,7 +291,7 @@ impl ElectrumLikeSync for UrlClient {
|
|||||||
fn els_batch_script_get_history<'s, I: IntoIterator<Item = &'s Script>>(
|
fn els_batch_script_get_history<'s, I: IntoIterator<Item = &'s Script>>(
|
||||||
&self,
|
&self,
|
||||||
scripts: I,
|
scripts: I,
|
||||||
) -> Result<Vec<Vec<ELSGetHistoryRes>>, Error> {
|
) -> Result<Vec<Vec<ElsGetHistoryRes>>, Error> {
|
||||||
let future = async {
|
let future = async {
|
||||||
let mut results = vec![];
|
let mut results = vec![];
|
||||||
for chunk in ChunksIterator::new(scripts.into_iter(), self.concurrency as usize) {
|
for chunk in ChunksIterator::new(scripts.into_iter(), self.concurrency as usize) {
|
||||||
@ -299,7 +299,7 @@ impl ElectrumLikeSync for UrlClient {
|
|||||||
for script in chunk {
|
for script in chunk {
|
||||||
futs.push(self._script_get_history(&script));
|
futs.push(self._script_get_history(&script));
|
||||||
}
|
}
|
||||||
let partial_results: Vec<Vec<ELSGetHistoryRes>> = futs.try_collect().await?;
|
let partial_results: Vec<Vec<ElsGetHistoryRes>> = futs.try_collect().await?;
|
||||||
results.extend(partial_results);
|
results.extend(partial_results);
|
||||||
}
|
}
|
||||||
Ok(stream::iter(results).collect().await)
|
Ok(stream::iter(results).collect().await)
|
||||||
|
@ -26,7 +26,7 @@ use crate::wallet::time::Instant;
|
|||||||
use crate::wallet::utils::ChunksIterator;
|
use crate::wallet::utils::ChunksIterator;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ELSGetHistoryRes {
|
pub struct ElsGetHistoryRes {
|
||||||
pub height: i32,
|
pub height: i32,
|
||||||
pub tx_hash: Txid,
|
pub tx_hash: Txid,
|
||||||
}
|
}
|
||||||
@ -37,7 +37,7 @@ pub trait ElectrumLikeSync {
|
|||||||
fn els_batch_script_get_history<'s, I: IntoIterator<Item = &'s Script> + Clone>(
|
fn els_batch_script_get_history<'s, I: IntoIterator<Item = &'s Script> + Clone>(
|
||||||
&self,
|
&self,
|
||||||
scripts: I,
|
scripts: I,
|
||||||
) -> Result<Vec<Vec<ELSGetHistoryRes>>, Error>;
|
) -> Result<Vec<Vec<ElsGetHistoryRes>>, Error>;
|
||||||
|
|
||||||
fn els_batch_transaction_get<'s, I: IntoIterator<Item = &'s Txid> + Clone>(
|
fn els_batch_transaction_get<'s, I: IntoIterator<Item = &'s Txid> + Clone>(
|
||||||
&self,
|
&self,
|
||||||
@ -77,7 +77,7 @@ pub trait ElectrumLikeSync {
|
|||||||
|
|
||||||
for (i, chunk) in ChunksIterator::new(script_iter, stop_gap).enumerate() {
|
for (i, chunk) in ChunksIterator::new(script_iter, stop_gap).enumerate() {
|
||||||
// TODO if i == last, should create another chunk of addresses in db
|
// TODO if i == last, should create another chunk of addresses in db
|
||||||
let call_result: Vec<Vec<ELSGetHistoryRes>> =
|
let call_result: Vec<Vec<ElsGetHistoryRes>> =
|
||||||
maybe_await!(self.els_batch_script_get_history(chunk.iter()))?;
|
maybe_await!(self.els_batch_script_get_history(chunk.iter()))?;
|
||||||
let max_index = call_result
|
let max_index = call_result
|
||||||
.iter()
|
.iter()
|
||||||
@ -87,7 +87,7 @@ pub trait ElectrumLikeSync {
|
|||||||
if let Some(max) = max_index {
|
if let Some(max) = max_index {
|
||||||
max_indexes.insert(keychain, max + (i * chunk_size) as u32);
|
max_indexes.insert(keychain, max + (i * chunk_size) as u32);
|
||||||
}
|
}
|
||||||
let flattened: Vec<ELSGetHistoryRes> = call_result.into_iter().flatten().collect();
|
let flattened: Vec<ElsGetHistoryRes> = call_result.into_iter().flatten().collect();
|
||||||
debug!("#{} of {:?} results:{}", i, keychain, flattened.len());
|
debug!("#{} of {:?} results:{}", i, keychain, flattened.len());
|
||||||
if flattened.is_empty() {
|
if flattened.is_empty() {
|
||||||
// Didn't find anything in the last `stop_gap` script_pubkeys, breaking
|
// Didn't find anything in the last `stop_gap` script_pubkeys, breaking
|
||||||
|
@ -39,7 +39,7 @@ macro_rules! impl_batch_operations {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn set_utxo(&mut self, utxo: &LocalUtxo) -> Result<(), Error> {
|
fn set_utxo(&mut self, utxo: &LocalUtxo) -> Result<(), Error> {
|
||||||
let key = MapKey::UTXO(Some(&utxo.outpoint)).as_map_key();
|
let key = MapKey::Utxo(Some(&utxo.outpoint)).as_map_key();
|
||||||
let value = json!({
|
let value = json!({
|
||||||
"t": utxo.txout,
|
"t": utxo.txout,
|
||||||
"i": utxo.keychain,
|
"i": utxo.keychain,
|
||||||
@ -108,7 +108,7 @@ macro_rules! impl_batch_operations {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
|
fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
|
||||||
let key = MapKey::UTXO(Some(outpoint)).as_map_key();
|
let key = MapKey::Utxo(Some(outpoint)).as_map_key();
|
||||||
let res = self.remove(key);
|
let res = self.remove(key);
|
||||||
let res = $process_delete!(res);
|
let res = $process_delete!(res);
|
||||||
|
|
||||||
@ -222,7 +222,7 @@ impl Database for Tree {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn iter_utxos(&self) -> Result<Vec<LocalUtxo>, Error> {
|
fn iter_utxos(&self) -> Result<Vec<LocalUtxo>, Error> {
|
||||||
let key = MapKey::UTXO(None).as_map_key();
|
let key = MapKey::Utxo(None).as_map_key();
|
||||||
self.scan_prefix(key)
|
self.scan_prefix(key)
|
||||||
.map(|x| -> Result<_, Error> {
|
.map(|x| -> Result<_, Error> {
|
||||||
let (k, v) = x?;
|
let (k, v) = x?;
|
||||||
@ -293,7 +293,7 @@ impl Database for Tree {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
|
fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
|
||||||
let key = MapKey::UTXO(Some(outpoint)).as_map_key();
|
let key = MapKey::Utxo(Some(outpoint)).as_map_key();
|
||||||
self.get(key)?
|
self.get(key)?
|
||||||
.map(|b| -> Result<_, Error> {
|
.map(|b| -> Result<_, Error> {
|
||||||
let mut val: serde_json::Value = serde_json::from_slice(&b)?;
|
let mut val: serde_json::Value = serde_json::from_slice(&b)?;
|
||||||
|
@ -36,7 +36,7 @@ use crate::types::*;
|
|||||||
pub(crate) enum MapKey<'a> {
|
pub(crate) enum MapKey<'a> {
|
||||||
Path((Option<KeychainKind>, Option<u32>)),
|
Path((Option<KeychainKind>, Option<u32>)),
|
||||||
Script(Option<&'a Script>),
|
Script(Option<&'a Script>),
|
||||||
UTXO(Option<&'a OutPoint>),
|
Utxo(Option<&'a OutPoint>),
|
||||||
RawTx(Option<&'a Txid>),
|
RawTx(Option<&'a Txid>),
|
||||||
Transaction(Option<&'a Txid>),
|
Transaction(Option<&'a Txid>),
|
||||||
LastIndex(KeychainKind),
|
LastIndex(KeychainKind),
|
||||||
@ -54,7 +54,7 @@ impl MapKey<'_> {
|
|||||||
v
|
v
|
||||||
}
|
}
|
||||||
MapKey::Script(_) => b"s".to_vec(),
|
MapKey::Script(_) => b"s".to_vec(),
|
||||||
MapKey::UTXO(_) => b"u".to_vec(),
|
MapKey::Utxo(_) => b"u".to_vec(),
|
||||||
MapKey::RawTx(_) => b"r".to_vec(),
|
MapKey::RawTx(_) => b"r".to_vec(),
|
||||||
MapKey::Transaction(_) => b"t".to_vec(),
|
MapKey::Transaction(_) => b"t".to_vec(),
|
||||||
MapKey::LastIndex(st) => [b"c", st.as_ref()].concat(),
|
MapKey::LastIndex(st) => [b"c", st.as_ref()].concat(),
|
||||||
@ -66,7 +66,7 @@ impl MapKey<'_> {
|
|||||||
match self {
|
match self {
|
||||||
MapKey::Path((_, Some(child))) => child.to_be_bytes().to_vec(),
|
MapKey::Path((_, Some(child))) => child.to_be_bytes().to_vec(),
|
||||||
MapKey::Script(Some(s)) => serialize(*s),
|
MapKey::Script(Some(s)) => serialize(*s),
|
||||||
MapKey::UTXO(Some(s)) => serialize(*s),
|
MapKey::Utxo(Some(s)) => serialize(*s),
|
||||||
MapKey::RawTx(Some(s)) => serialize(*s),
|
MapKey::RawTx(Some(s)) => serialize(*s),
|
||||||
MapKey::Transaction(Some(s)) => serialize(*s),
|
MapKey::Transaction(Some(s)) => serialize(*s),
|
||||||
_ => vec![],
|
_ => vec![],
|
||||||
@ -145,7 +145,7 @@ impl BatchOperations for MemoryDatabase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn set_utxo(&mut self, utxo: &LocalUtxo) -> Result<(), Error> {
|
fn set_utxo(&mut self, utxo: &LocalUtxo) -> Result<(), Error> {
|
||||||
let key = MapKey::UTXO(Some(&utxo.outpoint)).as_map_key();
|
let key = MapKey::Utxo(Some(&utxo.outpoint)).as_map_key();
|
||||||
self.map
|
self.map
|
||||||
.insert(key, Box::new((utxo.txout.clone(), utxo.keychain)));
|
.insert(key, Box::new((utxo.txout.clone(), utxo.keychain)));
|
||||||
|
|
||||||
@ -211,7 +211,7 @@ impl BatchOperations for MemoryDatabase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
|
fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
|
||||||
let key = MapKey::UTXO(Some(outpoint)).as_map_key();
|
let key = MapKey::Utxo(Some(outpoint)).as_map_key();
|
||||||
let res = self.map.remove(&key);
|
let res = self.map.remove(&key);
|
||||||
self.deleted_keys.push(key);
|
self.deleted_keys.push(key);
|
||||||
|
|
||||||
@ -304,7 +304,7 @@ impl Database for MemoryDatabase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn iter_utxos(&self) -> Result<Vec<LocalUtxo>, Error> {
|
fn iter_utxos(&self) -> Result<Vec<LocalUtxo>, Error> {
|
||||||
let key = MapKey::UTXO(None).as_map_key();
|
let key = MapKey::Utxo(None).as_map_key();
|
||||||
self.map
|
self.map
|
||||||
.range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
|
.range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
|
||||||
.map(|(k, v)| {
|
.map(|(k, v)| {
|
||||||
@ -370,7 +370,7 @@ impl Database for MemoryDatabase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
|
fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
|
||||||
let key = MapKey::UTXO(Some(outpoint)).as_map_key();
|
let key = MapKey::Utxo(Some(outpoint)).as_map_key();
|
||||||
Ok(self.map.get(&key).map(|b| {
|
Ok(self.map.get(&key).map(|b| {
|
||||||
let (txout, keychain) = b.downcast_ref().cloned().unwrap();
|
let (txout, keychain) = b.downcast_ref().cloned().unwrap();
|
||||||
LocalUtxo {
|
LocalUtxo {
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
/// Invalid HD Key path, such as having a wildcard but a length != 1
|
/// Invalid HD Key path, such as having a wildcard but a length != 1
|
||||||
InvalidHDKeyPath,
|
InvalidHdKeyPath,
|
||||||
/// The provided descriptor doesn't match its checksum
|
/// The provided descriptor doesn't match its checksum
|
||||||
InvalidDescriptorChecksum,
|
InvalidDescriptorChecksum,
|
||||||
/// The descriptor contains hardened derivation steps on public extended keys
|
/// The descriptor contains hardened derivation steps on public extended keys
|
||||||
@ -32,11 +32,11 @@ pub enum Error {
|
|||||||
InvalidDescriptorCharacter(char),
|
InvalidDescriptorCharacter(char),
|
||||||
|
|
||||||
/// BIP32 error
|
/// BIP32 error
|
||||||
BIP32(bitcoin::util::bip32::Error),
|
Bip32(bitcoin::util::bip32::Error),
|
||||||
/// Error during base58 decoding
|
/// Error during base58 decoding
|
||||||
Base58(bitcoin::util::base58::Error),
|
Base58(bitcoin::util::base58::Error),
|
||||||
/// Key-related error
|
/// Key-related error
|
||||||
PK(bitcoin::util::key::Error),
|
Pk(bitcoin::util::key::Error),
|
||||||
/// Miniscript error
|
/// Miniscript error
|
||||||
Miniscript(miniscript::Error),
|
Miniscript(miniscript::Error),
|
||||||
/// Hex decoding error
|
/// Hex decoding error
|
||||||
@ -47,7 +47,7 @@ impl From<crate::keys::KeyError> for Error {
|
|||||||
fn from(key_error: crate::keys::KeyError) -> Error {
|
fn from(key_error: crate::keys::KeyError) -> Error {
|
||||||
match key_error {
|
match key_error {
|
||||||
crate::keys::KeyError::Miniscript(inner) => Error::Miniscript(inner),
|
crate::keys::KeyError::Miniscript(inner) => Error::Miniscript(inner),
|
||||||
crate::keys::KeyError::BIP32(inner) => Error::BIP32(inner),
|
crate::keys::KeyError::Bip32(inner) => Error::Bip32(inner),
|
||||||
e => Error::Key(e),
|
e => Error::Key(e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -61,9 +61,9 @@ impl std::fmt::Display for Error {
|
|||||||
|
|
||||||
impl std::error::Error for Error {}
|
impl std::error::Error for Error {}
|
||||||
|
|
||||||
impl_error!(bitcoin::util::bip32::Error, BIP32);
|
impl_error!(bitcoin::util::bip32::Error, Bip32);
|
||||||
impl_error!(bitcoin::util::base58::Error, Base58);
|
impl_error!(bitcoin::util::base58::Error, Base58);
|
||||||
impl_error!(bitcoin::util::key::Error, PK);
|
impl_error!(bitcoin::util::key::Error, Pk);
|
||||||
impl_error!(miniscript::Error, Miniscript);
|
impl_error!(miniscript::Error, Miniscript);
|
||||||
impl_error!(bitcoin::hashes::hex::Error, Hex);
|
impl_error!(bitcoin::hashes::hex::Error, Hex);
|
||||||
impl_error!(crate::descriptor::policy::PolicyError, Policy);
|
impl_error!(crate::descriptor::policy::PolicyError, Policy);
|
||||||
|
@ -56,7 +56,7 @@ pub type DerivedDescriptor<'s> = Descriptor<DerivedDescriptorKey<'s>>;
|
|||||||
///
|
///
|
||||||
/// [`psbt::Input`]: bitcoin::util::psbt::Input
|
/// [`psbt::Input`]: bitcoin::util::psbt::Input
|
||||||
/// [`psbt::Output`]: bitcoin::util::psbt::Output
|
/// [`psbt::Output`]: bitcoin::util::psbt::Output
|
||||||
pub type HDKeyPaths = BTreeMap<PublicKey, KeySource>;
|
pub type HdKeyPaths = BTreeMap<PublicKey, KeySource>;
|
||||||
|
|
||||||
/// Trait for types which can be converted into an [`ExtendedDescriptor`] and a [`KeyMap`] usable by a wallet in a specific [`Network`]
|
/// Trait for types which can be converted into an [`ExtendedDescriptor`] and a [`KeyMap`] usable by a wallet in a specific [`Network`]
|
||||||
pub trait IntoWalletDescriptor {
|
pub trait IntoWalletDescriptor {
|
||||||
@ -329,7 +329,7 @@ impl XKeyUtils for DescriptorXKey<ExtendedPrivKey> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) trait DerivedDescriptorMeta {
|
pub(crate) trait DerivedDescriptorMeta {
|
||||||
fn get_hd_keypaths(&self, secp: &SecpCtx) -> Result<HDKeyPaths, DescriptorError>;
|
fn get_hd_keypaths(&self, secp: &SecpCtx) -> Result<HdKeyPaths, DescriptorError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) trait DescriptorMeta {
|
pub(crate) trait DescriptorMeta {
|
||||||
@ -337,7 +337,7 @@ pub(crate) trait DescriptorMeta {
|
|||||||
fn get_extended_keys(&self) -> Result<Vec<DescriptorXKey<ExtendedPubKey>>, DescriptorError>;
|
fn get_extended_keys(&self) -> Result<Vec<DescriptorXKey<ExtendedPubKey>>, DescriptorError>;
|
||||||
fn derive_from_hd_keypaths<'s>(
|
fn derive_from_hd_keypaths<'s>(
|
||||||
&self,
|
&self,
|
||||||
hd_keypaths: &HDKeyPaths,
|
hd_keypaths: &HdKeyPaths,
|
||||||
secp: &'s SecpCtx,
|
secp: &'s SecpCtx,
|
||||||
) -> Option<DerivedDescriptor<'s>>;
|
) -> Option<DerivedDescriptor<'s>>;
|
||||||
fn derive_from_psbt_input<'s>(
|
fn derive_from_psbt_input<'s>(
|
||||||
@ -406,7 +406,7 @@ impl DescriptorMeta for ExtendedDescriptor {
|
|||||||
|
|
||||||
fn derive_from_hd_keypaths<'s>(
|
fn derive_from_hd_keypaths<'s>(
|
||||||
&self,
|
&self,
|
||||||
hd_keypaths: &HDKeyPaths,
|
hd_keypaths: &HdKeyPaths,
|
||||||
secp: &'s SecpCtx,
|
secp: &'s SecpCtx,
|
||||||
) -> Option<DerivedDescriptor<'s>> {
|
) -> Option<DerivedDescriptor<'s>> {
|
||||||
let index: HashMap<_, _> = hd_keypaths.values().map(|(a, b)| (a, b)).collect();
|
let index: HashMap<_, _> = hd_keypaths.values().map(|(a, b)| (a, b)).collect();
|
||||||
@ -505,7 +505,7 @@ impl DescriptorMeta for ExtendedDescriptor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> DerivedDescriptorMeta for DerivedDescriptor<'s> {
|
impl<'s> DerivedDescriptorMeta for DerivedDescriptor<'s> {
|
||||||
fn get_hd_keypaths(&self, secp: &SecpCtx) -> Result<HDKeyPaths, DescriptorError> {
|
fn get_hd_keypaths(&self, secp: &SecpCtx) -> Result<HdKeyPaths, DescriptorError> {
|
||||||
let mut answer = BTreeMap::new();
|
let mut answer = BTreeMap::new();
|
||||||
self.for_each_key(|key| {
|
self.for_each_key(|key| {
|
||||||
if let DescriptorPublicKey::XPub(xpub) = key.as_key().deref() {
|
if let DescriptorPublicKey::XPub(xpub) = key.as_key().deref() {
|
||||||
@ -537,7 +537,7 @@ mod test {
|
|||||||
use bitcoin::util::{bip32, psbt};
|
use bitcoin::util::{bip32, psbt};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::psbt::PSBTUtils;
|
use crate::psbt::PsbtUtils;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_derive_from_psbt_input_wpkh_wif() {
|
fn test_derive_from_psbt_input_wpkh_wif() {
|
||||||
|
@ -57,7 +57,7 @@ use log::{debug, error, info, trace};
|
|||||||
use crate::descriptor::{
|
use crate::descriptor::{
|
||||||
DerivedDescriptor, DerivedDescriptorKey, DescriptorMeta, ExtendedDescriptor, ExtractPolicy,
|
DerivedDescriptor, DerivedDescriptorKey, DescriptorMeta, ExtendedDescriptor, ExtractPolicy,
|
||||||
};
|
};
|
||||||
use crate::psbt::PSBTUtils;
|
use crate::psbt::PsbtUtils;
|
||||||
use crate::wallet::signer::{SignerId, SignersContainer};
|
use crate::wallet::signer::{SignerId, SignersContainer};
|
||||||
use crate::wallet::utils::{self, SecpCtx};
|
use crate::wallet::utils::{self, SecpCtx};
|
||||||
|
|
||||||
@ -69,7 +69,7 @@ use miniscript::psbt::PsbtInputSatisfier;
|
|||||||
|
|
||||||
/// Raw public key or extended key fingerprint
|
/// Raw public key or extended key fingerprint
|
||||||
#[derive(Debug, Clone, Default, Serialize)]
|
#[derive(Debug, Clone, Default, Serialize)]
|
||||||
pub struct PKOrF {
|
pub struct PkOrF {
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pubkey: Option<PublicKey>,
|
pubkey: Option<PublicKey>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
@ -78,14 +78,14 @@ pub struct PKOrF {
|
|||||||
fingerprint: Option<Fingerprint>,
|
fingerprint: Option<Fingerprint>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PKOrF {
|
impl PkOrF {
|
||||||
fn from_key(k: &DescriptorPublicKey, secp: &SecpCtx) -> Self {
|
fn from_key(k: &DescriptorPublicKey, secp: &SecpCtx) -> Self {
|
||||||
match k {
|
match k {
|
||||||
DescriptorPublicKey::SinglePub(pubkey) => PKOrF {
|
DescriptorPublicKey::SinglePub(pubkey) => PkOrF {
|
||||||
pubkey: Some(pubkey.key),
|
pubkey: Some(pubkey.key),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
DescriptorPublicKey::XPub(xpub) => PKOrF {
|
DescriptorPublicKey::XPub(xpub) => PkOrF {
|
||||||
fingerprint: Some(xpub.root_fingerprint(secp)),
|
fingerprint: Some(xpub.root_fingerprint(secp)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
@ -93,7 +93,7 @@ impl PKOrF {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn from_key_hash(k: hash160::Hash) -> Self {
|
fn from_key_hash(k: hash160::Hash) -> Self {
|
||||||
PKOrF {
|
PkOrF {
|
||||||
pubkey_hash: Some(k),
|
pubkey_hash: Some(k),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
@ -106,26 +106,26 @@ impl PKOrF {
|
|||||||
pub enum SatisfiableItem {
|
pub enum SatisfiableItem {
|
||||||
// Leaves
|
// Leaves
|
||||||
/// Signature for a raw public key
|
/// Signature for a raw public key
|
||||||
Signature(PKOrF),
|
Signature(PkOrF),
|
||||||
/// Signature for an extended key fingerprint
|
/// Signature for an extended key fingerprint
|
||||||
SignatureKey(PKOrF),
|
SignatureKey(PkOrF),
|
||||||
/// SHA256 preimage hash
|
/// SHA256 preimage hash
|
||||||
SHA256Preimage {
|
Sha256Preimage {
|
||||||
/// The digest value
|
/// The digest value
|
||||||
hash: sha256::Hash,
|
hash: sha256::Hash,
|
||||||
},
|
},
|
||||||
/// Double SHA256 preimage hash
|
/// Double SHA256 preimage hash
|
||||||
HASH256Preimage {
|
Hash256Preimage {
|
||||||
/// The digest value
|
/// The digest value
|
||||||
hash: sha256d::Hash,
|
hash: sha256d::Hash,
|
||||||
},
|
},
|
||||||
/// RIPEMD160 preimage hash
|
/// RIPEMD160 preimage hash
|
||||||
RIPEMD160Preimage {
|
Ripemd160Preimage {
|
||||||
/// The digest value
|
/// The digest value
|
||||||
hash: ripemd160::Hash,
|
hash: ripemd160::Hash,
|
||||||
},
|
},
|
||||||
/// SHA256 then RIPEMD160 preimage hash
|
/// SHA256 then RIPEMD160 preimage hash
|
||||||
HASH160Preimage {
|
Hash160Preimage {
|
||||||
/// The digest value
|
/// The digest value
|
||||||
hash: hash160::Hash,
|
hash: hash160::Hash,
|
||||||
},
|
},
|
||||||
@ -142,7 +142,7 @@ pub enum SatisfiableItem {
|
|||||||
/// Multi-signature public keys with threshold count
|
/// Multi-signature public keys with threshold count
|
||||||
Multisig {
|
Multisig {
|
||||||
/// The raw public key or extended key fingerprint
|
/// The raw public key or extended key fingerprint
|
||||||
keys: Vec<PKOrF>,
|
keys: Vec<PkOrF>,
|
||||||
/// The required threshold count
|
/// The required threshold count
|
||||||
threshold: usize,
|
threshold: usize,
|
||||||
},
|
},
|
||||||
@ -585,7 +585,7 @@ impl Policy {
|
|||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
let parsed_keys = keys.iter().map(|k| PKOrF::from_key(k, secp)).collect();
|
let parsed_keys = keys.iter().map(|k| PkOrF::from_key(k, secp)).collect();
|
||||||
|
|
||||||
let mut contribution = Satisfaction::Partial {
|
let mut contribution = Satisfaction::Partial {
|
||||||
n: keys.len(),
|
n: keys.len(),
|
||||||
@ -760,7 +760,7 @@ fn signer_id(key: &DescriptorPublicKey, secp: &SecpCtx) -> SignerId {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn signature(key: &DescriptorPublicKey, signers: &SignersContainer, secp: &SecpCtx) -> Policy {
|
fn signature(key: &DescriptorPublicKey, signers: &SignersContainer, secp: &SecpCtx) -> Policy {
|
||||||
let mut policy: Policy = SatisfiableItem::Signature(PKOrF::from_key(key, secp)).into();
|
let mut policy: Policy = SatisfiableItem::Signature(PkOrF::from_key(key, secp)).into();
|
||||||
|
|
||||||
policy.contribution = if signers.find(signer_id(key, secp)).is_some() {
|
policy.contribution = if signers.find(signer_id(key, secp)).is_some() {
|
||||||
Satisfaction::Complete {
|
Satisfaction::Complete {
|
||||||
@ -781,7 +781,7 @@ fn signature_key(
|
|||||||
let key_hash = DerivedDescriptorKey::new(key.clone(), secp)
|
let key_hash = DerivedDescriptorKey::new(key.clone(), secp)
|
||||||
.to_public_key()
|
.to_public_key()
|
||||||
.to_pubkeyhash();
|
.to_pubkeyhash();
|
||||||
let mut policy: Policy = SatisfiableItem::Signature(PKOrF::from_key_hash(key_hash)).into();
|
let mut policy: Policy = SatisfiableItem::Signature(PkOrF::from_key_hash(key_hash)).into();
|
||||||
|
|
||||||
if signers.find(SignerId::PkHash(key_hash)).is_some() {
|
if signers.find(SignerId::PkHash(key_hash)).is_some() {
|
||||||
policy.contribution = Satisfaction::Complete {
|
policy.contribution = Satisfaction::Complete {
|
||||||
@ -825,15 +825,15 @@ impl<Ctx: ScriptContext> ExtractPolicy for Miniscript<DescriptorPublicKey, Ctx>
|
|||||||
|
|
||||||
Some(policy)
|
Some(policy)
|
||||||
}
|
}
|
||||||
Terminal::Sha256(hash) => Some(SatisfiableItem::SHA256Preimage { hash: *hash }.into()),
|
Terminal::Sha256(hash) => Some(SatisfiableItem::Sha256Preimage { hash: *hash }.into()),
|
||||||
Terminal::Hash256(hash) => {
|
Terminal::Hash256(hash) => {
|
||||||
Some(SatisfiableItem::HASH256Preimage { hash: *hash }.into())
|
Some(SatisfiableItem::Hash256Preimage { hash: *hash }.into())
|
||||||
}
|
}
|
||||||
Terminal::Ripemd160(hash) => {
|
Terminal::Ripemd160(hash) => {
|
||||||
Some(SatisfiableItem::RIPEMD160Preimage { hash: *hash }.into())
|
Some(SatisfiableItem::Ripemd160Preimage { hash: *hash }.into())
|
||||||
}
|
}
|
||||||
Terminal::Hash160(hash) => {
|
Terminal::Hash160(hash) => {
|
||||||
Some(SatisfiableItem::HASH160Preimage { hash: *hash }.into())
|
Some(SatisfiableItem::Hash160Preimage { hash: *hash }.into())
|
||||||
}
|
}
|
||||||
Terminal::Multi(k, pks) => Policy::make_multisig(pks, signers, *k, false, secp)?,
|
Terminal::Multi(k, pks) => Policy::make_multisig(pks, signers, *k, false, secp)?,
|
||||||
// Identities
|
// Identities
|
||||||
|
@ -75,12 +75,12 @@ impl<T: DescriptorTemplate> IntoWalletDescriptor for T {
|
|||||||
/// # use bdk::{Wallet};
|
/// # use bdk::{Wallet};
|
||||||
/// # use bdk::database::MemoryDatabase;
|
/// # use bdk::database::MemoryDatabase;
|
||||||
/// # use bdk::wallet::AddressIndex::New;
|
/// # use bdk::wallet::AddressIndex::New;
|
||||||
/// use bdk::template::P2PKH;
|
/// use bdk::template::P2Pkh;
|
||||||
///
|
///
|
||||||
/// let key =
|
/// let key =
|
||||||
/// bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
|
/// bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
|
||||||
/// let wallet = Wallet::new_offline(
|
/// let wallet = Wallet::new_offline(
|
||||||
/// P2PKH(key),
|
/// P2Pkh(key),
|
||||||
/// None,
|
/// None,
|
||||||
/// Network::Testnet,
|
/// Network::Testnet,
|
||||||
/// MemoryDatabase::default(),
|
/// MemoryDatabase::default(),
|
||||||
@ -92,9 +92,9 @@ impl<T: DescriptorTemplate> IntoWalletDescriptor for T {
|
|||||||
/// );
|
/// );
|
||||||
/// # Ok::<_, Box<dyn std::error::Error>>(())
|
/// # Ok::<_, Box<dyn std::error::Error>>(())
|
||||||
/// ```
|
/// ```
|
||||||
pub struct P2PKH<K: IntoDescriptorKey<Legacy>>(pub K);
|
pub struct P2Pkh<K: IntoDescriptorKey<Legacy>>(pub K);
|
||||||
|
|
||||||
impl<K: IntoDescriptorKey<Legacy>> DescriptorTemplate for P2PKH<K> {
|
impl<K: IntoDescriptorKey<Legacy>> DescriptorTemplate for P2Pkh<K> {
|
||||||
fn build(self) -> Result<DescriptorTemplateOut, DescriptorError> {
|
fn build(self) -> Result<DescriptorTemplateOut, DescriptorError> {
|
||||||
descriptor!(pkh(self.0))
|
descriptor!(pkh(self.0))
|
||||||
}
|
}
|
||||||
@ -109,12 +109,12 @@ impl<K: IntoDescriptorKey<Legacy>> DescriptorTemplate for P2PKH<K> {
|
|||||||
/// # use bdk::{Wallet};
|
/// # use bdk::{Wallet};
|
||||||
/// # use bdk::database::MemoryDatabase;
|
/// # use bdk::database::MemoryDatabase;
|
||||||
/// # use bdk::wallet::AddressIndex::New;
|
/// # use bdk::wallet::AddressIndex::New;
|
||||||
/// use bdk::template::P2WPKH_P2SH;
|
/// use bdk::template::P2Wpkh_P2Sh;
|
||||||
///
|
///
|
||||||
/// let key =
|
/// let key =
|
||||||
/// bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
|
/// bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
|
||||||
/// let wallet = Wallet::new_offline(
|
/// let wallet = Wallet::new_offline(
|
||||||
/// P2WPKH_P2SH(key),
|
/// P2Wpkh_P2Sh(key),
|
||||||
/// None,
|
/// None,
|
||||||
/// Network::Testnet,
|
/// Network::Testnet,
|
||||||
/// MemoryDatabase::default(),
|
/// MemoryDatabase::default(),
|
||||||
@ -127,9 +127,9 @@ impl<K: IntoDescriptorKey<Legacy>> DescriptorTemplate for P2PKH<K> {
|
|||||||
/// # Ok::<_, Box<dyn std::error::Error>>(())
|
/// # Ok::<_, Box<dyn std::error::Error>>(())
|
||||||
/// ```
|
/// ```
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
pub struct P2WPKH_P2SH<K: IntoDescriptorKey<Segwitv0>>(pub K);
|
pub struct P2Wpkh_P2Sh<K: IntoDescriptorKey<Segwitv0>>(pub K);
|
||||||
|
|
||||||
impl<K: IntoDescriptorKey<Segwitv0>> DescriptorTemplate for P2WPKH_P2SH<K> {
|
impl<K: IntoDescriptorKey<Segwitv0>> DescriptorTemplate for P2Wpkh_P2Sh<K> {
|
||||||
fn build(self) -> Result<DescriptorTemplateOut, DescriptorError> {
|
fn build(self) -> Result<DescriptorTemplateOut, DescriptorError> {
|
||||||
descriptor!(sh(wpkh(self.0)))
|
descriptor!(sh(wpkh(self.0)))
|
||||||
}
|
}
|
||||||
@ -144,12 +144,12 @@ impl<K: IntoDescriptorKey<Segwitv0>> DescriptorTemplate for P2WPKH_P2SH<K> {
|
|||||||
/// # use bdk::{Wallet};
|
/// # use bdk::{Wallet};
|
||||||
/// # use bdk::database::MemoryDatabase;
|
/// # use bdk::database::MemoryDatabase;
|
||||||
/// # use bdk::wallet::AddressIndex::New;
|
/// # use bdk::wallet::AddressIndex::New;
|
||||||
/// use bdk::template::P2WPKH;
|
/// use bdk::template::P2Wpkh;
|
||||||
///
|
///
|
||||||
/// let key =
|
/// let key =
|
||||||
/// bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
|
/// bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
|
||||||
/// let wallet = Wallet::new_offline(
|
/// let wallet = Wallet::new_offline(
|
||||||
/// P2WPKH(key),
|
/// P2Wpkh(key),
|
||||||
/// None,
|
/// None,
|
||||||
/// Network::Testnet,
|
/// Network::Testnet,
|
||||||
/// MemoryDatabase::default(),
|
/// MemoryDatabase::default(),
|
||||||
@ -161,9 +161,9 @@ impl<K: IntoDescriptorKey<Segwitv0>> DescriptorTemplate for P2WPKH_P2SH<K> {
|
|||||||
/// );
|
/// );
|
||||||
/// # Ok::<_, Box<dyn std::error::Error>>(())
|
/// # Ok::<_, Box<dyn std::error::Error>>(())
|
||||||
/// ```
|
/// ```
|
||||||
pub struct P2WPKH<K: IntoDescriptorKey<Segwitv0>>(pub K);
|
pub struct P2Wpkh<K: IntoDescriptorKey<Segwitv0>>(pub K);
|
||||||
|
|
||||||
impl<K: IntoDescriptorKey<Segwitv0>> DescriptorTemplate for P2WPKH<K> {
|
impl<K: IntoDescriptorKey<Segwitv0>> DescriptorTemplate for P2Wpkh<K> {
|
||||||
fn build(self) -> Result<DescriptorTemplateOut, DescriptorError> {
|
fn build(self) -> Result<DescriptorTemplateOut, DescriptorError> {
|
||||||
descriptor!(wpkh(self.0))
|
descriptor!(wpkh(self.0))
|
||||||
}
|
}
|
||||||
@ -173,7 +173,7 @@ impl<K: IntoDescriptorKey<Segwitv0>> DescriptorTemplate for P2WPKH<K> {
|
|||||||
///
|
///
|
||||||
/// Since there are hardened derivation steps, this template requires a private derivable key (generally a `xprv`/`tprv`).
|
/// Since there are hardened derivation steps, this template requires a private derivable key (generally a `xprv`/`tprv`).
|
||||||
///
|
///
|
||||||
/// See [`BIP44Public`] for a template that can work with a `xpub`/`tpub`.
|
/// See [`Bip44Public`] for a template that can work with a `xpub`/`tpub`.
|
||||||
///
|
///
|
||||||
/// ## Example
|
/// ## Example
|
||||||
///
|
///
|
||||||
@ -183,12 +183,12 @@ impl<K: IntoDescriptorKey<Segwitv0>> DescriptorTemplate for P2WPKH<K> {
|
|||||||
/// # use bdk::{Wallet, KeychainKind};
|
/// # use bdk::{Wallet, KeychainKind};
|
||||||
/// # use bdk::database::MemoryDatabase;
|
/// # use bdk::database::MemoryDatabase;
|
||||||
/// # use bdk::wallet::AddressIndex::New;
|
/// # use bdk::wallet::AddressIndex::New;
|
||||||
/// use bdk::template::BIP44;
|
/// use bdk::template::Bip44;
|
||||||
///
|
///
|
||||||
/// let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
|
/// let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
|
||||||
/// let wallet = Wallet::new_offline(
|
/// let wallet = Wallet::new_offline(
|
||||||
/// BIP44(key.clone(), KeychainKind::External),
|
/// Bip44(key.clone(), KeychainKind::External),
|
||||||
/// Some(BIP44(key, KeychainKind::Internal)),
|
/// Some(Bip44(key, KeychainKind::Internal)),
|
||||||
/// Network::Testnet,
|
/// Network::Testnet,
|
||||||
/// MemoryDatabase::default()
|
/// MemoryDatabase::default()
|
||||||
/// )?;
|
/// )?;
|
||||||
@ -197,11 +197,11 @@ impl<K: IntoDescriptorKey<Segwitv0>> DescriptorTemplate for P2WPKH<K> {
|
|||||||
/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "pkh([c55b303f/44'/0'/0']tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU/0/*)#xgaaevjx");
|
/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "pkh([c55b303f/44'/0'/0']tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU/0/*)#xgaaevjx");
|
||||||
/// # Ok::<_, Box<dyn std::error::Error>>(())
|
/// # Ok::<_, Box<dyn std::error::Error>>(())
|
||||||
/// ```
|
/// ```
|
||||||
pub struct BIP44<K: DerivableKey<Legacy>>(pub K, pub KeychainKind);
|
pub struct Bip44<K: DerivableKey<Legacy>>(pub K, pub KeychainKind);
|
||||||
|
|
||||||
impl<K: DerivableKey<Legacy>> DescriptorTemplate for BIP44<K> {
|
impl<K: DerivableKey<Legacy>> DescriptorTemplate for Bip44<K> {
|
||||||
fn build(self) -> Result<DescriptorTemplateOut, DescriptorError> {
|
fn build(self) -> Result<DescriptorTemplateOut, DescriptorError> {
|
||||||
P2PKH(legacy::make_bipxx_private(44, self.0, self.1)?).build()
|
P2Pkh(legacy::make_bipxx_private(44, self.0, self.1)?).build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,7 +211,7 @@ impl<K: DerivableKey<Legacy>> DescriptorTemplate for BIP44<K> {
|
|||||||
///
|
///
|
||||||
/// This template requires the parent fingerprint to populate correctly the metadata of PSBTs.
|
/// This template requires the parent fingerprint to populate correctly the metadata of PSBTs.
|
||||||
///
|
///
|
||||||
/// See [`BIP44`] for a template that does the full derivation, but requires private data
|
/// See [`Bip44`] for a template that does the full derivation, but requires private data
|
||||||
/// for the key.
|
/// for the key.
|
||||||
///
|
///
|
||||||
/// ## Example
|
/// ## Example
|
||||||
@ -222,13 +222,13 @@ impl<K: DerivableKey<Legacy>> DescriptorTemplate for BIP44<K> {
|
|||||||
/// # use bdk::{Wallet, KeychainKind};
|
/// # use bdk::{Wallet, KeychainKind};
|
||||||
/// # use bdk::database::MemoryDatabase;
|
/// # use bdk::database::MemoryDatabase;
|
||||||
/// # use bdk::wallet::AddressIndex::New;
|
/// # use bdk::wallet::AddressIndex::New;
|
||||||
/// use bdk::template::BIP44Public;
|
/// use bdk::template::Bip44Public;
|
||||||
///
|
///
|
||||||
/// let key = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU")?;
|
/// let key = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU")?;
|
||||||
/// let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?;
|
/// let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?;
|
||||||
/// let wallet = Wallet::new_offline(
|
/// let wallet = Wallet::new_offline(
|
||||||
/// BIP44Public(key.clone(), fingerprint, KeychainKind::External),
|
/// Bip44Public(key.clone(), fingerprint, KeychainKind::External),
|
||||||
/// Some(BIP44Public(key, fingerprint, KeychainKind::Internal)),
|
/// Some(Bip44Public(key, fingerprint, KeychainKind::Internal)),
|
||||||
/// Network::Testnet,
|
/// Network::Testnet,
|
||||||
/// MemoryDatabase::default()
|
/// MemoryDatabase::default()
|
||||||
/// )?;
|
/// )?;
|
||||||
@ -237,11 +237,11 @@ impl<K: DerivableKey<Legacy>> DescriptorTemplate for BIP44<K> {
|
|||||||
/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "pkh([c55b303f/44'/0'/0']tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU/0/*)#xgaaevjx");
|
/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "pkh([c55b303f/44'/0'/0']tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU/0/*)#xgaaevjx");
|
||||||
/// # Ok::<_, Box<dyn std::error::Error>>(())
|
/// # Ok::<_, Box<dyn std::error::Error>>(())
|
||||||
/// ```
|
/// ```
|
||||||
pub struct BIP44Public<K: DerivableKey<Legacy>>(pub K, pub bip32::Fingerprint, pub KeychainKind);
|
pub struct Bip44Public<K: DerivableKey<Legacy>>(pub K, pub bip32::Fingerprint, pub KeychainKind);
|
||||||
|
|
||||||
impl<K: DerivableKey<Legacy>> DescriptorTemplate for BIP44Public<K> {
|
impl<K: DerivableKey<Legacy>> DescriptorTemplate for Bip44Public<K> {
|
||||||
fn build(self) -> Result<DescriptorTemplateOut, DescriptorError> {
|
fn build(self) -> Result<DescriptorTemplateOut, DescriptorError> {
|
||||||
P2PKH(legacy::make_bipxx_public(44, self.0, self.1, self.2)?).build()
|
P2Pkh(legacy::make_bipxx_public(44, self.0, self.1, self.2)?).build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,7 +249,7 @@ impl<K: DerivableKey<Legacy>> DescriptorTemplate for BIP44Public<K> {
|
|||||||
///
|
///
|
||||||
/// Since there are hardened derivation steps, this template requires a private derivable key (generally a `xprv`/`tprv`).
|
/// Since there are hardened derivation steps, this template requires a private derivable key (generally a `xprv`/`tprv`).
|
||||||
///
|
///
|
||||||
/// See [`BIP49Public`] for a template that can work with a `xpub`/`tpub`.
|
/// See [`Bip49Public`] for a template that can work with a `xpub`/`tpub`.
|
||||||
///
|
///
|
||||||
/// ## Example
|
/// ## Example
|
||||||
///
|
///
|
||||||
@ -259,12 +259,12 @@ impl<K: DerivableKey<Legacy>> DescriptorTemplate for BIP44Public<K> {
|
|||||||
/// # use bdk::{Wallet, KeychainKind};
|
/// # use bdk::{Wallet, KeychainKind};
|
||||||
/// # use bdk::database::MemoryDatabase;
|
/// # use bdk::database::MemoryDatabase;
|
||||||
/// # use bdk::wallet::AddressIndex::New;
|
/// # use bdk::wallet::AddressIndex::New;
|
||||||
/// use bdk::template::BIP49;
|
/// use bdk::template::Bip49;
|
||||||
///
|
///
|
||||||
/// let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
|
/// let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
|
||||||
/// let wallet = Wallet::new_offline(
|
/// let wallet = Wallet::new_offline(
|
||||||
/// BIP49(key.clone(), KeychainKind::External),
|
/// Bip49(key.clone(), KeychainKind::External),
|
||||||
/// Some(BIP49(key, KeychainKind::Internal)),
|
/// Some(Bip49(key, KeychainKind::Internal)),
|
||||||
/// Network::Testnet,
|
/// Network::Testnet,
|
||||||
/// MemoryDatabase::default()
|
/// MemoryDatabase::default()
|
||||||
/// )?;
|
/// )?;
|
||||||
@ -273,11 +273,11 @@ impl<K: DerivableKey<Legacy>> DescriptorTemplate for BIP44Public<K> {
|
|||||||
/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "sh(wpkh([c55b303f/49\'/0\'/0\']tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L/0/*))#gsmdv4xr");
|
/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "sh(wpkh([c55b303f/49\'/0\'/0\']tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L/0/*))#gsmdv4xr");
|
||||||
/// # Ok::<_, Box<dyn std::error::Error>>(())
|
/// # Ok::<_, Box<dyn std::error::Error>>(())
|
||||||
/// ```
|
/// ```
|
||||||
pub struct BIP49<K: DerivableKey<Segwitv0>>(pub K, pub KeychainKind);
|
pub struct Bip49<K: DerivableKey<Segwitv0>>(pub K, pub KeychainKind);
|
||||||
|
|
||||||
impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for BIP49<K> {
|
impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip49<K> {
|
||||||
fn build(self) -> Result<DescriptorTemplateOut, DescriptorError> {
|
fn build(self) -> Result<DescriptorTemplateOut, DescriptorError> {
|
||||||
P2WPKH_P2SH(segwit_v0::make_bipxx_private(49, self.0, self.1)?).build()
|
P2Wpkh_P2Sh(segwit_v0::make_bipxx_private(49, self.0, self.1)?).build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,7 +287,7 @@ impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for BIP49<K> {
|
|||||||
///
|
///
|
||||||
/// This template requires the parent fingerprint to populate correctly the metadata of PSBTs.
|
/// This template requires the parent fingerprint to populate correctly the metadata of PSBTs.
|
||||||
///
|
///
|
||||||
/// See [`BIP49`] for a template that does the full derivation, but requires private data
|
/// See [`Bip49`] for a template that does the full derivation, but requires private data
|
||||||
/// for the key.
|
/// for the key.
|
||||||
///
|
///
|
||||||
/// ## Example
|
/// ## Example
|
||||||
@ -298,13 +298,13 @@ impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for BIP49<K> {
|
|||||||
/// # use bdk::{Wallet, KeychainKind};
|
/// # use bdk::{Wallet, KeychainKind};
|
||||||
/// # use bdk::database::MemoryDatabase;
|
/// # use bdk::database::MemoryDatabase;
|
||||||
/// # use bdk::wallet::AddressIndex::New;
|
/// # use bdk::wallet::AddressIndex::New;
|
||||||
/// use bdk::template::BIP49Public;
|
/// use bdk::template::Bip49Public;
|
||||||
///
|
///
|
||||||
/// let key = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L")?;
|
/// let key = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L")?;
|
||||||
/// let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?;
|
/// let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?;
|
||||||
/// let wallet = Wallet::new_offline(
|
/// let wallet = Wallet::new_offline(
|
||||||
/// BIP49Public(key.clone(), fingerprint, KeychainKind::External),
|
/// Bip49Public(key.clone(), fingerprint, KeychainKind::External),
|
||||||
/// Some(BIP49Public(key, fingerprint, KeychainKind::Internal)),
|
/// Some(Bip49Public(key, fingerprint, KeychainKind::Internal)),
|
||||||
/// Network::Testnet,
|
/// Network::Testnet,
|
||||||
/// MemoryDatabase::default()
|
/// MemoryDatabase::default()
|
||||||
/// )?;
|
/// )?;
|
||||||
@ -313,11 +313,11 @@ impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for BIP49<K> {
|
|||||||
/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "sh(wpkh([c55b303f/49\'/0\'/0\']tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L/0/*))#gsmdv4xr");
|
/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "sh(wpkh([c55b303f/49\'/0\'/0\']tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L/0/*))#gsmdv4xr");
|
||||||
/// # Ok::<_, Box<dyn std::error::Error>>(())
|
/// # Ok::<_, Box<dyn std::error::Error>>(())
|
||||||
/// ```
|
/// ```
|
||||||
pub struct BIP49Public<K: DerivableKey<Segwitv0>>(pub K, pub bip32::Fingerprint, pub KeychainKind);
|
pub struct Bip49Public<K: DerivableKey<Segwitv0>>(pub K, pub bip32::Fingerprint, pub KeychainKind);
|
||||||
|
|
||||||
impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for BIP49Public<K> {
|
impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip49Public<K> {
|
||||||
fn build(self) -> Result<DescriptorTemplateOut, DescriptorError> {
|
fn build(self) -> Result<DescriptorTemplateOut, DescriptorError> {
|
||||||
P2WPKH_P2SH(segwit_v0::make_bipxx_public(49, self.0, self.1, self.2)?).build()
|
P2Wpkh_P2Sh(segwit_v0::make_bipxx_public(49, self.0, self.1, self.2)?).build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -325,7 +325,7 @@ impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for BIP49Public<K> {
|
|||||||
///
|
///
|
||||||
/// Since there are hardened derivation steps, this template requires a private derivable key (generally a `xprv`/`tprv`).
|
/// Since there are hardened derivation steps, this template requires a private derivable key (generally a `xprv`/`tprv`).
|
||||||
///
|
///
|
||||||
/// See [`BIP84Public`] for a template that can work with a `xpub`/`tpub`.
|
/// See [`Bip84Public`] for a template that can work with a `xpub`/`tpub`.
|
||||||
///
|
///
|
||||||
/// ## Example
|
/// ## Example
|
||||||
///
|
///
|
||||||
@ -335,12 +335,12 @@ impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for BIP49Public<K> {
|
|||||||
/// # use bdk::{Wallet, KeychainKind};
|
/// # use bdk::{Wallet, KeychainKind};
|
||||||
/// # use bdk::database::MemoryDatabase;
|
/// # use bdk::database::MemoryDatabase;
|
||||||
/// # use bdk::wallet::AddressIndex::New;
|
/// # use bdk::wallet::AddressIndex::New;
|
||||||
/// use bdk::template::BIP84;
|
/// use bdk::template::Bip84;
|
||||||
///
|
///
|
||||||
/// let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
|
/// let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
|
||||||
/// let wallet = Wallet::new_offline(
|
/// let wallet = Wallet::new_offline(
|
||||||
/// BIP84(key.clone(), KeychainKind::External),
|
/// Bip84(key.clone(), KeychainKind::External),
|
||||||
/// Some(BIP84(key, KeychainKind::Internal)),
|
/// Some(Bip84(key, KeychainKind::Internal)),
|
||||||
/// Network::Testnet,
|
/// Network::Testnet,
|
||||||
/// MemoryDatabase::default()
|
/// MemoryDatabase::default()
|
||||||
/// )?;
|
/// )?;
|
||||||
@ -349,11 +349,11 @@ impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for BIP49Public<K> {
|
|||||||
/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "wpkh([c55b303f/84\'/0\'/0\']tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q/0/*)#nkk5dtkg");
|
/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "wpkh([c55b303f/84\'/0\'/0\']tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q/0/*)#nkk5dtkg");
|
||||||
/// # Ok::<_, Box<dyn std::error::Error>>(())
|
/// # Ok::<_, Box<dyn std::error::Error>>(())
|
||||||
/// ```
|
/// ```
|
||||||
pub struct BIP84<K: DerivableKey<Segwitv0>>(pub K, pub KeychainKind);
|
pub struct Bip84<K: DerivableKey<Segwitv0>>(pub K, pub KeychainKind);
|
||||||
|
|
||||||
impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for BIP84<K> {
|
impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip84<K> {
|
||||||
fn build(self) -> Result<DescriptorTemplateOut, DescriptorError> {
|
fn build(self) -> Result<DescriptorTemplateOut, DescriptorError> {
|
||||||
P2WPKH(segwit_v0::make_bipxx_private(84, self.0, self.1)?).build()
|
P2Wpkh(segwit_v0::make_bipxx_private(84, self.0, self.1)?).build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -363,7 +363,7 @@ impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for BIP84<K> {
|
|||||||
///
|
///
|
||||||
/// This template requires the parent fingerprint to populate correctly the metadata of PSBTs.
|
/// This template requires the parent fingerprint to populate correctly the metadata of PSBTs.
|
||||||
///
|
///
|
||||||
/// See [`BIP84`] for a template that does the full derivation, but requires private data
|
/// See [`Bip84`] for a template that does the full derivation, but requires private data
|
||||||
/// for the key.
|
/// for the key.
|
||||||
///
|
///
|
||||||
/// ## Example
|
/// ## Example
|
||||||
@ -374,13 +374,13 @@ impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for BIP84<K> {
|
|||||||
/// # use bdk::{Wallet, KeychainKind};
|
/// # use bdk::{Wallet, KeychainKind};
|
||||||
/// # use bdk::database::MemoryDatabase;
|
/// # use bdk::database::MemoryDatabase;
|
||||||
/// # use bdk::wallet::AddressIndex::New;
|
/// # use bdk::wallet::AddressIndex::New;
|
||||||
/// use bdk::template::BIP84Public;
|
/// use bdk::template::Bip84Public;
|
||||||
///
|
///
|
||||||
/// let key = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q")?;
|
/// let key = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q")?;
|
||||||
/// let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?;
|
/// let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?;
|
||||||
/// let wallet = Wallet::new_offline(
|
/// let wallet = Wallet::new_offline(
|
||||||
/// BIP84Public(key.clone(), fingerprint, KeychainKind::External),
|
/// Bip84Public(key.clone(), fingerprint, KeychainKind::External),
|
||||||
/// Some(BIP84Public(key, fingerprint, KeychainKind::Internal)),
|
/// Some(Bip84Public(key, fingerprint, KeychainKind::Internal)),
|
||||||
/// Network::Testnet,
|
/// Network::Testnet,
|
||||||
/// MemoryDatabase::default()
|
/// MemoryDatabase::default()
|
||||||
/// )?;
|
/// )?;
|
||||||
@ -389,11 +389,11 @@ impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for BIP84<K> {
|
|||||||
/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "wpkh([c55b303f/84\'/0\'/0\']tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q/0/*)#nkk5dtkg");
|
/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "wpkh([c55b303f/84\'/0\'/0\']tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q/0/*)#nkk5dtkg");
|
||||||
/// # Ok::<_, Box<dyn std::error::Error>>(())
|
/// # Ok::<_, Box<dyn std::error::Error>>(())
|
||||||
/// ```
|
/// ```
|
||||||
pub struct BIP84Public<K: DerivableKey<Segwitv0>>(pub K, pub bip32::Fingerprint, pub KeychainKind);
|
pub struct Bip84Public<K: DerivableKey<Segwitv0>>(pub K, pub bip32::Fingerprint, pub KeychainKind);
|
||||||
|
|
||||||
impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for BIP84Public<K> {
|
impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip84Public<K> {
|
||||||
fn build(self) -> Result<DescriptorTemplateOut, DescriptorError> {
|
fn build(self) -> Result<DescriptorTemplateOut, DescriptorError> {
|
||||||
P2WPKH(segwit_v0::make_bipxx_public(84, self.0, self.1, self.2)?).build()
|
P2Wpkh(segwit_v0::make_bipxx_public(84, self.0, self.1, self.2)?).build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -496,7 +496,7 @@ mod test {
|
|||||||
bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")
|
bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
check(
|
check(
|
||||||
P2PKH(prvkey).build(),
|
P2Pkh(prvkey).build(),
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
&["mwJ8hxFYW19JLuc65RCTaP4v1rzVU8cVMT"],
|
&["mwJ8hxFYW19JLuc65RCTaP4v1rzVU8cVMT"],
|
||||||
@ -507,7 +507,7 @@ mod test {
|
|||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
check(
|
check(
|
||||||
P2PKH(pubkey).build(),
|
P2Pkh(pubkey).build(),
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
&["muZpTpBYhxmRFuCjLc7C6BBDF32C8XVJUi"],
|
&["muZpTpBYhxmRFuCjLc7C6BBDF32C8XVJUi"],
|
||||||
@ -521,7 +521,7 @@ mod test {
|
|||||||
bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")
|
bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
check(
|
check(
|
||||||
P2WPKH_P2SH(prvkey).build(),
|
P2Wpkh_P2Sh(prvkey).build(),
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
&["2NB4ox5VDRw1ecUv6SnT3VQHPXveYztRqk5"],
|
&["2NB4ox5VDRw1ecUv6SnT3VQHPXveYztRqk5"],
|
||||||
@ -532,7 +532,7 @@ mod test {
|
|||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
check(
|
check(
|
||||||
P2WPKH_P2SH(pubkey).build(),
|
P2Wpkh_P2Sh(pubkey).build(),
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
&["2N5LiC3CqzxDamRTPG1kiNv1FpNJQ7x28sb"],
|
&["2N5LiC3CqzxDamRTPG1kiNv1FpNJQ7x28sb"],
|
||||||
@ -546,7 +546,7 @@ mod test {
|
|||||||
bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")
|
bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
check(
|
check(
|
||||||
P2WPKH(prvkey).build(),
|
P2Wpkh(prvkey).build(),
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
&["bcrt1q4525hmgw265tl3drrl8jjta7ayffu6jfcwxx9y"],
|
&["bcrt1q4525hmgw265tl3drrl8jjta7ayffu6jfcwxx9y"],
|
||||||
@ -557,7 +557,7 @@ mod test {
|
|||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
check(
|
check(
|
||||||
P2WPKH(pubkey).build(),
|
P2Wpkh(pubkey).build(),
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
&["bcrt1qngw83fg8dz0k749cg7k3emc7v98wy0c7azaa6h"],
|
&["bcrt1qngw83fg8dz0k749cg7k3emc7v98wy0c7azaa6h"],
|
||||||
@ -569,7 +569,7 @@ mod test {
|
|||||||
fn test_bip44_template() {
|
fn test_bip44_template() {
|
||||||
let prvkey = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
|
let prvkey = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
|
||||||
check(
|
check(
|
||||||
BIP44(prvkey, KeychainKind::External).build(),
|
Bip44(prvkey, KeychainKind::External).build(),
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
&[
|
&[
|
||||||
@ -579,7 +579,7 @@ mod test {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
check(
|
check(
|
||||||
BIP44(prvkey, KeychainKind::Internal).build(),
|
Bip44(prvkey, KeychainKind::Internal).build(),
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
&[
|
&[
|
||||||
@ -596,7 +596,7 @@ mod test {
|
|||||||
let pubkey = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU").unwrap();
|
let pubkey = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU").unwrap();
|
||||||
let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f").unwrap();
|
let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f").unwrap();
|
||||||
check(
|
check(
|
||||||
BIP44Public(pubkey, fingerprint, KeychainKind::External).build(),
|
Bip44Public(pubkey, fingerprint, KeychainKind::External).build(),
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
&[
|
&[
|
||||||
@ -606,7 +606,7 @@ mod test {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
check(
|
check(
|
||||||
BIP44Public(pubkey, fingerprint, KeychainKind::Internal).build(),
|
Bip44Public(pubkey, fingerprint, KeychainKind::Internal).build(),
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
&[
|
&[
|
||||||
@ -622,7 +622,7 @@ mod test {
|
|||||||
fn test_bip49_template() {
|
fn test_bip49_template() {
|
||||||
let prvkey = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
|
let prvkey = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
|
||||||
check(
|
check(
|
||||||
BIP49(prvkey, KeychainKind::External).build(),
|
Bip49(prvkey, KeychainKind::External).build(),
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
&[
|
&[
|
||||||
@ -632,7 +632,7 @@ mod test {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
check(
|
check(
|
||||||
BIP49(prvkey, KeychainKind::Internal).build(),
|
Bip49(prvkey, KeychainKind::Internal).build(),
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
&[
|
&[
|
||||||
@ -649,7 +649,7 @@ mod test {
|
|||||||
let pubkey = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L").unwrap();
|
let pubkey = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L").unwrap();
|
||||||
let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f").unwrap();
|
let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f").unwrap();
|
||||||
check(
|
check(
|
||||||
BIP49Public(pubkey, fingerprint, KeychainKind::External).build(),
|
Bip49Public(pubkey, fingerprint, KeychainKind::External).build(),
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
&[
|
&[
|
||||||
@ -659,7 +659,7 @@ mod test {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
check(
|
check(
|
||||||
BIP49Public(pubkey, fingerprint, KeychainKind::Internal).build(),
|
Bip49Public(pubkey, fingerprint, KeychainKind::Internal).build(),
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
&[
|
&[
|
||||||
@ -675,7 +675,7 @@ mod test {
|
|||||||
fn test_bip84_template() {
|
fn test_bip84_template() {
|
||||||
let prvkey = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
|
let prvkey = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
|
||||||
check(
|
check(
|
||||||
BIP84(prvkey, KeychainKind::External).build(),
|
Bip84(prvkey, KeychainKind::External).build(),
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
&[
|
&[
|
||||||
@ -685,7 +685,7 @@ mod test {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
check(
|
check(
|
||||||
BIP84(prvkey, KeychainKind::Internal).build(),
|
Bip84(prvkey, KeychainKind::Internal).build(),
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
&[
|
&[
|
||||||
@ -702,7 +702,7 @@ mod test {
|
|||||||
let pubkey = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q").unwrap();
|
let pubkey = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q").unwrap();
|
||||||
let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f").unwrap();
|
let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f").unwrap();
|
||||||
check(
|
check(
|
||||||
BIP84Public(pubkey, fingerprint, KeychainKind::External).build(),
|
Bip84Public(pubkey, fingerprint, KeychainKind::External).build(),
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
&[
|
&[
|
||||||
@ -712,7 +712,7 @@ mod test {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
check(
|
check(
|
||||||
BIP84Public(pubkey, fingerprint, KeychainKind::Internal).build(),
|
Bip84Public(pubkey, fingerprint, KeychainKind::Internal).build(),
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
&[
|
&[
|
||||||
|
16
src/error.rs
16
src/error.rs
@ -47,7 +47,7 @@ pub enum Error {
|
|||||||
/// the desired outputs plus fee, if there is not such combination this error is thrown
|
/// the desired outputs plus fee, if there is not such combination this error is thrown
|
||||||
BnBNoExactMatch,
|
BnBNoExactMatch,
|
||||||
/// Happens when trying to spend an UTXO that is not in the internal database
|
/// Happens when trying to spend an UTXO that is not in the internal database
|
||||||
UnknownUTXO,
|
UnknownUtxo,
|
||||||
/// Thrown when a tx is not found in the internal database
|
/// Thrown when a tx is not found in the internal database
|
||||||
TransactionNotFound,
|
TransactionNotFound,
|
||||||
/// Happens when trying to bump a transaction that is already confirmed
|
/// Happens when trying to bump a transaction that is already confirmed
|
||||||
@ -97,15 +97,15 @@ pub enum Error {
|
|||||||
/// Miniscript error
|
/// Miniscript error
|
||||||
Miniscript(miniscript::Error),
|
Miniscript(miniscript::Error),
|
||||||
/// BIP32 error
|
/// BIP32 error
|
||||||
BIP32(bitcoin::util::bip32::Error),
|
Bip32(bitcoin::util::bip32::Error),
|
||||||
/// An ECDSA error
|
/// An ECDSA error
|
||||||
Secp256k1(bitcoin::secp256k1::Error),
|
Secp256k1(bitcoin::secp256k1::Error),
|
||||||
/// Error serializing or deserializing JSON data
|
/// Error serializing or deserializing JSON data
|
||||||
JSON(serde_json::Error),
|
Json(serde_json::Error),
|
||||||
/// Hex decoding error
|
/// Hex decoding error
|
||||||
Hex(bitcoin::hashes::hex::Error),
|
Hex(bitcoin::hashes::hex::Error),
|
||||||
/// Partially signed bitcoin transaction error
|
/// Partially signed bitcoin transaction error
|
||||||
PSBT(bitcoin::util::psbt::Error),
|
Psbt(bitcoin::util::psbt::Error),
|
||||||
|
|
||||||
//KeyMismatch(bitcoin::secp256k1::PublicKey, bitcoin::secp256k1::PublicKey),
|
//KeyMismatch(bitcoin::secp256k1::PublicKey, bitcoin::secp256k1::PublicKey),
|
||||||
//MissingInputUTXO(usize),
|
//MissingInputUTXO(usize),
|
||||||
@ -158,7 +158,7 @@ impl From<crate::keys::KeyError> for Error {
|
|||||||
fn from(key_error: crate::keys::KeyError) -> Error {
|
fn from(key_error: crate::keys::KeyError) -> Error {
|
||||||
match key_error {
|
match key_error {
|
||||||
crate::keys::KeyError::Miniscript(inner) => Error::Miniscript(inner),
|
crate::keys::KeyError::Miniscript(inner) => Error::Miniscript(inner),
|
||||||
crate::keys::KeyError::BIP32(inner) => Error::BIP32(inner),
|
crate::keys::KeyError::Bip32(inner) => Error::Bip32(inner),
|
||||||
crate::keys::KeyError::InvalidChecksum => Error::ChecksumMismatch,
|
crate::keys::KeyError::InvalidChecksum => Error::ChecksumMismatch,
|
||||||
e => Error::Key(e),
|
e => Error::Key(e),
|
||||||
}
|
}
|
||||||
@ -167,11 +167,11 @@ impl From<crate::keys::KeyError> for Error {
|
|||||||
|
|
||||||
impl_error!(bitcoin::consensus::encode::Error, Encode);
|
impl_error!(bitcoin::consensus::encode::Error, Encode);
|
||||||
impl_error!(miniscript::Error, Miniscript);
|
impl_error!(miniscript::Error, Miniscript);
|
||||||
impl_error!(bitcoin::util::bip32::Error, BIP32);
|
impl_error!(bitcoin::util::bip32::Error, Bip32);
|
||||||
impl_error!(bitcoin::secp256k1::Error, Secp256k1);
|
impl_error!(bitcoin::secp256k1::Error, Secp256k1);
|
||||||
impl_error!(serde_json::Error, JSON);
|
impl_error!(serde_json::Error, Json);
|
||||||
impl_error!(bitcoin::hashes::hex::Error, Hex);
|
impl_error!(bitcoin::hashes::hex::Error, Hex);
|
||||||
impl_error!(bitcoin::util::psbt::Error, PSBT);
|
impl_error!(bitcoin::util::psbt::Error, Psbt);
|
||||||
|
|
||||||
#[cfg(feature = "electrum")]
|
#[cfg(feature = "electrum")]
|
||||||
impl_error!(electrum_client::Error, Electrum);
|
impl_error!(electrum_client::Error, Electrum);
|
||||||
|
@ -873,13 +873,13 @@ pub enum KeyError {
|
|||||||
Message(String),
|
Message(String),
|
||||||
|
|
||||||
/// BIP32 error
|
/// BIP32 error
|
||||||
BIP32(bitcoin::util::bip32::Error),
|
Bip32(bitcoin::util::bip32::Error),
|
||||||
/// Miniscript error
|
/// Miniscript error
|
||||||
Miniscript(miniscript::Error),
|
Miniscript(miniscript::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_error!(miniscript::Error, Miniscript, KeyError);
|
impl_error!(miniscript::Error, Miniscript, KeyError);
|
||||||
impl_error!(bitcoin::util::bip32::Error, BIP32, KeyError);
|
impl_error!(bitcoin::util::bip32::Error, Bip32, KeyError);
|
||||||
|
|
||||||
impl std::fmt::Display for KeyError {
|
impl std::fmt::Display for KeyError {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
@ -251,7 +251,7 @@ pub(crate) mod types;
|
|||||||
pub mod wallet;
|
pub mod wallet;
|
||||||
|
|
||||||
pub use descriptor::template;
|
pub use descriptor::template;
|
||||||
pub use descriptor::HDKeyPaths;
|
pub use descriptor::HdKeyPaths;
|
||||||
pub use error::Error;
|
pub use error::Error;
|
||||||
pub use types::*;
|
pub use types::*;
|
||||||
pub use wallet::address_validator;
|
pub use wallet::address_validator;
|
||||||
|
@ -12,11 +12,11 @@
|
|||||||
use bitcoin::util::psbt::PartiallySignedTransaction as PSBT;
|
use bitcoin::util::psbt::PartiallySignedTransaction as PSBT;
|
||||||
use bitcoin::TxOut;
|
use bitcoin::TxOut;
|
||||||
|
|
||||||
pub trait PSBTUtils {
|
pub trait PsbtUtils {
|
||||||
fn get_utxo_for(&self, input_index: usize) -> Option<TxOut>;
|
fn get_utxo_for(&self, input_index: usize) -> Option<TxOut>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PSBTUtils for PSBT {
|
impl PsbtUtils for PSBT {
|
||||||
fn get_utxo_for(&self, input_index: usize) -> Option<TxOut> {
|
fn get_utxo_for(&self, input_index: usize) -> Option<TxOut> {
|
||||||
let tx = &self.global.unsigned_tx;
|
let tx = &self.global.unsigned_tx;
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
//! fn validate(
|
//! fn validate(
|
||||||
//! &self,
|
//! &self,
|
||||||
//! keychain: KeychainKind,
|
//! keychain: KeychainKind,
|
||||||
//! hd_keypaths: &HDKeyPaths,
|
//! hd_keypaths: &HdKeyPaths,
|
||||||
//! script: &Script
|
//! script: &Script
|
||||||
//! ) -> Result<(), AddressValidatorError> {
|
//! ) -> Result<(), AddressValidatorError> {
|
||||||
//! let address = Address::from_script(script, Network::Testnet)
|
//! let address = Address::from_script(script, Network::Testnet)
|
||||||
@ -67,7 +67,7 @@ use std::fmt;
|
|||||||
|
|
||||||
use bitcoin::Script;
|
use bitcoin::Script;
|
||||||
|
|
||||||
use crate::descriptor::HDKeyPaths;
|
use crate::descriptor::HdKeyPaths;
|
||||||
use crate::types::KeychainKind;
|
use crate::types::KeychainKind;
|
||||||
|
|
||||||
/// Errors that can be returned to fail the validation of an address
|
/// Errors that can be returned to fail the validation of an address
|
||||||
@ -105,7 +105,7 @@ pub trait AddressValidator: Send + Sync + fmt::Debug {
|
|||||||
fn validate(
|
fn validate(
|
||||||
&self,
|
&self,
|
||||||
keychain: KeychainKind,
|
keychain: KeychainKind,
|
||||||
hd_keypaths: &HDKeyPaths,
|
hd_keypaths: &HdKeyPaths,
|
||||||
script: &Script,
|
script: &Script,
|
||||||
) -> Result<(), AddressValidatorError>;
|
) -> Result<(), AddressValidatorError>;
|
||||||
}
|
}
|
||||||
@ -124,7 +124,7 @@ mod test {
|
|||||||
fn validate(
|
fn validate(
|
||||||
&self,
|
&self,
|
||||||
_keychain: KeychainKind,
|
_keychain: KeychainKind,
|
||||||
_hd_keypaths: &HDKeyPaths,
|
_hd_keypaths: &HdKeyPaths,
|
||||||
_script: &bitcoin::Script,
|
_script: &bitcoin::Script,
|
||||||
) -> Result<(), AddressValidatorError> {
|
) -> Result<(), AddressValidatorError> {
|
||||||
Err(AddressValidatorError::InvalidScript)
|
Err(AddressValidatorError::InvalidScript)
|
||||||
|
@ -59,7 +59,7 @@ use crate::descriptor::{
|
|||||||
Policy, XKeyUtils,
|
Policy, XKeyUtils,
|
||||||
};
|
};
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::psbt::PSBTUtils;
|
use crate::psbt::PsbtUtils;
|
||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
|
|
||||||
const CACHE_ADDR_BATCH_SIZE: u32 = 100;
|
const CACHE_ADDR_BATCH_SIZE: u32 = 100;
|
||||||
@ -465,13 +465,13 @@ where
|
|||||||
(None, Some(csv)) => csv,
|
(None, Some(csv)) => csv,
|
||||||
|
|
||||||
// RBF with a specific value but that value is too high
|
// RBF with a specific value but that value is too high
|
||||||
(Some(tx_builder::RBFValue::Value(rbf)), _) if rbf >= 0xFFFFFFFE => {
|
(Some(tx_builder::RbfValue::Value(rbf)), _) if rbf >= 0xFFFFFFFE => {
|
||||||
return Err(Error::Generic(
|
return Err(Error::Generic(
|
||||||
"Cannot enable RBF with a nSequence >= 0xFFFFFFFE".into(),
|
"Cannot enable RBF with a nSequence >= 0xFFFFFFFE".into(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
// RBF with a specific value requested, but the value is incompatible with CSV
|
// RBF with a specific value requested, but the value is incompatible with CSV
|
||||||
(Some(tx_builder::RBFValue::Value(rbf)), Some(csv))
|
(Some(tx_builder::RbfValue::Value(rbf)), Some(csv))
|
||||||
if !check_nsequence_rbf(rbf, csv) =>
|
if !check_nsequence_rbf(rbf, csv) =>
|
||||||
{
|
{
|
||||||
return Err(Error::Generic(format!(
|
return Err(Error::Generic(format!(
|
||||||
@ -481,7 +481,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RBF enabled with the default value with CSV also enabled. CSV takes precedence
|
// RBF enabled with the default value with CSV also enabled. CSV takes precedence
|
||||||
(Some(tx_builder::RBFValue::Default), Some(csv)) => csv,
|
(Some(tx_builder::RbfValue::Default), Some(csv)) => csv,
|
||||||
// Valid RBF, either default or with a specific value. We ignore the `CSV` value
|
// Valid RBF, either default or with a specific value. We ignore the `CSV` value
|
||||||
// because we've already checked it before
|
// because we've already checked it before
|
||||||
(Some(rbf), _) => rbf.get_value(),
|
(Some(rbf), _) => rbf.get_value(),
|
||||||
@ -750,7 +750,7 @@ where
|
|||||||
.database
|
.database
|
||||||
.borrow()
|
.borrow()
|
||||||
.get_previous_output(&txin.previous_output)?
|
.get_previous_output(&txin.previous_output)?
|
||||||
.ok_or(Error::UnknownUTXO)?;
|
.ok_or(Error::UnknownUtxo)?;
|
||||||
|
|
||||||
let (weight, keychain) = match self
|
let (weight, keychain) = match self
|
||||||
.database
|
.database
|
||||||
@ -1260,7 +1260,7 @@ where
|
|||||||
) {
|
) {
|
||||||
Ok(psbt_input) => psbt_input,
|
Ok(psbt_input) => psbt_input,
|
||||||
Err(e) => match e {
|
Err(e) => match e {
|
||||||
Error::UnknownUTXO => Input {
|
Error::UnknownUtxo => Input {
|
||||||
sighash_type: params.sighash,
|
sighash_type: params.sighash,
|
||||||
..Input::default()
|
..Input::default()
|
||||||
},
|
},
|
||||||
@ -1326,7 +1326,7 @@ where
|
|||||||
.database
|
.database
|
||||||
.borrow()
|
.borrow()
|
||||||
.get_path_from_script_pubkey(&utxo.txout.script_pubkey)?
|
.get_path_from_script_pubkey(&utxo.txout.script_pubkey)?
|
||||||
.ok_or(Error::UnknownUTXO)?;
|
.ok_or(Error::UnknownUtxo)?;
|
||||||
|
|
||||||
let mut psbt_input = Input {
|
let mut psbt_input = Input {
|
||||||
sighash_type,
|
sighash_type,
|
||||||
@ -2047,7 +2047,7 @@ mod test {
|
|||||||
builder
|
builder
|
||||||
.add_recipient(addr.script_pubkey(), 30_000)
|
.add_recipient(addr.script_pubkey(), 30_000)
|
||||||
.add_recipient(addr.script_pubkey(), 10_000)
|
.add_recipient(addr.script_pubkey(), 10_000)
|
||||||
.ordering(super::tx_builder::TxOrdering::BIP69Lexicographic);
|
.ordering(super::tx_builder::TxOrdering::Bip69Lexicographic);
|
||||||
let (psbt, details) = builder.finish().unwrap();
|
let (psbt, details) = builder.finish().unwrap();
|
||||||
|
|
||||||
assert_eq!(psbt.global.unsigned_tx.output.len(), 3);
|
assert_eq!(psbt.global.unsigned_tx.output.len(), 3);
|
||||||
|
@ -146,7 +146,7 @@ pub enum SignerError {
|
|||||||
/// The `witness_script` field of the transaction is requied to sign this input
|
/// The `witness_script` field of the transaction is requied to sign this input
|
||||||
MissingWitnessScript,
|
MissingWitnessScript,
|
||||||
/// The fingerprint and derivation path are missing from the psbt input
|
/// The fingerprint and derivation path are missing from the psbt input
|
||||||
MissingHDKeypath,
|
MissingHdKeypath,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for SignerError {
|
impl fmt::Display for SignerError {
|
||||||
|
@ -143,7 +143,7 @@ pub(crate) struct TxParams {
|
|||||||
pub(crate) sighash: Option<SigHashType>,
|
pub(crate) sighash: Option<SigHashType>,
|
||||||
pub(crate) ordering: TxOrdering,
|
pub(crate) ordering: TxOrdering,
|
||||||
pub(crate) locktime: Option<u32>,
|
pub(crate) locktime: Option<u32>,
|
||||||
pub(crate) rbf: Option<RBFValue>,
|
pub(crate) rbf: Option<RbfValue>,
|
||||||
pub(crate) version: Option<Version>,
|
pub(crate) version: Option<Version>,
|
||||||
pub(crate) change_policy: ChangeSpendPolicy,
|
pub(crate) change_policy: ChangeSpendPolicy,
|
||||||
pub(crate) force_non_witness_utxo: bool,
|
pub(crate) force_non_witness_utxo: bool,
|
||||||
@ -278,7 +278,7 @@ impl<'a, B, D: BatchDatabase, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderConte
|
|||||||
pub fn add_utxos(&mut self, outpoints: &[OutPoint]) -> Result<&mut Self, Error> {
|
pub fn add_utxos(&mut self, outpoints: &[OutPoint]) -> Result<&mut Self, Error> {
|
||||||
let utxos = outpoints
|
let utxos = outpoints
|
||||||
.iter()
|
.iter()
|
||||||
.map(|outpoint| self.wallet.get_utxo(*outpoint)?.ok_or(Error::UnknownUTXO))
|
.map(|outpoint| self.wallet.get_utxo(*outpoint)?.ok_or(Error::UnknownUtxo))
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
for utxo in utxos {
|
for utxo in utxos {
|
||||||
@ -563,7 +563,7 @@ impl<'a, B, D: BatchDatabase, Cs: CoinSelectionAlgorithm<D>> TxBuilder<'a, B, D,
|
|||||||
///
|
///
|
||||||
/// This will use the default nSequence value of `0xFFFFFFFD`.
|
/// This will use the default nSequence value of `0xFFFFFFFD`.
|
||||||
pub fn enable_rbf(&mut self) -> &mut Self {
|
pub fn enable_rbf(&mut self) -> &mut Self {
|
||||||
self.params.rbf = Some(RBFValue::Default);
|
self.params.rbf = Some(RbfValue::Default);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -575,7 +575,7 @@ impl<'a, B, D: BatchDatabase, Cs: CoinSelectionAlgorithm<D>> TxBuilder<'a, B, D,
|
|||||||
/// If the `nsequence` is higher than `0xFFFFFFFD` an error will be thrown, since it would not
|
/// If the `nsequence` is higher than `0xFFFFFFFD` an error will be thrown, since it would not
|
||||||
/// be a valid nSequence to signal RBF.
|
/// be a valid nSequence to signal RBF.
|
||||||
pub fn enable_rbf_with_sequence(&mut self, nsequence: u32) -> &mut Self {
|
pub fn enable_rbf_with_sequence(&mut self, nsequence: u32) -> &mut Self {
|
||||||
self.params.rbf = Some(RBFValue::Value(nsequence));
|
self.params.rbf = Some(RbfValue::Value(nsequence));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -612,7 +612,7 @@ pub enum TxOrdering {
|
|||||||
/// Unchanged
|
/// Unchanged
|
||||||
Untouched,
|
Untouched,
|
||||||
/// BIP69 / Lexicographic
|
/// BIP69 / Lexicographic
|
||||||
BIP69Lexicographic,
|
Bip69Lexicographic,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for TxOrdering {
|
impl Default for TxOrdering {
|
||||||
@ -638,7 +638,7 @@ impl TxOrdering {
|
|||||||
|
|
||||||
tx.output.shuffle(&mut rng);
|
tx.output.shuffle(&mut rng);
|
||||||
}
|
}
|
||||||
TxOrdering::BIP69Lexicographic => {
|
TxOrdering::Bip69Lexicographic => {
|
||||||
tx.input.sort_unstable_by_key(|txin| {
|
tx.input.sort_unstable_by_key(|txin| {
|
||||||
(txin.previous_output.txid, txin.previous_output.vout)
|
(txin.previous_output.txid, txin.previous_output.vout)
|
||||||
});
|
});
|
||||||
@ -665,16 +665,16 @@ impl Default for Version {
|
|||||||
///
|
///
|
||||||
/// Has a default value of `0xFFFFFFFD`
|
/// Has a default value of `0xFFFFFFFD`
|
||||||
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)]
|
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)]
|
||||||
pub(crate) enum RBFValue {
|
pub(crate) enum RbfValue {
|
||||||
Default,
|
Default,
|
||||||
Value(u32),
|
Value(u32),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RBFValue {
|
impl RbfValue {
|
||||||
pub(crate) fn get_value(&self) -> u32 {
|
pub(crate) fn get_value(&self) -> u32 {
|
||||||
match self {
|
match self {
|
||||||
RBFValue::Default => 0xFFFFFFFD,
|
RbfValue::Default => 0xFFFFFFFD,
|
||||||
RBFValue::Value(v) => *v,
|
RbfValue::Value(v) => *v,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -759,7 +759,7 @@ mod test {
|
|||||||
let original_tx = ordering_test_tx!();
|
let original_tx = ordering_test_tx!();
|
||||||
let mut tx = original_tx;
|
let mut tx = original_tx;
|
||||||
|
|
||||||
TxOrdering::BIP69Lexicographic.sort_tx(&mut tx);
|
TxOrdering::Bip69Lexicographic.sort_tx(&mut tx);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
tx.input[0].previous_output,
|
tx.input[0].previous_output,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user