Skip to content

Commit 844c9ed

Browse files
committed
wip(refactor(wallet))!: remove signers APIs
- use default empty `SignersContainer::new()` on both wallet `create_with_params` and `load_with_params`. - remove `add_signer`, `set_keymap` and `get_signers` methods. - updates `FullyNodedExport::export_wallet` to export public descriptors only, and updates it's tests accordingly. - remove test assertions for signers/keymaps creation/load.
1 parent e03af20 commit 844c9ed

File tree

5 files changed

+56
-235
lines changed

5 files changed

+56
-235
lines changed

wallet/src/wallet/export.rs

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ use core::fmt;
6060
use core::str::FromStr;
6161
use serde::{Deserialize, Serialize};
6262

63-
use miniscript::descriptor::{ShInner, WshInner};
63+
use miniscript::descriptor::{KeyMap, ShInner, WshInner};
6464
use miniscript::{Descriptor, ScriptContext, Terminal};
6565

6666
use crate::types::KeychainKind;
@@ -119,11 +119,8 @@ impl FullyNodedExport {
119119
) -> Result<Self, &'static str> {
120120
let descriptor = wallet
121121
.public_descriptor(KeychainKind::External)
122-
.to_string_with_secret(
123-
&wallet
124-
.get_signers(KeychainKind::External)
125-
.as_key_map(wallet.secp_ctx()),
126-
);
122+
.to_string_with_secret(&KeyMap::new());
123+
127124
let descriptor = remove_checksum(descriptor);
128125
Self::is_compatible_with_core(&descriptor)?;
129126

