Skip to content

Commit 4386463

Browse files
nickfarrowLLFourn
authored andcommitted
test plain tweaks and formatting
1 parent 7731fea commit 4386463

File tree

1 file changed

+74
-38
lines changed

1 file changed

+74
-38
lines changed

schnorr_fun/src/frost.rs

+74-38
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
//! ## FROST multisignature scheme
22
//!
33
//! The FROST (Flexible Round-Optimized Schnorr Threshold) multisignature scheme allows you aggregate
4-
//! multiple public keys into a single public key. To sign a message under this public key, a threshold t-of-n secret keys
4+
//! multiple public keys into a single joint public key. To sign a message under this public key, a threshold t-of-n secret keys
55
//! must use a common set of nonces to each produce a signature share. These signature shares are then combined
6-
//! to form a signature that is valid under the aggregate key.
6+
//! to form a signature that is valid under the joint public key.
77
//!
88
//! This implementation has **not yet** been made compatible with other existing FROST implementations
99
//! (notably [secp256k1-zkp]).
@@ -42,8 +42,8 @@
4242
//! let recieved_shares = vec![shares[0].clone(), shares2[0].clone(), shares3[0].clone()];
4343
//! # let recieved_shares3 = vec![shares[2].clone(), shares2[2].clone(), shares3[2].clone()];
4444
//! let proofs_of_possession = vec![pop, pop2, pop3];
45-
//! // finish keygen by verifying the shares we recieved as well as proofs-of-possession
46-
//! // and calulate our secret share of the joint FROST key
45+
//! // finish keygen by verifying the shares we recieved as well as proofs-of-possession,
46+
//! // and calulate our secret share of the joint FROST key.
4747
//! let (secret_share, frost_key) = frost
4848
//! .finish_keygen_to_xonly(
4949
//! keygen.clone(),
@@ -75,7 +75,6 @@
7575
//! ]
7676
//! .concat();
7777
//! # let sid3 = [
78-
//! # frost_key.joint_public_key.to_bytes().as_slice(),
7978
//! # verification_shares_bytes.concat().as_slice(),
8079
//! # b"frost-very-unique-id".as_slice(),
8180
//! # b"2".as_slice(),
@@ -89,7 +88,7 @@
8988
//! // recieve public nonces from other participants with their index
9089
//! let nonces = vec![(0, nonce.public()), (2, recieved_nonce3)];
9190
//! # let nonces3 = vec![(0, nonce.public()), (2, recieved_nonce3)];
92-
//! // start a sign session with these nonces for this message
91+
//! // start a sign session with these nonces for a message
9392
//! let session = frost.start_sign_session(&frost_key, nonces, Message::plain("test", b"test"));
9493
//! # let session3 = frost.start_sign_session(&frost_key, nonces3, Message::plain("test", b"test"));
9594
//! // create a partial signature using our secret share and secret nonce
@@ -423,7 +422,7 @@ impl FrostKey {
423422
}
424423
}
425424

