-
Notifications
You must be signed in to change notification settings - Fork 28
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
[frost] Make "tweaks" mutate #190
Conversation
In case you want a non-zero point generically
Prior to this commit tweaks were being stored in a separate field inside `FrostKey` and were applied at signature combination time. In frostsnap we actually want to be able to do "one-way" tweaks where you forget the original polynomial (at least the first coefficient). This is not an API safety concern but we strictly don't want the original to exist anymore. The next problem we address is that we don't want you to need the full polynomial for signing. Instead we make the user provide a "paired" secret share which is the secret scalar and index paired with the shared key (first coefficient of polynomial). This is a convenient combination since it allows you to hash the shared key to figure out a tweak and then apply it to both the shared key and the shared secret.
ec8a662
to
5bea2bd
Compare
So it doesn't start with zero points.
This is reviewable now. Please excuse poor documentation. I think I'll do a full sweep after I've attempted implementing the bip. See #189 for why I did multiplicative tweaking. |
Thank you for the PR ! I have rebased my work on top of this PR here, everything ok. I also tested add and mul tweaks on signet, separately and together, both worked. The awkward parts were 1) applying tweaks to both Consider these minor nits :) Thank you again ! Also particularly appreciate |
Hmm I was actually thinking you wouldn't have to do this unless in your protocol signers are also verifying signature shares (which I guess in LN context is likely).
Good point I think |
What drives this for me at the moment: EDIT: and the |
@irriden I can relax this a bit but you will need |
To make arithmetic API simpler at the cost of making the caller call `.non_zero()` etc
15677b5
to
29962aa
Compare
@irriden see the two last commits. Hopefully the tweaking is more straightforward now. There is no longer two variants of tweakings "xonly" and normal tweaks. To do an xonly tweak you just do a normal I've made it so you don't need a |
Right now I am not verifying signature shares, I am leaving identifiable aborts for later :)
All sounds great thank you !
Seems to me So EDIT: I do see that these two params could be created explicitly without creating a Do not worry too much about this, I'm happy to ensure tweaks are applied to both
Yes, just the final signature, not the partial signatures. |
So it's clearer how you can avoid a coordinator
See 4e22279 where I make a method to make it more discoverable how this is meant to work. |
Thank you ! I am going to keep using the Nonetheless seems to me this would be particularly useful in the case where one of the parties is used as the coordinator. |
schnorr_fun/src/frost/shared_key.rs
Outdated
/// Constructor to create a from a vector of points where each item represent a polynomial | ||
/// coefficient. | ||
/// | ||
/// Returns `None` if the first coefficient is [`Point::zero`]. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not true anymore. It can be None
is the poly is empty. I think I might make two different from_poly
s one for Zero
and another for NonZero
. The Zero
one will be infallible.
[edit] maybe just the Zero
one and call non_zero
to get the non_zero one.
Pair the secret shares using the shared key so you know it's correct. Also cleaned up the accessing the public key in order to do the implementation. ..and some other misc changes 🤗
No need to clone here
As well as make more generic the bincode/serde impls
/// The resulting shared key will be `SharedKey<Normal, Zero>`. It's up to the caller to do the zero check with [`non_zero`] | ||
/// | ||
/// [`non_zero`]: Self::non_zero | ||
pub fn from_poly(poly: Vec<Point<Normal, Public, Zero>>) -> Self { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this again because there's nothing special about preventing Zero
for a shared key?
I always feel weird seeing it allowed. Why avoid panics when the user passes an empty poly for the shared key? (maybe they just don't know it but have a secret share?)
} | ||
|
||
/// The public key the session was started under | ||
pub fn public_key(&self) -> Point<EvenY> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I liked how you re-allowed SharedKey to be Normal
, but here the signing session is forced into a BIP340 context. No problem for us but maybe other people would want signing for Normal
keys?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no way to sign with Normal
keys though.
schnorr_fun/src/frost/shared_key.rs
Outdated
/// encoded as 33 bytes. | ||
/// | ||
/// ⚠ Unlike other secp256kfun things this doesn't exactly match the serde/bincode | ||
/// implemenations which will length prefix the list of points. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am curious as to why? Or is this just a note that serde/bincode prefix the length so you'll have to keep that in mind if you mix & match?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the first time I'm creating a to_bytes
on something that is variable length and I just felt like noting the difference. Maybe the comment is more trouble than it's worth. You definitely shouldn't mix and match.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed you made all the public keys shared_key
and then changed back. Looks like they are no longer going with shared_key
on the BIP also!
Very much like 🐙 = coordinator
Proptest with all the variations of tweaks looks very robust.
One completely unrelated thing I just noticed is that create_shares_and_pop
is kind of confusing, makes it sound like something is getting popped off a vec.
I didn't look too deeply into the secp256kfun casting between point types etc. but the idea of checking the types like this makes sense.
There's quite a few spelling mistakes, not sure whether you care much for that, happy to fix up in commit or another PR. Everything else LGTM!
signature share verification was unnecessarily slow because you get to regenerate their whole verification share each time. Now you can cache it. Also verification shares are only for EvenY keys. We now have a concept of "share image" which is more general I'm not entirely sure I like but I'll leave it in for now.
I just pushed a commit to make "verification shares" a first class type. Now you use the verification shares to verify signature shares. @irriden you can now create a polynomial from "share images" rather than "verification shares" because verification shares are strictly something you can verify a signature share against (i.e. homomorphically linked to a
heh it will be gone soon I hope.
Feel free to push doc fixes you catch at anytime. I fixed up a few given that you made me self-conscious about it! |
There's no need for the `Frost` type to do signing/verification. It's needed to start the session but not after.
Added 84ac38b which made things make a bit more sense. |
Hi @LLFourn, Thank you for the ping. For now I remain on 151c6d6.
where That's all the info that an individual signer gets. The individual signer doesn't get the "share images" of the other signers. My solution will be to get rid of the |
Prior to this PR tweaks were being stored in a separate field inside
FrostKey
and were applied at signature combination time. In frostsnap we actually want to be able to do "one-way" tweaks where you forget the original polynomial (at least the first coefficient). This is not an API safety concern but we strictly don't want the original to exist anymore in memory.The next problem we address is that we don't want you to need the full polynomial for signing. Instead we make the user provide a "paired" secret share which is the secret scalar and index paired with the shared key (first coefficient of polynomial). This is a convenient combination since it allows you to hash the shared key to figure out a tweak and then apply it to both the shared key and the shared secret.
See commits individually. eb6dc14 is the frost only one.
I haven't updated docs yet because I intend to integrate some bip-frost stuff which will change the API again. I haven't updated the examples yet so this is not really mergable.