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
|
itself on accuracy, correctness, and removing common pit falls developers may
|
||||||
face.
|
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 lazy_static::lazy_static;
|
||||||
|
|
||||||
use tiny_keccak::{Hasher, Keccak};
|
use tiny_keccak::{Hasher, Keccak};
|
||||||
|
|
|
@ -34,12 +34,17 @@ pub(crate) mod frost;
|
||||||
|
|
||||||
mod serialize;
|
mod serialize;
|
||||||
|
|
||||||
|
/// RingCT structs and functionality.
|
||||||
pub mod ringct;
|
pub mod ringct;
|
||||||
|
|
||||||
|
/// Transaction structs.
|
||||||
pub mod transaction;
|
pub mod transaction;
|
||||||
|
/// Block structs.
|
||||||
pub mod block;
|
pub mod block;
|
||||||
|
|
||||||
|
/// Monero daemon RPC interface.
|
||||||
pub mod rpc;
|
pub mod rpc;
|
||||||
|
/// Wallet functionality, enabling scanning and sending transactions.
|
||||||
pub mod wallet;
|
pub mod wallet;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -5,7 +5,9 @@ use curve25519_dalek::{constants::ED25519_BASEPOINT_TABLE, scalar::Scalar, edwar
|
||||||
pub(crate) mod hash_to_point;
|
pub(crate) mod hash_to_point;
|
||||||
pub use hash_to_point::{raw_hash_to_point, 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;
|
pub mod clsag;
|
||||||
|
/// Bulletproofs(+) structs, along with proving and verifying functionality.
|
||||||
pub mod bulletproofs;
|
pub mod bulletproofs;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
|
@ -13,6 +13,7 @@ use crate::{hash, hash_to_scalar, serialize::write_varint, transaction::Input};
|
||||||
mod extra;
|
mod extra;
|
||||||
pub(crate) use extra::{PaymentId, ExtraField, Extra};
|
pub(crate) use extra::{PaymentId, ExtraField, Extra};
|
||||||
|
|
||||||
|
/// Address encoding and decoding functionality.
|
||||||
pub mod address;
|
pub mod address;
|
||||||
use address::{Network, AddressType, AddressMeta, 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)]
|
#[derive(Clone, Copy, PartialEq, Eq, Default, Debug, Zeroize)]
|
||||||
pub struct Scalar(pub DScalar);
|
pub struct Scalar(pub DScalar);
|
||||||
deref_borrow!(Scalar, DScalar);
|
deref_borrow!(Scalar, DScalar);
|
||||||
|
@ -176,12 +176,12 @@ math_neg!(Scalar, Scalar, DScalar::add, DScalar::sub, DScalar::mul);
|
||||||
from_uint!(Scalar, DScalar);
|
from_uint!(Scalar, DScalar);
|
||||||
|
|
||||||
impl Scalar {
|
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 {
|
pub fn from_bytes_mod_order_wide(bytes: &[u8; 64]) -> Scalar {
|
||||||
Self(DScalar::from_bytes_mod_order_wide(bytes))
|
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 {
|
pub fn from_hash<D: Digest<OutputSize = U64>>(hash: D) -> Scalar {
|
||||||
let mut output = [0u8; 64];
|
let mut output = [0u8; 64];
|
||||||
output.copy_from_slice(&hash.finalize());
|
output.copy_from_slice(&hash.finalize());
|
||||||
|
@ -287,7 +287,7 @@ macro_rules! dalek_group {
|
||||||
$BASEPOINT_POINT: ident,
|
$BASEPOINT_POINT: ident,
|
||||||
$BASEPOINT_TABLE: 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)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug, Zeroize)]
|
||||||
pub struct $Point(pub $DPoint);
|
pub struct $Point(pub $DPoint);
|
||||||
deref_borrow!($Point, $DPoint);
|
deref_borrow!($Point, $DPoint);
|
||||||
|
@ -355,7 +355,7 @@ macro_rules! dalek_group {
|
||||||
impl PrimeGroup for $Point {}
|
impl PrimeGroup for $Point {}
|
||||||
|
|
||||||
/// Wrapper around the dalek Table type, offering efficient multiplication against the
|
/// Wrapper around the dalek Table type, offering efficient multiplication against the
|
||||||
/// basepoint
|
/// basepoint.
|
||||||
pub struct $Table(pub $DTable);
|
pub struct $Table(pub $DTable);
|
||||||
deref_borrow!($Table, $DTable);
|
deref_borrow!($Table, $DTable);
|
||||||
pub const $BASEPOINT_TABLE: $Table = $Table(constants::$BASEPOINT_TABLE);
|
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
|
/// 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
|
/// 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
|
/// 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
|
/// 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
|
/// 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>(
|
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,
|
rng: &mut R,
|
||||||
transcript: &mut T,
|
transcript: &mut T,
|
||||||
generators: (Generators<G0>, Generators<G1>),
|
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,
|
/// 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
|
/// 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>(
|
pub fn prove_without_bias<R: RngCore + CryptoRng, T: Clone + Transcript>(
|
||||||
rng: &mut R,
|
rng: &mut R,
|
||||||
transcript: &mut T,
|
transcript: &mut T,
|
||||||
|
@ -307,7 +307,7 @@ where
|
||||||
scalar_convert(f0).map(|f1| Self::prove_internal(rng, transcript, generators, (f0, f1)))
|
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>(
|
pub fn verify<R: RngCore + CryptoRng, T: Clone + Transcript>(
|
||||||
&self,
|
&self,
|
||||||
rng: &mut R,
|
rng: &mut R,
|
||||||
|
|
|
@ -2,7 +2,7 @@ use ff::PrimeFieldBits;
|
||||||
|
|
||||||
use zeroize::Zeroize;
|
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>(
|
pub fn scalar_normalize<F0: PrimeFieldBits + Zeroize, F1: PrimeFieldBits>(
|
||||||
mut scalar: F0,
|
mut scalar: F0,
|
||||||
) -> (F0, F1) {
|
) -> (F0, F1) {
|
||||||
|
@ -45,7 +45,7 @@ pub fn scalar_normalize<F0: PrimeFieldBits + Zeroize, F1: PrimeFieldBits>(
|
||||||
(res1, res2)
|
(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>(
|
pub fn scalar_convert<F0: PrimeFieldBits + Zeroize, F1: PrimeFieldBits>(
|
||||||
mut scalar: F0,
|
mut scalar: F0,
|
||||||
) -> Option<F1> {
|
) -> Option<F1> {
|
||||||
|
@ -56,7 +56,7 @@ pub fn scalar_convert<F0: PrimeFieldBits + Zeroize, F1: PrimeFieldBits>(
|
||||||
res
|
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>(
|
pub fn mutual_scalar_from_bytes<F0: PrimeFieldBits + Zeroize, F1: PrimeFieldBits>(
|
||||||
bytes: &[u8],
|
bytes: &[u8],
|
||||||
) -> (F0, F1) {
|
) -> (F0, F1) {
|
||||||
|
|
|
@ -8,27 +8,27 @@ use transcript::Transcript;
|
||||||
use crate::{Curve, FrostError, FrostView, 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.
|
||||||
pub trait Algorithm<C: Curve>: Clone {
|
pub trait Algorithm<C: Curve>: Clone {
|
||||||
type Transcript: Transcript + Clone + Debug;
|
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;
|
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;
|
fn transcript(&mut self) -> &mut Self::Transcript;
|
||||||
|
|
||||||
/// Obtain the list of nonces to generate, as specified by the basepoints to create commitments
|
/// 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
|
/// against per-nonce. These are not committed to by FROST on the underlying transcript.
|
||||||
fn nonces(&self) -> Vec<Vec<C::G>>;
|
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>(
|
fn preprocess_addendum<R: RngCore + CryptoRng>(
|
||||||
&mut self,
|
&mut self,
|
||||||
rng: &mut R,
|
rng: &mut R,
|
||||||
params: &FrostView<C>,
|
params: &FrostView<C>,
|
||||||
) -> 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<Re: Read>(
|
fn process_addendum<Re: Read>(
|
||||||
&mut self,
|
&mut self,
|
||||||
params: &FrostView<C>,
|
params: &FrostView<C>,
|
||||||
|
@ -36,10 +36,10 @@ pub trait Algorithm<C: Curve>: Clone {
|
||||||
reader: &mut Re,
|
reader: &mut Re,
|
||||||
) -> Result<(), FrostError>;
|
) -> 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
|
/// The secret will already have been its lagrange coefficient applied so it is the necessary
|
||||||
/// key share
|
/// key share.
|
||||||
/// 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: &FrostView<C>,
|
params: &FrostView<C>,
|
||||||
|
@ -48,12 +48,12 @@ pub trait Algorithm<C: Curve>: Clone {
|
||||||
msg: &[u8],
|
msg: &[u8],
|
||||||
) -> C::F;
|
) -> C::F;
|
||||||
|
|
||||||
/// Verify a signature
|
/// Verify a signature.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn verify(&self, group_key: C::G, nonces: &[Vec<C::G>], sum: C::F) -> Option<Self::Signature>;
|
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
|
/// Verify a specific share given as a response. Used to determine blame if signature
|
||||||
/// verification fails
|
/// verification fails.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn verify_share(&self, verification_share: C::G, nonces: &[Vec<C::G>], share: C::F) -> bool;
|
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 {
|
pub trait Hram<C: Curve>: Clone {
|
||||||
/// HRAM function to generate a challenge
|
/// HRAM function to generate a challenge.
|
||||||
/// H2 from the IETF draft despite having a different argument set (not pre-formatted)
|
/// H2 from the IETF draft, despite having a different argument set (not being pre-formatted).
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
fn hram(R: &C::G, A: &C::G, m: &[u8]) -> C::F;
|
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> {
|
impl<C: Curve, H: Hram<C>> Algorithm<C> for Schnorr<C, H> {
|
||||||
type Transcript = IetfTranscript;
|
type Transcript = IetfTranscript;
|
||||||
type Signature = SchnorrSignature<C>;
|
type Signature = SchnorrSignature<C>;
|
||||||
|
|
|
@ -29,7 +29,7 @@ mod ed448;
|
||||||
#[cfg(feature = "ed448")]
|
#[cfg(feature = "ed448")]
|
||||||
pub use ed448::{Ed448, Ietf8032Ed448Hram, NonIetfEd448Hram};
|
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)]
|
#[derive(Clone, Error, Debug)]
|
||||||
pub enum CurveError {
|
pub enum CurveError {
|
||||||
#[error("invalid scalar")]
|
#[error("invalid scalar")]
|
||||||
|
@ -38,23 +38,23 @@ pub enum CurveError {
|
||||||
InvalidPoint,
|
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
|
// 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)
|
// 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>
|
// 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
|
// 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
|
// advantages in the modern day to be worth the hassle -- Kayaba
|
||||||
pub trait Curve: Clone + Copy + PartialEq + Eq + Debug + Zeroize {
|
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
|
// This is available via G::Scalar yet `C::G::Scalar` is ambiguous, forcing horrific accesses
|
||||||
type F: PrimeField + PrimeFieldBits + Zeroize;
|
type F: PrimeField + PrimeFieldBits + Zeroize;
|
||||||
/// Group element type
|
/// Group element type.
|
||||||
type G: Group<Scalar = Self::F> + GroupOps + PrimeGroup + Zeroize;
|
type G: Group<Scalar = Self::F> + GroupOps + PrimeGroup + Zeroize;
|
||||||
|
|
||||||
/// ID for this curve
|
/// ID for this curve.
|
||||||
const ID: &'static [u8];
|
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
|
// While group does provide this in its API, privacy coins may want to use a custom basepoint
|
||||||
fn generator() -> Self::G;
|
fn generator() -> Self::G;
|
||||||
|
|
||||||
|
@ -66,22 +66,22 @@ pub trait Curve: Clone + Copy + PartialEq + Eq + Debug + Zeroize {
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
fn hash_to_F(dst: &[u8], msg: &[u8]) -> Self::F;
|
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> {
|
fn hash_msg(msg: &[u8]) -> Vec<u8> {
|
||||||
Self::hash_to_vec(b"msg", msg)
|
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> {
|
fn hash_commitments(commitments: &[u8]) -> Vec<u8> {
|
||||||
Self::hash_to_vec(b"com", commitments)
|
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 {
|
fn hash_binding_factor(binding: &[u8]) -> Self::F {
|
||||||
Self::hash_to_F(b"rho", binding)
|
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 {
|
fn random_nonce<R: RngCore + CryptoRng>(mut secret: Self::F, rng: &mut R) -> Self::F {
|
||||||
let mut seed = vec![0; 32];
|
let mut seed = vec![0; 32];
|
||||||
rng.fill_bytes(&mut seed);
|
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.
|
/// 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
|
/// This key MUST NOT be considered usable until all parties confirm they have completed the
|
||||||
/// issue, yet simply confirming protocol completion without issue is enough to confirm the same
|
/// protocol without issue.
|
||||||
/// key was generated as long as a lack of duplicated commitments was also confirmed when they were
|
|
||||||
/// broadcasted initially
|
|
||||||
fn complete_r2<Re: Read, R: RngCore + CryptoRng, C: Curve>(
|
fn complete_r2<Re: Read, R: RngCore + CryptoRng, C: Curve>(
|
||||||
rng: &mut R,
|
rng: &mut R,
|
||||||
params: FrostParams,
|
params: FrostParams,
|
||||||
|
@ -291,15 +289,16 @@ impl<C: Curve> Drop for KeyMachine<C> {
|
||||||
impl<C: Curve> ZeroizeOnDrop for KeyMachine<C> {}
|
impl<C: Curve> ZeroizeOnDrop for KeyMachine<C> {}
|
||||||
|
|
||||||
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 should be unique among multisigs.
|
||||||
pub fn new(params: FrostParams, context: String) -> KeyGenMachine<C> {
|
pub fn new(params: FrostParams, context: String) -> KeyGenMachine<C> {
|
||||||
KeyGenMachine { params, context, _curve: PhantomData }
|
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
|
/// 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>(
|
pub fn generate_coefficients<R: RngCore + CryptoRng>(
|
||||||
self,
|
self,
|
||||||
rng: &mut R,
|
rng: &mut R,
|
||||||
|
@ -320,11 +319,9 @@ impl<C: Curve> KeyGenMachine<C> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Curve> SecretShareMachine<C> {
|
impl<C: Curve> SecretShareMachine<C> {
|
||||||
/// Continue generating a key
|
/// Continue generating a key.
|
||||||
/// Takes in everyone else's commitments, which are expected to be in a Vec where participant
|
/// Takes in everyone else's commitments. Returns a HashMap of byte vectors representing secret
|
||||||
/// index = Vec index. An empty vector is expected at index 0 to allow for this. An empty vector
|
/// shares. These MUST be encrypted and only then sent to their respective participants.
|
||||||
/// 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
|
|
||||||
pub fn generate_secret_shares<Re: Read, R: RngCore + CryptoRng>(
|
pub fn generate_secret_shares<Re: Read, R: RngCore + CryptoRng>(
|
||||||
mut self,
|
mut self,
|
||||||
rng: &mut R,
|
rng: &mut R,
|
||||||
|
@ -343,12 +340,10 @@ impl<C: Curve> SecretShareMachine<C> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Curve> KeyMachine<C> {
|
impl<C: Curve> KeyMachine<C> {
|
||||||
/// Complete key generation
|
/// Complete key generation.
|
||||||
/// Takes in everyone elses' shares submitted to us as a Vec, expecting participant index =
|
/// Takes in everyone elses' shares submitted to us. Returns a FrostCore object representing the
|
||||||
/// Vec index with an empty vector at index 0 and index i. Returns a byte vector representing the
|
/// generated keys. Successful protocol completion MUST be confirmed by all parties before these
|
||||||
/// group's public key, while setting a valid secret share inside the machine. > t participants
|
/// keys may be safely used.
|
||||||
/// must report completion without issue before this key can be considered usable, yet you should
|
|
||||||
/// wait for all participants to report as such
|
|
||||||
pub fn complete<Re: Read, R: RngCore + CryptoRng>(
|
pub fn complete<Re: Read, R: RngCore + CryptoRng>(
|
||||||
mut self,
|
mut self,
|
||||||
rng: &mut R,
|
rng: &mut R,
|
||||||
|
|
|
@ -51,15 +51,15 @@ pub(crate) fn validate_map<T>(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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 FrostParams {
|
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.
|
||||||
n: u16,
|
n: u16,
|
||||||
/// Index of the participant being acted for
|
/// Index of the participant being acted for.
|
||||||
i: u16,
|
i: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ pub enum FrostError {
|
||||||
InternalError(&'static str),
|
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 {
|
pub fn lagrange<F: PrimeField>(i: u16, included: &[u16]) -> F {
|
||||||
let mut num = F::one();
|
let mut num = F::one();
|
||||||
let mut denom = 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()
|
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)]
|
#[derive(Clone, PartialEq, Eq, Zeroize)]
|
||||||
pub struct FrostCore<C: Curve> {
|
pub struct FrostCore<C: Curve> {
|
||||||
/// FROST Parameters
|
/// FROST Parameters.
|
||||||
#[zeroize(skip)]
|
#[zeroize(skip)]
|
||||||
params: FrostParams,
|
params: FrostParams,
|
||||||
|
|
||||||
/// Secret share key
|
/// Secret share key.
|
||||||
secret_share: C::F,
|
secret_share: C::F,
|
||||||
/// Group key
|
/// Group key.
|
||||||
group_key: C::G,
|
group_key: C::G,
|
||||||
/// Verification shares
|
/// Verification shares.
|
||||||
#[zeroize(skip)]
|
#[zeroize(skip)]
|
||||||
verification_shares: HashMap<u16, C::G>,
|
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)]
|
#[derive(Clone, Debug, Zeroize)]
|
||||||
pub struct FrostKeys<C: Curve> {
|
pub struct FrostKeys<C: Curve> {
|
||||||
/// Core keys
|
/// Core keys.
|
||||||
#[zeroize(skip)]
|
#[zeroize(skip)]
|
||||||
core: Arc<FrostCore<C>>,
|
core: Arc<FrostCore<C>>,
|
||||||
|
|
||||||
/// Offset applied to these keys
|
/// Offset applied to these keys.
|
||||||
pub(crate) offset: Option<C::F>,
|
pub(crate) offset: Option<C::F>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,10 +315,10 @@ impl<C: Curve> FrostKeys<C> {
|
||||||
FrostKeys { core: Arc::new(core), offset: None }
|
FrostKeys { core: Arc::new(core), offset: None }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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) -> FrostKeys<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
|
||||||
|
@ -336,12 +336,12 @@ impl<C: Curve> FrostKeys<C> {
|
||||||
self.core.secret_share
|
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 {
|
pub fn group_key(&self) -> C::G {
|
||||||
self.core.group_key + (C::generator() * self.offset.unwrap_or_else(C::F::zero))
|
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> {
|
pub(crate) fn verification_shares(&self) -> HashMap<u16, C::G> {
|
||||||
self.core.verification_shares()
|
self.core.verification_shares()
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ use crate::{
|
||||||
FrostError, FrostCore, FrostKeys, validate_map,
|
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> {
|
pub trait CurvePromote<C2: Curve> {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
|
@ -86,7 +86,7 @@ pub struct GeneratorPromotion<C1: Curve, C2: Curve> {
|
||||||
_c2: PhantomData<C2>,
|
_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
|
// The linear DLEq proofs are much more efficient than an exponential key gen
|
||||||
impl<C1: Curve, C2: Curve> GeneratorPromotion<C1, C2>
|
impl<C1: Curve, C2: Curve> GeneratorPromotion<C1, C2>
|
||||||
where
|
where
|
||||||
|
|
|
@ -22,7 +22,7 @@ use crate::{
|
||||||
curve::Curve, FrostError, FrostParams, FrostKeys, FrostView, algorithm::Algorithm, validate_map,
|
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)]
|
#[derive(Clone)]
|
||||||
pub struct Params<C: Curve, A: Algorithm<C>> {
|
pub struct Params<C: Curve, A: Algorithm<C>> {
|
||||||
algorithm: A,
|
algorithm: A,
|
||||||
|
@ -369,20 +369,17 @@ pub trait PreprocessMachine {
|
||||||
type Signature: Clone + PartialEq + fmt::Debug;
|
type Signature: Clone + PartialEq + fmt::Debug;
|
||||||
type SignMachine: SignMachine<Self::Signature>;
|
type SignMachine: SignMachine<Self::Signature>;
|
||||||
|
|
||||||
/// Perform the preprocessing round required in order to sign
|
/// Perform the preprocessing round required in order to sign.
|
||||||
/// Returns a byte vector which must be transmitted to all parties selected for this signing
|
/// Returns a byte vector to be broadcast to all participants, over an authenticated channel.
|
||||||
/// process, over an authenticated channel
|
|
||||||
fn preprocess<R: RngCore + CryptoRng>(self, rng: &mut R) -> (Self::SignMachine, Vec<u8>);
|
fn preprocess<R: RngCore + CryptoRng>(self, rng: &mut R) -> (Self::SignMachine, Vec<u8>);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait SignMachine<S> {
|
pub trait SignMachine<S> {
|
||||||
type SignatureMachine: SignatureMachine<S>;
|
type SignatureMachine: SignatureMachine<S>;
|
||||||
|
|
||||||
/// Sign a message
|
/// Sign a message.
|
||||||
/// Takes in the participant's commitments, which are expected to be in a Vec where participant
|
/// Takes in the participants' preprocesses. Returns a byte vector representing a signature share
|
||||||
/// index = Vec index. None is expected at index 0 to allow for this. None is also expected at
|
/// to be broadcast to all participants, over an authenticated channel.
|
||||||
/// 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
|
|
||||||
fn sign<Re: Read>(
|
fn sign<Re: Read>(
|
||||||
self,
|
self,
|
||||||
commitments: HashMap<u16, Re>,
|
commitments: HashMap<u16, Re>,
|
||||||
|
@ -391,14 +388,12 @@ pub trait SignMachine<S> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait SignatureMachine<S> {
|
pub trait SignatureMachine<S> {
|
||||||
/// Complete signing
|
/// Complete signing.
|
||||||
/// Takes in everyone elses' shares submitted to us as a Vec, expecting participant index =
|
/// Takes in everyone elses' shares. Returns the signature.
|
||||||
/// Vec index with None at index 0 and index i. Returns a byte vector representing the serialized
|
|
||||||
/// signature
|
|
||||||
fn complete<Re: Read>(self, shares: HashMap<u16, Re>) -> Result<S, FrostError>;
|
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>> {
|
pub struct AlgorithmMachine<C: Curve, A: Algorithm<C>> {
|
||||||
params: Params<C, A>,
|
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> {
|
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(
|
pub fn new(
|
||||||
algorithm: A,
|
algorithm: A,
|
||||||
keys: FrostKeys<C>,
|
keys: FrostKeys<C>,
|
||||||
|
|
|
@ -11,22 +11,22 @@ use digest::{typenum::type_operators::IsGreaterOrEqual, consts::U256, Digest, Ou
|
||||||
pub trait Transcript {
|
pub trait Transcript {
|
||||||
type Challenge: Clone + Send + Sync + AsRef<[u8]>;
|
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;
|
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]);
|
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]);
|
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
|
/// 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;
|
fn challenge(&mut self, label: &'static [u8]) -> Self::Challenge;
|
||||||
|
|
||||||
/// Produce a RNG seed. Helper function for parties needing to generate random data from an
|
/// 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
|
/// 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];
|
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 {}
|
pub trait SecureDigest: Clone + Digest {}
|
||||||
impl<D: Clone + Digest> SecureDigest for D where D::OutputSize: IsGreaterOrEqual<U256> {}
|
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)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct DigestTranscript<D: SecureDigest>(D);
|
pub struct DigestTranscript<D: SecureDigest>(D);
|
||||||
|
|
||||||
|
|
|
@ -11,35 +11,35 @@ pub struct Cli {
|
||||||
|
|
||||||
#[derive(Debug, clap::Subcommand)]
|
#[derive(Debug, clap::Subcommand)]
|
||||||
pub enum Subcommand {
|
pub enum Subcommand {
|
||||||
/// Key management CLI utilities
|
// Key management CLI utilities
|
||||||
#[clap(subcommand)]
|
#[clap(subcommand)]
|
||||||
Key(sc_cli::KeySubcommand),
|
Key(sc_cli::KeySubcommand),
|
||||||
|
|
||||||
/// Build a chain specification
|
// Build a chain specification
|
||||||
BuildSpec(sc_cli::BuildSpecCmd),
|
BuildSpec(sc_cli::BuildSpecCmd),
|
||||||
|
|
||||||
/// Validate blocks
|
// Validate blocks
|
||||||
CheckBlock(sc_cli::CheckBlockCmd),
|
CheckBlock(sc_cli::CheckBlockCmd),
|
||||||
|
|
||||||
/// Export blocks
|
// Export blocks
|
||||||
ExportBlocks(sc_cli::ExportBlocksCmd),
|
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),
|
ExportState(sc_cli::ExportStateCmd),
|
||||||
|
|
||||||
/// Import blocks
|
// Import blocks
|
||||||
ImportBlocks(sc_cli::ImportBlocksCmd),
|
ImportBlocks(sc_cli::ImportBlocksCmd),
|
||||||
|
|
||||||
/// Remove the entire chain
|
// Remove the entire chain
|
||||||
PurgeChain(sc_cli::PurgeChainCmd),
|
PurgeChain(sc_cli::PurgeChainCmd),
|
||||||
|
|
||||||
/// Revert the chain to a previous state
|
// Revert the chain to a previous state
|
||||||
Revert(sc_cli::RevertCmd),
|
Revert(sc_cli::RevertCmd),
|
||||||
|
|
||||||
/// Sub-commands concerned with benchmarking
|
// Sub-commands concerned with benchmarking
|
||||||
#[clap(subcommand)]
|
#[clap(subcommand)]
|
||||||
Benchmark(frame_benchmarking_cli::BenchmarkCmd),
|
Benchmark(frame_benchmarking_cli::BenchmarkCmd),
|
||||||
|
|
||||||
/// DB meta columns information
|
// DB meta columns information
|
||||||
ChainInfo(sc_cli::ChainInfoCmd),
|
ChainInfo(sc_cli::ChainInfoCmd),
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,23 +31,23 @@ pub use pallet_balances::Call as BalancesCall;
|
||||||
use pallet_transaction_payment::CurrencyAdapter;
|
use pallet_transaction_payment::CurrencyAdapter;
|
||||||
use pallet_contracts::{migration, DefaultContractAccessWeight};
|
use pallet_contracts::{migration, DefaultContractAccessWeight};
|
||||||
|
|
||||||
/// An index to a block
|
/// An index to a block.
|
||||||
pub type BlockNumber = u32;
|
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;
|
pub type Signature = MultiSignature;
|
||||||
|
|
||||||
/// Some way of identifying an account on the chain. We intentionally make it equivalent
|
/// 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;
|
pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;
|
||||||
|
|
||||||
/// Balance of an account
|
/// Balance of an account.
|
||||||
pub type Balance = u64;
|
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;
|
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 type Hash = sp_core::H256;
|
||||||
|
|
||||||
pub mod opaque {
|
pub mod opaque {
|
||||||
|
@ -79,7 +79,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
|
||||||
pub const MILLISECS_PER_BLOCK: u64 = 6000;
|
pub const MILLISECS_PER_BLOCK: u64 = 6000;
|
||||||
pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK;
|
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 MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);
|
||||||
pub const HOURS: BlockNumber = MINUTES * 60;
|
pub const HOURS: BlockNumber = MINUTES * 60;
|
||||||
pub const DAYS: BlockNumber = HOURS * 24;
|
pub const DAYS: BlockNumber = HOURS * 24;
|
||||||
|
|
Loading…
Reference in a new issue