Update bitcoin, miniscript, electrum-client
This commit is contained in:
@@ -76,6 +76,7 @@ use std::str::FromStr;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use miniscript::descriptor::{ShInner, WshInner};
|
||||
use miniscript::{Descriptor, DescriptorPublicKey, ScriptContext, Terminal};
|
||||
|
||||
use crate::database::BatchDatabase;
|
||||
@@ -107,6 +108,10 @@ impl FromStr for WalletExport {
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_checksum(s: String) -> String {
|
||||
s.splitn(2, '#').next().map(String::from).unwrap()
|
||||
}
|
||||
|
||||
impl WalletExport {
|
||||
/// Export a wallet
|
||||
///
|
||||
@@ -127,6 +132,7 @@ impl WalletExport {
|
||||
let descriptor = wallet
|
||||
.descriptor
|
||||
.to_string_with_secret(&wallet.signers.as_key_map(wallet.secp_ctx()));
|
||||
let descriptor = remove_checksum(descriptor);
|
||||
Self::is_compatible_with_core(&descriptor)?;
|
||||
|
||||
let blockheight = match wallet.database.borrow().iter_txs(false) {
|
||||
@@ -150,7 +156,9 @@ impl WalletExport {
|
||||
};
|
||||
|
||||
let desc_to_string = |d: &Descriptor<DescriptorPublicKey>| {
|
||||
d.to_string_with_secret(&wallet.change_signers.as_key_map(wallet.secp_ctx()))
|
||||
let descriptor =
|
||||
d.to_string_with_secret(&wallet.change_signers.as_key_map(wallet.secp_ctx()));
|
||||
remove_checksum(descriptor)
|
||||
};
|
||||
if export.change_descriptor() != wallet.change_descriptor.as_ref().map(desc_to_string) {
|
||||
return Err("Incompatible change descriptor");
|
||||
@@ -161,7 +169,7 @@ impl WalletExport {
|
||||
|
||||
fn is_compatible_with_core(descriptor: &str) -> Result<(), &'static str> {
|
||||
fn check_ms<Ctx: ScriptContext>(
|
||||
terminal: Terminal<String, Ctx>,
|
||||
terminal: &Terminal<String, Ctx>,
|
||||
) -> Result<(), &'static str> {
|
||||
if let Terminal::Multi(_, _) = terminal {
|
||||
Ok(())
|
||||
@@ -170,13 +178,22 @@ impl WalletExport {
|
||||
}
|
||||
}
|
||||
|
||||
// pkh(), wpkh(), sh(wpkh()) are always fine, as well as multi() and sortedmulti()
|
||||
match Descriptor::<String>::from_str(descriptor).map_err(|_| "Invalid descriptor")? {
|
||||
Descriptor::Pk(_)
|
||||
| Descriptor::Pkh(_)
|
||||
| Descriptor::Wpkh(_)
|
||||
| Descriptor::ShWpkh(_) => Ok(()),
|
||||
Descriptor::Sh(ms) => check_ms(ms.node),
|
||||
Descriptor::Wsh(ms) | Descriptor::ShWsh(ms) => check_ms(ms.node),
|
||||
Descriptor::Pkh(_) | Descriptor::Wpkh(_) => Ok(()),
|
||||
Descriptor::Sh(sh) => match sh.as_inner() {
|
||||
ShInner::Wpkh(_) => Ok(()),
|
||||
ShInner::SortedMulti(_) => Ok(()),
|
||||
ShInner::Wsh(wsh) => match wsh.as_inner() {
|
||||
WshInner::SortedMulti(_) => Ok(()),
|
||||
WshInner::Ms(ms) => check_ms(&ms.node),
|
||||
},
|
||||
ShInner::Ms(ms) => check_ms(&ms.node),
|
||||
},
|
||||
Descriptor::Wsh(wsh) => match wsh.as_inner() {
|
||||
WshInner::SortedMulti(_) => Ok(()),
|
||||
WshInner::Ms(ms) => check_ms(&ms.node),
|
||||
},
|
||||
_ => Err("The descriptor is not compatible with Bitcoin Core"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,11 +36,11 @@ use bitcoin::secp256k1::Secp256k1;
|
||||
|
||||
use bitcoin::consensus::encode::serialize;
|
||||
use bitcoin::util::base58;
|
||||
use bitcoin::util::bip32::ChildNumber;
|
||||
use bitcoin::util::psbt::raw::Key as PSBTKey;
|
||||
use bitcoin::util::psbt::PartiallySignedTransaction as PSBT;
|
||||
use bitcoin::{Address, Network, OutPoint, Script, Transaction, TxOut, Txid};
|
||||
|
||||
use miniscript::descriptor::DescriptorTrait;
|
||||
use miniscript::psbt::PsbtInputSatisfier;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
@@ -60,16 +60,14 @@ use address_validator::AddressValidator;
|
||||
use coin_selection::DefaultCoinSelectionAlgorithm;
|
||||
use signer::{Signer, SignerOrdering, SignersContainer};
|
||||
use tx_builder::{BumpFee, CreateTx, FeePolicy, TxBuilder, TxParams};
|
||||
use utils::{
|
||||
check_nlocktime, check_nsequence_rbf, descriptor_to_pk_ctx, After, Older, SecpCtx,
|
||||
DUST_LIMIT_SATOSHI,
|
||||
};
|
||||
use utils::{check_nlocktime, check_nsequence_rbf, After, Older, SecpCtx, DUST_LIMIT_SATOSHI};
|
||||
|
||||
use crate::blockchain::{Blockchain, Progress};
|
||||
use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
|
||||
use crate::descriptor::derived::AsDerived;
|
||||
use crate::descriptor::{
|
||||
get_checksum, DescriptorMeta, DescriptorScripts, ExtendedDescriptor, ExtractPolicy, Policy,
|
||||
ToWalletDescriptor, XKeyUtils,
|
||||
get_checksum, DerivedDescriptor, DerivedDescriptorMeta, DescriptorMeta, DescriptorScripts,
|
||||
ExtendedDescriptor, ExtractPolicy, Policy, ToWalletDescriptor, XKeyUtils,
|
||||
};
|
||||
use crate::error::Error;
|
||||
use crate::psbt::PSBTUtils;
|
||||
@@ -134,7 +132,9 @@ where
|
||||
client: B,
|
||||
current_height: Option<u32>,
|
||||
) -> Result<Self, Error> {
|
||||
let (descriptor, keymap) = descriptor.to_wallet_descriptor(network)?;
|
||||
let secp = Secp256k1::new();
|
||||
|
||||
let (descriptor, keymap) = descriptor.to_wallet_descriptor(&secp, network)?;
|
||||
database.check_descriptor_checksum(
|
||||
KeychainKind::External,
|
||||
get_checksum(&descriptor.to_string())?.as_bytes(),
|
||||
@@ -142,7 +142,8 @@ where
|
||||
let signers = Arc::new(SignersContainer::from(keymap));
|
||||
let (change_descriptor, change_signers) = match change_descriptor {
|
||||
Some(desc) => {
|
||||
let (change_descriptor, change_keymap) = desc.to_wallet_descriptor(network)?;
|
||||
let (change_descriptor, change_keymap) =
|
||||
desc.to_wallet_descriptor(&secp, network)?;
|
||||
database.check_descriptor_checksum(
|
||||
KeychainKind::Internal,
|
||||
get_checksum(&change_descriptor.to_string())?.as_bytes(),
|
||||
@@ -168,7 +169,7 @@ where
|
||||
current_height,
|
||||
client,
|
||||
database: RefCell::new(database),
|
||||
secp: Secp256k1::new(),
|
||||
secp,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -181,12 +182,11 @@ where
|
||||
/// Return a newly generated address using the external descriptor
|
||||
pub fn get_new_address(&self) -> Result<Address, Error> {
|
||||
let index = self.fetch_and_increment_index(KeychainKind::External)?;
|
||||
let deriv_ctx = descriptor_to_pk_ctx(&self.secp);
|
||||
|
||||
self.descriptor
|
||||
.derive(ChildNumber::from_normal_idx(index)?)
|
||||
.address(self.network, deriv_ctx)
|
||||
.ok_or(Error::ScriptDoesntHaveAddressForm)
|
||||
.as_derived(index, &self.secp)
|
||||
.address(self.network)
|
||||
.map_err(|_| Error::ScriptDoesntHaveAddressForm)
|
||||
}
|
||||
|
||||
/// Return whether or not a `script` is part of this wallet (either internal or external)
|
||||
@@ -666,7 +666,6 @@ where
|
||||
let vbytes = tx.get_weight() as f32 / 4.0;
|
||||
let feerate = details.fees as f32 / vbytes;
|
||||
|
||||
let deriv_ctx = descriptor_to_pk_ctx(&self.secp);
|
||||
// remove the inputs from the tx and process them
|
||||
let original_txin = tx.input.drain(..).collect::<Vec<_>>();
|
||||
let original_utxos = original_txin
|
||||
@@ -686,7 +685,7 @@ where
|
||||
Some((keychain, _)) => (
|
||||
self._get_descriptor_for_keychain(keychain)
|
||||
.0
|
||||
.max_satisfaction_weight(deriv_ctx)
|
||||
.max_satisfaction_weight()
|
||||
.unwrap(),
|
||||
keychain,
|
||||
),
|
||||
@@ -855,7 +854,7 @@ where
|
||||
// - Try to derive the descriptor by looking at the txout. If it's in our database, we
|
||||
// know exactly which `keychain` to use, and which derivation index it is
|
||||
// - If that fails, try to derive it by looking at the psbt input: the complete logic
|
||||
// is in `src/descriptor/mod.rs`, but it will basically look at `hd_keypaths`,
|
||||
// is in `src/descriptor/mod.rs`, but it will basically look at `bip32_derivation`,
|
||||
// `redeem_script` and `witness_script` to determine the right derivation
|
||||
// - If that also fails, it will try it on the internal descriptor, if present
|
||||
let desc = psbt
|
||||
@@ -879,7 +878,6 @@ where
|
||||
match desc {
|
||||
Some(desc) => {
|
||||
let mut tmp_input = bitcoin::TxIn::default();
|
||||
let deriv_ctx = descriptor_to_pk_ctx(&self.secp);
|
||||
match desc.satisfy(
|
||||
&mut tmp_input,
|
||||
(
|
||||
@@ -887,7 +885,6 @@ where
|
||||
After::new(current_height, false),
|
||||
Older::new(current_height, create_height, false),
|
||||
),
|
||||
deriv_ctx,
|
||||
) {
|
||||
Ok(_) => {
|
||||
let psbt_input = &mut psbt.inputs[n];
|
||||
@@ -933,31 +930,30 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn get_descriptor_for_txout(&self, txout: &TxOut) -> Result<Option<ExtendedDescriptor>, Error> {
|
||||
fn get_descriptor_for_txout(
|
||||
&self,
|
||||
txout: &TxOut,
|
||||
) -> Result<Option<DerivedDescriptor<'_>>, Error> {
|
||||
Ok(self
|
||||
.database
|
||||
.borrow()
|
||||
.get_path_from_script_pubkey(&txout.script_pubkey)?
|
||||
.map(|(keychain, child)| (self.get_descriptor_for_keychain(keychain), child))
|
||||
.map(|(desc, child)| desc.derive(ChildNumber::from_normal_idx(child).unwrap())))
|
||||
.map(|(desc, child)| desc.as_derived(child, &self.secp)))
|
||||
}
|
||||
|
||||
fn get_change_address(&self) -> Result<Script, Error> {
|
||||
let deriv_ctx = descriptor_to_pk_ctx(&self.secp);
|
||||
|
||||
let (desc, keychain) = self._get_descriptor_for_keychain(KeychainKind::Internal);
|
||||
let index = self.fetch_and_increment_index(keychain)?;
|
||||
|
||||
Ok(desc
|
||||
.derive(ChildNumber::from_normal_idx(index)?)
|
||||
.script_pubkey(deriv_ctx))
|
||||
Ok(desc.as_derived(index, &self.secp).script_pubkey())
|
||||
}
|
||||
|
||||
fn fetch_and_increment_index(&self, keychain: KeychainKind) -> Result<u32, Error> {
|
||||
let (descriptor, keychain) = self._get_descriptor_for_keychain(keychain);
|
||||
let index = match descriptor.is_fixed() {
|
||||
true => 0,
|
||||
false => self.database.borrow_mut().increment_last_index(keychain)?,
|
||||
let index = match descriptor.is_deriveable() {
|
||||
false => 0,
|
||||
true => self.database.borrow_mut().increment_last_index(keychain)?,
|
||||
};
|
||||
|
||||
if self
|
||||
@@ -969,12 +965,11 @@ where
|
||||
self.cache_addresses(keychain, index, CACHE_ADDR_BATCH_SIZE)?;
|
||||
}
|
||||
|
||||
let deriv_ctx = descriptor_to_pk_ctx(&self.secp);
|
||||
let derived_descriptor = descriptor.as_derived(index, &self.secp);
|
||||
|
||||
let hd_keypaths = derived_descriptor.get_hd_keypaths(&self.secp)?;
|
||||
let script = derived_descriptor.script_pubkey();
|
||||
|
||||
let hd_keypaths = descriptor.get_hd_keypaths(index, &self.secp)?;
|
||||
let script = descriptor
|
||||
.derive(ChildNumber::from_normal_idx(index)?)
|
||||
.script_pubkey(deriv_ctx);
|
||||
for validator in &self.address_validators {
|
||||
validator.validate(keychain, &hd_keypaths, &script)?;
|
||||
}
|
||||
@@ -989,7 +984,7 @@ where
|
||||
mut count: u32,
|
||||
) -> Result<(), Error> {
|
||||
let (descriptor, keychain) = self._get_descriptor_for_keychain(keychain);
|
||||
if descriptor.is_fixed() {
|
||||
if !descriptor.is_deriveable() {
|
||||
if from > 0 {
|
||||
return Ok(());
|
||||
}
|
||||
@@ -997,16 +992,12 @@ where
|
||||
count = 1;
|
||||
}
|
||||
|
||||
let deriv_ctx = descriptor_to_pk_ctx(&self.secp);
|
||||
|
||||
let mut address_batch = self.database.borrow().begin_batch();
|
||||
|
||||
let start_time = time::Instant::new();
|
||||
for i in from..(from + count) {
|
||||
address_batch.set_script_pubkey(
|
||||
&descriptor
|
||||
.derive(ChildNumber::from_normal_idx(i)?)
|
||||
.script_pubkey(deriv_ctx),
|
||||
&descriptor.as_derived(i, &self.secp).script_pubkey(),
|
||||
keychain,
|
||||
i,
|
||||
)?;
|
||||
@@ -1025,7 +1016,6 @@ where
|
||||
}
|
||||
|
||||
fn get_available_utxos(&self) -> Result<Vec<(UTXO, usize)>, Error> {
|
||||
let deriv_ctx = descriptor_to_pk_ctx(&self.secp);
|
||||
Ok(self
|
||||
.list_unspent()?
|
||||
.into_iter()
|
||||
@@ -1034,7 +1024,7 @@ where
|
||||
(
|
||||
utxo,
|
||||
self.get_descriptor_for_keychain(keychain)
|
||||
.max_satisfaction_weight(deriv_ctx)
|
||||
.max_satisfaction_weight()
|
||||
.unwrap(),
|
||||
)
|
||||
})
|
||||
@@ -1174,19 +1164,19 @@ where
|
||||
};
|
||||
|
||||
let (desc, _) = self._get_descriptor_for_keychain(keychain);
|
||||
psbt_input.hd_keypaths = desc.get_hd_keypaths(child, &self.secp)?;
|
||||
let derived_descriptor = desc.derive(ChildNumber::from_normal_idx(child)?);
|
||||
let derived_descriptor = desc.as_derived(child, &self.secp);
|
||||
psbt_input.bip32_derivation = derived_descriptor.get_hd_keypaths(&self.secp)?;
|
||||
|
||||
psbt_input.redeem_script = derived_descriptor.psbt_redeem_script(&self.secp);
|
||||
psbt_input.witness_script = derived_descriptor.psbt_witness_script(&self.secp);
|
||||
psbt_input.redeem_script = derived_descriptor.psbt_redeem_script();
|
||||
psbt_input.witness_script = derived_descriptor.psbt_witness_script();
|
||||
|
||||
let prev_output = input.previous_output;
|
||||
if let Some(prev_tx) = self.database.borrow().get_raw_tx(&prev_output.txid)? {
|
||||
if derived_descriptor.is_witness() {
|
||||
if desc.is_witness() {
|
||||
psbt_input.witness_utxo =
|
||||
Some(prev_tx.output[prev_output.vout as usize].clone());
|
||||
}
|
||||
if !derived_descriptor.is_witness() || params.force_non_witness_utxo {
|
||||
if !desc.is_witness() || params.force_non_witness_utxo {
|
||||
psbt_input.non_witness_utxo = Some(prev_tx);
|
||||
}
|
||||
}
|
||||
@@ -1207,11 +1197,12 @@ where
|
||||
.get_path_from_script_pubkey(&tx_output.script_pubkey)?
|
||||
{
|
||||
let (desc, _) = self._get_descriptor_for_keychain(keychain);
|
||||
psbt_output.hd_keypaths = desc.get_hd_keypaths(child, &self.secp)?;
|
||||
let derived_descriptor = desc.as_derived(child, &self.secp);
|
||||
|
||||
psbt_output.bip32_derivation = derived_descriptor.get_hd_keypaths(&self.secp)?;
|
||||
if params.include_output_redeem_witness_script {
|
||||
let derived_descriptor = desc.derive(ChildNumber::from_normal_idx(child)?);
|
||||
psbt_output.witness_script = derived_descriptor.psbt_witness_script(&self.secp);
|
||||
psbt_output.redeem_script = derived_descriptor.psbt_redeem_script(&self.secp);
|
||||
psbt_output.witness_script = derived_descriptor.psbt_witness_script();
|
||||
psbt_output.redeem_script = derived_descriptor.psbt_redeem_script();
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1237,8 +1228,10 @@ where
|
||||
|
||||
// merge hd_keypaths
|
||||
let desc = self.get_descriptor_for_keychain(keychain);
|
||||
let mut hd_keypaths = desc.get_hd_keypaths(child, &self.secp)?;
|
||||
psbt_input.hd_keypaths.append(&mut hd_keypaths);
|
||||
let mut hd_keypaths = desc
|
||||
.as_derived(child, &self.secp)
|
||||
.get_hd_keypaths(&self.secp)?;
|
||||
psbt_input.bip32_derivation.append(&mut hd_keypaths);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1283,9 +1276,9 @@ where
|
||||
|
||||
let mut run_setup = false;
|
||||
|
||||
let max_address = match self.descriptor.is_fixed() {
|
||||
true => 0,
|
||||
false => max_address_param.unwrap_or(CACHE_ADDR_BATCH_SIZE),
|
||||
let max_address = match self.descriptor.is_deriveable() {
|
||||
false => 0,
|
||||
true => max_address_param.unwrap_or(CACHE_ADDR_BATCH_SIZE),
|
||||
};
|
||||
if self
|
||||
.database
|
||||
@@ -1298,9 +1291,9 @@ where
|
||||
}
|
||||
|
||||
if let Some(change_descriptor) = &self.change_descriptor {
|
||||
let max_address = match change_descriptor.is_fixed() {
|
||||
true => 0,
|
||||
false => max_address_param.unwrap_or(CACHE_ADDR_BATCH_SIZE),
|
||||
let max_address = match change_descriptor.is_deriveable() {
|
||||
false => 0,
|
||||
true => max_address_param.unwrap_or(CACHE_ADDR_BATCH_SIZE),
|
||||
};
|
||||
|
||||
if self
|
||||
@@ -1946,9 +1939,9 @@ mod test {
|
||||
.drain_wallet();
|
||||
let (psbt, _) = builder.finish().unwrap();
|
||||
|
||||
assert_eq!(psbt.inputs[0].hd_keypaths.len(), 1);
|
||||
assert_eq!(psbt.inputs[0].bip32_derivation.len(), 1);
|
||||
assert_eq!(
|
||||
psbt.inputs[0].hd_keypaths.values().nth(0).unwrap(),
|
||||
psbt.inputs[0].bip32_derivation.values().nth(0).unwrap(),
|
||||
&(
|
||||
Fingerprint::from_str("d34db33f").unwrap(),
|
||||
DerivationPath::from_str("m/44'/0'/0'/0/0").unwrap()
|
||||
@@ -1972,9 +1965,9 @@ mod test {
|
||||
.drain_wallet();
|
||||
let (psbt, _) = builder.finish().unwrap();
|
||||
|
||||
assert_eq!(psbt.outputs[0].hd_keypaths.len(), 1);
|
||||
assert_eq!(psbt.outputs[0].bip32_derivation.len(), 1);
|
||||
assert_eq!(
|
||||
psbt.outputs[0].hd_keypaths.values().nth(0).unwrap(),
|
||||
psbt.outputs[0].bip32_derivation.values().nth(0).unwrap(),
|
||||
&(
|
||||
Fingerprint::from_str("d34db33f").unwrap(),
|
||||
DerivationPath::from_str("m/44'/0'/0'/0/5").unwrap()
|
||||
@@ -3188,8 +3181,8 @@ mod test {
|
||||
.drain_wallet();
|
||||
let (mut psbt, _) = builder.finish().unwrap();
|
||||
|
||||
psbt.inputs[0].hd_keypaths.clear();
|
||||
assert_eq!(psbt.inputs[0].hd_keypaths.len(), 0);
|
||||
psbt.inputs[0].bip32_derivation.clear();
|
||||
assert_eq!(psbt.inputs[0].bip32_derivation.len(), 0);
|
||||
|
||||
let (signed_psbt, finalized) = wallet.sign(psbt, None).unwrap();
|
||||
assert_eq!(finalized, true);
|
||||
@@ -3233,7 +3226,7 @@ mod test {
|
||||
"wpkh(025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee6357)",
|
||||
)
|
||||
.unwrap()
|
||||
.script_pubkey(miniscript::NullCtx),
|
||||
.script_pubkey(),
|
||||
});
|
||||
psbt.inputs.push(dud_input);
|
||||
psbt.global.unsigned_tx.input.push(bitcoin::TxIn::default());
|
||||
|
||||
@@ -220,7 +220,7 @@ impl Signer for DescriptorXKey<ExtendedPrivKey> {
|
||||
}
|
||||
|
||||
let (public_key, deriv_path) = match psbt.inputs[input_index]
|
||||
.hd_keypaths
|
||||
.bip32_derivation
|
||||
.iter()
|
||||
.filter_map(|(pk, &(fingerprint, ref path))| {
|
||||
if self.matches(&(fingerprint, path.clone()), &secp).is_some() {
|
||||
@@ -562,7 +562,7 @@ mod signers_container_tests {
|
||||
use crate::descriptor;
|
||||
use crate::descriptor::ToWalletDescriptor;
|
||||
use crate::keys::{DescriptorKey, ToDescriptorKey};
|
||||
use bitcoin::secp256k1::All;
|
||||
use bitcoin::secp256k1::{All, Secp256k1};
|
||||
use bitcoin::util::bip32;
|
||||
use bitcoin::util::psbt::PartiallySignedTransaction;
|
||||
use bitcoin::Network;
|
||||
@@ -574,10 +574,12 @@ mod signers_container_tests {
|
||||
// This happens usually when a set of signers is created from a descriptor with private keys.
|
||||
#[test]
|
||||
fn signers_with_same_ordering() {
|
||||
let secp = Secp256k1::new();
|
||||
|
||||
let (prvkey1, _, _) = setup_keys(TPRV0_STR);
|
||||
let (prvkey2, _, _) = setup_keys(TPRV1_STR);
|
||||
let desc = descriptor!(sh(multi(2, prvkey1, prvkey2))).unwrap();
|
||||
let (_, keymap) = desc.to_wallet_descriptor(Network::Testnet).unwrap();
|
||||
let (_, keymap) = desc.to_wallet_descriptor(&secp, Network::Testnet).unwrap();
|
||||
|
||||
let signers = SignersContainer::from(keymap);
|
||||
assert_eq!(signers.ids().len(), 2);
|
||||
|
||||
@@ -57,6 +57,8 @@ use std::marker::PhantomData;
|
||||
use bitcoin::util::psbt::PartiallySignedTransaction as PSBT;
|
||||
use bitcoin::{OutPoint, Script, SigHashType, Transaction};
|
||||
|
||||
use miniscript::descriptor::DescriptorTrait;
|
||||
|
||||
use super::coin_selection::{CoinSelectionAlgorithm, DefaultCoinSelectionAlgorithm};
|
||||
use crate::{database::BatchDatabase, Error, Wallet};
|
||||
use crate::{
|
||||
@@ -276,7 +278,6 @@ impl<'a, B, D: BatchDatabase, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderConte
|
||||
/// These have priority over the "unspendable" utxos, meaning that if a utxo is present both in
|
||||
/// the "utxos" and the "unspendable" list, it will be spent.
|
||||
pub fn add_utxos(&mut self, outpoints: &[OutPoint]) -> Result<&mut Self, Error> {
|
||||
let deriv_ctx = crate::wallet::descriptor_to_pk_ctx(self.wallet.secp_ctx());
|
||||
let utxos = outpoints
|
||||
.iter()
|
||||
.map(|outpoint| self.wallet.get_utxo(*outpoint)?.ok_or(Error::UnknownUTXO))
|
||||
@@ -284,7 +285,7 @@ impl<'a, B, D: BatchDatabase, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderConte
|
||||
|
||||
for utxo in utxos {
|
||||
let descriptor = self.wallet.get_descriptor_for_keychain(utxo.keychain);
|
||||
let satisfaction_weight = descriptor.max_satisfaction_weight(deriv_ctx).unwrap();
|
||||
let satisfaction_weight = descriptor.max_satisfaction_weight().unwrap();
|
||||
self.params.utxos.push((utxo, satisfaction_weight));
|
||||
}
|
||||
|
||||
|
||||
@@ -23,9 +23,7 @@
|
||||
// SOFTWARE.
|
||||
|
||||
use bitcoin::secp256k1::{All, Secp256k1};
|
||||
use bitcoin::util::bip32;
|
||||
|
||||
use miniscript::descriptor::DescriptorPublicKeyCtx;
|
||||
use miniscript::{MiniscriptKey, Satisfier, ToPublicKey};
|
||||
|
||||
// De-facto standard "dust limit" (even though it should change based on the output type)
|
||||
@@ -110,7 +108,7 @@ pub(crate) fn check_nlocktime(nlocktime: u32, required: u32) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
impl<ToPkCtx: Copy, Pk: MiniscriptKey + ToPublicKey<ToPkCtx>> Satisfier<ToPkCtx, Pk> for After {
|
||||
impl<Pk: MiniscriptKey + ToPublicKey> Satisfier<Pk> for After {
|
||||
fn check_after(&self, n: u32) -> bool {
|
||||
if let Some(current_height) = self.current_height {
|
||||
current_height >= n
|
||||
@@ -140,7 +138,7 @@ impl Older {
|
||||
}
|
||||
}
|
||||
|
||||
impl<ToPkCtx: Copy, Pk: MiniscriptKey + ToPublicKey<ToPkCtx>> Satisfier<ToPkCtx, Pk> for Older {
|
||||
impl<Pk: MiniscriptKey + ToPublicKey> Satisfier<Pk> for Older {
|
||||
fn check_older(&self, n: u32) -> bool {
|
||||
if let Some(current_height) = self.current_height {
|
||||
// TODO: test >= / >
|
||||
@@ -152,12 +150,6 @@ impl<ToPkCtx: Copy, Pk: MiniscriptKey + ToPublicKey<ToPkCtx>> Satisfier<ToPkCtx,
|
||||
}
|
||||
|
||||
pub(crate) type SecpCtx = Secp256k1<All>;
|
||||
pub(crate) fn descriptor_to_pk_ctx(secp: &SecpCtx) -> DescriptorPublicKeyCtx<'_, All> {
|
||||
// Create a `to_pk_ctx` with a dummy derivation index, since we always use this on descriptor
|
||||
// that have already been derived with `Descriptor::derive()`, so the child number added here
|
||||
// is ignored.
|
||||
DescriptorPublicKeyCtx::new(secp, bip32::ChildNumber::Normal { index: 0 })
|
||||
}
|
||||
|
||||
pub struct ChunksIterator<I: Iterator> {
|
||||
iter: I,
|
||||
|
||||
Reference in New Issue
Block a user