-
Notifications
You must be signed in to change notification settings - Fork 169
Description
I am starting to realize that most operations one might want to do on a Descriptor are only meaningful either if the descriptor has all the keys in their "extended" form or if all of them are "derived", not both: generally speaking, all the operations that need to call to_public_key() somewhere want the derived keys (and there are actual assertions in the code to ensure that), while other functions that work on the full paths of the keys like matches() want the original descriptor with the wildcard keys.
I think it would be nice to have the compiler check that the right methods are called on the right descriptor, and one way to do that would be to add a PhatomData "tag" to the Pk type that basically carries this information. For instance, the MiniscriptKey trait could be changed to take a type argument which we could call, let's say, "KeyState" and there would be two possibile "states", one called "Extended" and one called "Derived".
For key types that cannot be derived further by definition, only the "Derived" type would be implemented (i.e. impl MiniscriptKey<Derived> for bitcoin::PublicKey), while for types that can be derived like DescriptorPublicKey both would be implemented with a generic. Then, ToPublicKey would only be implemented for the Derived version, which would ensure that all the methods that need to_public_key() cannot possibly be called on a non-derived key. Other methods like derive() and matches() would instead only be available for Descriptors where their key type is Extended, like: impl<Pk: MiniscriptKey<Extended>> Descriptor<Pk> ... . The derive() method would obviously be responsible for translating the keys from the Extended state to the Derived state.
I haven't actually tried implementing this concept (yet), so there's a good chance that this is either not useful at all, completely broken, or just not the best way to do it, but I'm curious to hear your feedback on this topic!