From ac17645fc8c5e6eb22217c5ae6011db2c3334949 Mon Sep 17 00:00:00 2001 From: Luke Parker Date: Tue, 28 Jun 2022 00:06:12 -0400 Subject: [PATCH] Rename MultisigParams/MultisigKeys/MultisigView to Frost* --- coins/monero/src/ringct/clsag/multisig.rs | 8 ++--- coins/monero/src/wallet/send/multisig.rs | 4 +-- crypto/frost/src/algorithm.rs | 14 ++++---- crypto/frost/src/key_gen.rs | 25 +++++++------- crypto/frost/src/lib.rs | 40 +++++++++++------------ crypto/frost/src/sign.rs | 16 ++++----- crypto/frost/src/tests/curve.rs | 6 ++-- crypto/frost/src/tests/mod.rs | 10 +++--- crypto/frost/src/tests/schnorr.rs | 4 +-- crypto/frost/src/tests/vectors.rs | 8 ++--- processor/src/coin/mod.rs | 4 +-- processor/src/coin/monero.rs | 6 ++-- processor/src/wallet.rs | 12 +++---- 13 files changed, 79 insertions(+), 78 deletions(-) diff --git a/coins/monero/src/ringct/clsag/multisig.rs b/coins/monero/src/ringct/clsag/multisig.rs index dfeeda5f..8d15b0e2 100644 --- a/coins/monero/src/ringct/clsag/multisig.rs +++ b/coins/monero/src/ringct/clsag/multisig.rs @@ -14,7 +14,7 @@ use curve25519_dalek::{ use group::Group; use transcript::{Transcript, RecommendedTranscript}; -use frost::{curve::Ed25519, FrostError, MultisigView, algorithm::Algorithm}; +use frost::{curve::Ed25519, FrostError, FrostView, algorithm::Algorithm}; use dalek_ff_group as dfg; use crate::{ @@ -126,7 +126,7 @@ impl Algorithm for ClsagMultisig { fn preprocess_addendum( &mut self, rng: &mut R, - view: &MultisigView, + view: &FrostView, nonces: &[dfg::Scalar; 2] ) -> Vec { self.H = hash_to_point(&view.group_key().0); @@ -144,7 +144,7 @@ impl Algorithm for ClsagMultisig { fn process_addendum( &mut self, - view: &MultisigView, + view: &FrostView, l: u16, commitments: &[dfg::EdwardsPoint; 2], serialized: &[u8] @@ -192,7 +192,7 @@ impl Algorithm for ClsagMultisig { fn sign_share( &mut self, - view: &MultisigView, + view: &FrostView, nonce_sum: dfg::EdwardsPoint, b: dfg::Scalar, nonce: dfg::Scalar, diff --git a/coins/monero/src/wallet/send/multisig.rs b/coins/monero/src/wallet/send/multisig.rs index 67a39d93..c2de702c 100644 --- a/coins/monero/src/wallet/send/multisig.rs +++ b/coins/monero/src/wallet/send/multisig.rs @@ -8,7 +8,7 @@ use curve25519_dalek::{traits::Identity, scalar::Scalar, edwards::{EdwardsPoint, use transcript::{Transcript, RecommendedTranscript}; use frost::{ curve::Ed25519, - FrostError, MultisigKeys, + FrostError, FrostKeys, sign::{ PreprocessMachine, SignMachine, SignatureMachine, AlgorithmMachine, AlgorithmSignMachine, AlgorithmSignatureMachine @@ -57,7 +57,7 @@ impl SignableTransaction { pub async fn multisig( self, rpc: &Rpc, - keys: MultisigKeys, + keys: FrostKeys, mut transcript: RecommendedTranscript, height: usize, mut included: Vec diff --git a/crypto/frost/src/algorithm.rs b/crypto/frost/src/algorithm.rs index fbd1dec8..21d51521 100644 --- a/crypto/frost/src/algorithm.rs +++ b/crypto/frost/src/algorithm.rs @@ -4,7 +4,7 @@ use rand_core::{RngCore, CryptoRng}; use transcript::Transcript; -use crate::{Curve, FrostError, MultisigView, schnorr}; +use crate::{Curve, FrostError, FrostView, schnorr}; pub use schnorr::SchnorrSignature; /// Algorithm to use FROST with @@ -19,14 +19,14 @@ pub trait Algorithm: Clone { fn preprocess_addendum( &mut self, rng: &mut R, - params: &MultisigView, + params: &FrostView, nonces: &[C::F; 2], ) -> Vec; /// Proccess the addendum for the specified participant. Guaranteed to be ordered fn process_addendum( &mut self, - params: &MultisigView, + params: &FrostView, l: u16, commitments: &[C::G; 2], serialized: &[u8], @@ -38,7 +38,7 @@ pub trait Algorithm: Clone { /// The nonce will already have been processed into the combined form d + (e * p) fn sign_share( &mut self, - params: &MultisigView, + params: &FrostView, nonce_sum: C::G, binding: C::F, nonce: C::F, @@ -114,7 +114,7 @@ impl> Algorithm for Schnorr { fn preprocess_addendum( &mut self, _: &mut R, - _: &MultisigView, + _: &FrostView, _: &[C::F; 2], ) -> Vec { vec![] @@ -122,7 +122,7 @@ impl> Algorithm for Schnorr { fn process_addendum( &mut self, - _: &MultisigView, + _: &FrostView, _: u16, _: &[C::G; 2], _: &[u8], @@ -132,7 +132,7 @@ impl> Algorithm for Schnorr { fn sign_share( &mut self, - params: &MultisigView, + params: &FrostView, nonce_sum: C::G, _: C::F, nonce: C::F, diff --git a/crypto/frost/src/key_gen.rs b/crypto/frost/src/key_gen.rs index f48a82fd..aeb18ca0 100644 --- a/crypto/frost/src/key_gen.rs +++ b/crypto/frost/src/key_gen.rs @@ -8,7 +8,7 @@ use multiexp::{multiexp_vartime, BatchVerifier}; use crate::{ curve::Curve, - FrostError, MultisigParams, MultisigKeys, + FrostError, FrostParams, FrostKeys, schnorr::{self, SchnorrSignature}, validate_map }; @@ -29,7 +29,7 @@ fn challenge(context: &str, l: u16, R: &[u8], Am: &[u8]) -> C::F { // the serialized commitments to be broadcasted over an authenticated channel to all parties fn generate_key_r1( rng: &mut R, - params: &MultisigParams, + params: &FrostParams, context: &str, ) -> (Vec, Vec) { let t = usize::from(params.t); @@ -72,7 +72,7 @@ fn generate_key_r1( // Verify the received data from the first round of key generation fn verify_r1( rng: &mut R, - params: &MultisigParams, + params: &FrostParams, context: &str, our_commitments: Vec, mut serialized: HashMap>, @@ -149,7 +149,7 @@ fn polynomial( // counterparty to receive fn generate_key_r2( rng: &mut R, - params: &MultisigParams, + params: &FrostParams, context: &str, coefficients: Vec, our_commitments: Vec, @@ -190,12 +190,12 @@ fn generate_key_r2( /// broadcasted initially fn complete_r2( rng: &mut R, - params: MultisigParams, + params: FrostParams, mut secret_share: C::F, commitments: HashMap>, // Vec to preserve ownership mut serialized: HashMap>, -) -> Result, FrostError> { +) -> Result, FrostError> { validate_map( &mut serialized, &(1 ..= params.n()).into_iter().collect::>(), @@ -256,12 +256,13 @@ fn complete_r2( for i in 1 ..= params.n() { verification_shares.insert(i, multiexp_vartime(&exponential(i, &stripes), C::LITTLE_ENDIAN)); } + // Removing this check would enable optimizing the above from t + (n * t) to t + ((n - 1) * t) debug_assert_eq!(C::GENERATOR_TABLE * secret_share, verification_shares[¶ms.i()]); // TODO: Clear serialized and shares Ok( - MultisigKeys { + FrostKeys { params, secret_share, group_key: stripes[0], @@ -272,20 +273,20 @@ fn complete_r2( } pub struct KeyGenMachine { - params: MultisigParams, + params: FrostParams, context: String, _curve: PhantomData, } pub struct SecretShareMachine { - params: MultisigParams, + params: FrostParams, context: String, coefficients: Vec, our_commitments: Vec, } pub struct KeyMachine { - params: MultisigParams, + params: FrostParams, secret: C::F, commitments: HashMap>, } @@ -293,7 +294,7 @@ pub struct KeyMachine { impl KeyGenMachine { /// Creates a new machine to generate a key for the specified curve in the specified multisig // The context string must be unique among multisigs - pub fn new(params: MultisigParams, context: String) -> KeyGenMachine { + pub fn new(params: FrostParams, context: String) -> KeyGenMachine { KeyGenMachine { params, context, _curve: PhantomData } } @@ -351,7 +352,7 @@ impl KeyMachine { self, rng: &mut R, shares: HashMap>, - ) -> Result, FrostError> { + ) -> Result, FrostError> { complete_r2(rng, self.params, self.secret, self.commitments, shares) } } diff --git a/crypto/frost/src/lib.rs b/crypto/frost/src/lib.rs index 2e53b723..e337b70e 100644 --- a/crypto/frost/src/lib.rs +++ b/crypto/frost/src/lib.rs @@ -18,7 +18,7 @@ pub mod tests; /// Parameters for a multisig // These fields can not be made public as they should be static #[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct MultisigParams { +pub struct FrostParams { /// Participants needed to sign on behalf of the group t: u16, /// Amount of participants @@ -27,12 +27,12 @@ pub struct MultisigParams { i: u16, } -impl MultisigParams { +impl FrostParams { pub fn new( t: u16, n: u16, i: u16 - ) -> Result { + ) -> Result { if (t == 0) || (n == 0) { Err(FrostError::ZeroParameter(t, n))?; } @@ -46,7 +46,7 @@ impl MultisigParams { Err(FrostError::InvalidParticipantIndex(n, i))?; } - Ok(MultisigParams{ t, n, i }) + Ok(FrostParams{ t, n, i }) } pub fn t(&self) -> u16 { self.t } @@ -86,14 +86,14 @@ pub enum FrostError { // View of keys passable to algorithm implementations #[derive(Clone)] -pub struct MultisigView { +pub struct FrostView { group_key: C::G, included: Vec, secret_share: C::F, verification_shares: HashMap, } -impl MultisigView { +impl FrostView { pub fn group_key(&self) -> C::G { self.group_key } @@ -134,9 +134,9 @@ pub fn lagrange( } #[derive(Clone, PartialEq, Eq, Debug)] -pub struct MultisigKeys { - /// Multisig Parameters - params: MultisigParams, +pub struct FrostKeys { + /// FROST Parameters + params: FrostParams, /// Secret share key secret_share: C::F, @@ -149,12 +149,12 @@ pub struct MultisigKeys { offset: Option, } -impl MultisigKeys { +impl FrostKeys { /// Offset the keys by a given scalar to allow for account and privacy schemes /// This offset is ephemeral and will not be included when these keys are serialized /// Keys offset multiple times will form a new offset of their sum /// Not IETF compliant - pub fn offset(&self, offset: C::F) -> MultisigKeys { + pub fn offset(&self, offset: C::F) -> FrostKeys { let mut res = self.clone(); // Carry any existing offset // Enables schemes like Monero's subaddresses which have a per-subaddress offset and then a @@ -164,7 +164,7 @@ impl MultisigKeys { res } - pub fn params(&self) -> MultisigParams { + pub fn params(&self) -> FrostParams { self.params } @@ -180,7 +180,7 @@ impl MultisigKeys { self.verification_shares.clone() } - pub fn view(&self, included: &[u16]) -> Result, FrostError> { + pub fn view(&self, included: &[u16]) -> Result, FrostError> { if (included.len() < self.params.t.into()) || (usize::from(self.params.n) < included.len()) { Err(FrostError::InvalidSigningSet("invalid amount of participants included".to_string()))?; } @@ -189,7 +189,7 @@ impl MultisigKeys { let offset = self.offset.unwrap_or(C::F::zero()); let offset_share = offset * C::F::from(included.len().try_into().unwrap()).invert().unwrap(); - Ok(MultisigView { + Ok(FrostView { group_key: self.group_key, secret_share: secret_share + offset_share, verification_shares: self.verification_shares.iter().map( @@ -207,7 +207,7 @@ impl MultisigKeys { } pub fn serialize(&self) -> Vec { - let mut serialized = Vec::with_capacity(MultisigKeys::::serialized_len(self.params.n)); + let mut serialized = Vec::with_capacity(FrostKeys::::serialized_len(self.params.n)); serialized.extend(u64::try_from(C::ID.len()).unwrap().to_be_bytes()); serialized.extend(C::ID); serialized.extend(&self.params.t.to_be_bytes()); @@ -221,7 +221,7 @@ impl MultisigKeys { serialized } - pub fn deserialize(serialized: &[u8]) -> Result, FrostError> { + pub fn deserialize(serialized: &[u8]) -> Result, FrostError> { let mut start = u64::try_from(C::ID.len()).unwrap().to_be_bytes().to_vec(); start.extend(C::ID); let mut cursor = start.len(); @@ -229,7 +229,7 @@ impl MultisigKeys { if serialized.len() < (cursor + 4) { Err( FrostError::InternalError( - "MultisigKeys serialization is missing its curve/participant quantities".to_string() + "FrostKeys serialization is missing its curve/participant quantities".to_string() ) )?; } @@ -246,7 +246,7 @@ impl MultisigKeys { let n = u16::from_be_bytes(serialized[cursor .. (cursor + 2)].try_into().unwrap()); cursor += 2; - if serialized.len() != MultisigKeys::::serialized_len(n) { + if serialized.len() != FrostKeys::::serialized_len(n) { Err(FrostError::InternalError("incorrect serialization length".to_string()))?; } @@ -271,8 +271,8 @@ impl MultisigKeys { } Ok( - MultisigKeys { - params: MultisigParams::new(t, n, i) + FrostKeys { + params: FrostParams::new(t, n, i) .map_err(|_| FrostError::InternalError("invalid parameters".to_string()))?, secret_share, group_key, diff --git a/crypto/frost/src/sign.rs b/crypto/frost/src/sign.rs index 8ea0f61c..902607f7 100644 --- a/crypto/frost/src/sign.rs +++ b/crypto/frost/src/sign.rs @@ -10,24 +10,24 @@ use transcript::Transcript; use crate::{ curve::Curve, FrostError, - MultisigParams, MultisigKeys, MultisigView, + FrostParams, FrostKeys, FrostView, algorithm::Algorithm, validate_map }; -/// Pairing of an Algorithm with a MultisigKeys instance and this specific signing set +/// Pairing of an Algorithm with a FrostKeys instance and this specific signing set #[derive(Clone)] pub struct Params> { algorithm: A, - keys: Arc>, - view: MultisigView, + keys: Arc>, + view: FrostView, } // Currently public to enable more complex operations as desired, yet solely used in testing impl> Params { pub fn new( algorithm: A, - keys: Arc>, + keys: Arc>, included: &[u16], ) -> Result, FrostError> { let mut included = included.to_vec(); @@ -60,11 +60,11 @@ impl> Params { Ok(Params { algorithm, view: keys.view(&included).unwrap(), keys }) } - pub fn multisig_params(&self) -> MultisigParams { + pub fn multisig_params(&self) -> FrostParams { self.keys.params } - pub fn view(&self) -> MultisigView { + pub fn view(&self) -> FrostView { self.view.clone() } } @@ -291,7 +291,7 @@ impl> AlgorithmMachine { /// Creates a new machine to generate a key for the specified curve in the specified multisig pub fn new( algorithm: A, - keys: Arc>, + keys: Arc>, included: &[u16], ) -> Result, FrostError> { Ok(AlgorithmMachine { params: Params::new(algorithm, keys, included)? }) diff --git a/crypto/frost/src/tests/curve.rs b/crypto/frost/src/tests/curve.rs index d7327605..48dd78de 100644 --- a/crypto/frost/src/tests/curve.rs +++ b/crypto/frost/src/tests/curve.rs @@ -2,7 +2,7 @@ use rand_core::{RngCore, CryptoRng}; use group::{ff::Field, Group}; -use crate::{Curve, MultisigKeys, tests::key_gen}; +use crate::{Curve, FrostKeys, tests::key_gen}; // Test generation of FROST keys fn key_generation(rng: &mut R) { @@ -13,7 +13,7 @@ fn key_generation(rng: &mut R) { // Test serialization of generated keys fn keys_serialization(rng: &mut R) { for (_, keys) in key_gen::<_, C>(rng) { - assert_eq!(&MultisigKeys::::deserialize(&keys.serialize()).unwrap(), &*keys); + assert_eq!(&FrostKeys::::deserialize(&keys.serialize()).unwrap(), &*keys); } } @@ -35,7 +35,7 @@ pub fn test_curve(rng: &mut R) { } } - // Test FROST key generation and serialization of MultisigKeys works as expected + // Test FROST key generation and serialization of FrostKeys works as expected key_generation::<_, C>(rng); keys_serialization::<_, C>(rng); } diff --git a/crypto/frost/src/tests/mod.rs b/crypto/frost/src/tests/mod.rs index fa45f6f1..87f2bf83 100644 --- a/crypto/frost/src/tests/mod.rs +++ b/crypto/frost/src/tests/mod.rs @@ -6,7 +6,7 @@ use group::ff::Field; use crate::{ Curve, - MultisigParams, MultisigKeys, + FrostParams, FrostKeys, lagrange, key_gen::KeyGenMachine, algorithm::Algorithm, @@ -36,12 +36,12 @@ pub fn clone_without( pub fn key_gen( rng: &mut R -) -> HashMap>> { +) -> HashMap>> { let mut machines = HashMap::new(); let mut commitments = HashMap::new(); for i in 1 ..= PARTICIPANTS { let machine = KeyGenMachine::::new( - MultisigParams::new(THRESHOLD, PARTICIPANTS, i).unwrap(), + FrostParams::new(THRESHOLD, PARTICIPANTS, i).unwrap(), "FROST Test key_gen".to_string() ); let (machine, these_commitments) = machine.generate_coefficients(rng); @@ -89,7 +89,7 @@ pub fn key_gen( }).collect::>() } -pub fn recover(keys: &HashMap>) -> C::F { +pub fn recover(keys: &HashMap>) -> C::F { let first = keys.values().next().expect("no keys provided"); assert!(keys.len() >= first.params().t().into(), "not enough keys provided"); let included = keys.keys().cloned().collect::>(); @@ -105,7 +105,7 @@ pub fn recover(keys: &HashMap>) -> C::F { pub fn algorithm_machines>( rng: &mut R, algorithm: A, - keys: &HashMap>>, + keys: &HashMap>>, ) -> HashMap> { let mut included = vec![]; while included.len() < usize::from(keys[&1].params().t()) { diff --git a/crypto/frost/src/tests/schnorr.rs b/crypto/frost/src/tests/schnorr.rs index c9550577..7ef1806a 100644 --- a/crypto/frost/src/tests/schnorr.rs +++ b/crypto/frost/src/tests/schnorr.rs @@ -5,7 +5,7 @@ use rand_core::{RngCore, CryptoRng}; use group::ff::Field; use crate::{ - Curve, MultisigKeys, schnorr::{self, SchnorrSignature}, algorithm::{Hram, Schnorr}, + Curve, FrostKeys, schnorr::{self, SchnorrSignature}, algorithm::{Hram, Schnorr}, tests::{key_gen, algorithm_machines, sign as sign_test} }; @@ -80,7 +80,7 @@ pub(crate) fn core_batch_verify(rng: &mut R) { fn sign_core( rng: &mut R, group_key: C::G, - keys: &HashMap>> + keys: &HashMap>> ) { const MESSAGE: &'static [u8] = b"Hello, World!"; diff --git a/crypto/frost/src/tests/vectors.rs b/crypto/frost/src/tests/vectors.rs index e0def162..00f745fb 100644 --- a/crypto/frost/src/tests/vectors.rs +++ b/crypto/frost/src/tests/vectors.rs @@ -3,7 +3,7 @@ use std::{sync::Arc, collections::HashMap}; use rand_core::{RngCore, CryptoRng}; use crate::{ - Curve, MultisigKeys, + Curve, FrostKeys, algorithm::{Schnorr, Hram}, sign::{PreprocessPackage, SignMachine, SignatureMachine, AlgorithmMachine}, tests::{curve::test_curve, schnorr::test_schnorr, recover} @@ -22,8 +22,8 @@ pub struct Vectors { pub sig: String } -// Load these vectors into MultisigKeys using a custom serialization it'll deserialize -fn vectors_to_multisig_keys(vectors: &Vectors) -> HashMap> { +// Load these vectors into FrostKeys using a custom serialization it'll deserialize +fn vectors_to_multisig_keys(vectors: &Vectors) -> HashMap> { let shares = vectors.shares.iter().map( |secret| C::F_from_slice(&hex::decode(secret).unwrap()).unwrap() ).collect::>(); @@ -45,7 +45,7 @@ fn vectors_to_multisig_keys(vectors: &Vectors) -> HashMap::deserialize(&serialized).unwrap(); + let these_keys = FrostKeys::::deserialize(&serialized).unwrap(); assert_eq!(these_keys.params().t(), vectors.threshold); assert_eq!(usize::from(these_keys.params().n()), shares.len()); assert_eq!(these_keys.params().i(), i); diff --git a/processor/src/coin/mod.rs b/processor/src/coin/mod.rs index 79945665..6e7308db 100644 --- a/processor/src/coin/mod.rs +++ b/processor/src/coin/mod.rs @@ -4,7 +4,7 @@ use async_trait::async_trait; use thiserror::Error; use transcript::RecommendedTranscript; -use frost::{curve::Curve, MultisigKeys, sign::PreprocessMachine}; +use frost::{curve::Curve, FrostKeys, sign::PreprocessMachine}; pub mod monero; pub use self::monero::Monero; @@ -57,7 +57,7 @@ pub trait Coin { async fn prepare_send( &self, - keys: Arc>, + keys: Arc>, transcript: RecommendedTranscript, height: usize, inputs: Vec, diff --git a/processor/src/coin/monero.rs b/processor/src/coin/monero.rs index 5e045892..980dedde 100644 --- a/processor/src/coin/monero.rs +++ b/processor/src/coin/monero.rs @@ -6,7 +6,7 @@ use curve25519_dalek::scalar::Scalar; use dalek_ff_group as dfg; use transcript::RecommendedTranscript; -use frost::{curve::Ed25519, MultisigKeys}; +use frost::{curve::Ed25519, FrostKeys}; use monero_serai::{ transaction::{Timelock, Transaction}, @@ -52,7 +52,7 @@ impl From for Output { #[derive(Debug)] pub struct SignableTransaction( - Arc>, + Arc>, RecommendedTranscript, usize, MSignableTransaction @@ -140,7 +140,7 @@ impl Coin for Monero { async fn prepare_send( &self, - keys: Arc>, + keys: Arc>, transcript: RecommendedTranscript, height: usize, mut inputs: Vec, diff --git a/processor/src/wallet.rs b/processor/src/wallet.rs index 6789cb8f..79458ce1 100644 --- a/processor/src/wallet.rs +++ b/processor/src/wallet.rs @@ -4,17 +4,17 @@ use rand_core::OsRng; use transcript::{Transcript, RecommendedTranscript}; -use frost::{curve::Curve, MultisigKeys, sign::{PreprocessMachine, SignMachine, SignatureMachine}}; +use frost::{curve::Curve, FrostKeys, sign::{PreprocessMachine, SignMachine, SignatureMachine}}; use crate::{coin::{CoinError, Output, Coin}, SignError, Network}; pub struct WalletKeys { - keys: MultisigKeys, + keys: FrostKeys, creation_height: usize } impl WalletKeys { - pub fn new(keys: MultisigKeys, creation_height: usize) -> WalletKeys { + pub fn new(keys: FrostKeys, creation_height: usize) -> WalletKeys { WalletKeys { keys, creation_height } } @@ -26,7 +26,7 @@ impl WalletKeys { // system, there are potentially other benefits to binding this to a specific group key // It's no longer possible to influence group key gen to key cancel without breaking the hash // function as well, although that degree of influence means key gen is broken already - fn bind(&self, chain: &[u8]) -> MultisigKeys { + fn bind(&self, chain: &[u8]) -> FrostKeys { const DST: &[u8] = b"Serai Processor Wallet Chain Bind"; let mut transcript = RecommendedTranscript::new(DST); transcript.append_message(b"chain", chain); @@ -200,8 +200,8 @@ fn select_inputs_outputs( pub struct Wallet { db: D, coin: C, - keys: Vec<(Arc>, Vec)>, - pending: Vec<(usize, MultisigKeys)> + keys: Vec<(Arc>, Vec)>, + pending: Vec<(usize, FrostKeys)> } impl Wallet {