Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Descriptors parsing checks #128

Open
darosior opened this issue May 5, 2022 · 0 comments
Open

Descriptors parsing checks #128

darosior opened this issue May 5, 2022 · 0 comments

Comments

@darosior
Copy link
Member

darosior commented May 5, 2022

I was previously reluctant to do parsing checks on the descriptors as it's harder to get the semantics right than when compiling the policy. But the compile-time checks don't achieve much, and we can already check a number of things without much semantics (like the maximum number of keys, check for duplicates).

Also, we already analyze the Unvault descriptor semantic with success to get the threshold, so why not for parsing checks?

revault_tx/src/scripts.rs

Lines 510 to 560 in 4bddb1d

fn unvault_descriptor_managers_threshold<Pk: MiniscriptKey>(
desc: &Descriptor<Pk>,
) -> Option<usize> {
let ms = match &desc {
Descriptor::Wsh(ref wsh) => match wsh.as_inner() {
WshInner::Ms(ms) => ms,
WshInner::SortedMulti(_) => unreachable!("Unvault descriptor is not a sorted multi"),
},
_ => unreachable!("Unvault descriptor is always a P2WSH"),
};
let policy = ms
.lift()
.expect("Lifting can't fail on a Miniscript")
.normalized();
// The Unvault descriptor is always of the form 'or(mans_branch, stks_branch)'
match policy {
SemanticPolicy::Threshold(1, ref subs) => {
assert_eq!(subs.len(), 2);
// The 'mans_branch' can be identified as the one containing the CSV. It is always an
// 'and()' of CSV + Managers (the latter being potentially a thresh) and optionally
// along with Cosigning Servers
for sub in subs {
match sub {
SemanticPolicy::Threshold(k, ref subs)
if k == &subs.len()
&& subs
.iter()
.any(|sub| matches!(sub, SemanticPolicy::Older(..))) =>
{
// Now, the mans are either a Threshold or directly pks (in the case the
// thresh is an 'and()', pks are flattened in the upper 'and()').
return subs.iter().find_map(|sub| match sub {
SemanticPolicy::Threshold(k, _) => Some(*k),
_ => None,
});
}
_ => continue,
}
}
unreachable!(
"Given an Unvault descriptor which doesn't contain a second-to-top \
branch with a CSV"
);
}
_ => unreachable!("Given an Unvault descriptor that doesn't contain a 'or()' at the root"),
}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Development

No branches or pull requests

1 participant