@@ -147,11 +144,7 @@ impl FullyNodedExport {
147144
let change_descriptor = {
148145
let descriptor = wallet
149146
.public_descriptor(KeychainKind::Internal)
150-
.to_string_with_secret(
151-
&wallet
152-
.get_signers(KeychainKind::Internal)
153-
.as_key_map(wallet.secp_ctx()),
154-
);
147+
.to_string_with_secret(&KeyMap::new());
155148
Some(remove_checksum(descriptor))
156149
};
157150

@@ -239,16 +232,23 @@ mod test {
239232
wallet
240233
}
241234

235+
// TODO: (@leonardo) what's the best way to update these tests ?
242236
#[test]
243237
fn test_export_bip44() {
244238
let descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)";
239+
let public_descriptor = "wpkh([a12b02f4/44'/0'/0']xpub6BzhLAQUDcBUfHRQHZxDF2AbcJqp4Kaeq6bzJpXrjrWuK26ymTFwkEFbxPra2bJ7yeZKbDjfDeFwxe93JMqpo5SsPJH6dZdvV9kMzJkAZ69/0/*)";
240+
245241
let change_descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/1/*)";
242+
let public_change_descriptor = "wpkh([a12b02f4/44'/0'/0']xpub6BzhLAQUDcBUfHRQHZxDF2AbcJqp4Kaeq6bzJpXrjrWuK26ymTFwkEFbxPra2bJ7yeZKbDjfDeFwxe93JMqpo5SsPJH6dZdvV9kMzJkAZ69/1/*)";
246243

247244
let wallet = get_test_wallet(descriptor, change_descriptor, Network::Bitcoin);
248245
let export = FullyNodedExport::export_wallet(&wallet, "Test Label", true).unwrap();
249246

250-
assert_eq!(export.descriptor(), descriptor);
251-
assert_eq!(export.change_descriptor(), Some(change_descriptor.into()));
247+
assert_eq!(export.descriptor(), public_descriptor);
248+
assert_eq!(
249+
export.change_descriptor(),
250+
Some(public_change_descriptor.into())
251+
);
252252
assert_eq!(export.blockheight, 5000);
253253
assert_eq!(export.label, "Test Label");
254254
}
@@ -305,24 +305,33 @@ mod test {
305305
#[test]
306306
fn test_export_tr() {
307307
let descriptor = "tr([73c5da0a/86'/0'/0']tprv8fMn4hSKPRC1oaCPqxDb1JWtgkpeiQvZhsr8W2xuy3GEMkzoArcAWTfJxYb6Wj8XNNDWEjfYKK4wGQXh3ZUXhDF2NcnsALpWTeSwarJt7Vc/0/*)";
308+
let public_descriptor = "tr([73c5da0a/86'/0'/0']tpubDC3pD7UZXnsgh3EBjbtBQiB1FnLask7UHBSunZ1DPK4dCFFZoFRkgxHB8gt42FvLzx1DpxfHWxAsYaY6b643RVcGjDxXxns7wKKYnnfEcbB/0/*)";
309+
308310
let change_descriptor = "tr([73c5da0a/86'/0'/0']tprv8fMn4hSKPRC1oaCPqxDb1JWtgkpeiQvZhsr8W2xuy3GEMkzoArcAWTfJxYb6Wj8XNNDWEjfYKK4wGQXh3ZUXhDF2NcnsALpWTeSwarJt7Vc/1/*)";
311+
let public_change_descriptor = "tr([73c5da0a/86'/0'/0']tpubDC3pD7UZXnsgh3EBjbtBQiB1FnLask7UHBSunZ1DPK4dCFFZoFRkgxHB8gt42FvLzx1DpxfHWxAsYaY6b643RVcGjDxXxns7wKKYnnfEcbB/1/*)";
312+
309313
let wallet = get_test_wallet(descriptor, change_descriptor, Network::Testnet);
310314
let export = FullyNodedExport::export_wallet(&wallet, "Test Label", true).unwrap();
311-
assert_eq!(export.descriptor(), descriptor);
312-
assert_eq!(export.change_descriptor(), Some(change_descriptor.into()));
315+
assert_eq!(export.descriptor(), public_descriptor);
316+
assert_eq!(
317+
export.change_descriptor(),
318+
Some(public_change_descriptor.into())
319+
);
313320
assert_eq!(export.blockheight, 5000);
314321
assert_eq!(export.label, "Test Label");
315322
}
316323

317324
#[test]
318325
fn test_export_to_json() {
319326
let descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)";
327+
let public_descriptor = "wpkh([a12b02f4/44'/0'/0']xpub6BzhLAQUDcBUfHRQHZxDF2AbcJqp4Kaeq6bzJpXrjrWuK26ymTFwkEFbxPra2bJ7yeZKbDjfDeFwxe93JMqpo5SsPJH6dZdvV9kMzJkAZ69/0/*)";
328+
320329
let change_descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/1/*)";
321330

322331
let wallet = get_test_wallet(descriptor, change_descriptor, Network::Bitcoin);
323332
let export = FullyNodedExport::export_wallet(&wallet, "Test Label", true).unwrap();
324333

325-
assert_eq!(export.to_string(), "{\"descriptor\":\"wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44\'/0\'/0\'/0/*)\",\"blockheight\":5000,\"label\":\"Test Label\"}");
334+
assert_eq!(export.to_string(), format!("{{\"descriptor\":\"{public_descriptor}\",\"blockheight\":5000,\"label\":\"Test Label\"}}"));
326335
}
327336

328337
#[test]

wallet/src/wallet/mod.rs

Lines changed: 11 additions & 170 deletions
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,11 @@ use bdk_chain::{
3434
FullTxOut, Indexed, IndexedTxGraph, Indexer, Merge,
3535
};
3636
use bitcoin::{
37-
absolute,
38-
consensus::encode::serialize,
39-
constants::genesis_block,
40-
psbt,
41-
secp256k1::Secp256k1,
42-
sighash::{EcdsaSighashType, TapSighashType},
37+
absolute, consensus::encode::serialize, constants::genesis_block, psbt, secp256k1::Secp256k1,
4338
transaction, Address, Amount, Block, BlockHash, FeeRate, Network, OutPoint, Psbt, ScriptBuf,
4439
Sequence, SignedAmount, Transaction, TxOut, Txid, Weight, Witness,
4540
};
46-
use miniscript::{
47-
descriptor::KeyMap,
48-
psbt::{PsbtExt, PsbtInputExt, PsbtInputSatisfier},
49-
};
41+
use miniscript::psbt::{PsbtExt, PsbtInputExt, PsbtInputSatisfier};
5042
use rand_core::RngCore;
5143

5244
mod changeset;
@@ -70,7 +62,7 @@ use crate::types::*;
7062
use crate::wallet::{
7163
coin_selection::{DefaultCoinSelectionAlgorithm, Excess, InsufficientFunds},
7264
error::{BuildFeeBumpError, CreateTxError, MiniscriptPsbtError},
73-
signer::{SignOptions, SignerError, SignerOrdering, SignersContainer, TransactionSigner},
65+
signer::{SignOptions, SignerError, SignersContainer},
7466
tx_builder::{FeePolicy, TxBuilder, TxParams},
7567
utils::{check_nsequence_rbf, After, Older, SecpCtx},
7668
};
@@ -417,22 +409,14 @@ impl Wallet {
417409
check_wallet_descriptor(&descriptor)?;
418410
descriptor_keymap.extend(params.descriptor_keymap);
419411

420-
let signers = Arc::new(SignersContainer::build(
421-
descriptor_keymap,
422-
&descriptor,
423-
&secp,
424-
));
412+
let signers = Arc::new(SignersContainer::new());
425413

426414
let (change_descriptor, change_signers) = match params.change_descriptor {
427415
Some(make_desc) => {
428416
let (change_descriptor, mut internal_keymap) = make_desc(&secp, network)?;
429417
check_wallet_descriptor(&change_descriptor)?;
430418
internal_keymap.extend(params.change_descriptor_keymap);
431-
let change_signers = Arc::new(SignersContainer::build(
432-
internal_keymap,
433-
&change_descriptor,
434-
&secp,
435-
));
419+
let change_signers = Arc::new(SignersContainer::new());
436420
(Some(change_descriptor), change_signers)
437421
}
438422
None => (None, Arc::new(SignersContainer::new())),
@@ -580,7 +564,7 @@ impl Wallet {
580564
}));
581565
}
582566
}
583-
let signers = Arc::new(SignersContainer::build(external_keymap, &descriptor, &secp));
567+
let signers = Arc::new(SignersContainer::new());
584568

585569
let mut change_descriptor = None;
586570
let mut internal_keymap = params.change_descriptor_keymap;
@@ -634,11 +618,7 @@ impl Wallet {
634618
}
635619

636620
let change_signers = match change_descriptor {
637-
Some(ref change_descriptor) => Arc::new(SignersContainer::build(
638-
internal_keymap,
639-
change_descriptor,
640-
&secp,
641-
)),
621+
Some(ref change_descriptor) => Arc::new(SignersContainer::new()),
642622
None => Arc::new(SignersContainer::new()),
643623
};
644624

@@ -1207,70 +1187,6 @@ impl Wallet {
12071187
)
12081188
}
12091189

1210-
/// Add an external signer
1211-
///
1212-
/// See [the `signer` module](signer) for an example.
1213-
pub fn add_signer(
1214-
&mut self,
1215-
keychain: KeychainKind,
1216-
ordering: SignerOrdering,
1217-
signer: Arc<dyn TransactionSigner>,
1218-
) {
1219-
let signers = match keychain {
1220-
KeychainKind::External => Arc::make_mut(&mut self.signers),
1221-
KeychainKind::Internal => Arc::make_mut(&mut self.change_signers),
1222-
};
1223-
1224-
signers.add_external(signer.id(&self.secp), ordering, signer);
1225-
}
1226-
1227-
/// Set the keymap for a given keychain.
1228-
///
1229-
/// Note this does nothing if the given keychain has no descriptor because we won't
1230-
/// know the context (segwit, taproot, etc) in which to create signatures.
1231-
pub fn set_keymap(&mut self, keychain: KeychainKind, keymap: KeyMap) {
1232-
let wallet_signers = match keychain {
1233-
KeychainKind::External => Arc::make_mut(&mut self.signers),
1234-
KeychainKind::Internal => Arc::make_mut(&mut self.change_signers),
1235-
};
1236-
if let Some(descriptor) = self.indexed_graph.index.get_descriptor(keychain) {
1237-
*wallet_signers = SignersContainer::build(keymap, descriptor, &self.secp)
1238-
}
1239-
}
1240-
1241-
/// Set the keymap for each keychain.
1242-
pub fn set_keymaps(&mut self, keymaps: impl IntoIterator<Item = (KeychainKind, KeyMap)>) {
1243-
for (keychain, keymap) in keymaps {
1244-
self.set_keymap(keychain, keymap);
1245-
}
1246-
}
1247-
1248-
/// Get the signers
1249-
///
1250-
/// ## Example
1251-
///
1252-
/// ```
1253-
/// # use bdk_wallet::{Wallet, KeychainKind};
1254-
/// # use bdk_wallet::bitcoin::Network;
1255-
/// let descriptor = "wpkh(tprv8ZgxMBicQKsPe73PBRSmNbTfbcsZnwWhz5eVmhHpi31HW29Z7mc9B4cWGRQzopNUzZUT391DeDJxL2PefNunWyLgqCKRMDkU1s2s8bAfoSk/84'/1'/0'/0/*)";
1256-
/// let change_descriptor = "wpkh(tprv8ZgxMBicQKsPe73PBRSmNbTfbcsZnwWhz5eVmhHpi31HW29Z7mc9B4cWGRQzopNUzZUT391DeDJxL2PefNunWyLgqCKRMDkU1s2s8bAfoSk/84'/1'/0'/1/*)";
1257-
/// let wallet = Wallet::create(descriptor, change_descriptor)
1258-
/// .network(Network::Testnet)
1259-
/// .create_wallet_no_persist()?;
1260-
/// for secret_key in wallet.get_signers(KeychainKind::External).signers().iter().filter_map(|s| s.descriptor_secret_key()) {
1261-
/// // secret_key: tprv8ZgxMBicQKsPe73PBRSmNbTfbcsZnwWhz5eVmhHpi31HW29Z7mc9B4cWGRQzopNUzZUT391DeDJxL2PefNunWyLgqCKRMDkU1s2s8bAfoSk/84'/0'/0'/0/*
1262-
/// println!("secret_key: {}", secret_key);
1263-
/// }
1264-
///
1265-
/// Ok::<(), Box<dyn std::error::Error>>(())
1266-
/// ```
1267-
pub fn get_signers(&self, keychain: KeychainKind) -> Arc<SignersContainer> {
1268-
match keychain {
1269-
KeychainKind::External => Arc::clone(&self.signers),
1270-
KeychainKind::Internal => Arc::clone(&self.change_signers),
1271-
}
1272-
}
1273-
12741190
/// Start building a transaction.
12751191
///
12761192
/// This returns a blank [`TxBuilder`] from which you can specify the parameters for the
@@ -1657,7 +1573,8 @@ impl Wallet {
16571573
/// .add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000));
16581574
/// builder.finish()?
16591575
/// };
1660-
/// let _ = wallet.sign(&mut psbt, SignOptions::default())?;
1576+
/// // FIXME: (@leonardo) should use the `psbt.sign` instead!
1577+
/// // let _ = wallet.sign(&mut psbt, SignOptions::default())?;
16611578
/// let tx = psbt.clone().extract_tx().expect("tx");
16621579
/// // broadcast tx but it's taking too long to confirm so we want to bump the fee
16631580
/// let mut psbt = {
@@ -1667,7 +1584,8 @@ impl Wallet {
16671584
/// builder.finish()?
16681585
/// };
16691586
///
1670-
/// let _ = wallet.sign(&mut psbt, SignOptions::default())?;
1587+
/// // FIXME: (@leonardo) should use the `psbt.sign` instead!
1588+
/// // let _ = wallet.sign(&mut psbt, SignOptions::default())?;
16711589
/// let fee_bumped_tx = psbt.extract_tx();
16721590
/// // broadcast fee_bumped_tx to replace original
16731591
/// # Ok::<(), anyhow::Error>(())
@@ -1827,83 +1745,6 @@ impl Wallet {
18271745
})
18281746
}
18291747

1830-
/// Sign a transaction with all the wallet's signers, in the order specified by every signer's
1831-
/// [`SignerOrdering`]. This function returns the `Result` type with an encapsulated `bool` that
1832-
/// has the value true if the PSBT was finalized, or false otherwise.
1833-
///
1834-
/// The [`SignOptions`] can be used to tweak the behavior of the software signers, and the way
1835-
/// the transaction is finalized at the end. Note that it can't be guaranteed that *every*
1836-
/// signers will follow the options, but the "software signers" (WIF keys and `xprv`) defined
1837-
/// in this library will.
1838-
///
1839-
/// ## Example
1840-
///
1841-
/// ```
1842-
/// # use std::str::FromStr;
1843-
/// # use bitcoin::*;
1844-
/// # use bdk_wallet::*;
1845-
/// # use bdk_wallet::ChangeSet;
1846-
/// # use bdk_wallet::error::CreateTxError;
1847-
/// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
1848-
/// # let mut wallet = doctest_wallet!();
1849-
/// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap().assume_checked();
1850-
/// let mut psbt = {
1851-
/// let mut builder = wallet.build_tx();
1852-
/// builder.add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000));
1853-
/// builder.finish()?
1854-
/// };
1855-
/// let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
1856-
/// assert!(finalized, "we should have signed all the inputs");
1857-
/// # Ok::<(),anyhow::Error>(())
1858-
pub fn sign(&self, psbt: &mut Psbt, sign_options: SignOptions) -> Result<bool, SignerError> {
1859-
// This adds all the PSBT metadata for the inputs, which will help us later figure out how
1860-
// to derive our keys
1861-
self.update_psbt_with_descriptor(psbt)
1862-
.map_err(SignerError::MiniscriptPsbt)?;
1863-
1864-
// If we aren't allowed to use `witness_utxo`, ensure that every input (except p2tr and
1865-
// finalized ones) has the `non_witness_utxo`
1866-
if !sign_options.trust_witness_utxo
1867-
&& psbt
1868-
.inputs
1869-
.iter()
1870-
.filter(|i| i.final_script_witness.is_none() && i.final_script_sig.is_none())
1871-
.filter(|i| i.tap_internal_key.is_none() && i.tap_merkle_root.is_none())
1872-
.any(|i| i.non_witness_utxo.is_none())
1873-
{
1874-
return Err(SignerError::MissingNonWitnessUtxo);
1875-
}
1876-
1877-
// If the user hasn't explicitly opted-in, refuse to sign the transaction unless every input
1878-
// is using `SIGHASH_ALL` or `SIGHASH_DEFAULT` for taproot
1879-
if !sign_options.allow_all_sighashes
1880-
&& !psbt.inputs.iter().all(|i| {
1881-
i.sighash_type.is_none()
1882-
|| i.sighash_type == Some(EcdsaSighashType::All.into())
1883-
|| i.sighash_type == Some(TapSighashType::All.into())
1884-
|| i.sighash_type == Some(TapSighashType::Default.into())
1885-
})
1886-
{
1887-
return Err(SignerError::NonStandardSighash);
1888-
}
1889-
1890-
for signer in self
1891-
.signers
1892-
.signers()
1893-
.iter()
1894-
.chain(self.change_signers.signers().iter())
1895-
{
1896-
signer.sign_transaction(psbt, &sign_options, &self.secp)?;
1897-
}
1898-
1899-
// attempt to finalize
1900-
if sign_options.try_finalize {
1901-
self.finalize_psbt(psbt, sign_options)
1902-
} else {
1903-
Ok(false)
1904-
}
1905-
}
1906-
19071748
/// Return the spending policies for the wallet's descriptor
19081749
pub fn policies(&self, keychain: KeychainKind) -> Result<Option<Policy>, DescriptorError> {
19091750
let signers = match keychain {

wallet/src/wallet/signer.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,12 @@
7272
//! let mut wallet = Wallet::create(descriptor, change_descriptor)
7373
//! .network(Network::Testnet)
7474
//! .create_wallet_no_persist()?;
75-
//! wallet.add_signer(
76-
//! KeychainKind::External,
77-
//! SignerOrdering(200),
78-
//! Arc::new(custom_signer)
79-
//! );
75+
//! // FIXME: (@leonardo) should be removed ?
76+
//! // wallet.add_signer(
77+
//! // KeychainKind::External,
78+
//! // SignerOrdering(200),
79+
//! // Arc::new(custom_signer)
80+
//! // );
8081
//!
8182
//! # Ok::<_, anyhow::Error>(())
8283
//! ```

0 commit comments

Comments
 (0)