descriptors: cache the receive and change descriptors
This commit is contained in:
parent
ca3d7c1f33
commit
4f3daa7741
@ -223,7 +223,10 @@ pub fn looper(
|
||||
) {
|
||||
let mut last_poll = None;
|
||||
let mut synced = false;
|
||||
let descs = [desc.receive_descriptor(), desc.change_descriptor()];
|
||||
let descs = [
|
||||
desc.receive_descriptor().clone(),
|
||||
desc.change_descriptor().clone(),
|
||||
];
|
||||
|
||||
maybe_initialize_tip(&bit, &db);
|
||||
|
||||
|
||||
@ -194,7 +194,11 @@ fn is_valid_desc_key(key: &descriptor::DescriptorPublicKey) -> bool {
|
||||
/// An [InheritanceDescriptor] that contains multipath keys for (and only for) the receive keychain
|
||||
/// and the change keychain.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct MultipathDescriptor(descriptor::Descriptor<descriptor::DescriptorPublicKey>);
|
||||
pub struct MultipathDescriptor {
|
||||
multi_desc: descriptor::Descriptor<descriptor::DescriptorPublicKey>,
|
||||
receive_desc: InheritanceDescriptor,
|
||||
change_desc: InheritanceDescriptor,
|
||||
}
|
||||
|
||||
/// A Miniscript descriptor with a main, unencombered, branch (the main owner of the coins)
|
||||
/// and a timelocked branch (the heir). All keys in this descriptor are singlepath.
|
||||
@ -207,7 +211,7 @@ pub struct DerivedInheritanceDescriptor(descriptor::Descriptor<DerivedPublicKey>
|
||||
|
||||
impl fmt::Display for MultipathDescriptor {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
write!(f, "{}", self.multi_desc)
|
||||
}
|
||||
}
|
||||
|
||||
@ -277,8 +281,26 @@ impl str::FromStr for MultipathDescriptor {
|
||||
.iter()
|
||||
.find(|s| matches!(s, SemanticPolicy::Key(_)))
|
||||
.ok_or(DescCreationError::IncompatibleDesc)?;
|
||||
let multi_desc = descriptor::Descriptor::Wsh(wsh_desc);
|
||||
|
||||
Ok(MultipathDescriptor(descriptor::Descriptor::Wsh(wsh_desc)))
|
||||
// Compute the receive and change "sub" descriptors right away. According to our pubkey
|
||||
// check above, there must be only two of those, 0 and 1.
|
||||
// We use /0/* for receiving and /1/* for change.
|
||||
// FIXME: don't rely on into_single_descs()'s ordering.
|
||||
let mut singlepath_descs = multi_desc
|
||||
.clone()
|
||||
.into_single_descriptors()
|
||||
.expect("Can't error, all paths have the same length")
|
||||
.into_iter();
|
||||
assert_eq!(singlepath_descs.len(), 2);
|
||||
let receive_desc = InheritanceDescriptor(singlepath_descs.next().expect("First of 2"));
|
||||
let change_desc = InheritanceDescriptor(singlepath_descs.next().expect("Second of 2"));
|
||||
|
||||
Ok(MultipathDescriptor {
|
||||
multi_desc,
|
||||
receive_desc,
|
||||
change_desc,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -341,15 +363,33 @@ impl MultipathDescriptor {
|
||||
.expect("Well typed");
|
||||
miniscript::Segwitv0::check_local_validity(&tl_miniscript)
|
||||
.expect("Miniscript must be sane");
|
||||
|
||||
Ok(MultipathDescriptor(descriptor::Descriptor::Wsh(
|
||||
let multi_desc = descriptor::Descriptor::Wsh(
|
||||
descriptor::Wsh::new(tl_miniscript).expect("Must pass sanity checks"),
|
||||
)))
|
||||
);
|
||||
|
||||
// Compute the receive and change "sub" descriptors right away. According to our pubkey
|
||||
// check above, there must be only two of those, 0 and 1.
|
||||
// We use /0/* for receiving and /1/* for change.
|
||||
// FIXME: don't rely on into_single_descs()'s ordering.
|
||||
let mut singlepath_descs = multi_desc
|
||||
.clone()
|
||||
.into_single_descriptors()
|
||||
.expect("Can't error, all paths have the same length")
|
||||
.into_iter();
|
||||
assert_eq!(singlepath_descs.len(), 2);
|
||||
let receive_desc = InheritanceDescriptor(singlepath_descs.next().expect("First of 2"));
|
||||
let change_desc = InheritanceDescriptor(singlepath_descs.next().expect("Second of 2"));
|
||||
|
||||
Ok(MultipathDescriptor {
|
||||
multi_desc,
|
||||
receive_desc,
|
||||
change_desc,
|
||||
})
|
||||
}
|
||||
|
||||
/// Whether all xpubs contained in this descriptor are for the passed expected network.
|
||||
pub fn all_xpubs_net_is(&self, expected_net: bitcoin::Network) -> bool {
|
||||
self.0.for_each_key(|xpub| {
|
||||
self.multi_desc.for_each_key(|xpub| {
|
||||
if let descriptor::DescriptorPublicKey::MultiXPub(xpub) = xpub {
|
||||
xpub.xkey.network == expected_net
|
||||
} else {
|
||||
@ -358,52 +398,19 @@ impl MultipathDescriptor {
|
||||
})
|
||||
}
|
||||
|
||||
// TODO: Cache it inside the struct, it's very inefficient to use into_single_descriptors() for
|
||||
// every single derivation.
|
||||
/// Get the descriptor for receiving addresses.
|
||||
pub fn receive_descriptor(&self) -> InheritanceDescriptor {
|
||||
let singlepath_descs = self
|
||||
.0
|
||||
.clone()
|
||||
.into_single_descriptors()
|
||||
.expect("Can't error, all paths have the same length");
|
||||
assert_eq!(singlepath_descs.len(), 2);
|
||||
|
||||
// We use /0/* for receiving, so it's the first descriptor between <0;1>.
|
||||
// FIXME: don't rely on ordering.
|
||||
InheritanceDescriptor(
|
||||
singlepath_descs
|
||||
.into_iter()
|
||||
.next()
|
||||
.expect("Just checked the length"),
|
||||
)
|
||||
pub fn receive_descriptor(&self) -> &InheritanceDescriptor {
|
||||
&self.receive_desc
|
||||
}
|
||||
|
||||
// TODO: Cache it inside the struct, it's very inefficient to use into_single_descriptors() for
|
||||
// every single derivation.
|
||||
/// Get the descriptor for change addresses.
|
||||
pub fn change_descriptor(&self) -> InheritanceDescriptor {
|
||||
let singlepath_descs = self
|
||||
.0
|
||||
.clone()
|
||||
.into_single_descriptors()
|
||||
.expect("Can't error, all paths have the same length");
|
||||
assert_eq!(singlepath_descs.len(), 2);
|
||||
|
||||
// We use /1/* for change, so it's the second descriptor between <0;1>.
|
||||
// FIXME: don't rely on ordering.
|
||||
InheritanceDescriptor(
|
||||
singlepath_descs
|
||||
.into_iter()
|
||||
.rev()
|
||||
.next()
|
||||
.expect("Just checked the length"),
|
||||
)
|
||||
pub fn change_descriptor(&self) -> &InheritanceDescriptor {
|
||||
&self.change_desc
|
||||
}
|
||||
|
||||
/// Get the value (in blocks) of the relative timelock for the heir's spending path.
|
||||
pub fn timelock_value(&self) -> u32 {
|
||||
let wsh_desc = match &self.0 {
|
||||
let wsh_desc = match &self.multi_desc {
|
||||
descriptor::Descriptor::Wsh(desc) => desc,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
@ -600,8 +600,8 @@ mod tests {
|
||||
// Create a dummy config with this bitcoind
|
||||
let desc_str = "wsh(andor(pk(xpub68JJTXc1MWK8KLW4HGLXZBJknja7kDUJuFHnM424LbziEXsfkh1WQCiEjjHw4zLqSUm4rvhgyGkkuRowE9tCJSgt3TQB5J3SKAbZ2SdcKST/<0;1>/*),older(10000),pk(xpub68JJTXc1MWK8PEQozKsRatrUHXKFNkD1Cb1BuQU9Xr5moCv87anqGyXLyUd4KpnDyZgo3gz4aN1r3NiaoweFW8UutBsBbgKHzaD5HkTkifK/<0;1>/*)))#yudtr0k5";
|
||||
let desc = MultipathDescriptor::from_str(desc_str).unwrap();
|
||||
let receive_desc = desc.receive_descriptor();
|
||||
let change_desc = desc.change_descriptor();
|
||||
let receive_desc = desc.receive_descriptor().clone();
|
||||
let change_desc = desc.change_descriptor().clone();
|
||||
let config = Config {
|
||||
bitcoin_config,
|
||||
bitcoind_config: Some(bitcoind_config),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user