refactor: remove SortedMultiVec and use Terminal::SortedMulti#915
refactor: remove SortedMultiVec and use Terminal::SortedMulti#915trevarj wants to merge 1 commit intorust-bitcoin:masterfrom
Conversation
2c77295 to
9b0b1c0
Compare
|
(CI is failing because the integration tests don't compile) Hmmmm, okay, this seems reasonable enough to me. Does Core allow |
Working on fixing the integration tests now! Will ping you when it's ready, my bad. |
9b0b1c0 to
816620a
Compare
| Descriptor::Sh(sh) => match sh.as_inner() { | ||
| miniscript::descriptor::ShInner::Wsh(wsh) => match wsh.as_inner() { | ||
| miniscript::descriptor::WshInner::SortedMulti(ref smv) => { | ||
| let ms = Miniscript::from_ast(smv.sorted_node()).unwrap(); |
There was a problem hiding this comment.
The key point here was to call sorted_node() and now we don't have something so convenient. See the HACK in find_sks_ms
There was a problem hiding this comment.
Interesting. So, the issue is that we want to get all the keys in the descriptor, in the order they'd be needed, and we're using pk_iter for this. Since pk_iter can't sort the keys, we have to sort them after the fact.
This is a bit of a weird thing to desire -- does this test actually fail without this? It seems like we never use the ordering of sks_reqd. In fact, we lose the ordering because we iterate over it, produce signatures, then stick them into the BTreeMap psbt.inputs[0].partial_sigs.
Also, since #910 I think the logic in this example is actually wrong, or at least inconsistent -- it would sort sortedmulti but not sortedmulti_a. And your hack doesn't change this.
So can we just drop the sortedmulti logic here and treat sortedmulti like multi?
| ShInner::Wsh(ref wsh) => { | ||
| let ms = wsh.as_inner(); | ||
| if let Terminal::SortedMulti(ref thresh) = ms.node { | ||
| PkIter::from_sortedmulti(thresh.data()) |
There was a problem hiding this comment.
Cannot call thresh.into_sorted_bip67() due to lacking ToPublicKey on Pk here. It would clean up the integration test changes (. I'm sure it would be useful for users as well.HACK)
There was a problem hiding this comment.
Right -- I get the desire that pk_iter return the keys in the correct order. But as you note, without a ToPublicKey bound, we don't actually know the correct order (and the user might not either, e.g. if there are wildcards in the keys).
We also can't make this do the right thing for ToPublicKey keys because Rust lacks specialization. (There are tons of places in this crate where we suffer from this, and you'll find that if you keep trying to clean stuff up, you will run into missing language features basically every single time.)
I think we need to just live with this.
There was a problem hiding this comment.
There are tons of places in this crate where we suffer from this, and you'll find that if you keep trying to clean stuff up, you will run into missing language features basically every single time.
@apoelstra don't worry, in 2035 when specialization stabilizes we can get to it!
| } | ||
|
|
||
| #[test] | ||
| fn too_many_pubkeys_for_p2sh() { |
There was a problem hiding this comment.
FYI: migrated from deleted sortedmulti.rs file.
src/descriptor/segwitv0.rs
Outdated
| let mut witness = match self.inner { | ||
| WshInner::SortedMulti(ref smv) => smv.satisfy(satisfier)?, | ||
| WshInner::Ms(ref ms) => ms.satisfy_malleable(satisfier)?, | ||
| let mut witness = if let Terminal::SortedMulti(..) = self.ms.node { |
There was a problem hiding this comment.
All the if let Terminal::SortedMulti(..)'s are kind of bothering me.
Does it make sense to add a function on Miniscript called is_sortedmulti() or something?
There was a problem hiding this comment.
Probably yes, but I'm curious what the heck is going on here. Why are we calling the non-malleable satisfier for sortedmultis? (What I suspect is: the old SortedMultiVec type had a satisfy method but no satisfy_malleable method, presumably because for multisigs, malleability is irrelevant. We needed to branch because SortedMultiVec is a distinct type, and then the branch wound up looking sus with one side saying satisfy and the other side saying satisfy_malleable, just because of this API gap.)
SO I think that in this PR, we just always want to call self.ms.satisfy_malleable, and not branch at all.
There was a problem hiding this comment.
I based it off of this, which is from the deleted SortedMultiVec.
- /// Attempt to produce a satisfying witness for the
- /// witness script represented by the parse tree
- pub fn satisfy<S>(&self, satisfier: S) -> Result<Vec<Vec<u8>>, Error>
- where
- Pk: ToPublicKey,
- S: Satisfier<Pk>,
- {
- let ms = Miniscript::from_ast(self.sorted_node()).expect("Multi node typecheck");
- ms.satisfy(satisfier)We needed to branch because SortedMultiVec is a distinct type, and then the branch wound up looking sus with one side saying satisfy and the other side saying satisfy_malleable, just because of this API gap.
I don't think I could have guessed that lol...trusting you and changing to only call satisfy_malleable
|
@apoelstra did a self-review with some questions. Let me know what you think, thanks! |
|
816620a needs rebase |
816620a to
f9d0bdd
Compare
|
f9d0bdd needs rebase |
b4d73ec to
366974f
Compare
| ShInner::Wsh(ref wsh) => { | ||
| let ms = wsh.as_inner(); | ||
| if let Terminal::SortedMulti(ref thresh) = ms.node { | ||
| PkIter::from_sortedmulti(thresh.data()) |
There was a problem hiding this comment.
There are tons of places in this crate where we suffer from this, and you'll find that if you keep trying to clean stuff up, you will run into missing language features basically every single time.
@apoelstra don't worry, in 2035 when specialization stabilizes we can get to it!
src/descriptor/segwitv0.rs
Outdated
| let mut witness = match self.inner { | ||
| WshInner::SortedMulti(ref smv) => smv.satisfy(satisfier)?, | ||
| WshInner::Ms(ref ms) => ms.satisfy_malleable(satisfier)?, | ||
| let mut witness = if let Terminal::SortedMulti(..) = self.ms.node { |
There was a problem hiding this comment.
I based it off of this, which is from the deleted SortedMultiVec.
- /// Attempt to produce a satisfying witness for the
- /// witness script represented by the parse tree
- pub fn satisfy<S>(&self, satisfier: S) -> Result<Vec<Vec<u8>>, Error>
- where
- Pk: ToPublicKey,
- S: Satisfier<Pk>,
- {
- let ms = Miniscript::from_ast(self.sorted_node()).expect("Multi node typecheck");
- ms.satisfy(satisfier)We needed to branch because SortedMultiVec is a distinct type, and then the branch wound up looking sus with one side saying satisfy and the other side saying satisfy_malleable, just because of this API gap.
I don't think I could have guessed that lol...trusting you and changing to only call satisfy_malleable
| | Terminal::Multi(_) | ||
| | Terminal::SortedMulti(_) | ||
| | Terminal::MultiA(_) | ||
| | Terminal::SortedMultiA(_) => { |
There was a problem hiding this comment.
Saw SortedMultiA was also missing from this.
| match (&self.node, n) { | ||
| (Terminal::PkK(key), 0) | (Terminal::PkH(key), 0) => Some(key.clone()), | ||
| (Terminal::Multi(thresh), _) => thresh.data().get(n).cloned(), | ||
| (Terminal::SortedMulti(thresh), _) => thresh.data().get(n).cloned(), |
There was a problem hiding this comment.
I missed this on the first iteration since type-driven development failed me with the _ => fallback.
@apoelstra It resolves the HACK that was mentioned in this comment.
| Terminal::Multi(ref thresh) | Terminal::SortedMulti(ref thresh) | ||
| if !thresh.iter().all(&mut pred) => | ||
| { |
- Utilize the Miniscript parsing to handle sortedmulti as a Terminal. - Deleted sortedmulti.rs (SortedMultiVec) - Refactor Wsh to only wrap a Miniscript now that SortedMultiVec isn't used. - Refactor ShInner to remove SortedMulti variant and only use the Ms variant for sortedmulti scripts
366974f to
941205b
Compare
sortedmulti scripts
Now that sortedmulti_a is supported as a Terminal, I think it makes sense to
move sortedmulti over in the same way by following what multi does and applying
the sorting functions that were introduced in eba1aff.
Like sortedmulti_a, sortedmulti is sorted upon encoding and cannot be decoded
into from Script.