-
Notifications
You must be signed in to change notification settings - Fork 5
Description
I believe that when specifying Bitocin related protocols we should only use xonly keys at the last moment when we need to produce something that goes on chain e.g a key or signature. In retrospect xonly keys may have been a mistake but I think if we take this approach we can minimise the complexity they introduce and maybe make that 1 byte we save worth it!
Of course is not how the current spec is written. It takes in xonly keys into key aggregation and outputs a key in a kind of hybrid state that can be used to sign with as an xonly key but can also be tweaked as a ordinary key or xonly key. Applying the JIT xonly approach here means taking a two stage key generation approach. First, the inputs to key aggregation would be ordinary keys and the output would be an ordinary key. This ordinary key could then have bip32 tweaks applied to it. Eventually it could be turned into into a xonly key that could have xonly tweaks applied to it (no bip32 tweaks) and could be used to start a signing session.
Other than the complexity of all the negation accounting that has to go on with the way the spec is currently written what concerns me most is that people are going to want to do things like "nested MuSig" where each MuSig key may be another MuSig key (or even a FROST key). I can't clearly see how badly this will compound the problem but on the other hand I didn't expect xonly keys to introduce this much complexity in the first place.
So here's how I see pros and cons:
Pros:
- Less likely to be sprawling complexity with nested schemes or composition with other schemes.
- Only needs a single
gacc
negation flag (instead of the xor of three) applied at signing time. (see below) - BIP32 applied to keygen input and output is not ambiguous. Since MuSig is creating a xonly key to sign with then how should I apply BIP32 to it? I was thinking I should just put
02
in front of the xonly key. The correct answer is that there isGetBytes33
which returns the full internal ordinary key. It feels like MuSig can't make up its mind whether it works with xonly keys or not. - Set the precedent for the JIT xonly approach early so others can avoid mistakenly thinking that xonly inputs to ptotocols is what the experts think is the way to go.
Cons:
- Introduces a two-stage MuSig key state
- Breaks association of xonly as the public key for all schnorr signatures (although FROST will do this anyway so this is a pro to me)
- xonly keys would have to be converted to ordinary keys before being used as inputs in MuSig. You might need a different keypair type for MuSig than for Schnorr.
For me the pros overwhelm the cons. Of course I have left out the "con" that this will require some work to rewrite and re-engineer the spec. I had planned to implement all of this in the python spec and make a PR but I was informed that I should make this suggestion as soon as possible because it was looking to be finalised soon.
Less negation variables
It is obvious why this change would get rid of the need of the gp/has_even_y(P)
flag . The less obvious result is how gacc
and g
can be merged into one. This comes because you can set the initial value of gacc
to has_even_y(Q)
when you go from ordinary aggregate key to xonly. In fact you can do this simplification without changing the type of input keys so this suggestion is somewhat orthogonal. For example here I implement the transition from a ordinary aggregate key to a BIP340 xonly aggregate key. This still uses xonly input keys. Though since this change implies a multi-stage keygen context anyway it makes sense that these things go together.
Let me know what you think and whether it's worth pursing doing the python implementation. Sorry again for suggesting big changes this late in the process.