426-
/// A [`FrostKey`] that has been converted into a [`XOnlyFrostKey`] key.
425+
/// A [`FrostKey`] that has been converted into an [`XOnlyFrostKey`] key.
427426
///
428427
/// This is the BIP340 compatible version of the key which you can put in a segwitv1 output and create BIP340 signatures under.
429428
/// Tweaks applied to a `XOnlyFrostKey` are XOnly tweaks to the joint public key.
@@ -900,7 +899,11 @@ mod test {
900899

901900
proptest! {
902901
#[test]
903-
fn frost_prop_test((n_parties, threshold) in (3u32..8).prop_flat_map(|n| (Just(n), 3u32..=n)), tweak1 in option::of(any::<Scalar<Public, Zero>>()), tweak2 in option::of(any::<Scalar<Public, Zero>>())) {
902+
fn frost_prop_test(
903+
(n_parties, threshold) in (3u32..8).prop_flat_map(|n| (Just(n), 3u32..=n)),
904+
tweak1 in option::of(any::<Scalar<Public, Zero>>()),
905+
tweak2 in option::of(any::<Scalar<Public, Zero>>())
906+
) {
904907
let frost = Frost::new(Schnorr::<Sha256, Deterministic<Sha256>>::new(
905908
Deterministic::<Sha256>::default(),
906909
));
@@ -910,7 +913,10 @@ mod test {
910913
// create some scalar polynomial for each party
911914
let mut scalar_polys = vec![];
912915
for i in 1..=n_parties {
913-
let scalar_poly = (1..=threshold).map(|j| Scalar::from_non_zero_u32(NonZeroU32::new(i*j).expect("starts from 1"))).collect();
916+
let scalar_poly = (1..=threshold).map(|j|
917+
Scalar::from_non_zero_u32(NonZeroU32::new(i*j)
918+
.expect("starts from 1")))
919+
.collect();
914920
scalar_polys.push(ScalarPoly::new(scalar_poly));
915921
}
916922
let point_polys: Vec<PointPoly> = scalar_polys.iter().map(|sp| sp.to_point_poly()).collect();
@@ -930,37 +936,45 @@ mod test {
930936
for party_index in 0..n_parties {
931937
recieved_shares.push(vec![]);
932938
for share_index in 0..n_parties {
933-
recieved_shares[party_index as usize].push(shares_vec[share_index as usize][party_index as usize].clone());
939+
recieved_shares[party_index as usize]
940+
.push(shares_vec[share_index as usize][party_index as usize].clone());
934941
}
935942
}
936943

937944
// finish keygen for each party
938945
let (secret_shares, frost_keys): (Vec<Scalar>, Vec<XOnlyFrostKey>) = (0..n_parties).map(|i| {
939-
let (secret_share, frost_key) = frost.finish_keygen(
946+
let (secret_share, mut frost_key) = frost.finish_keygen(
940947
KeyGen.clone(),
941948
i,
942949
recieved_shares[i as usize].clone(),
943950
proofs_of_possession.clone(),
944951
)
945952
.unwrap();
946-
let mut xonly_frost_key = frost_key.into_xonly_key();
953+
// apply some plain tweak
954+
if let Some(tweak) = tweak1 {
955+
frost_key = frost_key.tweak(tweak).unwrap();
956+
}
947957

948-
// apply some xonly tweaks
949-
for tweak in [tweak1, tweak2] {
950-
if let Some(tweak) = tweak {
951-
xonly_frost_key = xonly_frost_key.tweak(tweak).unwrap();
952-
}
958+
let mut xonly_frost_key = frost_key.into_xonly_key();
959+
// apply some xonly tweak
960+
if let Some(tweak) = tweak2 {
961+
xonly_frost_key = xonly_frost_key.tweak(tweak).unwrap();
953962
}
954963
(secret_share, xonly_frost_key)
955964
}).unzip();
956965

957966
// use a boolean mask for which t participants are signers
958967
let mut signer_mask = vec![true; threshold as usize];
959968
signer_mask.append(&mut vec![false; (n_parties - threshold) as usize]);
960-
// shuffle the mask for random signers (roughly shuffled and deterministic based on signers_mask_seed)
969+
// shuffle the mask for random signers
961970
signer_mask.shuffle(&mut TestRng::deterministic_rng(RngAlgorithm::ChaCha));
962971

963-
let signer_indexes: Vec<_> = signer_mask.iter().enumerate().filter(|(_, is_signer)| **is_signer).map(|(i,_)| i).collect();
972+
let signer_indexes: Vec<_> = signer_mask
973+
.iter()
974+
.enumerate()
975+
.filter(|(_, is_signer)| **is_signer)
976+
.map(|(i,_)| i)
977+
.collect();
964978

965979
let verification_shares_bytes: Vec<_> = frost_keys[signer_indexes[0]]
966980
.verification_shares
@@ -988,17 +1002,38 @@ mod test {
9881002
}
9891003

9901004
// Create Frost signing session
991-
let signing_session = frost.start_sign_session(&frost_keys[signer_indexes[0]], recieved_nonces.clone(), Message::plain("test", b"test"));
1005+
let signing_session = frost.start_sign_session(
1006+
&frost_keys[signer_indexes[0]],
1007+
recieved_nonces.clone(),
1008+
Message::plain("test", b"test")
1009+
);
9921010

9931011
let mut signatures = vec![];
9941012
for i in 0..signer_indexes.len() {
9951013
let signer_index = signer_indexes[i] as usize;
996-
let session = frost.start_sign_session(&frost_keys[signer_index], recieved_nonces.clone(), Message::plain("test", b"test"));
997-
let sig = frost.sign(&frost_keys[signer_index], &session, signer_index as u32, &secret_shares[signer_index], nonces[i].clone());
998-
assert!(frost.verify_signature_share(&frost_keys[signer_index], &session, signer_index as u32, sig));
1014+
let session = frost.start_sign_session(
1015+
&frost_keys[signer_index],
1016+
recieved_nonces.clone(),
1017+
Message::plain("test", b"test")
1018+
);
1019+
let sig = frost.sign(
1020+
&frost_keys[signer_index],
1021+
&session, signer_index as u32,
1022+
&secret_shares[signer_index],
1023+
nonces[i].clone()
1024+
);
1025+
assert!(frost.verify_signature_share(
1026+
&frost_keys[signer_index],
1027+
&session,
1028+
signer_index as u32,
1029+
sig)
1030+
);
9991031
signatures.push(sig);
10001032
}
1001-
let combined_sig = frost.combine_signature_shares(&frost_keys[signer_indexes[0] as usize], &signing_session, signatures);
1033+
let combined_sig = frost.combine_signature_shares(
1034+
&frost_keys[signer_indexes[0] as usize],
1035+
&signing_session,
1036+
signatures);
10021037

10031038
assert!(frost.schnorr.verify(
10041039
&frost_keys[signer_indexes[0] as usize].joint_public_key,
@@ -1030,23 +1065,23 @@ mod test {
10301065
let (shares3, pop3) = frost.create_shares(&KeyGen, sp3);
10311066
let proofs_of_possession = vec![pop1, pop2, pop3];
10321067

1033-
let (secret_share1, frost_key) = frost
1068+
let (secret_share1, mut frost_key) = frost
10341069
.finish_keygen(
10351070
KeyGen.clone(),
10361071
0,
10371072
vec![shares1[0].clone(), shares2[0].clone(), shares3[0].clone()],
10381073
proofs_of_possession.clone(),
10391074
)
10401075
.unwrap();
1041-
let (_secret_share2, frost_key2) = frost
1076+
let (_secret_share2, mut frost_key2) = frost
10421077
.finish_keygen(
10431078
KeyGen.clone(),
10441079
1,
10451080
vec![shares1[1].clone(), shares2[1].clone(), shares3[1].clone()],
10461081
proofs_of_possession.clone(),
10471082
)
10481083
.unwrap();
1049-
let (secret_share3, frost_key3) = frost
1084+
let (secret_share3, mut frost_key3) = frost
10501085
.finish_keygen(
10511086
KeyGen.clone(),
10521087
2,
@@ -1058,14 +1093,7 @@ mod test {
10581093
assert_eq!(frost_key, frost_key2);
10591094
assert_eq!(frost_key, frost_key3);
10601095

1061-
// Currently we are not doing any non-xonly tweak tests
1062-
let mut xonly_frost_key = frost_key.into_xonly_key();
1063-
let mut xonly_frost_key2 = frost_key2.into_xonly_key();
1064-
let mut xonly_frost_key3 = frost_key3.into_xonly_key();
1065-
1066-
assert_eq!(xonly_frost_key, xonly_frost_key2);
1067-
assert_eq!(xonly_frost_key, xonly_frost_key3);
1068-
1096+
// plain tweak
10691097
let use_tweak = true;
10701098
let tweak = if use_tweak {
10711099
Scalar::from_bytes([
@@ -1078,10 +1106,18 @@ mod test {
10781106
Scalar::zero()
10791107
};
10801108

1081-
xonly_frost_key = xonly_frost_key.tweak(tweak.clone()).expect("tweak worked");
1082-
xonly_frost_key2 = xonly_frost_key2.tweak(tweak.clone()).expect("tweak worked");
1083-
xonly_frost_key3 = xonly_frost_key3.tweak(tweak).expect("tweak worked");
1109+
frost_key = frost_key.tweak(tweak.clone()).expect("tweak worked");
1110+
frost_key2 = frost_key2.tweak(tweak.clone()).expect("tweak worked");
1111+
frost_key3 = frost_key3.tweak(tweak).expect("tweak worked");
1112+
1113+
let mut xonly_frost_key = frost_key.into_xonly_key();
1114+
let mut xonly_frost_key2 = frost_key2.into_xonly_key();
1115+
let mut xonly_frost_key3 = frost_key3.into_xonly_key();
1116+
1117+
assert_eq!(xonly_frost_key, xonly_frost_key2);
1118+
assert_eq!(xonly_frost_key, xonly_frost_key3);
10841119

1120+
// xonly tweak
10851121
let tweak = if use_tweak {
10861122
Scalar::from_bytes([
10871123
0xE8, 0xF7, 0x92, 0xFF, 0x92, 0x25, 0xA2, 0xAF, 0x01, 0x02, 0xAF, 0xFF, 0x4A, 0x9A,

0 commit comments

Comments
 (0)