mirror of
https://github.com/serai-dex/serai.git
synced 2025-01-22 02:34:55 +00:00
Expand and correct documentation
This commit is contained in:
parent
19cd609cba
commit
ca091a5f04
18 changed files with 137 additions and 118 deletions
|
@ -4,4 +4,16 @@ A modern Monero transaction library intended for usage in wallets. It prides
|
|||
itself on accuracy, correctness, and removing common pit falls developers may
|
||||
face.
|
||||
|
||||
Threshold multisignature support is available via the `multisig` feature.
|
||||
monero-serai contains safety features, such as first-class acknowledgement of
|
||||
the burning bug, yet also a high level API around creating transactions.
|
||||
monero-serai also offers a FROST-based multisig, which is orders of magnitude
|
||||
more performant than Monero's.
|
||||
|
||||
monero-serai was written for Serai, a decentralized exchange aiming to support
|
||||
Monero. Despite this, monero-serai is intended to be a widely usable library,
|
||||
accurate to Monero. monero-serai guarantees the functionality needed for Serai,
|
||||
yet will not deprive functionality from other users, and may potentially leave
|
||||
Serai's umbrella at some point.
|
||||
|
||||
Various legacy transaction formats are not currently implemented, yet
|
||||
monero-serai is still increasing its support for various transaction types.
|
||||
|
|
5
coins/monero/generators/README.md
Normal file
5
coins/monero/generators/README.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
# Monero Generators
|
||||
|
||||
Generators used by Monero in both its Pedersen commitments and Bulletproofs(+).
|
||||
An implementation of Monero's `ge_fromfe_frombytes_vartime`, simply called
|
||||
`hash_to_point` here, is included, as needed to generate generators.
|
|
@ -1,3 +1,7 @@
|
|||
//! Generators used by Monero in both its Pedersen commitments and Bulletproofs(+).
|
||||
//! An implementation of Monero's `ge_fromfe_frombytes_vartime`, simply called
|
||||
//! `hash_to_point` here, is included, as needed to generate generators.
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
use tiny_keccak::{Hasher, Keccak};
|
||||
|
|
|
@ -34,12 +34,17 @@ pub(crate) mod frost;
|
|||
|
||||
mod serialize;
|
||||
|
||||
/// RingCT structs and functionality.
|
||||
pub mod ringct;
|
||||
|
||||
/// Transaction structs.
|
||||
pub mod transaction;
|
||||
/// Block structs.
|
||||
pub mod block;
|
||||
|
||||
/// Monero daemon RPC interface.
|
||||
pub mod rpc;
|
||||
/// Wallet functionality, enabling scanning and sending transactions.
|
||||
pub mod wallet;
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -5,7 +5,9 @@ use curve25519_dalek::{constants::ED25519_BASEPOINT_TABLE, scalar::Scalar, edwar
|
|||
pub(crate) mod hash_to_point;
|
||||
pub use hash_to_point::{raw_hash_to_point, hash_to_point};
|
||||
|
||||
/// CLSAG struct, along with signing and verifying functionality.
|
||||
pub mod clsag;
|
||||
/// Bulletproofs(+) structs, along with proving and verifying functionality.
|
||||
pub mod bulletproofs;
|
||||
|
||||
use crate::{
|
||||
|
|
|
@ -13,6 +13,7 @@ use crate::{hash, hash_to_scalar, serialize::write_varint, transaction::Input};
|
|||
mod extra;
|
||||
pub(crate) use extra::{PaymentId, ExtraField, Extra};
|
||||
|
||||
/// Address encoding and decoding functionality.
|
||||
pub mod address;
|
||||
use address::{Network, AddressType, AddressMeta, Address};
|
||||
|
||||
|
|
|
@ -167,7 +167,7 @@ macro_rules! from_uint {
|
|||
};
|
||||
}
|
||||
|
||||
/// Wrapper around the dalek Scalar type
|
||||
/// Wrapper around the dalek Scalar type.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Default, Debug, Zeroize)]
|
||||
pub struct Scalar(pub DScalar);
|
||||
deref_borrow!(Scalar, DScalar);
|
||||
|
@ -176,12 +176,12 @@ math_neg!(Scalar, Scalar, DScalar::add, DScalar::sub, DScalar::mul);
|
|||
from_uint!(Scalar, DScalar);
|
||||
|
||||
impl Scalar {
|
||||
/// Perform wide reduction on a 64-byte array to create a Scalar without bias
|
||||
/// Perform wide reduction on a 64-byte array to create a Scalar without bias.
|
||||
pub fn from_bytes_mod_order_wide(bytes: &[u8; 64]) -> Scalar {
|
||||
Self(DScalar::from_bytes_mod_order_wide(bytes))
|
||||
}
|
||||
|
||||
/// Derive a Scalar without bias from a digest via wide reduction
|
||||
/// Derive a Scalar without bias from a digest via wide reduction.
|
||||
pub fn from_hash<D: Digest<OutputSize = U64>>(hash: D) -> Scalar {
|
||||
let mut output = [0u8; 64];
|
||||
output.copy_from_slice(&hash.finalize());
|
||||
|
@ -287,7 +287,7 @@ macro_rules! dalek_group {
|
|||
$BASEPOINT_POINT: ident,
|
||||
$BASEPOINT_TABLE: ident
|
||||
) => {
|
||||
/// Wrapper around the dalek Point type. For Ed25519, this is restricted to the prime subgroup
|
||||
/// Wrapper around the dalek Point type. For Ed25519, this is restricted to the prime subgroup.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Zeroize)]
|
||||
pub struct $Point(pub $DPoint);
|
||||
deref_borrow!($Point, $DPoint);
|
||||
|
@ -355,7 +355,7 @@ macro_rules! dalek_group {
|
|||
impl PrimeGroup for $Point {}
|
||||
|
||||
/// Wrapper around the dalek Table type, offering efficient multiplication against the
|
||||
/// basepoint
|
||||
/// basepoint.
|
||||
pub struct $Table(pub $DTable);
|
||||
deref_borrow!($Table, $DTable);
|
||||
pub const $BASEPOINT_TABLE: $Table = $Table(constants::$BASEPOINT_TABLE);
|
||||
|
|
|
@ -277,11 +277,11 @@ where
|
|||
/// Prove the cross-Group Discrete Log Equality for the points derived from the scalar created as
|
||||
/// the output of the passed in Digest. Given the non-standard requirements to achieve
|
||||
/// uniformity, needing to be < 2^x instead of less than a prime moduli, this is the simplest way
|
||||
/// to safely and securely generate a Scalar, without risk of failure, nor bias
|
||||
/// to safely and securely generate a Scalar, without risk of failure, nor bias.
|
||||
/// It also ensures a lack of determinable relation between keys, guaranteeing security in the
|
||||
/// currently expected use case for this, atomic swaps, where each swap leaks the key. Knowing
|
||||
/// the relationship between keys would allow breaking all swaps after just one
|
||||
pub fn prove<R: RngCore + CryptoRng, T: Clone + Transcript, D: Digest>(
|
||||
/// the relationship between keys would allow breaking all swaps after just one.
|
||||
rng: &mut R,
|
||||
transcript: &mut T,
|
||||
generators: (Generators<G0>, Generators<G1>),
|
||||
|
@ -297,7 +297,7 @@ where
|
|||
|
||||
/// Prove the cross-Group Discrete Log Equality for the points derived from the scalar passed in,
|
||||
/// failing if it's not mutually valid. This allows for rejection sampling externally derived
|
||||
/// scalars until they're safely usable, as needed
|
||||
/// scalars until they're safely usable, as needed.
|
||||
pub fn prove_without_bias<R: RngCore + CryptoRng, T: Clone + Transcript>(
|
||||
rng: &mut R,
|
||||
transcript: &mut T,
|
||||
|
@ -307,7 +307,7 @@ where
|
|||
scalar_convert(f0).map(|f1| Self::prove_internal(rng, transcript, generators, (f0, f1)))
|
||||
}
|
||||
|
||||
/// Verify a cross-Group Discrete Log Equality statement, returning the points proven for
|
||||
/// Verify a cross-Group Discrete Log Equality statement, returning the points proven for.
|
||||
pub fn verify<R: RngCore + CryptoRng, T: Clone + Transcript>(
|
||||
&self,
|
||||
rng: &mut R,
|
||||
|
|
|
@ -2,7 +2,7 @@ use ff::PrimeFieldBits;
|
|||
|
||||
use zeroize::Zeroize;
|
||||
|
||||
/// Convert a uniform scalar into one usable on both fields, clearing the top bits as needed
|
||||
/// Convert a uniform scalar into one usable on both fields, clearing the top bits as needed.
|
||||
pub fn scalar_normalize<F0: PrimeFieldBits + Zeroize, F1: PrimeFieldBits>(
|
||||
mut scalar: F0,
|
||||
) -> (F0, F1) {
|
||||
|
@ -45,7 +45,7 @@ pub fn scalar_normalize<F0: PrimeFieldBits + Zeroize, F1: PrimeFieldBits>(
|
|||
(res1, res2)
|
||||
}
|
||||
|
||||
/// Helper to convert a scalar between fields. Returns None if the scalar isn't mutually valid
|
||||
/// Helper to convert a scalar between fields. Returns None if the scalar isn't mutually valid.
|
||||
pub fn scalar_convert<F0: PrimeFieldBits + Zeroize, F1: PrimeFieldBits>(
|
||||
mut scalar: F0,
|
||||
) -> Option<F1> {
|
||||
|
@ -56,7 +56,7 @@ pub fn scalar_convert<F0: PrimeFieldBits + Zeroize, F1: PrimeFieldBits>(
|
|||
res
|
||||
}
|
||||
|
||||
/// Create a mutually valid scalar from bytes via bit truncation to not introduce bias
|
||||
/// Create a mutually valid scalar from bytes via bit truncation to not introduce bias.
|
||||
pub fn mutual_scalar_from_bytes<F0: PrimeFieldBits + Zeroize, F1: PrimeFieldBits>(
|
||||
bytes: &[u8],
|
||||
) -> (F0, F1) {
|
||||
|
|
|
@ -8,27 +8,27 @@ use transcript::Transcript;
|
|||
use crate::{Curve, FrostError, FrostView, schnorr};
|
||||
pub use schnorr::SchnorrSignature;
|
||||
|
||||
/// Algorithm to use FROST with
|
||||
/// Algorithm to use FROST with.
|
||||
pub trait Algorithm<C: Curve>: Clone {
|
||||
type Transcript: Transcript + Clone + Debug;
|
||||
/// The resulting type of the signatures this algorithm will produce
|
||||
/// The resulting type of the signatures this algorithm will produce.
|
||||
type Signature: Clone + PartialEq + Debug;
|
||||
|
||||
/// Obtain a mutable borrow of the underlying transcript
|
||||
/// Obtain a mutable borrow of the underlying transcript.
|
||||
fn transcript(&mut self) -> &mut Self::Transcript;
|
||||
|
||||
/// Obtain the list of nonces to generate, as specified by the basepoints to create commitments
|
||||
/// against per-nonce. These are not committed to by FROST on the underlying transcript
|
||||
/// Obtain the list of nonces to generate, as specified by the basepoints to create commitments.
|
||||
/// against per-nonce. These are not committed to by FROST on the underlying transcript.
|
||||
fn nonces(&self) -> Vec<Vec<C::G>>;
|
||||
|
||||
/// Generate an addendum to FROST"s preprocessing stage
|
||||
/// Generate an addendum to FROST"s preprocessing stage.
|
||||
fn preprocess_addendum<R: RngCore + CryptoRng>(
|
||||
&mut self,
|
||||
rng: &mut R,
|
||||
params: &FrostView<C>,
|
||||
) -> 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<Re: Read>(
|
||||
&mut self,
|
||||
params: &FrostView<C>,
|
||||
|
@ -36,10 +36,10 @@ pub trait Algorithm<C: Curve>: Clone {
|
|||
reader: &mut Re,
|
||||
) -> Result<(), FrostError>;
|
||||
|
||||
/// Sign a share with the given secret/nonce
|
||||
/// Sign a share with the given secret/nonce.
|
||||
/// The secret will already have been its lagrange coefficient applied so it is the necessary
|
||||
/// key share
|
||||
/// The nonce will already have been processed into the combined form d + (e * p)
|
||||
/// key share.
|
||||
/// The nonce will already have been processed into the combined form d + (e * p).
|
||||
fn sign_share(
|
||||
&mut self,
|
||||
params: &FrostView<C>,
|
||||
|
@ -48,12 +48,12 @@ pub trait Algorithm<C: Curve>: Clone {
|
|||
msg: &[u8],
|
||||
) -> C::F;
|
||||
|
||||
/// Verify a signature
|
||||
/// Verify a signature.
|
||||
#[must_use]
|
||||
fn verify(&self, group_key: C::G, nonces: &[Vec<C::G>], sum: C::F) -> Option<Self::Signature>;
|
||||
|
||||
/// Verify a specific share given as a response. Used to determine blame if signature
|
||||
/// verification fails
|
||||
/// verification fails.
|
||||
#[must_use]
|
||||
fn verify_share(&self, verification_share: C::G, nonces: &[Vec<C::G>], share: C::F) -> bool;
|
||||
}
|
||||
|
@ -84,8 +84,8 @@ impl Transcript for IetfTranscript {
|
|||
}
|
||||
|
||||
pub trait Hram<C: Curve>: Clone {
|
||||
/// HRAM function to generate a challenge
|
||||
/// H2 from the IETF draft despite having a different argument set (not pre-formatted)
|
||||
/// HRAM function to generate a challenge.
|
||||
/// H2 from the IETF draft, despite having a different argument set (not being pre-formatted).
|
||||
#[allow(non_snake_case)]
|
||||
fn hram(R: &C::G, A: &C::G, m: &[u8]) -> C::F;
|
||||
}
|
||||
|
@ -109,7 +109,7 @@ impl<C: Curve, H: Hram<C>> Schnorr<C, H> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Implementation of Schnorr signatures for use with FROST
|
||||
/// Implementation of Schnorr signatures for use with FROST.
|
||||
impl<C: Curve, H: Hram<C>> Algorithm<C> for Schnorr<C, H> {
|
||||
type Transcript = IetfTranscript;
|
||||
type Signature = SchnorrSignature<C>;
|
||||
|
|
|
@ -29,7 +29,7 @@ mod ed448;
|
|||
#[cfg(feature = "ed448")]
|
||||
pub use ed448::{Ed448, Ietf8032Ed448Hram, NonIetfEd448Hram};
|
||||
|
||||
/// Set of errors for curve-related operations, namely encoding and decoding
|
||||
/// Set of errors for curve-related operations, namely encoding and decoding.
|
||||
#[derive(Clone, Error, Debug)]
|
||||
pub enum CurveError {
|
||||
#[error("invalid scalar")]
|
||||
|
@ -38,23 +38,23 @@ pub enum CurveError {
|
|||
InvalidPoint,
|
||||
}
|
||||
|
||||
/// Unified trait to manage a field/group
|
||||
/// Unified trait to manage an elliptic curve.
|
||||
// This should be moved into its own crate if the need for generic cryptography over ff/group
|
||||
// continues, which is the exact reason ff/group exists (to provide a generic interface)
|
||||
// elliptic-curve exists, yet it doesn't really serve the same role, nor does it use &[u8]/Vec<u8>
|
||||
// It uses GenericArray which will hopefully be deprecated as Rust evolves and doesn't offer enough
|
||||
// advantages in the modern day to be worth the hassle -- Kayaba
|
||||
pub trait Curve: Clone + Copy + PartialEq + Eq + Debug + Zeroize {
|
||||
/// Scalar field element type
|
||||
/// Scalar field element type.
|
||||
// This is available via G::Scalar yet `C::G::Scalar` is ambiguous, forcing horrific accesses
|
||||
type F: PrimeField + PrimeFieldBits + Zeroize;
|
||||
/// Group element type
|
||||
/// Group element type.
|
||||
type G: Group<Scalar = Self::F> + GroupOps + PrimeGroup + Zeroize;
|
||||
|
||||
/// ID for this curve
|
||||
/// ID for this curve.
|
||||
const ID: &'static [u8];
|
||||
|
||||
/// Generator for the group
|
||||
/// Generator for the group.
|
||||
// While group does provide this in its API, privacy coins may want to use a custom basepoint
|
||||
fn generator() -> Self::G;
|
||||
|
||||
|
@ -66,22 +66,22 @@ pub trait Curve: Clone + Copy + PartialEq + Eq + Debug + Zeroize {
|
|||
#[allow(non_snake_case)]
|
||||
fn hash_to_F(dst: &[u8], msg: &[u8]) -> Self::F;
|
||||
|
||||
/// Hash the message for the binding factor. H4 from the IETF draft
|
||||
/// Hash the message for the binding factor. H4 from the IETF draft.
|
||||
fn hash_msg(msg: &[u8]) -> Vec<u8> {
|
||||
Self::hash_to_vec(b"msg", msg)
|
||||
}
|
||||
|
||||
/// Hash the commitments for the binding factor. H5 from the IETF draft
|
||||
/// Hash the commitments for the binding factor. H5 from the IETF draft.
|
||||
fn hash_commitments(commitments: &[u8]) -> Vec<u8> {
|
||||
Self::hash_to_vec(b"com", commitments)
|
||||
}
|
||||
|
||||
/// Hash the commitments and message to calculate the binding factor. H1 from the IETF draft
|
||||
/// Hash the commitments and message to calculate the binding factor. H1 from the IETF draft.
|
||||
fn hash_binding_factor(binding: &[u8]) -> Self::F {
|
||||
Self::hash_to_F(b"rho", binding)
|
||||
}
|
||||
|
||||
/// Securely generate a random nonce. H3 from the IETF draft
|
||||
/// Securely generate a random nonce. H3 from the IETF draft.
|
||||
fn random_nonce<R: RngCore + CryptoRng>(mut secret: Self::F, rng: &mut R) -> Self::F {
|
||||
let mut seed = vec![0; 32];
|
||||
rng.fill_bytes(&mut seed);
|
||||
|
|
|
@ -178,10 +178,8 @@ fn generate_key_r2<Re: Read, R: RngCore + CryptoRng, C: Curve>(
|
|||
}
|
||||
|
||||
/// Finishes round 2 and returns both the secret share and the serialized public key.
|
||||
/// This key is not usable until all parties confirm they have completed the protocol without
|
||||
/// issue, yet simply confirming protocol completion without issue is enough to confirm the same
|
||||
/// key was generated as long as a lack of duplicated commitments was also confirmed when they were
|
||||
/// broadcasted initially
|
||||
/// This key MUST NOT be considered usable until all parties confirm they have completed the
|
||||
/// protocol without issue.
|
||||
fn complete_r2<Re: Read, R: RngCore + CryptoRng, C: Curve>(
|
||||
rng: &mut R,
|
||||
params: FrostParams,
|
||||
|
@ -291,15 +289,16 @@ impl<C: Curve> Drop for KeyMachine<C> {
|
|||
impl<C: Curve> ZeroizeOnDrop for KeyMachine<C> {}
|
||||
|
||||
impl<C: Curve> KeyGenMachine<C> {
|
||||
/// Creates a new machine to generate a key for the specified curve in the specified multisig
|
||||
// The context string must be unique among multisigs
|
||||
/// Creates a new machine to generate a key for the specified curve in the specified multisig.
|
||||
// The context string should be unique among multisigs.
|
||||
pub fn new(params: FrostParams, context: String) -> KeyGenMachine<C> {
|
||||
KeyGenMachine { params, context, _curve: PhantomData }
|
||||
}
|
||||
|
||||
/// Start generating a key according to the FROST DKG spec
|
||||
/// Start generating a key according to the FROST DKG spec.
|
||||
/// Returns a serialized list of commitments to be sent to all parties over an authenticated
|
||||
/// channel. If any party submits multiple sets of commitments, they MUST be treated as malicious
|
||||
/// channel. If any party submits multiple sets of commitments, they MUST be treated as
|
||||
/// malicious.
|
||||
pub fn generate_coefficients<R: RngCore + CryptoRng>(
|
||||
self,
|
||||
rng: &mut R,
|
||||
|
@ -320,11 +319,9 @@ impl<C: Curve> KeyGenMachine<C> {
|
|||
}
|
||||
|
||||
impl<C: Curve> SecretShareMachine<C> {
|
||||
/// Continue generating a key
|
||||
/// Takes in everyone else's commitments, which are expected to be in a Vec where participant
|
||||
/// index = Vec index. An empty vector is expected at index 0 to allow for this. An empty vector
|
||||
/// is also expected at index i which is locally handled. Returns a byte vector representing a
|
||||
/// secret share for each other participant which should be encrypted before sending
|
||||
/// Continue generating a key.
|
||||
/// Takes in everyone else's commitments. Returns a HashMap of byte vectors representing secret
|
||||
/// shares. These MUST be encrypted and only then sent to their respective participants.
|
||||
pub fn generate_secret_shares<Re: Read, R: RngCore + CryptoRng>(
|
||||
mut self,
|
||||
rng: &mut R,
|
||||
|
@ -343,12 +340,10 @@ impl<C: Curve> SecretShareMachine<C> {
|
|||
}
|
||||
|
||||
impl<C: Curve> KeyMachine<C> {
|
||||
/// Complete key generation
|
||||
/// Takes in everyone elses' shares submitted to us as a Vec, expecting participant index =
|
||||
/// Vec index with an empty vector at index 0 and index i. Returns a byte vector representing the
|
||||
/// group's public key, while setting a valid secret share inside the machine. > t participants
|
||||
/// must report completion without issue before this key can be considered usable, yet you should
|
||||
/// wait for all participants to report as such
|
||||
/// Complete key generation.
|
||||
/// Takes in everyone elses' shares submitted to us. Returns a FrostCore object representing the
|
||||
/// generated keys. Successful protocol completion MUST be confirmed by all parties before these
|
||||
/// keys may be safely used.
|
||||
pub fn complete<Re: Read, R: RngCore + CryptoRng>(
|
||||
mut self,
|
||||
rng: &mut R,
|
||||
|
|
|
@ -51,15 +51,15 @@ pub(crate) fn validate_map<T>(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Parameters for a multisig
|
||||
/// Parameters for a multisig.
|
||||
// These fields can not be made public as they should be static
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
pub struct FrostParams {
|
||||
/// Participants needed to sign on behalf of the group
|
||||
/// Participants needed to sign on behalf of the group.
|
||||
t: u16,
|
||||
/// Amount of participants
|
||||
/// Amount of participants.
|
||||
n: u16,
|
||||
/// Index of the participant being acted for
|
||||
/// Index of the participant being acted for.
|
||||
i: u16,
|
||||
}
|
||||
|
||||
|
@ -122,7 +122,7 @@ pub enum FrostError {
|
|||
InternalError(&'static str),
|
||||
}
|
||||
|
||||
/// Calculate the lagrange coefficient for a signing set
|
||||
/// Calculate the lagrange coefficient for a signing set.
|
||||
pub fn lagrange<F: PrimeField>(i: u16, included: &[u16]) -> F {
|
||||
let mut num = F::one();
|
||||
let mut denom = F::one();
|
||||
|
@ -141,18 +141,18 @@ pub fn lagrange<F: PrimeField>(i: u16, included: &[u16]) -> F {
|
|||
num * denom.invert().unwrap()
|
||||
}
|
||||
|
||||
/// Core keys generated by performing a FROST keygen protocol
|
||||
/// Core keys generated by performing a FROST keygen protocol.
|
||||
#[derive(Clone, PartialEq, Eq, Zeroize)]
|
||||
pub struct FrostCore<C: Curve> {
|
||||
/// FROST Parameters
|
||||
/// FROST Parameters.
|
||||
#[zeroize(skip)]
|
||||
params: FrostParams,
|
||||
|
||||
/// Secret share key
|
||||
/// Secret share key.
|
||||
secret_share: C::F,
|
||||
/// Group key
|
||||
/// Group key.
|
||||
group_key: C::G,
|
||||
/// Verification shares
|
||||
/// Verification shares.
|
||||
#[zeroize(skip)]
|
||||
verification_shares: HashMap<u16, C::G>,
|
||||
}
|
||||
|
@ -273,14 +273,14 @@ impl<C: Curve> FrostCore<C> {
|
|||
}
|
||||
}
|
||||
|
||||
/// FROST keys usable for signing
|
||||
/// FROST keys usable for signing.
|
||||
#[derive(Clone, Debug, Zeroize)]
|
||||
pub struct FrostKeys<C: Curve> {
|
||||
/// Core keys
|
||||
/// Core keys.
|
||||
#[zeroize(skip)]
|
||||
core: Arc<FrostCore<C>>,
|
||||
|
||||
/// Offset applied to these keys
|
||||
/// Offset applied to these keys.
|
||||
pub(crate) offset: Option<C::F>,
|
||||
}
|
||||
|
||||
|
@ -315,10 +315,10 @@ impl<C: Curve> FrostKeys<C> {
|
|||
FrostKeys { core: Arc::new(core), offset: None }
|
||||
}
|
||||
|
||||
/// 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
|
||||
/// 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) -> FrostKeys<C> {
|
||||
let mut res = self.clone();
|
||||
// Carry any existing offset
|
||||
|
@ -336,12 +336,12 @@ impl<C: Curve> FrostKeys<C> {
|
|||
self.core.secret_share
|
||||
}
|
||||
|
||||
/// Returns the group key with any offset applied
|
||||
/// Returns the group key with any offset applied.
|
||||
pub fn group_key(&self) -> C::G {
|
||||
self.core.group_key + (C::generator() * self.offset.unwrap_or_else(C::F::zero))
|
||||
}
|
||||
|
||||
/// Returns all participants' verification shares without any offsetting
|
||||
/// Returns all participants' verification shares without any offsetting.
|
||||
pub(crate) fn verification_shares(&self) -> HashMap<u16, C::G> {
|
||||
self.core.verification_shares()
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ use crate::{
|
|||
FrostError, FrostCore, FrostKeys, validate_map,
|
||||
};
|
||||
|
||||
/// Promote a set of keys to another Curve definition
|
||||
/// Promote a set of keys to another Curve definition.
|
||||
pub trait CurvePromote<C2: Curve> {
|
||||
#[doc(hidden)]
|
||||
#[allow(non_snake_case)]
|
||||
|
@ -86,7 +86,7 @@ pub struct GeneratorPromotion<C1: Curve, C2: Curve> {
|
|||
_c2: PhantomData<C2>,
|
||||
}
|
||||
|
||||
/// Promote a set of keys from one generator to another
|
||||
/// Promote a set of keys from one generator to another.
|
||||
// The linear DLEq proofs are much more efficient than an exponential key gen
|
||||
impl<C1: Curve, C2: Curve> GeneratorPromotion<C1, C2>
|
||||
where
|
||||
|
|
|
@ -22,7 +22,7 @@ use crate::{
|
|||
curve::Curve, FrostError, FrostParams, FrostKeys, FrostView, algorithm::Algorithm, validate_map,
|
||||
};
|
||||
|
||||
/// Pairing of an Algorithm with a FrostKeys instance and this specific signing set
|
||||
/// Pairing of an Algorithm with a FrostKeys instance and this specific signing set.
|
||||
#[derive(Clone)]
|
||||
pub struct Params<C: Curve, A: Algorithm<C>> {
|
||||
algorithm: A,
|
||||
|
@ -369,20 +369,17 @@ pub trait PreprocessMachine {
|
|||
type Signature: Clone + PartialEq + fmt::Debug;
|
||||
type SignMachine: SignMachine<Self::Signature>;
|
||||
|
||||
/// Perform the preprocessing round required in order to sign
|
||||
/// Returns a byte vector which must be transmitted to all parties selected for this signing
|
||||
/// process, over an authenticated channel
|
||||
/// Perform the preprocessing round required in order to sign.
|
||||
/// Returns a byte vector to be broadcast to all participants, over an authenticated channel.
|
||||
fn preprocess<R: RngCore + CryptoRng>(self, rng: &mut R) -> (Self::SignMachine, Vec<u8>);
|
||||
}
|
||||
|
||||
pub trait SignMachine<S> {
|
||||
type SignatureMachine: SignatureMachine<S>;
|
||||
|
||||
/// Sign a message
|
||||
/// Takes in the participant's commitments, which are expected to be in a Vec where participant
|
||||
/// index = Vec index. None is expected at index 0 to allow for this. None is also expected at
|
||||
/// index i which is locally handled. Returns a byte vector representing a share of the signature
|
||||
/// for every other participant to receive, over an authenticated channel
|
||||
/// Sign a message.
|
||||
/// Takes in the participants' preprocesses. Returns a byte vector representing a signature share
|
||||
/// to be broadcast to all participants, over an authenticated channel.
|
||||
fn sign<Re: Read>(
|
||||
self,
|
||||
commitments: HashMap<u16, Re>,
|
||||
|
@ -391,14 +388,12 @@ pub trait SignMachine<S> {
|
|||
}
|
||||
|
||||
pub trait SignatureMachine<S> {
|
||||
/// Complete signing
|
||||
/// Takes in everyone elses' shares submitted to us as a Vec, expecting participant index =
|
||||
/// Vec index with None at index 0 and index i. Returns a byte vector representing the serialized
|
||||
/// signature
|
||||
/// Complete signing.
|
||||
/// Takes in everyone elses' shares. Returns the signature.
|
||||
fn complete<Re: Read>(self, shares: HashMap<u16, Re>) -> Result<S, FrostError>;
|
||||
}
|
||||
|
||||
/// State machine which manages signing for an arbitrary signature algorithm
|
||||
/// State machine which manages signing for an arbitrary signature algorithm.
|
||||
pub struct AlgorithmMachine<C: Curve, A: Algorithm<C>> {
|
||||
params: Params<C, A>,
|
||||
}
|
||||
|
@ -414,7 +409,7 @@ pub struct AlgorithmSignatureMachine<C: Curve, A: Algorithm<C>> {
|
|||
}
|
||||
|
||||
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 signature with the specified keys.
|
||||
pub fn new(
|
||||
algorithm: A,
|
||||
keys: FrostKeys<C>,
|
||||
|
|
|
@ -11,22 +11,22 @@ use digest::{typenum::type_operators::IsGreaterOrEqual, consts::U256, Digest, Ou
|
|||
pub trait Transcript {
|
||||
type Challenge: Clone + Send + Sync + AsRef<[u8]>;
|
||||
|
||||
/// Create a new transcript with the specified name
|
||||
/// Create a new transcript with the specified name.
|
||||
fn new(name: &'static [u8]) -> Self;
|
||||
|
||||
/// Apply a domain separator to the transcript
|
||||
/// Apply a domain separator to the transcript.
|
||||
fn domain_separate(&mut self, label: &'static [u8]);
|
||||
|
||||
/// Append a message to the transcript
|
||||
/// Append a message to the transcript.
|
||||
fn append_message(&mut self, label: &'static [u8], message: &[u8]);
|
||||
|
||||
/// Produce a challenge. This MUST update the transcript as it does so, preventing the same
|
||||
/// challenge from being generated multiple times
|
||||
/// challenge from being generated multiple times.
|
||||
fn challenge(&mut self, label: &'static [u8]) -> Self::Challenge;
|
||||
|
||||
/// Produce a RNG seed. Helper function for parties needing to generate random data from an
|
||||
/// agreed upon state. Internally calls the challenge function for the needed bytes, converting
|
||||
/// them to the seed format rand_core expects
|
||||
/// them to the seed format rand_core expects.
|
||||
fn rng_seed(&mut self, label: &'static [u8]) -> [u8; 32];
|
||||
}
|
||||
|
||||
|
@ -50,12 +50,12 @@ impl DigestTranscriptMember {
|
|||
}
|
||||
}
|
||||
|
||||
/// A trait defining Digests with at least a 256-byte output size, assuming at least a 128-bit
|
||||
/// level of security accordingly
|
||||
pub trait SecureDigest: Clone + Digest {}
|
||||
impl<D: Clone + Digest> SecureDigest for D where D::OutputSize: IsGreaterOrEqual<U256> {}
|
||||
/// A trait defining cryptographic Digests with at least a 256-byte output size, assuming at least
|
||||
/// a 128-bit level of security accordingly.
|
||||
|
||||
/// A simple transcript format constructed around the specified hash algorithm
|
||||
/// A simple transcript format constructed around the specified hash algorithm.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct DigestTranscript<D: SecureDigest>(D);
|
||||
|
||||
|
|
|
@ -11,35 +11,35 @@ pub struct Cli {
|
|||
|
||||
#[derive(Debug, clap::Subcommand)]
|
||||
pub enum Subcommand {
|
||||
/// Key management CLI utilities
|
||||
// Key management CLI utilities
|
||||
#[clap(subcommand)]
|
||||
Key(sc_cli::KeySubcommand),
|
||||
|
||||
/// Build a chain specification
|
||||
// Build a chain specification
|
||||
BuildSpec(sc_cli::BuildSpecCmd),
|
||||
|
||||
/// Validate blocks
|
||||
// Validate blocks
|
||||
CheckBlock(sc_cli::CheckBlockCmd),
|
||||
|
||||
/// Export blocks
|
||||
// Export blocks
|
||||
ExportBlocks(sc_cli::ExportBlocksCmd),
|
||||
|
||||
/// Export the state of a given block into a chain spec
|
||||
// Export the state of a given block into a chain spec
|
||||
ExportState(sc_cli::ExportStateCmd),
|
||||
|
||||
/// Import blocks
|
||||
// Import blocks
|
||||
ImportBlocks(sc_cli::ImportBlocksCmd),
|
||||
|
||||
/// Remove the entire chain
|
||||
// Remove the entire chain
|
||||
PurgeChain(sc_cli::PurgeChainCmd),
|
||||
|
||||
/// Revert the chain to a previous state
|
||||
// Revert the chain to a previous state
|
||||
Revert(sc_cli::RevertCmd),
|
||||
|
||||
/// Sub-commands concerned with benchmarking
|
||||
// Sub-commands concerned with benchmarking
|
||||
#[clap(subcommand)]
|
||||
Benchmark(frame_benchmarking_cli::BenchmarkCmd),
|
||||
|
||||
/// DB meta columns information
|
||||
// DB meta columns information
|
||||
ChainInfo(sc_cli::ChainInfoCmd),
|
||||
}
|
||||
|
|
|
@ -31,23 +31,23 @@ pub use pallet_balances::Call as BalancesCall;
|
|||
use pallet_transaction_payment::CurrencyAdapter;
|
||||
use pallet_contracts::{migration, DefaultContractAccessWeight};
|
||||
|
||||
/// An index to a block
|
||||
/// An index to a block.
|
||||
pub type BlockNumber = u32;
|
||||
|
||||
/// Alias to 512-bit hash when used in the context of a transaction signature on the chain
|
||||
/// Alias to 512-bit hash when used in the context of a transaction signature on the chain.
|
||||
pub type Signature = MultiSignature;
|
||||
|
||||
/// Some way of identifying an account on the chain. We intentionally make it equivalent
|
||||
/// to the public key of our transaction signing scheme
|
||||
/// to the public key of our transaction signing scheme.
|
||||
pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;
|
||||
|
||||
/// Balance of an account
|
||||
/// Balance of an account.
|
||||
pub type Balance = u64;
|
||||
|
||||
/// Index of a transaction in the chain, for a given account
|
||||
/// Index of a transaction in the chain, for a given account.
|
||||
pub type Index = u32;
|
||||
|
||||
/// A hash of some data used by the chain
|
||||
/// A hash of some data used by the chain.
|
||||
pub type Hash = sp_core::H256;
|
||||
|
||||
pub mod opaque {
|
||||
|
@ -79,7 +79,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
|
|||
pub const MILLISECS_PER_BLOCK: u64 = 6000;
|
||||
pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK;
|
||||
|
||||
/// Measured in blocks
|
||||
/// Measured in blocks.
|
||||
pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);
|
||||
pub const HOURS: BlockNumber = MINUTES * 60;
|
||||
pub const DAYS: BlockNumber = HOURS * 24;
|
||||
|
|
Loading…
Reference in a new issue