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