[descriptor] Perform additional checks before using a descriptor
Fixes #287
This commit is contained in:
parent
6092c6e789
commit
7843732e17
@ -31,6 +31,8 @@ pub enum Error {
|
|||||||
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
|
||||||
|
HardenedDerivationXpub,
|
||||||
|
|
||||||
/// Error thrown while working with [`keys`](crate::keys)
|
/// Error thrown while working with [`keys`](crate::keys)
|
||||||
Key(crate::keys::KeyError),
|
Key(crate::keys::KeyError),
|
||||||
|
@ -198,6 +198,36 @@ impl IntoWalletDescriptor for DescriptorTemplateOut {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Wrapper for `IntoWalletDescriptor` that performs additional checks on the keys contained in the
|
||||||
|
/// descriptor
|
||||||
|
pub(crate) fn into_wallet_descriptor_checked<T: IntoWalletDescriptor>(
|
||||||
|
inner: T,
|
||||||
|
secp: &SecpCtx,
|
||||||
|
network: Network,
|
||||||
|
) -> Result<(ExtendedDescriptor, KeyMap), DescriptorError> {
|
||||||
|
let (descriptor, keymap) = inner.into_wallet_descriptor(secp, network)?;
|
||||||
|
|
||||||
|
// Ensure the keys don't contain any hardened derivation steps or hardened wildcards
|
||||||
|
let descriptor_contains_hardened_steps = descriptor.for_any_key(|k| {
|
||||||
|
if let DescriptorPublicKey::XPub(DescriptorXKey {
|
||||||
|
derivation_path,
|
||||||
|
wildcard,
|
||||||
|
..
|
||||||
|
}) = k.as_key()
|
||||||
|
{
|
||||||
|
return *wildcard == Wildcard::Hardened
|
||||||
|
|| derivation_path.into_iter().any(ChildNumber::is_hardened);
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
});
|
||||||
|
if descriptor_contains_hardened_steps {
|
||||||
|
return Err(DescriptorError::HardenedDerivationXpub);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((descriptor, keymap))
|
||||||
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
/// Used internally mainly by the `descriptor!()` and `fragment!()` macros
|
/// Used internally mainly by the `descriptor!()` and `fragment!()` macros
|
||||||
pub trait CheckMiniscript<Ctx: miniscript::ScriptContext> {
|
pub trait CheckMiniscript<Ctx: miniscript::ScriptContext> {
|
||||||
@ -740,4 +770,18 @@ mod test {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(wallet_desc, wallet_desc2)
|
assert_eq!(wallet_desc, wallet_desc2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_into_wallet_descriptor_checked() {
|
||||||
|
let secp = Secp256k1::new();
|
||||||
|
|
||||||
|
let descriptor = "wpkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/0'/1/2/*)";
|
||||||
|
let result = into_wallet_descriptor_checked(descriptor, &secp, Network::Testnet);
|
||||||
|
|
||||||
|
assert!(result.is_err());
|
||||||
|
assert!(matches!(
|
||||||
|
result.unwrap_err(),
|
||||||
|
DescriptorError::HardenedDerivationXpub
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,8 +66,9 @@ use crate::blockchain::{Blockchain, Progress};
|
|||||||
use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
|
use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
|
||||||
use crate::descriptor::derived::AsDerived;
|
use crate::descriptor::derived::AsDerived;
|
||||||
use crate::descriptor::{
|
use crate::descriptor::{
|
||||||
get_checksum, DerivedDescriptor, DerivedDescriptorMeta, DescriptorMeta, DescriptorScripts,
|
get_checksum, into_wallet_descriptor_checked, DerivedDescriptor, DerivedDescriptorMeta,
|
||||||
ExtendedDescriptor, ExtractPolicy, IntoWalletDescriptor, Policy, XKeyUtils,
|
DescriptorMeta, DescriptorScripts, ExtendedDescriptor, ExtractPolicy, IntoWalletDescriptor,
|
||||||
|
Policy, XKeyUtils,
|
||||||
};
|
};
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::psbt::PSBTUtils;
|
use crate::psbt::PSBTUtils;
|
||||||
@ -134,7 +135,7 @@ where
|
|||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
let secp = Secp256k1::new();
|
let secp = Secp256k1::new();
|
||||||
|
|
||||||
let (descriptor, keymap) = descriptor.into_wallet_descriptor(&secp, network)?;
|
let (descriptor, keymap) = into_wallet_descriptor_checked(descriptor, &secp, network)?;
|
||||||
database.check_descriptor_checksum(
|
database.check_descriptor_checksum(
|
||||||
KeychainKind::External,
|
KeychainKind::External,
|
||||||
get_checksum(&descriptor.to_string())?.as_bytes(),
|
get_checksum(&descriptor.to_string())?.as_bytes(),
|
||||||
@ -143,7 +144,7 @@ where
|
|||||||
let (change_descriptor, change_signers) = match change_descriptor {
|
let (change_descriptor, change_signers) = match change_descriptor {
|
||||||
Some(desc) => {
|
Some(desc) => {
|
||||||
let (change_descriptor, change_keymap) =
|
let (change_descriptor, change_keymap) =
|
||||||
desc.into_wallet_descriptor(&secp, network)?;
|
into_wallet_descriptor_checked(desc, &secp, network)?;
|
||||||
database.check_descriptor_checksum(
|
database.check_descriptor_checksum(
|
||||||
KeychainKind::Internal,
|
KeychainKind::Internal,
|
||||||
get_checksum(&change_descriptor.to_string())?.as_bytes(),
|
get_checksum(&change_descriptor.to_string())?.as_bytes(),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user