mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-08 12:19:24 +00:00
Use const values for our traits where we can
This commit is contained in:
@@ -41,7 +41,7 @@ fn generate_key_r1<R: RngCore + CryptoRng, C: Curve>(
|
||||
// Step 1: Generate t random values to form a polynomial with
|
||||
coefficients.push(C::F::random(&mut *rng));
|
||||
// Step 3: Generate public commitments
|
||||
commitments.push(C::generator_table() * coefficients[i]);
|
||||
commitments.push(C::GENERATOR_TABLE * coefficients[i]);
|
||||
// Serialize them for publication
|
||||
serialized.extend(&C::G_to_bytes(&commitments[i]));
|
||||
}
|
||||
@@ -59,7 +59,7 @@ fn generate_key_r1<R: RngCore + CryptoRng, C: Curve>(
|
||||
challenge::<C>(
|
||||
context,
|
||||
params.i(),
|
||||
&C::G_to_bytes(&(C::generator_table() * r)),
|
||||
&C::G_to_bytes(&(C::GENERATOR_TABLE * r)),
|
||||
&serialized
|
||||
)
|
||||
).serialize()
|
||||
@@ -224,7 +224,7 @@ fn complete_r2<R: RngCore + CryptoRng, C: Curve>(
|
||||
res
|
||||
};
|
||||
|
||||
let mut batch = BatchVerifier::new(shares.len(), C::little_endian());
|
||||
let mut batch = BatchVerifier::new(shares.len(), C::LITTLE_ENDIAN);
|
||||
for (l, share) in &shares {
|
||||
if *l == params.i() {
|
||||
continue;
|
||||
@@ -237,7 +237,7 @@ fn complete_r2<R: RngCore + CryptoRng, C: Curve>(
|
||||
// ensure that malleability isn't present is to use this n * t algorithm, which runs
|
||||
// per sender and not as an aggregate of all senders, which also enables blame
|
||||
let mut values = exponential(params.i, &commitments[l]);
|
||||
values.push((-*share, C::generator()));
|
||||
values.push((-*share, C::GENERATOR));
|
||||
batch.queue(rng, *l, values);
|
||||
}
|
||||
batch.verify_with_vartime_blame().map_err(|l| FrostError::InvalidCommitment(l))?;
|
||||
@@ -254,9 +254,9 @@ fn complete_r2<R: RngCore + CryptoRng, C: Curve>(
|
||||
// Calculate each user's verification share
|
||||
let mut verification_shares = HashMap::new();
|
||||
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));
|
||||
}
|
||||
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
|
||||
|
||||
|
||||
@@ -42,22 +42,19 @@ pub trait Curve: Clone + Copy + PartialEq + Eq + Debug {
|
||||
/// Precomputed table type
|
||||
type T: Mul<Self::F, Output = Self::G>;
|
||||
|
||||
/// Byte length of the curve ID
|
||||
// While C::id().len() is trivial, this bounds it to u8 for any proper Curve implementation
|
||||
fn id_len() -> u8;
|
||||
/// ID for this curve
|
||||
fn id() -> &'static [u8];
|
||||
const ID: &'static [u8];
|
||||
|
||||
/// Generator for the group
|
||||
// While group does provide this in its API, Jubjub users will want to use a custom basepoint
|
||||
fn generator() -> Self::G;
|
||||
// While group does provide this in its API, privacy coins will want to use a custom basepoint
|
||||
const GENERATOR: Self::G;
|
||||
|
||||
/// Table for the generator for the group
|
||||
/// If there isn't a precomputed table available, the generator itself should be used
|
||||
fn generator_table() -> Self::T;
|
||||
const GENERATOR_TABLE: Self::T;
|
||||
|
||||
/// If little endian is used for the scalar field's Repr
|
||||
fn little_endian() -> bool;
|
||||
const LITTLE_ENDIAN: bool;
|
||||
|
||||
/// Securely generate a random nonce. H4 from the IETF draft
|
||||
fn random_nonce<R: RngCore + CryptoRng>(secret: Self::F, rng: &mut R) -> Self::F;
|
||||
@@ -298,12 +295,12 @@ impl<C: Curve> MultisigKeys<C> {
|
||||
let offset_share = offset * C::F::from(included.len().try_into().unwrap()).invert().unwrap();
|
||||
|
||||
Ok(MultisigView {
|
||||
group_key: self.group_key + (C::generator_table() * offset),
|
||||
group_key: self.group_key + (C::GENERATOR_TABLE * offset),
|
||||
secret_share: secret_share + offset_share,
|
||||
verification_shares: self.verification_shares.iter().map(
|
||||
|(l, share)| (
|
||||
*l,
|
||||
(*share * lagrange::<C::F>(*l, &included)) + (C::generator_table() * offset_share)
|
||||
(*share * lagrange::<C::F>(*l, &included)) + (C::GENERATOR_TABLE * offset_share)
|
||||
)
|
||||
).collect(),
|
||||
included: included.to_vec(),
|
||||
@@ -311,15 +308,13 @@ impl<C: Curve> MultisigKeys<C> {
|
||||
}
|
||||
|
||||
pub fn serialized_len(n: u16) -> usize {
|
||||
1 + usize::from(C::id_len()) + (3 * 2) + C::F_len() + C::G_len() + (usize::from(n) * C::G_len())
|
||||
8 + C::ID.len() + (3 * 2) + C::F_len() + C::G_len() + (usize::from(n) * C::G_len())
|
||||
}
|
||||
|
||||
pub fn serialize(&self) -> Vec<u8> {
|
||||
let mut serialized = Vec::with_capacity(
|
||||
1 + usize::from(C::id_len()) + MultisigKeys::<C>::serialized_len(self.params.n)
|
||||
);
|
||||
serialized.push(C::id_len());
|
||||
serialized.extend(C::id());
|
||||
let mut serialized = Vec::with_capacity(MultisigKeys::<C>::serialized_len(self.params.n));
|
||||
serialized.extend(u64::try_from(C::ID.len()).unwrap().to_be_bytes());
|
||||
serialized.extend(C::ID);
|
||||
serialized.extend(&self.params.t.to_be_bytes());
|
||||
serialized.extend(&self.params.n.to_be_bytes());
|
||||
serialized.extend(&self.params.i.to_be_bytes());
|
||||
@@ -328,34 +323,28 @@ impl<C: Curve> MultisigKeys<C> {
|
||||
for l in 1 ..= self.params.n.into() {
|
||||
serialized.extend(&C::G_to_bytes(&self.verification_shares[&l]));
|
||||
}
|
||||
|
||||
serialized
|
||||
}
|
||||
|
||||
pub fn deserialize(serialized: &[u8]) -> Result<MultisigKeys<C>, FrostError> {
|
||||
if serialized.len() < 1 {
|
||||
Err(FrostError::InternalError("MultisigKeys serialization is empty".to_string()))?;
|
||||
let mut start = u64::try_from(C::ID.len()).unwrap().to_be_bytes().to_vec();
|
||||
start.extend(C::ID);
|
||||
let mut cursor = start.len();
|
||||
|
||||
if serialized.len() < (cursor + 4) {
|
||||
Err(
|
||||
FrostError::InternalError(
|
||||
"MultisigKeys serialization is missing its curve/participant quantities".to_string()
|
||||
)
|
||||
)?;
|
||||
}
|
||||
|
||||
let id_len: usize = serialized[0].into();
|
||||
let mut cursor = 1;
|
||||
|
||||
if serialized.len() < (cursor + id_len) {
|
||||
Err(FrostError::InternalError("ID wasn't included".to_string()))?;
|
||||
}
|
||||
|
||||
if C::id() != &serialized[cursor .. (cursor + id_len)] {
|
||||
if &start != &serialized[.. cursor] {
|
||||
Err(
|
||||
FrostError::InternalError(
|
||||
"curve is distinct between serialization and deserialization".to_string()
|
||||
)
|
||||
)?;
|
||||
}
|
||||
cursor += id_len;
|
||||
|
||||
if serialized.len() < (cursor + 4) {
|
||||
Err(FrostError::InternalError("participant quantities weren't included".to_string()))?;
|
||||
}
|
||||
|
||||
let t = u16::from_be_bytes(serialized[cursor .. (cursor + 2)].try_into().unwrap());
|
||||
cursor += 2;
|
||||
|
||||
@@ -28,7 +28,7 @@ pub(crate) fn sign<C: Curve>(
|
||||
challenge: C::F
|
||||
) -> SchnorrSignature<C> {
|
||||
SchnorrSignature {
|
||||
R: C::generator_table() * nonce,
|
||||
R: C::GENERATOR_TABLE * nonce,
|
||||
s: nonce + (private_key * challenge)
|
||||
}
|
||||
}
|
||||
@@ -38,15 +38,15 @@ pub(crate) fn verify<C: Curve>(
|
||||
challenge: C::F,
|
||||
signature: &SchnorrSignature<C>
|
||||
) -> bool {
|
||||
(C::generator_table() * signature.s) == (signature.R + (public_key * challenge))
|
||||
(C::GENERATOR_TABLE * signature.s) == (signature.R + (public_key * challenge))
|
||||
}
|
||||
|
||||
pub(crate) fn batch_verify<C: Curve, R: RngCore + CryptoRng>(
|
||||
rng: &mut R,
|
||||
triplets: &[(u16, C::G, C::F, SchnorrSignature<C>)]
|
||||
) -> Result<(), u16> {
|
||||
let mut values = [(C::F::one(), C::generator()); 3];
|
||||
let mut batch = BatchVerifier::new(triplets.len(), C::little_endian());
|
||||
let mut values = [(C::F::one(), C::GENERATOR); 3];
|
||||
let mut batch = BatchVerifier::new(triplets.len(), C::LITTLE_ENDIAN);
|
||||
for triple in triplets {
|
||||
// s = r + ca
|
||||
// sG == R + cA
|
||||
|
||||
@@ -84,7 +84,7 @@ fn preprocess<R: RngCore + CryptoRng, C: Curve, A: Algorithm<C>>(
|
||||
C::random_nonce(params.view().secret_share(), &mut *rng),
|
||||
C::random_nonce(params.view().secret_share(), &mut *rng)
|
||||
];
|
||||
let commitments = [C::generator_table() * nonces[0], C::generator_table() * nonces[1]];
|
||||
let commitments = [C::GENERATOR_TABLE * nonces[0], C::GENERATOR_TABLE * nonces[1]];
|
||||
let mut serialized = C::G_to_bytes(&commitments[0]);
|
||||
serialized.extend(&C::G_to_bytes(&commitments[1]));
|
||||
|
||||
|
||||
@@ -82,25 +82,12 @@ impl Curve for P256 {
|
||||
type G = ProjectivePoint;
|
||||
type T = ProjectivePoint;
|
||||
|
||||
fn id_len() -> u8 {
|
||||
u8::try_from(Self::id().len()).unwrap()
|
||||
}
|
||||
const ID: &'static [u8] = b"P-256";
|
||||
|
||||
fn id() -> &'static [u8] {
|
||||
b"P-256"
|
||||
}
|
||||
const GENERATOR: Self::G = Self::G::GENERATOR;
|
||||
const GENERATOR_TABLE: Self::G = Self::G::GENERATOR;
|
||||
|
||||
fn generator() -> Self::G {
|
||||
Self::G::GENERATOR
|
||||
}
|
||||
|
||||
fn generator_table() -> Self::T {
|
||||
Self::G::GENERATOR
|
||||
}
|
||||
|
||||
fn little_endian() -> bool {
|
||||
false
|
||||
}
|
||||
const LITTLE_ENDIAN: bool = false;
|
||||
|
||||
fn random_nonce<R: RngCore + CryptoRng>(secret: Self::F, rng: &mut R) -> Self::F {
|
||||
let mut seed = vec![0; 32];
|
||||
|
||||
@@ -113,7 +113,7 @@ pub fn recover<C: Curve>(keys: &HashMap<u16, MultisigKeys<C>>) -> C::F {
|
||||
C::F::zero(),
|
||||
|accum, (i, keys)| accum + (keys.secret_share() * lagrange::<C::F>(*i, &included))
|
||||
);
|
||||
assert_eq!(C::generator_table() * group_private, first.group_key(), "failed to recover keys");
|
||||
assert_eq!(C::GENERATOR_TABLE * group_private, first.group_key(), "failed to recover keys");
|
||||
group_private
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ pub(crate) fn core_sign<R: RngCore + CryptoRng, C: Curve>(rng: &mut R) {
|
||||
let challenge = C::F::random(rng); // Doesn't bother to craft an HRAM
|
||||
assert!(
|
||||
schnorr::verify::<C>(
|
||||
C::generator_table() * private_key,
|
||||
C::GENERATOR_TABLE * private_key,
|
||||
challenge,
|
||||
&schnorr::sign(private_key, nonce, challenge)
|
||||
)
|
||||
@@ -28,9 +28,9 @@ pub(crate) fn core_sign<R: RngCore + CryptoRng, C: Curve>(rng: &mut R) {
|
||||
pub(crate) fn core_verify<R: RngCore + CryptoRng, C: Curve>(rng: &mut R) {
|
||||
assert!(
|
||||
!schnorr::verify::<C>(
|
||||
C::generator_table() * C::F::random(&mut *rng),
|
||||
C::GENERATOR_TABLE * C::F::random(&mut *rng),
|
||||
C::F::random(rng),
|
||||
&SchnorrSignature { R: C::generator_table() * C::F::zero(), s: C::F::zero() }
|
||||
&SchnorrSignature { R: C::GENERATOR_TABLE * C::F::zero(), s: C::F::zero() }
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -48,7 +48,7 @@ pub(crate) fn core_batch_verify<R: RngCore + CryptoRng, C: Curve>(rng: &mut R) {
|
||||
|
||||
// Batch verify
|
||||
let triplets = (0 .. 5).map(
|
||||
|i| (u16::try_from(i + 1).unwrap(), C::generator_table() * keys[i], challenges[i], sigs[i])
|
||||
|i| (u16::try_from(i + 1).unwrap(), C::GENERATOR_TABLE * keys[i], challenges[i], sigs[i])
|
||||
).collect::<Vec<_>>();
|
||||
schnorr::batch_verify(rng, &triplets).unwrap();
|
||||
|
||||
@@ -113,7 +113,7 @@ fn sign_with_offset<R: RngCore + CryptoRng, C: Curve>(rng: &mut R) {
|
||||
for i in 1 ..= u16::try_from(keys.len()).unwrap() {
|
||||
keys.insert(i, Rc::new(keys[&i].offset(offset)));
|
||||
}
|
||||
let offset_key = group_key + (C::generator_table() * offset);
|
||||
let offset_key = group_key + (C::GENERATOR_TABLE * offset);
|
||||
|
||||
sign_core(rng, offset_key, &keys);
|
||||
}
|
||||
|
||||
@@ -26,14 +26,14 @@ fn vectors_to_multisig_keys<C: Curve>(vectors: &Vectors) -> HashMap<u16, Multisi
|
||||
|secret| C::F_from_slice(&hex::decode(secret).unwrap()).unwrap()
|
||||
).collect::<Vec<_>>();
|
||||
let verification_shares = shares.iter().map(
|
||||
|secret| C::generator() * secret
|
||||
|secret| C::GENERATOR * secret
|
||||
).collect::<Vec<_>>();
|
||||
|
||||
let mut keys = HashMap::new();
|
||||
for i in 1 ..= u16::try_from(shares.len()).unwrap() {
|
||||
let mut serialized = vec![];
|
||||
serialized.push(C::id_len());
|
||||
serialized.extend(C::id());
|
||||
serialized.extend(u64::try_from(C::ID.len()).unwrap().to_be_bytes());
|
||||
serialized.extend(C::ID);
|
||||
serialized.extend(vectors.threshold.to_be_bytes());
|
||||
serialized.extend(u16::try_from(shares.len()).unwrap().to_be_bytes());
|
||||
serialized.extend(i.to_be_bytes());
|
||||
@@ -59,7 +59,7 @@ pub fn vectors<C: Curve, H: Hram<C>>(vectors: Vectors) {
|
||||
let keys = vectors_to_multisig_keys::<C>(&vectors);
|
||||
let group_key = C::G_from_slice(&hex::decode(vectors.group_key).unwrap()).unwrap();
|
||||
assert_eq!(
|
||||
C::generator() * C::F_from_slice(&hex::decode(vectors.group_secret).unwrap()).unwrap(),
|
||||
C::GENERATOR * C::F_from_slice(&hex::decode(vectors.group_secret).unwrap()).unwrap(),
|
||||
group_key
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -87,8 +87,8 @@ pub fn vectors<C: Curve, H: Hram<C>>(vectors: Vectors) {
|
||||
C::F_from_slice(&hex::decode(vectors.nonces[c][1]).unwrap()).unwrap()
|
||||
];
|
||||
|
||||
let mut serialized = C::G_to_bytes(&(C::generator() * nonces[0]));
|
||||
serialized.extend(&C::G_to_bytes(&(C::generator() * nonces[1])));
|
||||
let mut serialized = C::G_to_bytes(&(C::GENERATOR * nonces[0]));
|
||||
serialized.extend(&C::G_to_bytes(&(C::GENERATOR * nonces[1])));
|
||||
|
||||
machine.unsafe_override_preprocess(
|
||||
PreprocessPackage { nonces, serialized: serialized.clone() }
|
||||
|
||||
Reference in New Issue
Block a user