diff --git a/Cargo.toml b/Cargo.toml index 06ac114..06d8ce0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,6 @@ resolver = "2" members = [ "frost-core", - #"frost-redjubjub", "frost-ed25519", "frost-ed448", "frost-p256", diff --git a/frost-redjubjub/Cargo.toml b/frost-redjubjub/Cargo.toml deleted file mode 100644 index 21d2be6..0000000 --- a/frost-redjubjub/Cargo.toml +++ /dev/null @@ -1,46 +0,0 @@ -[package] -name = "redjubjub" -edition = "2018" -# When releasing to crates.io: -# - Update html_root_url -# - Update CHANGELOG.md -# - Create git tag. -version = "0.4.0" -authors = ["Henry de Valence ", "Deirdre Connolly ", "Chelsea Komlo "] -readme = "README.md" -license = "MIT OR Apache-2.0" -repository = "https://github.com/ZcashFoundation/redjubjub" -categories = ["cryptography"] -keywords = ["cryptography", "crypto", "jubjub", "redjubjub", "zcash"] -description = "A standalone implementation of the RedJubjub signature scheme." - -[package.metadata.docs.rs] -features = ["nightly"] - -[dependencies] -blake2b_simd = "1.0" -byteorder = "1.4" -digest = "0.10" -jubjub = "0.8" -rand_core = "0.6" -serde = { version = "1", optional = true, features = ["derive"] } -thiserror = "1.0" -zeroize = { version = "1", default-features = false, features = ["zeroize_derive"] } - -[dev-dependencies] -bincode = "1" -criterion = "0.3" -proptest-derive = "0.3" -lazy_static = "1.4" -proptest = "1.0" -rand = "0.8" -rand_chacha = "0.3" -serde_json = "1.0" - -[features] -nightly = [] -default = ["serde"] - -[[bench]] -name = "bench" -harness = false diff --git a/frost-redjubjub/README.md b/frost-redjubjub/README.md deleted file mode 100644 index d041c08..0000000 --- a/frost-redjubjub/README.md +++ /dev/null @@ -1,52 +0,0 @@ -A minimal [RedJubjub][redjubjub] implementation for use in [Zebra][zebra]. - -Two parameterizations of RedJubjub are used in Zcash, one for -`BindingSig` and one for `SpendAuthSig`. This library distinguishes -these in the type system, using the [sealed] `SigType` trait as a -type-level enum. - -In addition to the `Signature`, `SigningKey`, `VerificationKey` types, -the library also provides `VerificationKeyBytes`, a [refinement] of a -`[u8; 32]` indicating that bytes represent an encoding of a RedJubjub -verification key. This allows the `VerificationKey` type to cache -verification checks related to the verification key encoding. - -## Examples - -Creating a `BindingSig`, serializing and deserializing it, and -verifying the signature: - -```rust -# use std::convert::TryFrom; -use rand::thread_rng; -use redjubjub::*; - -let msg = b"Hello!"; - -// Generate a secret key and sign the message -let sk = SigningKey::::new(thread_rng()); -let sig = sk.sign(thread_rng(), msg); - -// Types can be converted to raw byte arrays using From/Into -let sig_bytes: [u8; 64] = sig.into(); -let pk_bytes: [u8; 32] = VerificationKey::from(&sk).into(); - -// Deserialize and verify the signature. -let sig: Signature = sig_bytes.into(); -assert!( - VerificationKey::try_from(pk_bytes) - .and_then(|pk| pk.verify(msg, &sig)) - .is_ok() -); -``` - -## docs - -```shell,no_run -cargo doc --features "nightly" --open -``` - -[redjubjub]: https://zips.z.cash/protocol/protocol.pdf#concretereddsa -[zebra]: https://github.com/ZcashFoundation/zebra -[refinement]: https://en.wikipedia.org/wiki/Refinement_type -[sealed]: https://rust-lang.github.io/api-guidelines/future-proofing.html#sealed-traits-protect-against-downstream-implementations-c-sealed diff --git a/frost-redjubjub/benches/bench.rs b/frost-redjubjub/benches/bench.rs deleted file mode 100644 index cd9777e..0000000 --- a/frost-redjubjub/benches/bench.rs +++ /dev/null @@ -1,95 +0,0 @@ -use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; - -use rand::{thread_rng, Rng}; -use redjubjub::*; -use std::convert::TryFrom; - -enum Item { - SpendAuth { - vk_bytes: VerificationKeyBytes, - sig: Signature, - }, - Binding { - vk_bytes: VerificationKeyBytes, - sig: Signature, - }, -} - -fn sigs_with_distinct_keys() -> impl Iterator { - std::iter::repeat_with(|| { - let mut rng = thread_rng(); - let msg = b"Bench"; - match rng.gen::() % 2 { - 0 => { - let sk = SigningKey::::new(thread_rng()); - let vk_bytes = VerificationKey::from(&sk).into(); - let sig = sk.sign(thread_rng(), &msg[..]); - Item::SpendAuth { vk_bytes, sig } - } - 1 => { - let sk = SigningKey::::new(thread_rng()); - let vk_bytes = VerificationKey::from(&sk).into(); - let sig = sk.sign(thread_rng(), &msg[..]); - Item::Binding { vk_bytes, sig } - } - _ => panic!(), - } - }) -} - -fn bench_batch_verify(c: &mut Criterion) { - let mut group = c.benchmark_group("Batch Verification"); - for &n in [8usize, 16, 24, 32, 40, 48, 56, 64].iter() { - group.throughput(Throughput::Elements(n as u64)); - - let sigs = sigs_with_distinct_keys().take(n).collect::>(); - - group.bench_with_input( - BenchmarkId::new("Unbatched verification", n), - &sigs, - |b, sigs| { - b.iter(|| { - for item in sigs.iter() { - let msg = b"Bench"; - match item { - Item::SpendAuth { vk_bytes, sig } => { - let _ = VerificationKey::try_from(*vk_bytes) - .and_then(|vk| vk.verify(msg, sig)); - } - Item::Binding { vk_bytes, sig } => { - let _ = VerificationKey::try_from(*vk_bytes) - .and_then(|vk| vk.verify(msg, sig)); - } - } - } - }) - }, - ); - - group.bench_with_input( - BenchmarkId::new("Batched verification", n), - &sigs, - |b, sigs| { - b.iter(|| { - let mut batch = batch::Verifier::new(); - for item in sigs.iter() { - let msg = b"Bench"; - match item { - Item::SpendAuth { vk_bytes, sig } => { - batch.queue((*vk_bytes, *sig, msg)); - } - Item::Binding { vk_bytes, sig } => { - batch.queue((*vk_bytes, *sig, msg)); - } - } - } - batch.verify(thread_rng()) - }) - }, - ); - } - group.finish(); -} - -criterion_group!(benches, bench_batch_verify); -criterion_main!(benches); diff --git a/frost-redjubjub/src/batch.rs b/frost-redjubjub/src/batch.rs deleted file mode 100644 index 0bc3838..0000000 --- a/frost-redjubjub/src/batch.rs +++ /dev/null @@ -1,264 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of redjubjub. -// Copyright (c) 2019-2021 Zcash Foundation -// See LICENSE for licensing information. -// -// Authors: -// - Deirdre Connolly -// - Henry de Valence - -//! Performs batch RedJubjub signature verification. -//! -//! Batch verification asks whether *all* signatures in some set are valid, -//! rather than asking whether *each* of them is valid. This allows sharing -//! computations among all signature verifications, performing less work overall -//! at the cost of higher latency (the entire batch must complete), complexity of -//! caller code (which must assemble a batch of signatures across work-items), -//! and loss of the ability to easily pinpoint failing signatures. -//! - -use std::convert::TryFrom; - -use jubjub::*; -use rand_core::{CryptoRng, RngCore}; - -use crate::{private::Sealed, scalar_mul::VartimeMultiscalarMul, *}; - -// Shim to generate a random 128bit value in a [u64; 4], without -// importing `rand`. -fn gen_128_bits(mut rng: R) -> [u64; 4] { - let mut bytes = [0u64; 4]; - bytes[0] = rng.next_u64(); - bytes[1] = rng.next_u64(); - bytes -} - -#[derive(Clone, Debug)] -enum Inner { - SpendAuth { - vk_bytes: VerificationKeyBytes, - sig: Signature, - c: Scalar, - }, - Binding { - vk_bytes: VerificationKeyBytes, - sig: Signature, - c: Scalar, - }, -} - -/// A batch verification item. -/// -/// This struct exists to allow batch processing to be decoupled from the -/// lifetime of the message. This is useful when using the batch verification API -/// in an async context. -#[derive(Clone, Debug)] -pub struct Item { - inner: Inner, -} - -impl<'msg, M: AsRef<[u8]>> - From<( - VerificationKeyBytes, - Signature, - &'msg M, - )> for Item -{ - fn from( - (vk_bytes, sig, msg): ( - VerificationKeyBytes, - Signature, - &'msg M, - ), - ) -> Self { - // Compute c now to avoid dependency on the msg lifetime. - let c = HStar::default() - .update(&sig.r_bytes[..]) - .update(&vk_bytes.bytes[..]) - .update(msg) - .finalize(); - Self { - inner: Inner::SpendAuth { vk_bytes, sig, c }, - } - } -} - -impl<'msg, M: AsRef<[u8]>> From<(VerificationKeyBytes, Signature, &'msg M)> - for Item -{ - fn from( - (vk_bytes, sig, msg): (VerificationKeyBytes, Signature, &'msg M), - ) -> Self { - // Compute c now to avoid dependency on the msg lifetime. - let c = HStar::default() - .update(&sig.r_bytes[..]) - .update(&vk_bytes.bytes[..]) - .update(msg) - .finalize(); - Self { - inner: Inner::Binding { vk_bytes, sig, c }, - } - } -} - -impl Item { - /// Perform non-batched verification of this `Item`. - /// - /// This is useful (in combination with `Item::clone`) for implementing fallback - /// logic when batch verification fails. In contrast to - /// [`VerificationKey::verify`](crate::VerificationKey::verify), which requires - /// borrowing the message data, the `Item` type is unlinked from the lifetime of - /// the message. - #[allow(non_snake_case)] - pub fn verify_single(self) -> Result<(), Error> { - match self.inner { - Inner::Binding { vk_bytes, sig, c } => VerificationKey::::try_from(vk_bytes) - .and_then(|vk| vk.verify_prehashed(&sig, c)), - Inner::SpendAuth { vk_bytes, sig, c } => { - VerificationKey::::try_from(vk_bytes) - .and_then(|vk| vk.verify_prehashed(&sig, c)) - } - } - } -} - -#[derive(Default)] -/// A batch verification context. -pub struct Verifier { - /// Signature data queued for verification. - signatures: Vec, -} - -impl Verifier { - /// Construct a new batch verifier. - pub fn new() -> Verifier { - Verifier::default() - } - - /// Queue an Item for verification. - pub fn queue>(&mut self, item: I) { - self.signatures.push(item.into()); - } - - /// Perform batch verification, returning `Ok(())` if all signatures were - /// valid and `Err` otherwise. - /// - /// The batch verification equation is: - /// - /// h_G * -[sum(z_i * s_i)]P_G + sum(\[z_i\]R_i + [z_i * c_i]VK_i) = 0_G - /// - /// which we split out into: - /// - /// h_G * -[sum(z_i * s_i)]P_G + sum(\[z_i\]R_i) + sum([z_i * c_i]VK_i) = 0_G - /// - /// so that we can use multiscalar multiplication speedups. - /// - /// where for each signature i, - /// - VK_i is the verification key; - /// - R_i is the signature's R value; - /// - s_i is the signature's s value; - /// - c_i is the hash of the message and other data; - /// - z_i is a random 128-bit Scalar; - /// - h_G is the cofactor of the group; - /// - P_G is the generator of the subgroup; - /// - /// Since RedJubjub uses different subgroups for different types - /// of signatures, SpendAuth's and Binding's, we need to have yet - /// another point and associated scalar accumulator for all the - /// signatures of each type in our batch, but we can still - /// amortize computation nicely in one multiscalar multiplication: - /// - /// h_G * ( [-sum(z_i * s_i): i_type == SpendAuth]P_SpendAuth + [-sum(z_i * s_i): i_type == Binding]P_Binding + sum(\[z_i\]R_i) + sum([z_i * c_i]VK_i) ) = 0_G - /// - /// As follows elliptic curve scalar multiplication convention, - /// scalar variables are lowercase and group point variables - /// are uppercase. This does not exactly match the RedDSA - /// notation in the [protocol specification §B.1][ps]. - /// - /// [ps]: https://zips.z.cash/protocol/protocol.pdf#reddsabatchverify - #[allow(non_snake_case)] - pub fn verify(self, mut rng: R) -> Result<(), Error> { - let n = self.signatures.len(); - - let mut VK_coeffs = Vec::with_capacity(n); - let mut VKs = Vec::with_capacity(n); - let mut R_coeffs = Vec::with_capacity(self.signatures.len()); - let mut Rs = Vec::with_capacity(self.signatures.len()); - let mut P_spendauth_coeff = Scalar::zero(); - let mut P_binding_coeff = Scalar::zero(); - - for item in self.signatures.iter() { - let (s_bytes, r_bytes, c) = match item.inner { - Inner::SpendAuth { sig, c, .. } => (sig.s_bytes, sig.r_bytes, c), - Inner::Binding { sig, c, .. } => (sig.s_bytes, sig.r_bytes, c), - }; - - let s = { - // XXX-jubjub: should not use CtOption here - let maybe_scalar = Scalar::from_bytes(&s_bytes); - if maybe_scalar.is_some().into() { - maybe_scalar.unwrap() - } else { - return Err(Error::InvalidSignature); - } - }; - - let R = { - // XXX-jubjub: should not use CtOption here - // XXX-jubjub: inconsistent ownership in from_bytes - let maybe_point = AffinePoint::from_bytes(r_bytes); - if maybe_point.is_some().into() { - jubjub::ExtendedPoint::from(maybe_point.unwrap()) - } else { - return Err(Error::InvalidSignature); - } - }; - - let VK = match item.inner { - Inner::SpendAuth { vk_bytes, .. } => { - VerificationKey::::try_from(vk_bytes.bytes)?.point - } - Inner::Binding { vk_bytes, .. } => { - VerificationKey::::try_from(vk_bytes.bytes)?.point - } - }; - - let z = Scalar::from_raw(gen_128_bits(&mut rng)); - - let P_coeff = z * s; - match item.inner { - Inner::SpendAuth { .. } => { - P_spendauth_coeff -= P_coeff; - } - Inner::Binding { .. } => { - P_binding_coeff -= P_coeff; - } - }; - - R_coeffs.push(z); - Rs.push(R); - - VK_coeffs.push(Scalar::zero() + (z * c)); - VKs.push(VK); - } - - use std::iter::once; - - let scalars = once(&P_spendauth_coeff) - .chain(once(&P_binding_coeff)) - .chain(VK_coeffs.iter()) - .chain(R_coeffs.iter()); - - let basepoints = [SpendAuth::basepoint(), Binding::basepoint()]; - let points = basepoints.iter().chain(VKs.iter()).chain(Rs.iter()); - - let check = ExtendedPoint::vartime_multiscalar_mul(scalars, points); - - if check.is_small_order().into() { - Ok(()) - } else { - Err(Error::InvalidSignature) - } - } -} diff --git a/frost-redjubjub/src/constants.rs b/frost-redjubjub/src/constants.rs deleted file mode 100644 index d534680..0000000 --- a/frost-redjubjub/src/constants.rs +++ /dev/null @@ -1,24 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of redjubjub. -// Copyright (c) 2019-2021 Zcash Foundation -// See LICENSE for licensing information. -// -// Authors: -// - Henry de Valence - -/// The byte-encoding of the basepoint for `SpendAuthSig`. -// Extracted ad-hoc from librustzcash -// XXX add tests for this value. -pub const SPENDAUTHSIG_BASEPOINT_BYTES: [u8; 32] = [ - 48, 181, 242, 170, 173, 50, 86, 48, 188, 221, 219, 206, 77, 103, 101, 109, 5, 253, 28, 194, - 208, 55, 187, 83, 117, 182, 233, 109, 158, 1, 161, 215, -]; - -/// The byte-encoding of the basepoint for `BindingSig`. -// Extracted ad-hoc from librustzcash -// XXX add tests for this value. -pub const BINDINGSIG_BASEPOINT_BYTES: [u8; 32] = [ - 139, 106, 11, 56, 185, 250, 174, 60, 59, 128, 59, 71, 176, 241, 70, 173, 80, 171, 34, 30, 110, - 42, 251, 230, 219, 222, 69, 203, 169, 211, 129, 237, -]; diff --git a/frost-redjubjub/src/error.rs b/frost-redjubjub/src/error.rs deleted file mode 100644 index e130f45..0000000 --- a/frost-redjubjub/src/error.rs +++ /dev/null @@ -1,25 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of redjubjub. -// Copyright (c) 2019-2021 Zcash Foundation -// See LICENSE for licensing information. -// -// Authors: -// - Deirdre Connolly -// - Henry de Valence - -use thiserror::Error; - -/// An error related to RedJubJub signatures. -#[derive(Error, Debug, Copy, Clone, Eq, PartialEq)] -pub enum Error { - /// The encoding of a signing key was malformed. - #[error("Malformed signing key encoding.")] - MalformedSigningKey, - /// The encoding of a verification key was malformed. - #[error("Malformed verification key encoding.")] - MalformedVerificationKey, - /// Signature verification failed. - #[error("Invalid signature.")] - InvalidSignature, -} diff --git a/frost-redjubjub/src/frost.rs b/frost-redjubjub/src/frost.rs deleted file mode 100644 index e086206..0000000 --- a/frost-redjubjub/src/frost.rs +++ /dev/null @@ -1,733 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of redjubjub. -// Copyright (c) 2020-2021 Zcash Foundation -// See LICENSE for licensing information. -// -// Authors: -// - Chelsea H. Komlo -// - Deirdre Connolly -// - isis agora lovecruft - -//! An implementation of FROST (Flexible Round-Optimized Schnorr Threshold) -//! signatures. -//! -//! This implementation has been [independently -//! audited](https://github.com/ZcashFoundation/redjubjub/blob/main/zcash-frost-audit-report-20210323.pdf) -//! as of commit 76ba4ef / March 2021. If you are interested in deploying -//! FROST, please do not hesitate to consult the FROST authors. -//! -//! This implementation currently only supports key generation using a central -//! dealer. In the future, we will add support for key generation via a DKG, -//! as specified in the FROST paper. -//! Internally, keygen_with_dealer generates keys using Verifiable Secret -//! Sharing, where shares are generated using Shamir Secret Sharing. - -use std::{collections::HashMap, convert::TryFrom, marker::PhantomData}; - -use jubjub::Scalar; -use rand_core::{CryptoRng, RngCore}; -use zeroize::DefaultIsZeroes; - -use crate::private::Sealed; -use crate::{HStar, Signature, SpendAuth, VerificationKey}; - -/// A secret scalar value representing a single signer's secret key. -#[derive(Clone, Copy, Default, PartialEq)] -pub struct Secret(pub(crate) Scalar); - -// Zeroizes `Secret` to be the `Default` value on drop (when it goes out of -// scope). Luckily the derived `Default` includes the `Default` impl of -// jubjub::Fr/Scalar, which is four 0u64's under the hood. -impl DefaultIsZeroes for Secret {} - -impl From for Secret { - fn from(source: Scalar) -> Secret { - Secret(source) - } -} - -/// A public group element that represents a single signer's public key. -#[derive(Copy, Clone, Debug, PartialEq)] -pub struct Public(jubjub::ExtendedPoint); - -impl From for Public { - fn from(source: jubjub::ExtendedPoint) -> Public { - Public(source) - } -} - -/// A share generated by performing a (t-out-of-n) secret sharing scheme where -/// n is the total number of shares and t is the threshold required to -/// reconstruct the secret; in this case we use Shamir's secret sharing. -#[derive(Clone)] -pub struct Share { - receiver_index: u64, - /// Secret Key. - pub(crate) value: Secret, - /// The commitments to be distributed among signers. - pub(crate) commitment: ShareCommitment, -} - -/// A Jubjub point that is a commitment to one coefficient of our secret -/// polynomial. -/// -/// This is a (public) commitment to one coefficient of a secret polynomial used -/// for performing verifiable secret sharing for a Shamir secret share. -#[derive(Clone, PartialEq)] -pub(crate) struct Commitment(pub(crate) jubjub::AffinePoint); - -/// Contains the commitments to the coefficients for our secret polynomial _f_, -/// used to generate participants' key shares. -/// -/// [`ShareCommitment`] contains a set of commitments to the coefficients (which -/// themselves are scalars) for a secret polynomial f, where f is used to -/// generate each ith participant's key share f(i). Participants use this set of -/// commitments to perform verifiable secret sharing. -/// -/// Note that participants MUST be assured that they have the *same* -/// [`ShareCommitment`], either by performing pairwise comparison, or by using -/// some agreed-upon public location for publication, where each participant can -/// ensure that they received the correct (and same) value. -#[derive(Clone)] -pub struct ShareCommitment(pub(crate) Vec); - -/// The product of all signers' individual commitments, published as part of the -/// final signature. -#[derive(PartialEq)] -pub struct GroupCommitment(pub(crate) jubjub::AffinePoint); - -/// Secret and public key material generated by a dealer performing -/// [`keygen_with_dealer`]. -/// -/// To derive a FROST keypair, the receiver of the [`SharePackage`] *must* call -/// .into(), which under the hood also performs validation. -pub struct SharePackage { - /// The public signing key that represents the entire group. - pub(crate) group_public: VerificationKey, - /// Denotes the participant index each share is owned by. - pub index: u64, - /// This participant's public key. - pub(crate) public: Public, - /// This participant's share. - pub(crate) share: Share, -} - -impl TryFrom for KeyPackage { - type Error = &'static str; - - /// Tries to verify a share and construct a [`KeyPackage`] from it. - /// - /// When participants receive a [`SharePackage`] from the dealer, they - /// *MUST* verify the integrity of the share before continuing on to - /// transform it into a signing/verification keypair. Here, we assume that - /// every participant has the same view of the commitment issued by the - /// dealer, but implementations *MUST* make sure that all participants have - /// a consistent view of this commitment in practice. - fn try_from(sharepackage: SharePackage) -> Result { - verify_share(&sharepackage.share)?; - - Ok(KeyPackage { - index: sharepackage.index, - secret_share: sharepackage.share.value, - public: sharepackage.public, - group_public: sharepackage.group_public, - }) - } -} - -/// A FROST keypair, which can be generated either by a trusted dealer or using -/// a DKG. -/// -/// When using a central dealer, [`SharePackage`]s are distributed to -/// participants, who then perform verification, before deriving -/// [`KeyPackage`]s, which they store to later use during signing. -#[allow(dead_code)] -pub struct KeyPackage { - index: u64, - secret_share: Secret, - public: Public, - group_public: VerificationKey, -} - -/// Public data that contains all the signer's public keys as well as the -/// group public key. -/// -/// Used for verification purposes before publishing a signature. -pub struct PublicKeyPackage { - /// When performing signing, the coordinator must ensure that they have the - /// correct view of participant's public keys to perform verification before - /// publishing a signature. signer_pubkeys represents all signers for a - /// signing operation. - pub(crate) signer_pubkeys: HashMap, - /// group_public represents the joint public key for the entire group. - pub group_public: VerificationKey, -} - -/// Allows all participants' keys to be generated using a central, trusted -/// dealer. -/// -/// Under the hood, this performs verifiable secret sharing, which itself uses -/// Shamir secret sharing, from which each share becomes a participant's secret -/// key. The output from this function is a set of shares along with one single -/// commitment that participants use to verify the integrity of the share. The -/// number of signers is limited to 255. -pub fn keygen_with_dealer( - num_signers: u8, - threshold: u8, - mut rng: R, -) -> Result<(Vec, PublicKeyPackage), &'static str> { - let mut bytes = [0; 64]; - rng.fill_bytes(&mut bytes); - - let secret = Secret(Scalar::from_bytes_wide(&bytes)); - let group_public = VerificationKey::from(&secret.0); - let shares = generate_shares(&secret, num_signers, threshold, rng)?; - let mut sharepackages: Vec = Vec::with_capacity(num_signers as usize); - let mut signer_pubkeys: HashMap = HashMap::with_capacity(num_signers as usize); - - for share in shares { - let signer_public = Public(SpendAuth::basepoint() * share.value.0); - sharepackages.push(SharePackage { - index: share.receiver_index, - share: share.clone(), - public: signer_public, - group_public, - }); - - signer_pubkeys.insert(share.receiver_index, signer_public); - } - - Ok(( - sharepackages, - PublicKeyPackage { - signer_pubkeys, - group_public, - }, - )) -} - -/// Verifies that a share is consistent with a commitment. -/// -/// This ensures that this participant's share has been generated using the same -/// mechanism as all other signing participants. Note that participants *MUST* -/// ensure that they have the same view as all other participants of the -/// commitment! -fn verify_share(share: &Share) -> Result<(), &'static str> { - let f_result = SpendAuth::basepoint() * share.value.0; - - let x = Scalar::from(share.receiver_index as u64); - - let (_, result) = share.commitment.0.iter().fold( - (Scalar::one(), jubjub::ExtendedPoint::identity()), - |(x_to_the_i, sum_so_far), comm_i| (x_to_the_i * x, sum_so_far + comm_i.0 * x_to_the_i), - ); - - if !(f_result == result) { - return Err("Share is invalid."); - } - - Ok(()) -} - -/// Creates secret shares for a given secret. -/// -/// This function accepts a secret from which shares are generated. While in -/// FROST this secret should always be generated randomly, we allow this secret -/// to be specified for this internal function for testability. -/// -/// Internally, [`generate_shares`] performs verifiable secret sharing, which -/// generates shares via Shamir Secret Sharing, and then generates public -/// commitments to those shares. -/// -/// More specifically, [`generate_shares`]: -/// - Randomly samples of coefficients [a, b, c], this represents a secret -/// polynomial f -/// - For each participant i, their secret share is f(i) -/// - The commitment to the secret polynomial f is [g^a, g^b, g^c] -fn generate_shares( - secret: &Secret, - numshares: u8, - threshold: u8, - mut rng: R, -) -> Result, &'static str> { - if threshold < 1 { - return Err("Threshold cannot be 0"); - } - - if numshares < 1 { - return Err("Number of shares cannot be 0"); - } - - if threshold > numshares { - return Err("Threshold cannot exceed numshares"); - } - - let numcoeffs = threshold - 1; - - let mut coefficients: Vec = Vec::with_capacity(threshold as usize); - - let mut shares: Vec = Vec::with_capacity(numshares as usize); - - let mut commitment: ShareCommitment = ShareCommitment(Vec::with_capacity(threshold as usize)); - - for _ in 0..numcoeffs { - let mut bytes = [0; 64]; - rng.fill_bytes(&mut bytes); - coefficients.push(Scalar::from_bytes_wide(&bytes)); - } - - // Verifiable secret sharing, to make sure that participants can ensure their secret is consistent - // with every other participant's. - commitment.0.push(Commitment(jubjub::AffinePoint::from( - SpendAuth::basepoint() * secret.0, - ))); - - for c in &coefficients { - commitment.0.push(Commitment(jubjub::AffinePoint::from( - SpendAuth::basepoint() * c, - ))); - } - - // Evaluate the polynomial with `secret` as the constant term - // and `coeffs` as the other coefficients at the point x=share_index, - // using Horner's method. - for index in 1..numshares + 1 { - let scalar_index = Scalar::from(index as u64); - let mut value = Scalar::zero(); - - // Polynomial evaluation, for this index - for i in (0..numcoeffs).rev() { - value += &coefficients[i as usize]; - value *= scalar_index; - } - value += secret.0; - - shares.push(Share { - receiver_index: index as u64, - value: Secret(value), - commitment: commitment.clone(), - }); - } - - Ok(shares) -} - -/// Comprised of hiding and binding nonces. -/// -/// Note that [`SigningNonces`] must be used *only once* for a signing -/// operation; re-using nonces will result in leakage of a signer's long-lived -/// signing key. -#[derive(Clone, Copy, Default)] -pub struct SigningNonces { - hiding: Scalar, - binding: Scalar, -} - -// Zeroizes `SigningNonces` to be the `Default` value on drop (when it goes out -// of scope). Luckily the derived `Default` includes the `Default` impl of the -// `jubjub::Fr/Scalar`'s, which is four 0u64's under the hood. -impl DefaultIsZeroes for SigningNonces {} - -impl SigningNonces { - /// Generates a new signing nonce. - /// - /// Each participant generates signing nonces before performing a signing - /// operation. - pub fn new(rng: &mut R) -> Self - where - R: CryptoRng + RngCore, - { - fn random_nonzero_bytes(rng: &mut R) -> [u8; 64] - where - R: CryptoRng + RngCore, - { - let mut bytes = [0; 64]; - loop { - rng.fill_bytes(&mut bytes); - if bytes != [0; 64] { - return bytes; - } - } - } - - // The values of 'hiding' and 'binding' must be non-zero so that commitments are not the - // identity. - let hiding = Scalar::from_bytes_wide(&random_nonzero_bytes(rng)); - let binding = Scalar::from_bytes_wide(&random_nonzero_bytes(rng)); - - Self { hiding, binding } - } -} - -/// Published by each participant in the first round of the signing protocol. -/// -/// This step can be batched if desired by the implementation. Each -/// SigningCommitment can be used for exactly *one* signature. -#[derive(Copy, Clone)] -pub struct SigningCommitments { - /// The participant index - pub(crate) index: u64, - /// The hiding point. - pub(crate) hiding: jubjub::ExtendedPoint, - /// The binding point. - pub(crate) binding: jubjub::ExtendedPoint, -} - -impl From<(u64, &SigningNonces)> for SigningCommitments { - /// For SpendAuth signatures only, not Binding signatures, in RedJubjub/Zcash. - fn from((index, nonces): (u64, &SigningNonces)) -> Self { - Self { - index, - hiding: SpendAuth::basepoint() * nonces.hiding, - binding: SpendAuth::basepoint() * nonces.binding, - } - } -} - -/// Generated by the coordinator of the signing operation and distributed to -/// each signing party. -pub struct SigningPackage { - /// The set of commitments participants published in the first round of the - /// protocol. - pub signing_commitments: Vec, - /// Message which each participant will sign. - /// - /// Each signer should perform protocol-specific verification on the message. - pub message: Vec, -} - -/// A representation of a single signature used in FROST structures and messages. -#[derive(Clone, Copy, Default, PartialEq)] -pub struct SignatureResponse(pub(crate) Scalar); - -/// A participant's signature share, which the coordinator will use to aggregate -/// with all other signer's shares into the joint signature. -#[derive(Clone, Copy, Default)] -pub struct SignatureShare { - /// Represents the participant index. - pub(crate) index: u64, - /// This participant's signature over the message. - pub(crate) signature: SignatureResponse, -} - -// Zeroizes `SignatureShare` to be the `Default` value on drop (when it goes out -// of scope). Luckily the derived `Default` includes the `Default` impl of -// jubjub::Fr/Scalar, which is four 0u64's under the hood, and u32, which is -// 0u32. -impl DefaultIsZeroes for SignatureShare {} - -impl SignatureShare { - /// Tests if a signature share issued by a participant is valid before - /// aggregating it into a final joint signature to publish. - pub fn check_is_valid( - &self, - pubkey: &Public, - lambda_i: Scalar, - commitment: jubjub::ExtendedPoint, - challenge: Scalar, - ) -> Result<(), &'static str> { - if (SpendAuth::basepoint() * self.signature.0) - != (commitment + pubkey.0 * challenge * lambda_i) - { - return Err("Invalid signature share"); - } - Ok(()) - } -} - -/// Done once by each participant, to generate _their_ nonces and commitments -/// that are then used during signing. -/// -/// When performing signing using two rounds, num_nonces would equal 1, to -/// perform the first round. Batching entails generating more than one -/// nonce/commitment pair at a time. Nonces should be stored in secret storage -/// for later use, whereas the commitments are published. - -/// The number of nonces is limited to 255. This limit can be increased if it -/// turns out to be too conservative. -// TODO: Make sure the above is a correct statement, fix if needed in: -// https://github.com/ZcashFoundation/redjubjub/issues/111 -pub fn preprocess( - num_nonces: u8, - participant_index: u64, - rng: &mut R, -) -> (Vec, Vec) -where - R: CryptoRng + RngCore, -{ - let mut signing_nonces: Vec = Vec::with_capacity(num_nonces as usize); - let mut signing_commitments: Vec = Vec::with_capacity(num_nonces as usize); - - for _ in 0..num_nonces { - let nonces = SigningNonces::new(rng); - signing_commitments.push(SigningCommitments::from((participant_index, &nonces))); - signing_nonces.push(nonces); - } - - (signing_nonces, signing_commitments) -} - -/// Generates the binding factor that ensures each signature share is strongly -/// bound to a signing set, specific set of commitments, and a specific message. -fn gen_rho_i(index: u64, signing_package: &SigningPackage) -> Scalar { - // Hash signature message with HStar before deriving the binding factor. - // - // To avoid a collision with other inputs to the hash that generates the - // binding factor, we should hash our input message first. Our 'standard' - // hash is HStar, which uses a domain separator already, and is the same one - // that generates the binding factor. - let message_hash = HStar::default() - .update(signing_package.message.as_slice()) - .finalize(); - - let mut hasher = HStar::default(); - hasher - .update("FROST_rho".as_bytes()) - .update(index.to_be_bytes()) - .update(message_hash.to_bytes()); - - for item in signing_package.signing_commitments.iter() { - hasher.update(item.index.to_be_bytes()); - let hiding_bytes = jubjub::AffinePoint::from(item.hiding).to_bytes(); - hasher.update(hiding_bytes); - let binding_bytes = jubjub::AffinePoint::from(item.binding).to_bytes(); - hasher.update(binding_bytes); - } - - hasher.finalize() -} - -/// Generates the group commitment which is published as part of the joint -/// Schnorr signature. -fn gen_group_commitment( - signing_package: &SigningPackage, - bindings: &HashMap, -) -> Result { - let identity = jubjub::ExtendedPoint::identity(); - let mut accumulator = identity; - - for commitment in signing_package.signing_commitments.iter() { - // The following check prevents a party from accidentally revealing their share. - // Note that the '&&' operator would be sufficient. - if identity == commitment.binding || identity == commitment.hiding { - return Err("Commitment equals the identity."); - } - - let rho_i = bindings - .get(&commitment.index) - .ok_or("No matching commitment index")?; - accumulator += commitment.hiding + (commitment.binding * rho_i) - } - - Ok(GroupCommitment(jubjub::AffinePoint::from(accumulator))) -} - -/// Generates the challenge as is required for Schnorr signatures. -fn gen_challenge( - signing_package: &SigningPackage, - group_commitment: &GroupCommitment, - group_public: &VerificationKey, -) -> Scalar { - let group_commitment_bytes = jubjub::AffinePoint::from(group_commitment.0).to_bytes(); - - HStar::default() - .update(group_commitment_bytes) - .update(group_public.bytes.bytes) - .update(signing_package.message.as_slice()) - .finalize() -} - -/// Generates the lagrange coefficient for the i'th participant. -fn gen_lagrange_coeff( - signer_index: u64, - signing_package: &SigningPackage, -) -> Result { - let mut num = Scalar::one(); - let mut den = Scalar::one(); - for commitment in signing_package.signing_commitments.iter() { - if commitment.index == signer_index { - continue; - } - num *= Scalar::from(commitment.index as u64); - den *= Scalar::from(commitment.index as u64) - Scalar::from(signer_index as u64); - } - - if den == Scalar::zero() { - return Err("Duplicate shares provided"); - } - - // TODO: handle this unwrap better like other CtOption's - let lagrange_coeff = num * den.invert().unwrap(); - - Ok(lagrange_coeff) -} - -/// Performed once by each participant selected for the signing operation. -/// -/// Receives the message to be signed and a set of signing commitments and a set -/// of randomizing commitments to be used in that signing operation, including -/// that for this participant. -/// -/// Assumes the participant has already determined which nonce corresponds with -/// the commitment that was assigned by the coordinator in the SigningPackage. -pub fn sign( - signing_package: &SigningPackage, - participant_nonces: SigningNonces, - share_package: &SharePackage, -) -> Result { - let mut bindings: HashMap = - HashMap::with_capacity(signing_package.signing_commitments.len()); - - for comm in signing_package.signing_commitments.iter() { - let rho_i = gen_rho_i(comm.index, &signing_package); - bindings.insert(comm.index, rho_i); - } - - let lambda_i = gen_lagrange_coeff(share_package.index, &signing_package)?; - - let group_commitment = gen_group_commitment(&signing_package, &bindings)?; - - let challenge = gen_challenge( - &signing_package, - &group_commitment, - &share_package.group_public, - ); - - let participant_rho_i = bindings - .get(&share_package.index) - .ok_or("No matching binding!")?; - - // The Schnorr signature share - let signature: Scalar = participant_nonces.hiding - + (participant_nonces.binding * participant_rho_i) - + (lambda_i * share_package.share.value.0 * challenge); - - Ok(SignatureShare { - index: share_package.index, - signature: SignatureResponse(signature), - }) -} - -/// Verifies each participant's signature share, and if all are valid, -/// aggregates the shares into a signature to publish. -/// -/// Resulting signature is compatible with verification of a plain SpendAuth -/// signature. -/// -/// This operation is performed by a coordinator that can communicate with all -/// the signing participants before publishing the final signature. The -/// coordinator can be one of the participants or a semi-trusted third party -/// (who is trusted to not perform denial of service attacks, but does not learn -/// any secret information). Note that because the coordinator is trusted to -/// report misbehaving parties in order to avoid publishing an invalid -/// signature, if the coordinator themselves is a signer and misbehaves, they -/// can avoid that step. However, at worst, this results in a denial of -/// service attack due to publishing an invalid signature. -pub fn aggregate( - signing_package: &SigningPackage, - signing_shares: &[SignatureShare], - pubkeys: &PublicKeyPackage, -) -> Result, &'static str> { - let mut bindings: HashMap = - HashMap::with_capacity(signing_package.signing_commitments.len()); - - for comm in signing_package.signing_commitments.iter() { - let rho_i = gen_rho_i(comm.index, &signing_package); - bindings.insert(comm.index, rho_i); - } - - let group_commitment = gen_group_commitment(&signing_package, &bindings)?; - - let challenge = gen_challenge(&signing_package, &group_commitment, &pubkeys.group_public); - - for signing_share in signing_shares { - let signer_pubkey = pubkeys.signer_pubkeys[&signing_share.index]; - let lambda_i = gen_lagrange_coeff(signing_share.index, &signing_package)?; - let signer_commitment = signing_package - .signing_commitments - .iter() - .find(|comm| comm.index == signing_share.index) - .ok_or("No matching signing commitment for signer")?; - - let commitment_i = - signer_commitment.hiding + (signer_commitment.binding * bindings[&signing_share.index]); - - signing_share.check_is_valid(&signer_pubkey, lambda_i, commitment_i, challenge)?; - } - - // The aggregation of the signature shares by summing them up, resulting in - // a plain Schnorr signature. - let mut z = Scalar::zero(); - for signature_share in signing_shares { - z += signature_share.signature.0; - } - - Ok(Signature { - r_bytes: jubjub::AffinePoint::from(group_commitment.0).to_bytes(), - s_bytes: z.to_bytes(), - _marker: PhantomData, - }) -} - -#[cfg(test)] -mod tests { - use super::*; - use rand::thread_rng; - - fn reconstruct_secret(shares: Vec) -> Result { - let numshares = shares.len(); - - if numshares < 1 { - return Err("No shares provided"); - } - - let mut lagrange_coeffs: Vec = Vec::with_capacity(numshares as usize); - - for i in 0..numshares { - let mut num = Scalar::one(); - let mut den = Scalar::one(); - for j in 0..numshares { - if j == i { - continue; - } - num *= Scalar::from(shares[j].receiver_index as u64); - den *= Scalar::from(shares[j].receiver_index as u64) - - Scalar::from(shares[i].receiver_index as u64); - } - if den == Scalar::zero() { - return Err("Duplicate shares provided"); - } - lagrange_coeffs.push(num * den.invert().unwrap()); - } - - let mut secret = Scalar::zero(); - - for i in 0..numshares { - secret += lagrange_coeffs[i] * shares[i].value.0; - } - - Ok(secret) - } - - /// This is testing that Shamir's secret sharing to compute and arbitrary - /// value is working. - #[test] - fn check_share_generation() { - let mut rng = thread_rng(); - - let mut bytes = [0; 64]; - rng.fill_bytes(&mut bytes); - let secret = Secret(Scalar::from_bytes_wide(&bytes)); - - let _ = SpendAuth::basepoint() * secret.0; - - let shares = generate_shares(&secret, 5, 3, rng).unwrap(); - - for share in shares.iter() { - assert_eq!(verify_share(&share), Ok(())); - } - - assert_eq!(reconstruct_secret(shares).unwrap(), secret.0) - } -} diff --git a/frost-redjubjub/src/hash.rs b/frost-redjubjub/src/hash.rs deleted file mode 100644 index 4e8766c..0000000 --- a/frost-redjubjub/src/hash.rs +++ /dev/null @@ -1,40 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of redjubjub. -// Copyright (c) 2019-2021 Zcash Foundation -// See LICENSE for licensing information. -// -// Authors: -// - Deirdre Connolly -// - Henry de Valence - -use blake2b_simd::{Params, State}; -use jubjub::Scalar; - -/// Provides H^star, the hash-to-scalar function used by RedJubjub. -pub struct HStar { - state: State, -} - -impl Default for HStar { - fn default() -> Self { - let state = Params::new() - .hash_length(64) - .personal(b"Zcash_RedJubjubH") - .to_state(); - Self { state } - } -} - -impl HStar { - /// Add `data` to the hash, and return `Self` for chaining. - pub fn update(&mut self, data: impl AsRef<[u8]>) -> &mut Self { - self.state.update(data.as_ref()); - self - } - - /// Consume `self` to compute the hash output. - pub fn finalize(&self) -> Scalar { - Scalar::from_bytes_wide(self.state.finalize().as_array()) - } -} diff --git a/frost-redjubjub/src/lib.rs b/frost-redjubjub/src/lib.rs deleted file mode 100644 index 3b8a92d..0000000 --- a/frost-redjubjub/src/lib.rs +++ /dev/null @@ -1,78 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of redjubjub. -// Copyright (c) 2019-2021 Zcash Foundation -// See LICENSE for licensing information. -// -// Authors: -// - Deirdre Connolly -// - Henry de Valence - -#![deny(missing_docs)] -#![doc = include_str!("../README.md")] - -pub mod batch; -mod constants; -mod error; -pub mod frost; -mod hash; -mod messages; -mod scalar_mul; -pub(crate) mod signature; -mod signing_key; -mod verification_key; - -/// An element of the JubJub scalar field used for randomization of public and secret keys. -pub type Randomizer = jubjub::Scalar; - -use hash::HStar; - -pub use error::Error; -pub use signature::Signature; -pub use signing_key::SigningKey; -pub use verification_key::{VerificationKey, VerificationKeyBytes}; - -/// Abstracts over different RedJubJub parameter choices, [`Binding`] -/// and [`SpendAuth`]. -/// -/// As described [at the end of §5.4.6][concretereddsa] of the Zcash -/// protocol specification, the generator used in RedJubjub is left as -/// an unspecified parameter, chosen differently for each of -/// `BindingSig` and `SpendAuthSig`. -/// -/// To handle this, we encode the parameter choice as a genuine type -/// parameter. -/// -/// [concretereddsa]: https://zips.z.cash/protocol/protocol.pdf#concretereddsa -pub trait SigType: private::Sealed {} - -/// A type variable corresponding to Zcash's `BindingSig`. -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub enum Binding {} -impl SigType for Binding {} - -/// A type variable corresponding to Zcash's `SpendAuthSig`. -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub enum SpendAuth {} -impl SigType for SpendAuth {} - -pub(crate) mod private { - use super::*; - pub trait Sealed: Copy + Clone + Eq + PartialEq + std::fmt::Debug { - fn basepoint() -> jubjub::ExtendedPoint; - } - impl Sealed for Binding { - fn basepoint() -> jubjub::ExtendedPoint { - jubjub::AffinePoint::from_bytes(constants::BINDINGSIG_BASEPOINT_BYTES) - .unwrap() - .into() - } - } - impl Sealed for SpendAuth { - fn basepoint() -> jubjub::ExtendedPoint { - jubjub::AffinePoint::from_bytes(constants::SPENDAUTHSIG_BASEPOINT_BYTES) - .unwrap() - .into() - } - } -} diff --git a/frost-redjubjub/src/messages.rs b/frost-redjubjub/src/messages.rs deleted file mode 100644 index 1b335e6..0000000 --- a/frost-redjubjub/src/messages.rs +++ /dev/null @@ -1,269 +0,0 @@ -//! The FROST communication messages specified in [RFC-001] -//! -//! [RFC-001]: https://github.com/ZcashFoundation/redjubjub/blob/main/rfcs/0001-messages.md - -use crate::{frost, signature, verification_key, SpendAuth}; -use serde::{Deserialize, Serialize}; - -use std::collections::BTreeMap; - -#[cfg(test)] -use proptest_derive::Arbitrary; - -#[cfg(test)] -mod arbitrary; -mod constants; -mod serialize; -#[cfg(test)] -mod tests; -mod validate; - -/// Define our own `Secret` type instead of using [`frost::Secret`]. -/// -/// The serialization design specifies that `Secret` is a [`jubjub::Scalar`] that uses: -/// "a 32-byte little-endian canonical representation". -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)] -#[cfg_attr(test, derive(Arbitrary))] -pub struct Secret([u8; 32]); - -/// Define our own `Commitment` type instead of using [`frost::Commitment`]. -/// -/// The serialization design specifies that `Commitment` is an [`jubjub::AffinePoint`] that uses: -/// "a 32-byte little-endian canonical representation". -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Copy)] -#[cfg_attr(test, derive(Arbitrary))] -pub struct Commitment([u8; 32]); - -impl From for Commitment { - fn from(value: frost::Commitment) -> Commitment { - Commitment(jubjub::AffinePoint::from(value.0).to_bytes()) - } -} - -/// Define our own `GroupCommitment` type instead of using [`frost::GroupCommitment`]. -/// -/// The serialization design specifies that `GroupCommitment` is an [`jubjub::AffinePoint`] that uses: -/// "a 32-byte little-endian canonical representation". -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)] -#[cfg_attr(test, derive(Arbitrary))] -pub struct GroupCommitment([u8; 32]); - -/// Define our own `SignatureResponse` type instead of using [`frost::SignatureResponse`]. -/// -/// The serialization design specifies that `SignatureResponse` is a [`jubjub::Scalar`] that uses: -/// "a 32-byte little-endian canonical representation". -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)] -#[cfg_attr(test, derive(Arbitrary))] -pub struct SignatureResponse([u8; 32]); - -impl From> for SignatureResponse { - fn from(value: signature::Signature) -> SignatureResponse { - SignatureResponse(value.s_bytes) - } -} - -impl From> for GroupCommitment { - fn from(value: signature::Signature) -> GroupCommitment { - GroupCommitment(value.r_bytes) - } -} - -/// Define our own `VerificationKey` type instead of using [`verification_key::VerificationKey`]. -/// -/// The serialization design specifies that `VerificationKey` is a [`verification_key::VerificationKeyBytes`] that uses: -/// "a 32-byte little-endian canonical representation". -#[derive(Serialize, Deserialize, PartialEq, Debug, Copy, Clone)] -#[cfg_attr(test, derive(Arbitrary))] -pub struct VerificationKey([u8; 32]); - -impl From> for VerificationKey { - fn from(value: verification_key::VerificationKey) -> VerificationKey { - VerificationKey(<[u8; 32]>::from(value)) - } -} - -/// The data required to serialize a frost message. -#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] -#[cfg_attr(test, derive(Arbitrary))] -pub struct Message { - header: Header, - payload: Payload, -} - -/// The data required to serialize the common header fields for every message. -/// -/// Note: the `msg_type` is derived from the `payload` enum variant. -#[derive(Serialize, Deserialize, PartialEq, Debug, Clone, Copy)] -pub struct Header { - version: MsgVersion, - sender: ParticipantId, - receiver: ParticipantId, -} - -/// The data required to serialize the payload for a message. -#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] -#[cfg_attr(test, derive(Arbitrary))] -pub enum Payload { - SharePackage(SharePackage), - SigningCommitments(SigningCommitments), - SigningPackage(SigningPackage), - SignatureShare(SignatureShare), - AggregateSignature(AggregateSignature), -} - -/// The numeric values used to identify each [`Payload`] variant during serialization. -// TODO: spec says `#[repr(u8)]` but it is incompatible with `bincode` -// manual serialization and deserialization is needed. -#[repr(u32)] -#[non_exhaustive] -#[derive(Serialize, Deserialize, Debug, PartialEq)] -enum MsgType { - SharePackage, - SigningCommitments, - SigningPackage, - SignatureShare, - AggregateSignature, -} - -/// The numeric values used to identify the protocol version during serialization. -#[derive(PartialEq, Serialize, Deserialize, Debug, Clone, Copy)] -pub struct MsgVersion(u8); - -/// The numeric values used to identify each participant during serialization. -/// -/// In the `frost` module, participant ID `0` should be invalid. -/// But in serialization, we want participants to be indexed from `0..n`, -/// where `n` is the number of participants. -/// This helps us look up their shares and commitments in serialized arrays. -/// So in serialization, we assign the dealer and aggregator the highest IDs, -/// and mark those IDs as invalid for signers. -/// -/// "When performing Shamir secret sharing, a polynomial `f(x)` is used to generate -/// each party’s share of the secret. The actual secret is `f(0)` and the party with -/// ID `i` will be given a share with value `f(i)`. -/// Since a DKG may be implemented in the future, we recommend that the ID `0` be declared invalid." -/// https://raw.githubusercontent.com/ZcashFoundation/redjubjub/main/zcash-frost-audit-report-20210323.pdf#d -#[derive(PartialEq, Eq, Hash, PartialOrd, Debug, Copy, Clone, Ord)] -pub enum ParticipantId { - /// A serialized participant ID for a signer. - /// - /// Must be less than or equal to [`constants::MAX_SIGNER_PARTICIPANT_ID`]. - Signer(u64), - /// The fixed participant ID for the dealer as defined in [`constants::DEALER_PARTICIPANT_ID`]. - Dealer, - /// The fixed participant ID for the aggregator as defined in [`constants::AGGREGATOR_PARTICIPANT_ID`]. - Aggregator, -} - -impl From for u64 { - fn from(value: ParticipantId) -> u64 { - match value { - // An id of `0` is invalid in frost. - ParticipantId::Signer(id) => id + 1, - ParticipantId::Dealer => constants::DEALER_PARTICIPANT_ID, - ParticipantId::Aggregator => constants::AGGREGATOR_PARTICIPANT_ID, - } - } -} - -/// The data required to serialize [`frost::SharePackage`]. -/// -/// The dealer sends this message to each signer for this round. -/// With this, the signer should be able to build a [`SharePackage`] and use -/// the [`frost::sign()`] function. -/// -/// Note: [`frost::SharePackage::public`] can be calculated from [`SharePackage::secret_share`]. -#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] -#[cfg_attr(test, derive(Arbitrary))] -pub struct SharePackage { - /// The public signing key that represents the entire group: - /// [`frost::SharePackage::group_public`]. - group_public: VerificationKey, - /// This participant's secret key share: [`frost::SharePackage::share`]. - secret_share: Secret, - /// The commitments to the coefficients for our secret polynomial _f_, - /// used to generate participants' key shares. Participants use these to perform - /// verifiable secret sharing. - /// Share packages that contain duplicate or missing [`ParticipantId`]s are invalid. - /// [`ParticipantId`]s must be serialized in ascending numeric order. - share_commitment: BTreeMap, -} - -/// The data required to serialize [`frost::SigningCommitments`]. -/// -/// Each signer must send this message to the aggregator. -/// A signing commitment from the first round of the signing protocol. -#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] -#[cfg_attr(test, derive(Arbitrary))] -pub struct SigningCommitments { - /// The hiding point: [`frost::SigningCommitments::hiding`] - hiding: Commitment, - /// The binding point: [`frost::SigningCommitments::binding`] - binding: Commitment, -} - -/// The data required to serialize [`frost::SigningPackage`]. -/// -/// The aggregator decides what message is going to be signed and -/// sends it to each signer with all the commitments collected. -#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] -#[cfg_attr(test, derive(Arbitrary))] -pub struct SigningPackage { - /// The collected commitments for each signer as a hashmap of - /// unique participant identifiers: [`frost::SigningPackage::signing_commitments`] - /// - /// Signing packages that contain duplicate or missing [`ParticipantId`]s are invalid. - signing_commitments: BTreeMap, - /// The message to be signed: [`frost::SigningPackage::message`]. - /// - /// Each signer should perform protocol-specific verification on the message. - message: Vec, -} - -impl From for frost::SigningPackage { - fn from(value: SigningPackage) -> frost::SigningPackage { - let mut signing_commitments = Vec::new(); - for (participant_id, commitment) in &value.signing_commitments { - let s = frost::SigningCommitments { - index: u64::from(*participant_id), - // TODO: The `from_bytes()` response is a `CtOption` so we have to `unwrap()` - hiding: jubjub::ExtendedPoint::from( - jubjub::AffinePoint::from_bytes(commitment.hiding.0).unwrap(), - ), - binding: jubjub::ExtendedPoint::from( - jubjub::AffinePoint::from_bytes(commitment.binding.0).unwrap(), - ), - }; - signing_commitments.push(s); - } - - frost::SigningPackage { - signing_commitments, - message: value.message, - } - } -} - -/// The data required to serialize [`frost::SignatureShare`]. -/// -/// Each signer sends their signatures to the aggregator who is going to collect them -/// and generate a final spend signature. -#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] -#[cfg_attr(test, derive(Arbitrary))] -pub struct SignatureShare { - /// This participant's signature over the message: [`frost::SignatureShare::signature`] - signature: SignatureResponse, -} - -/// The data required to serialize a successful output from [`frost::aggregate()`]. -/// -/// The final signature is broadcasted by the aggregator to all signers. -#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] -#[cfg_attr(test, derive(Arbitrary))] -pub struct AggregateSignature { - /// The aggregated group commitment: [`signature::Signature::r_bytes`] returned by [`frost::aggregate()`] - group_commitment: GroupCommitment, - /// A plain Schnorr signature created by summing all the signature shares: - /// [`signature::Signature::s_bytes`] returned by [`frost::aggregate()`] - schnorr_signature: SignatureResponse, -} diff --git a/frost-redjubjub/src/messages/arbitrary.rs b/frost-redjubjub/src/messages/arbitrary.rs deleted file mode 100644 index 515b7a0..0000000 --- a/frost-redjubjub/src/messages/arbitrary.rs +++ /dev/null @@ -1,55 +0,0 @@ -use proptest::{ - arbitrary::{any, Arbitrary}, - prelude::*, -}; - -use super::*; - -impl Arbitrary for Header { - type Parameters = (); - - fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy { - ( - any::(), - any::(), - any::(), - ) - .prop_filter( - "Sender and receiver participant IDs can not be the same", - |(_, sender, receiver)| sender != receiver, - ) - .prop_map(|(version, sender, receiver)| Header { - version: version, - sender: sender, - receiver: receiver, - }) - .boxed() - } - - type Strategy = BoxedStrategy; -} - -impl Arbitrary for MsgVersion { - type Parameters = (); - - fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy { - Just(constants::BASIC_FROST_SERIALIZATION).boxed() - } - - type Strategy = BoxedStrategy; -} - -impl Arbitrary for ParticipantId { - type Parameters = (); - - fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy { - prop_oneof![ - (u64::MIN..=constants::MAX_SIGNER_PARTICIPANT_ID).prop_map(ParticipantId::Signer), - Just(ParticipantId::Dealer), - Just(ParticipantId::Aggregator), - ] - .boxed() - } - - type Strategy = BoxedStrategy; -} diff --git a/frost-redjubjub/src/messages/constants.rs b/frost-redjubjub/src/messages/constants.rs deleted file mode 100644 index 1a77103..0000000 --- a/frost-redjubjub/src/messages/constants.rs +++ /dev/null @@ -1,31 +0,0 @@ -//! Definitions of constants. - -use super::MsgVersion; - -/// The first version of FROST messages -pub const BASIC_FROST_SERIALIZATION: MsgVersion = MsgVersion(0); - -/// The fixed participant ID for the dealer. -pub const DEALER_PARTICIPANT_ID: u64 = u64::MAX - 1; - -/// The fixed participant ID for the aggregator. -pub const AGGREGATOR_PARTICIPANT_ID: u64 = u64::MAX; - -/// The maximum `ParticipantId::Signer` in this serialization format. -/// -/// We reserve two participant IDs for the dealer and aggregator. -pub const MAX_SIGNER_PARTICIPANT_ID: u64 = u64::MAX - 2; - -/// The maximum number of signers -/// -/// By protocol the number of signers can'e be more than 255. -pub const MAX_SIGNERS: u8 = 255; - -/// The maximum length of a Zcash message, in bytes. -pub const ZCASH_MAX_PROTOCOL_MESSAGE_LEN: usize = 2 * 1024 * 1024; - -/// The minimum number of signers of any FROST setup. -pub const MIN_SIGNERS: usize = 2; - -/// The minimum number of signers that must sign. -pub const MIN_THRESHOLD: usize = 2; diff --git a/frost-redjubjub/src/messages/serialize.rs b/frost-redjubjub/src/messages/serialize.rs deleted file mode 100644 index 0fba8fb..0000000 --- a/frost-redjubjub/src/messages/serialize.rs +++ /dev/null @@ -1,68 +0,0 @@ -//! Serialization rules specified in [RFC-001#Serialize-Deserialize] -//! -//! We automatically serialize and deserialize using serde derivations where possible. -//! Sometimes we need to implement ourselves, this file holds that code. -//! -//! [RFC-001#Serialize-Deserialize]: https://github.com/ZcashFoundation/redjubjub/blob/main/rfcs/0001-messages.md#serializationdeserialization - -use serde::ser::{Serialize, Serializer}; - -use serde::de::{self, Deserialize, Deserializer, Visitor}; - -use super::constants::{ - AGGREGATOR_PARTICIPANT_ID, DEALER_PARTICIPANT_ID, MAX_SIGNER_PARTICIPANT_ID, -}; -use super::*; - -use std::fmt; - -impl Serialize for ParticipantId { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - match *self { - ParticipantId::Signer(id) => { - assert!(id <= MAX_SIGNER_PARTICIPANT_ID); - serializer.serialize_u64(id) - } - ParticipantId::Dealer => serializer.serialize_u64(DEALER_PARTICIPANT_ID), - ParticipantId::Aggregator => serializer.serialize_u64(AGGREGATOR_PARTICIPANT_ID), - } - } -} - -struct ParticipantIdVisitor; - -impl<'de> Visitor<'de> for ParticipantIdVisitor { - type Value = ParticipantId; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str( - format!("an integer between {} and {}", std::u64::MIN, std::u64::MAX).as_str(), - ) - } - - fn visit_u64(self, value: u64) -> Result - where - E: de::Error, - { - // Note: deserialization can't fail, because all values are valid. - if value == DEALER_PARTICIPANT_ID { - return Ok(ParticipantId::Dealer); - } else if value == AGGREGATOR_PARTICIPANT_ID { - return Ok(ParticipantId::Aggregator); - } else { - return Ok(ParticipantId::Signer(value)); - } - } -} - -impl<'de> Deserialize<'de> for ParticipantId { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - deserializer.deserialize_u64(ParticipantIdVisitor) - } -} diff --git a/frost-redjubjub/src/messages/tests.rs b/frost-redjubjub/src/messages/tests.rs deleted file mode 100644 index f0f320e..0000000 --- a/frost-redjubjub/src/messages/tests.rs +++ /dev/null @@ -1,2 +0,0 @@ -mod integration; -mod prop; diff --git a/frost-redjubjub/src/messages/tests/integration.rs b/frost-redjubjub/src/messages/tests/integration.rs deleted file mode 100644 index e571669..0000000 --- a/frost-redjubjub/src/messages/tests/integration.rs +++ /dev/null @@ -1,805 +0,0 @@ -use crate::{ - frost, - messages::{ - validate::{MsgErr, Validate}, - *, - }, - verification_key, -}; -use rand::thread_rng; -use serde_json; -use std::convert::TryFrom; - -#[test] -fn validate_version() { - // A version number that we expect to be always invalid - const INVALID_VERSION: u8 = u8::MAX; - - let setup = basic_setup(); - - let header = Header { - version: MsgVersion(INVALID_VERSION), - sender: setup.dealer, - receiver: setup.signer1, - }; - - let validate = Validate::validate(&header); - assert_eq!(validate, Err(MsgErr::WrongVersion)); - - let validate = Validate::validate(&Header { - version: constants::BASIC_FROST_SERIALIZATION, - sender: setup.dealer, - receiver: setup.signer1, - }) - .err(); - - assert_eq!(validate, None); -} - -#[test] -fn validate_sender_receiver() { - let setup = basic_setup(); - - let header = Header { - version: constants::BASIC_FROST_SERIALIZATION, - sender: setup.signer1, - receiver: setup.signer1, - }; - - let validate = Validate::validate(&header); - assert_eq!(validate, Err(MsgErr::SameSenderAndReceiver)); -} - -#[test] -fn validate_sharepackage() { - let setup = basic_setup(); - let (mut shares, _pubkeys) = - frost::keygen_with_dealer(setup.num_signers, setup.threshold, setup.rng.clone()).unwrap(); - - let header = create_valid_header(setup.signer1, setup.signer2); - - let group_public = VerificationKey::from( - verification_key::VerificationKey::try_from(shares[0].group_public.bytes).unwrap(), - ); - let secret_share = Secret(shares[0].share.value.0.to_bytes()); - - let participants = vec![setup.signer1, setup.signer2]; - shares.truncate(2); - let share_commitment = generate_share_commitment(&shares, participants); - - let payload = Payload::SharePackage(SharePackage { - group_public, - secret_share: secret_share, - share_commitment: share_commitment, - }); - let validate_payload = Validate::validate(&payload); - let valid_payload = validate_payload.expect("a valid payload").clone(); - - let message = Message { - header, - payload: valid_payload.clone(), - }; - - let validate_message = Validate::validate(&message); - assert_eq!(validate_message, Err(MsgErr::SenderMustBeDealer)); - - // change the header - let header = create_valid_header(setup.dealer, setup.aggregator); - - let message = Message { - header, - payload: valid_payload, - }; - - let validate_message = Validate::validate(&message); - assert_eq!(validate_message, Err(MsgErr::ReceiverMustBeSigner)); - - let participants = vec![setup.signer1]; - shares.truncate(1); - let mut share_commitment = generate_share_commitment(&shares, participants); - - // change the payload to have only 1 commitment - let payload = Payload::SharePackage(SharePackage { - group_public, - secret_share: secret_share, - share_commitment: share_commitment.clone(), - }); - let validate_payload = Validate::validate(&payload); - assert_eq!( - validate_payload, - Err(MsgErr::NotEnoughCommitments(constants::MIN_SIGNERS)) - ); - - // build and use too many commitments - for i in 2..constants::MAX_SIGNERS as u64 + 2 { - share_commitment.insert( - ParticipantId::Signer(i), - share_commitment.clone()[&setup.signer1], - ); - } - let payload = Payload::SharePackage(SharePackage { - group_public, - secret_share, - share_commitment, - }); - let validate_payload = Validate::validate(&payload); - assert_eq!(validate_payload, Err(MsgErr::TooManyCommitments)); -} - -#[test] -fn serialize_sharepackage() { - let setup = basic_setup(); - - let (mut shares, _pubkeys) = - frost::keygen_with_dealer(setup.num_signers, setup.threshold, setup.rng.clone()).unwrap(); - - let header = create_valid_header(setup.dealer, setup.signer1); - - let group_public = VerificationKey::from( - verification_key::VerificationKey::try_from(shares[0].group_public.bytes).unwrap(), - ); - let secret_share = Secret(shares[0].share.value.0.to_bytes()); - - let participants = vec![setup.signer1]; - shares.truncate(1); - let share_commitment = generate_share_commitment(&shares, participants); - - let payload = Payload::SharePackage(SharePackage { - group_public, - secret_share, - share_commitment: share_commitment.clone(), - }); - - let message = Message { - header: header, - payload: payload.clone(), - }; - - // check general structure and header serialization/deserialization - serialize_message(message, setup.dealer, setup.signer1); - - // check payload serialization/deserialization - let mut payload_serialized_bytes = bincode::serialize(&payload).unwrap(); - // check the message type is correct - let deserialized_msg_type: MsgType = - bincode::deserialize(&payload_serialized_bytes[0..4]).unwrap(); - assert_eq!(deserialized_msg_type, MsgType::SharePackage); - - // remove the msg_type from the the payload - payload_serialized_bytes = - (&payload_serialized_bytes[4..payload_serialized_bytes.len()]).to_vec(); - - // group_public is 32 bytes - let deserialized_group_public: VerificationKey = - bincode::deserialize(&payload_serialized_bytes[0..32]).unwrap(); - // secret share is 32 bytes - let deserialized_secret_share: Secret = - bincode::deserialize(&payload_serialized_bytes[32..64]).unwrap(); - // rest of the message is the map: 32(Commitment) + 8(ParticipantId) + 8(map.len()) - let deserialized_share_commitment: BTreeMap = - bincode::deserialize(&payload_serialized_bytes[64..112]).unwrap(); - - // check the map len - let deserialized_map_len: u64 = - bincode::deserialize(&payload_serialized_bytes[64..72]).unwrap(); - assert_eq!(deserialized_map_len, 1); - - // no leftover bytes - assert_eq!(payload_serialized_bytes.len(), 112); - - assert_eq!(deserialized_group_public, group_public); - assert_eq!(deserialized_secret_share, secret_share); - assert_eq!(deserialized_share_commitment, share_commitment); -} - -#[test] -fn validate_signingcommitments() { - let mut setup = basic_setup(); - - let (_nonce, commitment) = frost::preprocess(1, u64::from(setup.signer1), &mut setup.rng); - - let header = create_valid_header(setup.aggregator, setup.signer2); - - let payload = Payload::SigningCommitments(SigningCommitments { - hiding: Commitment(jubjub::AffinePoint::from(commitment[0].hiding).to_bytes()), - binding: Commitment(jubjub::AffinePoint::from(commitment[0].binding).to_bytes()), - }); - - let message = Message { - header, - payload: payload.clone(), - }; - - let validate_message = Validate::validate(&message); - assert_eq!(validate_message, Err(MsgErr::SenderMustBeSigner)); - - // change the header - let header = create_valid_header(setup.signer1, setup.signer2); - - let message = Message { - header, - payload: payload.clone(), - }; - - let validate_message = Validate::validate(&message); - assert_eq!(validate_message, Err(MsgErr::ReceiverMustBeAggregator)); - - // change the header to be valid - let header = create_valid_header(setup.signer1, setup.aggregator); - - let validate_message = Validate::validate(&Message { header, payload }).err(); - - assert_eq!(validate_message, None); -} - -#[test] -fn serialize_signingcommitments() { - let mut setup = basic_setup(); - - let (_nonce, commitment) = frost::preprocess(1, u64::from(setup.signer1), &mut setup.rng); - - let header = create_valid_header(setup.aggregator, setup.signer1); - - let hiding = Commitment(jubjub::AffinePoint::from(commitment[0].hiding).to_bytes()); - let binding = Commitment(jubjub::AffinePoint::from(commitment[0].binding).to_bytes()); - - let payload = Payload::SigningCommitments(SigningCommitments { hiding, binding }); - - let message = Message { - header: header, - payload: payload.clone(), - }; - - // check general structure serialization/deserialization - serialize_message(message, setup.aggregator, setup.signer1); - - // check payload serialization/deserialization - let mut payload_serialized_bytes = bincode::serialize(&payload).unwrap(); - // check the message type is correct - let deserialized_msg_type: MsgType = - bincode::deserialize(&payload_serialized_bytes[0..4]).unwrap(); - assert_eq!(deserialized_msg_type, MsgType::SigningCommitments); - - // remove the msg_type from the the payload - payload_serialized_bytes = - (&payload_serialized_bytes[4..payload_serialized_bytes.len()]).to_vec(); - - // hiding is 32 bytes - let deserialized_hiding: Commitment = - bincode::deserialize(&payload_serialized_bytes[0..32]).unwrap(); - // binding is 43 bytes kore - let deserialized_binding: Commitment = - bincode::deserialize(&payload_serialized_bytes[32..64]).unwrap(); - - // no leftover bytes - assert_eq!(payload_serialized_bytes.len(), 64); - - assert_eq!(deserialized_hiding, hiding); - assert_eq!(deserialized_binding, binding); -} - -#[test] -fn validate_signingpackage() { - let mut setup = basic_setup(); - - let (_nonce, commitment1) = frost::preprocess(1, u64::from(setup.signer1), &mut setup.rng); - let (_nonce, commitment2) = frost::preprocess(1, u64::from(setup.signer2), &mut setup.rng); - - let header = create_valid_header(setup.signer1, setup.signer2); - - // try with only 1 commitment - let commitments = vec![commitment1[0]]; - let participants = vec![setup.signer1]; - let signing_commitments = create_signing_commitments(commitments, participants); - - let payload = Payload::SigningPackage(SigningPackage { - signing_commitments: signing_commitments.clone(), - message: "hola".as_bytes().to_vec(), - }); - let validate_payload = Validate::validate(&payload); - assert_eq!( - validate_payload, - Err(MsgErr::NotEnoughCommitments(constants::MIN_SIGNERS)) - ); - - // add too many commitments - let mut big_signing_commitments = BTreeMap::::new(); - for i in 0..constants::MAX_SIGNERS as u64 + 1 { - big_signing_commitments.insert( - ParticipantId::Signer(i), - signing_commitments[&setup.signer1].clone(), - ); - } - let payload = Payload::SigningPackage(SigningPackage { - signing_commitments: big_signing_commitments, - message: "hola".as_bytes().to_vec(), - }); - let validate_payload = Validate::validate(&payload); - assert_eq!(validate_payload, Err(MsgErr::TooManyCommitments)); - - // change to 2 commitments - let commitments = vec![commitment1[0], commitment2[0]]; - let participants = vec![setup.signer1, setup.signer2]; - let signing_commitments = create_signing_commitments(commitments, participants); - - let big_message = [0u8; constants::ZCASH_MAX_PROTOCOL_MESSAGE_LEN + 1].to_vec(); - let payload = Payload::SigningPackage(SigningPackage { - signing_commitments: signing_commitments.clone(), - message: big_message, - }); - let validate_payload = Validate::validate(&payload); - assert_eq!(validate_payload, Err(MsgErr::MsgTooBig)); - - let message = Message { - header, - payload: payload.clone(), - }; - let validate_message = Validate::validate(&message); - assert_eq!(validate_message, Err(MsgErr::SenderMustBeAggregator)); - - // change header - let header = create_valid_header(setup.aggregator, setup.dealer); - - let message = Message { - header: header, - payload: payload.clone(), - }; - - let validate_message = Validate::validate(&message); - assert_eq!(validate_message, Err(MsgErr::ReceiverMustBeSigner)); - - let header = create_valid_header(setup.aggregator, setup.signer1); - let payload = Payload::SigningPackage(SigningPackage { - signing_commitments, - message: "hola".as_bytes().to_vec(), - }); - - let validate_message = Validate::validate(&Message { header, payload }).err(); - assert_eq!(validate_message, None); -} - -#[test] -fn serialize_signingpackage() { - let mut setup = basic_setup(); - - let (_nonce, commitment1) = frost::preprocess(1, u64::from(setup.signer1), &mut setup.rng); - let (_nonce, commitment2) = frost::preprocess(1, u64::from(setup.signer2), &mut setup.rng); - - let header = create_valid_header(setup.aggregator, setup.signer1); - - let commitments = vec![commitment1[0], commitment2[0]]; - let participants = vec![setup.signer1, setup.signer2]; - let signing_commitments = create_signing_commitments(commitments, participants); - - let payload = Payload::SigningPackage(SigningPackage { - signing_commitments: signing_commitments.clone(), - message: "hola".as_bytes().to_vec(), - }); - - let message = Message { - header: header, - payload: payload.clone(), - }; - - // check general structure serialization/deserialization - serialize_message(message, setup.aggregator, setup.signer1); - - // check payload serialization/deserialization - let mut payload_serialized_bytes = bincode::serialize(&payload).unwrap(); - - // check the message type is correct - let deserialized_msg_type: MsgType = - bincode::deserialize(&payload_serialized_bytes[0..4]).unwrap(); - assert_eq!(deserialized_msg_type, MsgType::SigningPackage); - - // remove the msg_type from the the payload - payload_serialized_bytes = - (&payload_serialized_bytes[4..payload_serialized_bytes.len()]).to_vec(); - - // check the map len - let deserialized_map_len: u64 = bincode::deserialize(&payload_serialized_bytes[0..8]).unwrap(); - assert_eq!(deserialized_map_len, 2); - - // Each SigningCommitment is 64 bytes and the ParticipantId is 8 bytes. - // This is multiplied by the map len, also include the map len bytes. - let deserialized_signing_commitments: BTreeMap = - bincode::deserialize(&payload_serialized_bytes[0..152]).unwrap(); - - // Message is from the end of the map up to the end of the message. - let deserialized_message: Vec = - bincode::deserialize(&payload_serialized_bytes[152..payload_serialized_bytes.len()]) - .unwrap(); - - // no leftover bytes - assert_eq!(payload_serialized_bytes.len(), 164); - - assert_eq!(deserialized_signing_commitments, signing_commitments); - assert_eq!(deserialized_message, "hola".as_bytes().to_vec()); -} - -#[test] -fn validate_signatureshare() { - let mut setup = basic_setup(); - - // signers and aggregator should have this data from `SharePackage` - let (shares, _pubkeys) = - frost::keygen_with_dealer(setup.num_signers, setup.threshold, setup.rng.clone()).unwrap(); - - // create a signing package, this is done in the aggregator side. - // the signrs should have this data from `SigningPackage` - let (nonce1, commitment1) = frost::preprocess(1, u64::from(setup.signer1), &mut setup.rng); - let (_nonce2, commitment2) = frost::preprocess(1, u64::from(setup.signer2), &mut setup.rng); - let commitments = vec![commitment1[0], commitment2[0]]; - let participants = vec![setup.signer1, setup.signer2]; - let signing_commitments = create_signing_commitments(commitments, participants); - - let signing_package = frost::SigningPackage::from(SigningPackage { - signing_commitments: signing_commitments.clone(), - message: "hola".as_bytes().to_vec(), - }); - - // here we get started with the `SignatureShare` message. - let signature_share = frost::sign(&signing_package, nonce1[0], &shares[0]).unwrap(); - - // this header is invalid - let header = create_valid_header(setup.aggregator, setup.signer1); - - let payload = Payload::SignatureShare(SignatureShare { - signature: SignatureResponse(signature_share.signature.0.to_bytes()), - }); - - let message = Message { - header, - payload: payload.clone(), - }; - - let validate_message = Validate::validate(&message); - assert_eq!(validate_message, Err(MsgErr::SenderMustBeSigner)); - - // change the header, still invalid. - let header = create_valid_header(setup.signer1, setup.signer2); - - let message = Message { - header, - payload: payload.clone(), - }; - - let validate_message = Validate::validate(&message); - assert_eq!(validate_message, Err(MsgErr::ReceiverMustBeAggregator)); - - // change the header to be valid - let header = create_valid_header(setup.signer1, setup.aggregator); - - let validate_message = Validate::validate(&Message { header, payload }).err(); - - assert_eq!(validate_message, None); -} - -#[test] -fn serialize_signatureshare() { - let mut setup = basic_setup(); - - // signers and aggregator should have this data from `SharePackage` - let (shares, _pubkeys) = - frost::keygen_with_dealer(setup.num_signers, setup.threshold, setup.rng.clone()).unwrap(); - - // create a signing package, this is done in the aggregator side. - // the signers should have this data from `SigningPackage` - let (nonce1, commitment1) = frost::preprocess(1, u64::from(setup.signer1), &mut setup.rng); - let (_nonce2, commitment2) = frost::preprocess(1, u64::from(setup.signer2), &mut setup.rng); - let commitments = vec![commitment1[0], commitment2[0]]; - let participants = vec![setup.signer1, setup.signer2]; - let signing_commitments = create_signing_commitments(commitments, participants); - - let signing_package = frost::SigningPackage::from(SigningPackage { - signing_commitments: signing_commitments.clone(), - message: "hola".as_bytes().to_vec(), - }); - - // here we get started with the `SignatureShare` message. - let signature_share = frost::sign(&signing_package, nonce1[0], &shares[0]).unwrap(); - - // valid header - let header = create_valid_header(setup.signer1, setup.aggregator); - - let signature = SignatureResponse(signature_share.signature.0.to_bytes()); - let payload = Payload::SignatureShare(SignatureShare { signature }); - - let message = Message { - header: header, - payload: payload.clone(), - }; - - // check general structure serialization/deserialization - serialize_message(message, setup.signer1, setup.aggregator); - - // check payload serialization/deserialization - let mut payload_serialized_bytes = bincode::serialize(&payload).unwrap(); - - // check the message type is correct - let deserialized_msg_type: MsgType = - bincode::deserialize(&payload_serialized_bytes[0..4]).unwrap(); - assert_eq!(deserialized_msg_type, MsgType::SignatureShare); - - // remove the msg_type from the the payload - payload_serialized_bytes = - (&payload_serialized_bytes[4..payload_serialized_bytes.len()]).to_vec(); - - // signature is 32 bytes - let deserialized_signature: SignatureResponse = - bincode::deserialize(&payload_serialized_bytes[0..32]).unwrap(); - - // no leftover bytes - assert_eq!(payload_serialized_bytes.len(), 32); - - assert_eq!(deserialized_signature, signature); -} - -#[test] -fn validate_aggregatesignature() { - let (setup, group_signature_res) = full_setup(); - - // this header is invalid - let header = create_valid_header(setup.signer1, setup.aggregator); - - let payload = Payload::AggregateSignature(AggregateSignature { - group_commitment: GroupCommitment::from(group_signature_res), - schnorr_signature: SignatureResponse::from(group_signature_res), - }); - - let message = Message { - header, - payload: payload.clone(), - }; - - let validate_message = Validate::validate(&message); - assert_eq!(validate_message, Err(MsgErr::SenderMustBeAggregator)); - - // change the header, still invalid. - let header = create_valid_header(setup.aggregator, setup.dealer); - - let message = Message { - header, - payload: payload.clone(), - }; - - let validate_message = Validate::validate(&message); - assert_eq!(validate_message, Err(MsgErr::ReceiverMustBeSigner)); - - // change the header to be valid - let header = create_valid_header(setup.aggregator, setup.signer1); - - let validate_message = Validate::validate(&Message { header, payload }).err(); - - assert_eq!(validate_message, None); -} - -#[test] -fn serialize_aggregatesignature() { - let (setup, group_signature_res) = full_setup(); - - let header = create_valid_header(setup.aggregator, setup.signer1); - - let group_commitment = GroupCommitment::from(group_signature_res); - let schnorr_signature = SignatureResponse::from(group_signature_res); - let payload = Payload::AggregateSignature(AggregateSignature { - group_commitment, - schnorr_signature, - }); - - let message = Message { - header, - payload: payload.clone(), - }; - - // check general structure serialization/deserialization - serialize_message(message, setup.aggregator, setup.signer1); - - // check payload serialization/deserialization - let mut payload_serialized_bytes = bincode::serialize(&payload).unwrap(); - - // check the message type is correct - let deserialized_msg_type: MsgType = - bincode::deserialize(&payload_serialized_bytes[0..4]).unwrap(); - assert_eq!(deserialized_msg_type, MsgType::AggregateSignature); - - // remove the msg_type from the the payload - payload_serialized_bytes = - (&payload_serialized_bytes[4..payload_serialized_bytes.len()]).to_vec(); - - // group_commitment is 32 bytes - let deserialized_group_commiment: GroupCommitment = - bincode::deserialize(&payload_serialized_bytes[0..32]).unwrap(); - // schnorr_signature is 32 bytes - let deserialized_schnorr_signature: SignatureResponse = - bincode::deserialize(&payload_serialized_bytes[32..64]).unwrap(); - - // no leftover bytes - assert_eq!(payload_serialized_bytes.len(), 64); - - assert_eq!(deserialized_group_commiment, group_commitment); - assert_eq!(deserialized_schnorr_signature, schnorr_signature); -} - -#[test] -fn btreemap() { - let mut setup = basic_setup(); - let mut map = BTreeMap::new(); - - let (_nonce, commitment) = frost::preprocess(1, u64::from(setup.signer1), &mut setup.rng); - - let commitments = vec![commitment[0]]; - let participants = vec![setup.signer1]; - let signing_commitments = create_signing_commitments(commitments, participants); - - map.insert(ParticipantId::Signer(1), &signing_commitments); - map.insert(ParticipantId::Signer(2), &signing_commitments); - map.insert(ParticipantId::Signer(0), &signing_commitments); - - // Check the ascending order - let mut map_iter = map.iter(); - let (key, _) = map_iter.next().unwrap(); - assert_eq!(*key, ParticipantId::Signer(0)); - let (key, _) = map_iter.next().unwrap(); - assert_eq!(*key, ParticipantId::Signer(1)); - let (key, _) = map_iter.next().unwrap(); - assert_eq!(*key, ParticipantId::Signer(2)); - - // Add a repeated key - map.insert(ParticipantId::Signer(1), &signing_commitments); - // BTreeMap is not increasing - assert_eq!(map.len(), 3); -} - -// utility functions - -fn create_valid_header(sender: ParticipantId, receiver: ParticipantId) -> Header { - Validate::validate(&Header { - version: constants::BASIC_FROST_SERIALIZATION, - sender: sender, - receiver: receiver, - }) - .expect("always a valid header") - .clone() -} - -fn serialize_header( - header_serialized_bytes: Vec, - sender: ParticipantId, - receiver: ParticipantId, -) { - let deserialized_version: MsgVersion = - bincode::deserialize(&header_serialized_bytes[0..1]).unwrap(); - let deserialized_sender: ParticipantId = - bincode::deserialize(&header_serialized_bytes[1..9]).unwrap(); - let deserialized_receiver: ParticipantId = - bincode::deserialize(&header_serialized_bytes[9..17]).unwrap(); - assert_eq!(deserialized_version, constants::BASIC_FROST_SERIALIZATION); - assert_eq!(deserialized_sender, sender); - assert_eq!(deserialized_receiver, receiver); -} - -fn serialize_message(message: Message, sender: ParticipantId, receiver: ParticipantId) { - let serialized_bytes = bincode::serialize(&message).unwrap(); - let deserialized_bytes: Message = bincode::deserialize(&serialized_bytes).unwrap(); - assert_eq!(message, deserialized_bytes); - - let serialized_json = serde_json::to_string(&message).unwrap(); - let deserialized_json: Message = serde_json::from_str(serialized_json.as_str()).unwrap(); - assert_eq!(message, deserialized_json); - - let header_serialized_bytes = bincode::serialize(&message.header).unwrap(); - serialize_header(header_serialized_bytes, sender, receiver); - - // make sure the message fields are in the right order - let message_serialized_bytes = bincode::serialize(&message).unwrap(); - let deserialized_header: Header = - bincode::deserialize(&message_serialized_bytes[0..17]).unwrap(); - let deserialized_payload: Payload = - bincode::deserialize(&message_serialized_bytes[17..message_serialized_bytes.len()]) - .unwrap(); - assert_eq!(deserialized_header, message.header); - assert_eq!(deserialized_payload, message.payload); -} - -struct Setup { - rng: rand::rngs::ThreadRng, - num_signers: u8, - threshold: u8, - dealer: ParticipantId, - aggregator: ParticipantId, - signer1: ParticipantId, - signer2: ParticipantId, -} - -fn basic_setup() -> Setup { - Setup { - rng: thread_rng(), - num_signers: 3, - threshold: 2, - dealer: ParticipantId::Dealer, - aggregator: ParticipantId::Aggregator, - signer1: ParticipantId::Signer(0), - signer2: ParticipantId::Signer(1), - } -} - -fn full_setup() -> (Setup, signature::Signature) { - let mut setup = basic_setup(); - - // aggregator creates the shares and pubkeys for this round - let (shares, pubkeys) = - frost::keygen_with_dealer(setup.num_signers, setup.threshold, setup.rng.clone()).unwrap(); - - let mut nonces: std::collections::HashMap> = - std::collections::HashMap::with_capacity(setup.threshold as usize); - let mut commitments: Vec = - Vec::with_capacity(setup.threshold as usize); - - // aggregator generates nonces and signing commitments for each participant. - for participant_index in 1..(setup.threshold + 1) { - let (nonce, commitment) = frost::preprocess(1, participant_index as u64, &mut setup.rng); - nonces.insert(participant_index as u64, nonce); - commitments.push(commitment[0]); - } - - // aggregator generates a signing package - let mut signature_shares: Vec = - Vec::with_capacity(setup.threshold as usize); - let message = "message to sign".as_bytes().to_vec(); - let signing_package = frost::SigningPackage { - message: message.clone(), - signing_commitments: commitments, - }; - - // each participant generates their signature share - for (participant_index, nonce) in nonces { - let share_package = shares - .iter() - .find(|share| participant_index == share.index) - .unwrap(); - let nonce_to_use = nonce[0]; - let signature_share = frost::sign(&signing_package, nonce_to_use, share_package).unwrap(); - signature_shares.push(signature_share); - } - - // aggregator generate the final signature - let final_signature = - frost::aggregate(&signing_package, &signature_shares[..], &pubkeys).unwrap(); - (setup, final_signature) -} - -fn generate_share_commitment( - shares: &Vec, - participants: Vec, -) -> BTreeMap { - assert_eq!(shares.len(), participants.len()); - participants - .into_iter() - .zip(shares) - .map(|(participant_id, share)| { - ( - participant_id, - Commitment::from(share.share.commitment.0[0].clone()), - ) - }) - .collect() -} - -fn create_signing_commitments( - commitments: Vec, - participants: Vec, -) -> BTreeMap { - assert_eq!(commitments.len(), participants.len()); - participants - .into_iter() - .zip(commitments) - .map(|(participant_id, commitment)| { - let signing_commitment = SigningCommitments { - hiding: Commitment(jubjub::AffinePoint::from(commitment.hiding).to_bytes()), - binding: Commitment(jubjub::AffinePoint::from(commitment.binding).to_bytes()), - }; - (participant_id, signing_commitment) - }) - .collect() -} diff --git a/frost-redjubjub/src/messages/tests/prop.rs b/frost-redjubjub/src/messages/tests/prop.rs deleted file mode 100644 index e307a92..0000000 --- a/frost-redjubjub/src/messages/tests/prop.rs +++ /dev/null @@ -1,15 +0,0 @@ -use proptest::prelude::*; - -use crate::messages::*; - -proptest! { - #[test] - fn serialize_message( - message in any::(), - ) { - let serialized = bincode::serialize(&message).unwrap(); - let deserialized: Message = bincode::deserialize(serialized.as_slice()).unwrap(); - - prop_assert_eq!(message, deserialized); - } -} diff --git a/frost-redjubjub/src/messages/validate.rs b/frost-redjubjub/src/messages/validate.rs deleted file mode 100644 index 5d1d9ce..0000000 --- a/frost-redjubjub/src/messages/validate.rs +++ /dev/null @@ -1,143 +0,0 @@ -//! Validation rules specified in [RFC-001#rules] -//! -//! [RFC-001#rules]: https://github.com/ZcashFoundation/redjubjub/blob/main/rfcs/0001-messages.md#rules - -use super::constants::{ - BASIC_FROST_SERIALIZATION, MAX_SIGNERS, MIN_SIGNERS, MIN_THRESHOLD, - ZCASH_MAX_PROTOCOL_MESSAGE_LEN, -}; -use super::*; - -use thiserror::Error; - -pub trait Validate { - fn validate(&self) -> Result<&Self, MsgErr>; -} - -impl Validate for Message { - fn validate(&self) -> Result<&Self, MsgErr> { - match self.payload { - Payload::SharePackage(_) => { - if self.header.sender != ParticipantId::Dealer { - return Err(MsgErr::SenderMustBeDealer); - } - if !matches!(self.header.receiver, ParticipantId::Signer(_)) { - return Err(MsgErr::ReceiverMustBeSigner); - } - } - Payload::SigningCommitments(_) => { - if !matches!(self.header.sender, ParticipantId::Signer(_)) { - return Err(MsgErr::SenderMustBeSigner); - } - if self.header.receiver != ParticipantId::Aggregator { - return Err(MsgErr::ReceiverMustBeAggregator); - } - } - Payload::SigningPackage(_) => { - if self.header.sender != ParticipantId::Aggregator { - return Err(MsgErr::SenderMustBeAggregator); - } - if !matches!(self.header.receiver, ParticipantId::Signer(_)) { - return Err(MsgErr::ReceiverMustBeSigner); - } - } - Payload::SignatureShare(_) => { - if !matches!(self.header.sender, ParticipantId::Signer(_)) { - return Err(MsgErr::SenderMustBeSigner); - } - if self.header.receiver != ParticipantId::Aggregator { - return Err(MsgErr::ReceiverMustBeAggregator); - } - } - Payload::AggregateSignature(_) => { - if self.header.sender != ParticipantId::Aggregator { - return Err(MsgErr::SenderMustBeAggregator); - } - if !matches!(self.header.receiver, ParticipantId::Signer(_)) { - return Err(MsgErr::ReceiverMustBeSigner); - } - } - } - self.header.validate()?; - self.payload.validate()?; - Ok(self) - } -} - -impl Validate for Header { - fn validate(&self) -> Result<&Self, MsgErr> { - // Validate the message version. - // By now we only have 1 valid version so we compare against that. - if self.version != BASIC_FROST_SERIALIZATION { - return Err(MsgErr::WrongVersion); - } - - // Make sure the sender and the receiver are not the same. - if self.sender == self.receiver { - return Err(MsgErr::SameSenderAndReceiver); - } - Ok(self) - } -} - -impl Validate for Payload { - fn validate(&self) -> Result<&Self, MsgErr> { - match self { - Payload::SharePackage(share_package) => { - if share_package.share_commitment.len() < MIN_SIGNERS { - return Err(MsgErr::NotEnoughCommitments(MIN_SIGNERS)); - } - - if share_package.share_commitment.len() > MAX_SIGNERS.into() { - return Err(MsgErr::TooManyCommitments); - } - } - Payload::SigningCommitments(_) => {} - Payload::SigningPackage(signing_package) => { - if signing_package.message.len() > ZCASH_MAX_PROTOCOL_MESSAGE_LEN { - return Err(MsgErr::MsgTooBig); - } - - if signing_package.signing_commitments.len() < MIN_THRESHOLD { - return Err(MsgErr::NotEnoughCommitments(MIN_THRESHOLD)); - } - - if signing_package.signing_commitments.len() > MAX_SIGNERS.into() { - return Err(MsgErr::TooManyCommitments); - } - } - Payload::SignatureShare(_) => {} - Payload::AggregateSignature(_) => {} - } - - Ok(self) - } -} - -/// The error a message can produce if it fails validation. -#[derive(Error, Debug, PartialEq)] -pub enum MsgErr { - #[error("wrong version number")] - WrongVersion, - #[error("sender and receiver are the same")] - SameSenderAndReceiver, - #[error("the sender of this message must be the dealer")] - SenderMustBeDealer, - #[error("the receiver of this message must be a signer")] - ReceiverMustBeSigner, - #[error("the sender of this message must be a signer")] - SenderMustBeSigner, - #[error("the receiver of this message must be the aggregator")] - ReceiverMustBeAggregator, - #[error("the sender of this message must be the aggregator")] - SenderMustBeAggregator, - #[error("the number of signers must be at least {0}")] - NotEnoughCommitments(usize), - #[error("the number of signers can't be more than {}", MAX_SIGNERS)] - TooManyCommitments, - #[error( - "the message field can't be bigger than {}", - ZCASH_MAX_PROTOCOL_MESSAGE_LEN - )] - MsgTooBig, -} diff --git a/frost-redjubjub/src/scalar_mul.rs b/frost-redjubjub/src/scalar_mul.rs deleted file mode 100644 index fd169e4..0000000 --- a/frost-redjubjub/src/scalar_mul.rs +++ /dev/null @@ -1,195 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of redjubjub. -// Copyright (c) 2019-2021 Zcash Foundation -// Copyright (c) 2017-2021 isis agora lovecruft, Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - isis agora lovecruft -// - Henry de Valence -// - Deirdre Connolly - -use std::{borrow::Borrow, fmt::Debug}; - -use jubjub::*; - -pub trait NonAdjacentForm { - fn non_adjacent_form(&self, w: usize) -> [i8; 256]; -} - -/// A trait for variable-time multiscalar multiplication without precomputation. -pub trait VartimeMultiscalarMul { - /// The type of point being multiplied, e.g., `AffinePoint`. - type Point; - - /// Given an iterator of public scalars and an iterator of - /// `Option`s of points, compute either `Some(Q)`, where - /// $$ - /// Q = c\_1 P\_1 + \cdots + c\_n P\_n, - /// $$ - /// if all points were `Some(P_i)`, or else return `None`. - fn optional_multiscalar_mul(scalars: I, points: J) -> Option - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator>; - - /// Given an iterator of public scalars and an iterator of - /// public points, compute - /// $$ - /// Q = c\_1 P\_1 + \cdots + c\_n P\_n, - /// $$ - /// using variable-time operations. - /// - /// It is an error to call this function with two iterators of different lengths. - fn vartime_multiscalar_mul(scalars: I, points: J) -> Self::Point - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator, - J::Item: Borrow, - Self::Point: Clone, - { - Self::optional_multiscalar_mul( - scalars, - points.into_iter().map(|p| Some(p.borrow().clone())), - ) - .unwrap() - } -} - -impl NonAdjacentForm for Scalar { - /// Compute a width-\\(w\\) "Non-Adjacent Form" of this scalar. - /// - /// Thanks to curve25519-dalek - fn non_adjacent_form(&self, w: usize) -> [i8; 256] { - // required by the NAF definition - debug_assert!(w >= 2); - // required so that the NAF digits fit in i8 - debug_assert!(w <= 8); - - use byteorder::{ByteOrder, LittleEndian}; - - let mut naf = [0i8; 256]; - - let mut x_u64 = [0u64; 5]; - LittleEndian::read_u64_into(&self.to_bytes(), &mut x_u64[0..4]); - - let width = 1 << w; - let window_mask = width - 1; - - let mut pos = 0; - let mut carry = 0; - while pos < 256 { - // Construct a buffer of bits of the scalar, starting at bit `pos` - let u64_idx = pos / 64; - let bit_idx = pos % 64; - let bit_buf: u64; - if bit_idx < 64 - w { - // This window's bits are contained in a single u64 - bit_buf = x_u64[u64_idx] >> bit_idx; - } else { - // Combine the current u64's bits with the bits from the next u64 - bit_buf = (x_u64[u64_idx] >> bit_idx) | (x_u64[1 + u64_idx] << (64 - bit_idx)); - } - - // Add the carry into the current window - let window = carry + (bit_buf & window_mask); - - if window & 1 == 0 { - // If the window value is even, preserve the carry and continue. - // Why is the carry preserved? - // If carry == 0 and window & 1 == 0, then the next carry should be 0 - // If carry == 1 and window & 1 == 0, then bit_buf & 1 == 1 so the next carry should be 1 - pos += 1; - continue; - } - - if window < width / 2 { - carry = 0; - naf[pos] = window as i8; - } else { - carry = 1; - naf[pos] = (window as i8).wrapping_sub(width as i8); - } - - pos += w; - } - - naf - } -} - -/// Holds odd multiples 1A, 3A, ..., 15A of a point A. -#[derive(Copy, Clone)] -pub(crate) struct LookupTable5(pub(crate) [T; 8]); - -impl LookupTable5 { - /// Given public, odd \\( x \\) with \\( 0 < x < 2^4 \\), return \\(xA\\). - pub fn select(&self, x: usize) -> T { - debug_assert_eq!(x & 1, 1); - debug_assert!(x < 16); - - self.0[x / 2] - } -} - -impl Debug for LookupTable5 { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "LookupTable5({:?})", self.0) - } -} - -impl<'a> From<&'a ExtendedPoint> for LookupTable5 { - #[allow(non_snake_case)] - fn from(A: &'a ExtendedPoint) -> Self { - let mut Ai = [A.to_niels(); 8]; - let A2 = A.double(); - for i in 0..7 { - Ai[i + 1] = (&A2 + &Ai[i]).to_niels(); - } - // Now Ai = [A, 3A, 5A, 7A, 9A, 11A, 13A, 15A] - LookupTable5(Ai) - } -} - -impl VartimeMultiscalarMul for ExtendedPoint { - type Point = ExtendedPoint; - - #[allow(non_snake_case)] - fn optional_multiscalar_mul(scalars: I, points: J) -> Option - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator>, - { - let nafs: Vec<_> = scalars - .into_iter() - .map(|c| c.borrow().non_adjacent_form(5)) - .collect(); - - let lookup_tables = points - .into_iter() - .map(|P_opt| P_opt.map(|P| LookupTable5::::from(&P))) - .collect::>>()?; - - let mut r = ExtendedPoint::identity(); - - for i in (0..256).rev() { - let mut t = r.double(); - - for (naf, lookup_table) in nafs.iter().zip(lookup_tables.iter()) { - if naf[i] > 0 { - t = &t + &lookup_table.select(naf[i] as usize); - } else if naf[i] < 0 { - t = &t - &lookup_table.select(-naf[i] as usize); - } - } - - r = t; - } - - Some(r) - } -} diff --git a/frost-redjubjub/src/signature.rs b/frost-redjubjub/src/signature.rs deleted file mode 100644 index 43b1fbf..0000000 --- a/frost-redjubjub/src/signature.rs +++ /dev/null @@ -1,45 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of redjubjub. -// Copyright (c) 2019-2021 Zcash Foundation -// See LICENSE for licensing information. -// -// Authors: -// - Henry de Valence - -//! Redjubjub Signatures -use std::marker::PhantomData; - -use crate::SigType; - -/// A RedJubJub signature. -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct Signature { - pub(crate) r_bytes: [u8; 32], - pub(crate) s_bytes: [u8; 32], - pub(crate) _marker: PhantomData, -} - -impl From<[u8; 64]> for Signature { - fn from(bytes: [u8; 64]) -> Signature { - let mut r_bytes = [0; 32]; - r_bytes.copy_from_slice(&bytes[0..32]); - let mut s_bytes = [0; 32]; - s_bytes.copy_from_slice(&bytes[32..64]); - Signature { - r_bytes, - s_bytes, - _marker: PhantomData, - } - } -} - -impl From> for [u8; 64] { - fn from(sig: Signature) -> [u8; 64] { - let mut bytes = [0; 64]; - bytes[0..32].copy_from_slice(&sig.r_bytes[..]); - bytes[32..64].copy_from_slice(&sig.s_bytes[..]); - bytes - } -} diff --git a/frost-redjubjub/src/signing_key.rs b/frost-redjubjub/src/signing_key.rs deleted file mode 100644 index 2de5f32..0000000 --- a/frost-redjubjub/src/signing_key.rs +++ /dev/null @@ -1,133 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of redjubjub. -// Copyright (c) 2019-2021 Zcash Foundation -// See LICENSE for licensing information. -// -// Authors: -// - Deirdre Connolly -// - Henry de Valence - -use std::{ - convert::{TryFrom, TryInto}, - marker::PhantomData, -}; - -use crate::{Error, Randomizer, SigType, Signature, SpendAuth, VerificationKey}; - -use jubjub::Scalar; -use rand_core::{CryptoRng, RngCore}; - -/// A RedJubJub signing key. -#[derive(Copy, Clone, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -#[cfg_attr(feature = "serde", serde(try_from = "SerdeHelper"))] -#[cfg_attr(feature = "serde", serde(into = "SerdeHelper"))] -#[cfg_attr(feature = "serde", serde(bound = "T: SigType"))] -pub struct SigningKey { - sk: Scalar, - pk: VerificationKey, -} - -impl<'a, T: SigType> From<&'a SigningKey> for VerificationKey { - fn from(sk: &'a SigningKey) -> VerificationKey { - sk.pk.clone() - } -} - -impl From> for [u8; 32] { - fn from(sk: SigningKey) -> [u8; 32] { - sk.sk.to_bytes() - } -} - -impl TryFrom<[u8; 32]> for SigningKey { - type Error = Error; - - fn try_from(bytes: [u8; 32]) -> Result { - // XXX-jubjub: this should not use CtOption - let maybe_sk = Scalar::from_bytes(&bytes); - if maybe_sk.is_some().into() { - let sk = maybe_sk.unwrap(); - let pk = VerificationKey::from(&sk); - Ok(SigningKey { sk, pk }) - } else { - Err(Error::MalformedSigningKey) - } - } -} - -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -struct SerdeHelper([u8; 32]); - -impl TryFrom for SigningKey { - type Error = Error; - - fn try_from(helper: SerdeHelper) -> Result { - helper.0.try_into() - } -} - -impl From> for SerdeHelper { - fn from(sk: SigningKey) -> Self { - Self(sk.into()) - } -} - -impl SigningKey { - /// Randomize this public key with the given `randomizer`. - pub fn randomize(&self, randomizer: &Randomizer) -> SigningKey { - let sk = &self.sk + randomizer; - let pk = VerificationKey::from(&sk); - SigningKey { sk, pk } - } -} - -impl SigningKey { - /// Generate a new signing key. - pub fn new(mut rng: R) -> SigningKey { - let sk = { - let mut bytes = [0; 64]; - rng.fill_bytes(&mut bytes); - Scalar::from_bytes_wide(&bytes) - }; - let pk = VerificationKey::from(&sk); - SigningKey { sk, pk } - } - - /// Create a signature of type `T` on `msg` using this `SigningKey`. - // Similar to signature::Signer but without boxed errors. - pub fn sign(&self, mut rng: R, msg: &[u8]) -> Signature { - use crate::HStar; - - // Choose a byte sequence uniformly at random of length - // (\ell_H + 128)/8 bytes. For RedJubjub this is (512 + 128)/8 = 80. - let random_bytes = { - let mut bytes = [0; 80]; - rng.fill_bytes(&mut bytes); - bytes - }; - - let nonce = HStar::default() - .update(&random_bytes[..]) - .update(&self.pk.bytes.bytes[..]) // XXX ugly - .update(msg) - .finalize(); - - let r_bytes = jubjub::AffinePoint::from(&T::basepoint() * &nonce).to_bytes(); - - let c = HStar::default() - .update(&r_bytes[..]) - .update(&self.pk.bytes.bytes[..]) // XXX ugly - .update(msg) - .finalize(); - - let s_bytes = (&nonce + &(&c * &self.sk)).to_bytes(); - - Signature { - r_bytes, - s_bytes, - _marker: PhantomData, - } - } -} diff --git a/frost-redjubjub/src/verification_key.rs b/frost-redjubjub/src/verification_key.rs deleted file mode 100644 index 17d32ef..0000000 --- a/frost-redjubjub/src/verification_key.rs +++ /dev/null @@ -1,202 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of redjubjub. -// Copyright (c) 2019-2021 Zcash Foundation -// See LICENSE for licensing information. -// -// Authors: -// - Deirdre Connolly -// - Henry de Valence - -use std::{ - convert::TryFrom, - hash::{Hash, Hasher}, - marker::PhantomData, -}; - -use jubjub::Scalar; - -use crate::{Error, Randomizer, SigType, Signature, SpendAuth}; - -/// A refinement type for `[u8; 32]` indicating that the bytes represent -/// an encoding of a RedJubJub verification key. -/// -/// This is useful for representing a compressed verification key; the -/// [`VerificationKey`] type in this library holds other decompressed state -/// used in signature verification. -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct VerificationKeyBytes { - pub(crate) bytes: [u8; 32], - pub(crate) _marker: PhantomData, -} - -impl From<[u8; 32]> for VerificationKeyBytes { - fn from(bytes: [u8; 32]) -> VerificationKeyBytes { - VerificationKeyBytes { - bytes, - _marker: PhantomData, - } - } -} - -impl From> for [u8; 32] { - fn from(refined: VerificationKeyBytes) -> [u8; 32] { - refined.bytes - } -} - -impl Hash for VerificationKeyBytes { - fn hash(&self, state: &mut H) { - self.bytes.hash(state); - self._marker.hash(state); - } -} - -/// A valid RedJubJub verification key. -/// -/// This type holds decompressed state used in signature verification; if the -/// verification key may not be used immediately, it is probably better to use -/// [`VerificationKeyBytes`], which is a refinement type for `[u8; 32]`. -/// -/// ## Consensus properties -/// -/// The `TryFrom` conversion performs the following Zcash -/// consensus rule checks: -/// -/// 1. The check that the bytes are a canonical encoding of a verification key; -/// 2. The check that the verification key is not a point of small order. -#[derive(PartialEq, Copy, Clone, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -#[cfg_attr(feature = "serde", serde(try_from = "VerificationKeyBytes"))] -#[cfg_attr(feature = "serde", serde(into = "VerificationKeyBytes"))] -#[cfg_attr(feature = "serde", serde(bound = "T: SigType"))] -pub struct VerificationKey { - // XXX-jubjub: this should just be Point - pub(crate) point: jubjub::ExtendedPoint, - pub(crate) bytes: VerificationKeyBytes, -} - -impl From> for VerificationKeyBytes { - fn from(pk: VerificationKey) -> VerificationKeyBytes { - pk.bytes - } -} - -impl From> for [u8; 32] { - fn from(pk: VerificationKey) -> [u8; 32] { - pk.bytes.bytes - } -} - -impl TryFrom> for VerificationKey { - type Error = Error; - - fn try_from(bytes: VerificationKeyBytes) -> Result { - // XXX-jubjub: this should not use CtOption - // XXX-jubjub: this takes ownership of bytes, while Fr doesn't. - // This checks that the encoding is canonical... - let maybe_point = jubjub::AffinePoint::from_bytes(bytes.bytes); - if maybe_point.is_some().into() { - let point: jubjub::ExtendedPoint = maybe_point.unwrap().into(); - // Note that small-order verification keys (including the identity) are not - // rejected here. Previously they were rejected, but this was a bug as the - // RedDSA specification allows them. Zcash Sapling rejects small-order points - // for the RedJubjub spend authorization key rk; this now occurs separately. - // Meanwhile, Zcash Orchard uses a prime-order group, so the only small-order - // point would be the identity, which is allowed in Orchard. - Ok(VerificationKey { point, bytes }) - } else { - Err(Error::MalformedVerificationKey) - } - } -} - -impl TryFrom<[u8; 32]> for VerificationKey { - type Error = Error; - - fn try_from(bytes: [u8; 32]) -> Result { - use std::convert::TryInto; - VerificationKeyBytes::from(bytes).try_into() - } -} - -impl VerificationKey { - /// Randomize this verification key with the given `randomizer`. - /// - /// Randomization is only supported for `SpendAuth` keys. - pub fn randomize(&self, randomizer: &Randomizer) -> VerificationKey { - use crate::private::Sealed; - let point = &self.point + &(&SpendAuth::basepoint() * randomizer); - let bytes = VerificationKeyBytes { - bytes: jubjub::AffinePoint::from(&point).to_bytes(), - _marker: PhantomData, - }; - VerificationKey { bytes, point } - } -} - -impl VerificationKey { - pub(crate) fn from(s: &Scalar) -> VerificationKey { - let point = &T::basepoint() * s; - let bytes = VerificationKeyBytes { - bytes: jubjub::AffinePoint::from(&point).to_bytes(), - _marker: PhantomData, - }; - VerificationKey { bytes, point } - } - - /// Verify a purported `signature` over `msg` made by this verification key. - // This is similar to impl signature::Verifier but without boxed errors - pub fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), Error> { - use crate::HStar; - let c = HStar::default() - .update(&signature.r_bytes[..]) - .update(&self.bytes.bytes[..]) // XXX ugly - .update(msg) - .finalize(); - self.verify_prehashed(signature, c) - } - - /// Verify a purported `signature` with a prehashed challenge. - #[allow(non_snake_case)] - pub(crate) fn verify_prehashed( - &self, - signature: &Signature, - c: Scalar, - ) -> Result<(), Error> { - let r = { - // XXX-jubjub: should not use CtOption here - // XXX-jubjub: inconsistent ownership in from_bytes - let maybe_point = jubjub::AffinePoint::from_bytes(signature.r_bytes); - if maybe_point.is_some().into() { - jubjub::ExtendedPoint::from(maybe_point.unwrap()) - } else { - return Err(Error::InvalidSignature); - } - }; - - let s = { - // XXX-jubjub: should not use CtOption here - let maybe_scalar = Scalar::from_bytes(&signature.s_bytes); - if maybe_scalar.is_some().into() { - maybe_scalar.unwrap() - } else { - return Err(Error::InvalidSignature); - } - }; - - // XXX rewrite as normal double scalar mul - // Verify check is h * ( - s * B + R + c * A) == 0 - // h * ( s * B - c * A - R) == 0 - let sB = &T::basepoint() * &s; - let cA = &self.point * &c; - let check = sB - cA - r; - - if check.is_small_order().into() { - Ok(()) - } else { - Err(Error::InvalidSignature) - } - } -} diff --git a/frost-redjubjub/tests/batch.rs b/frost-redjubjub/tests/batch.rs deleted file mode 100644 index fe095dd..0000000 --- a/frost-redjubjub/tests/batch.rs +++ /dev/null @@ -1,99 +0,0 @@ -use rand::thread_rng; - -use redjubjub::*; - -#[test] -fn spendauth_batch_verify() { - let mut rng = thread_rng(); - let mut batch = batch::Verifier::new(); - for _ in 0..32 { - let sk = SigningKey::::new(&mut rng); - let vk = VerificationKey::from(&sk); - let msg = b"BatchVerifyTest"; - let sig = sk.sign(&mut rng, &msg[..]); - batch.queue((vk.into(), sig, msg)); - } - assert!(batch.verify(rng).is_ok()); -} - -#[test] -fn binding_batch_verify() { - let mut rng = thread_rng(); - let mut batch = batch::Verifier::new(); - for _ in 0..32 { - let sk = SigningKey::::new(&mut rng); - let vk = VerificationKey::from(&sk); - let msg = b"BatchVerifyTest"; - let sig = sk.sign(&mut rng, &msg[..]); - batch.queue((vk.into(), sig, msg)); - } - assert!(batch.verify(rng).is_ok()); -} - -#[test] -fn alternating_batch_verify() { - let mut rng = thread_rng(); - let mut batch = batch::Verifier::new(); - for i in 0..32 { - let item: batch::Item = match i % 2 { - 0 => { - let sk = SigningKey::::new(&mut rng); - let vk = VerificationKey::from(&sk); - let msg = b"BatchVerifyTest"; - let sig = sk.sign(&mut rng, &msg[..]); - (vk.into(), sig, msg).into() - } - 1 => { - let sk = SigningKey::::new(&mut rng); - let vk = VerificationKey::from(&sk); - let msg = b"BatchVerifyTest"; - let sig = sk.sign(&mut rng, &msg[..]); - (vk.into(), sig, msg).into() - } - _ => unreachable!(), - }; - batch.queue(item); - } - assert!(batch.verify(rng).is_ok()); -} - -#[test] -fn bad_batch_verify() { - let mut rng = thread_rng(); - let bad_index = 4; // must be even - let mut batch = batch::Verifier::new(); - let mut items = Vec::new(); - for i in 0..32 { - let item: batch::Item = match i % 2 { - 0 => { - let sk = SigningKey::::new(&mut rng); - let vk = VerificationKey::from(&sk); - let msg = b"BatchVerifyTest"; - let sig = if i != bad_index { - sk.sign(&mut rng, &msg[..]) - } else { - sk.sign(&mut rng, b"bad") - }; - (vk.into(), sig, msg).into() - } - 1 => { - let sk = SigningKey::::new(&mut rng); - let vk = VerificationKey::from(&sk); - let msg = b"BatchVerifyTest"; - let sig = sk.sign(&mut rng, &msg[..]); - (vk.into(), sig, msg).into() - } - _ => unreachable!(), - }; - items.push(item.clone()); - batch.queue(item); - } - assert!(batch.verify(rng).is_err()); - for (i, item) in items.drain(..).enumerate() { - if i != bad_index { - assert!(item.verify_single().is_ok()); - } else { - assert!(item.verify_single().is_err()); - } - } -} diff --git a/frost-redjubjub/tests/bincode.rs b/frost-redjubjub/tests/bincode.rs deleted file mode 100644 index 3cca7cd..0000000 --- a/frost-redjubjub/tests/bincode.rs +++ /dev/null @@ -1,111 +0,0 @@ -use std::convert::TryFrom; - -use proptest::prelude::*; - -use redjubjub::*; - -proptest! { - #[test] - fn secretkey_serialization( - bytes in prop::array::uniform32(any::()), - ) { - let sk_result_from = SigningKey::::try_from(bytes); - let sk_result_bincode: Result, _> - = bincode::deserialize(&bytes[..]); - - // Check 1: both decoding methods should agree - match (sk_result_from, sk_result_bincode) { - // Both agree on success - (Ok(sk_from), Ok(sk_bincode)) => { - let pk_bytes_from = VerificationKeyBytes::from(VerificationKey::from(&sk_from)); - let pk_bytes_bincode = VerificationKeyBytes::from(VerificationKey::from(&sk_bincode)); - assert_eq!(pk_bytes_from, pk_bytes_bincode); - - // Check 2: bincode encoding should match original bytes. - let bytes_bincode = bincode::serialize(&sk_from).unwrap(); - assert_eq!(&bytes[..], &bytes_bincode[..]); - - // Check 3: From encoding should match original bytes. - let bytes_from: [u8; 32] = sk_bincode.into(); - assert_eq!(&bytes[..], &bytes_from[..]); - } - // Both agree on failure - (Err(_), Err(_)) => {}, - _ => panic!("bincode and try_from do not agree"), - } - } - - #[test] - fn publickeybytes_serialization( - bytes in prop::array::uniform32(any::()), - ) { - let pk_bytes_from = VerificationKeyBytes::::from(bytes); - let pk_bytes_bincode: VerificationKeyBytes:: - = bincode::deserialize(&bytes[..]).unwrap(); - - // Check 1: both decoding methods should have the same result. - assert_eq!(pk_bytes_from, pk_bytes_bincode); - - // Check 2: bincode encoding should match original bytes. - let bytes_bincode = bincode::serialize(&pk_bytes_from).unwrap(); - assert_eq!(&bytes[..], &bytes_bincode[..]); - - // Check 3: From encoding should match original bytes. - let bytes_from: [u8; 32] = pk_bytes_bincode.into(); - assert_eq!(&bytes[..], &bytes_from[..]); - } - - #[test] - fn publickey_serialization( - bytes in prop::array::uniform32(any::()), - ) { - let pk_result_try_from = VerificationKey::::try_from(bytes); - let pk_result_bincode: Result, _> - = bincode::deserialize(&bytes[..]); - - // Check 1: both decoding methods should have the same result - match (pk_result_try_from, pk_result_bincode) { - // Both agree on success - (Ok(pk_try_from), Ok(pk_bincode)) => { - // Check 2: bincode encoding should match original bytes - let bytes_bincode = bincode::serialize(&pk_try_from).unwrap(); - assert_eq!(&bytes[..], &bytes_bincode[..]); - // Check 3: From encoding should match original bytes - let bytes_from: [u8; 32] = pk_bincode.into(); - assert_eq!(&bytes[..], &bytes_from[..]); - }, - // Both agree on failure - (Err(_), Err(_)) => {}, - _ => panic!("bincode and try_from do not agree"), - } - } - - #[test] - fn signature_serialization( - lo in prop::array::uniform32(any::()), - hi in prop::array::uniform32(any::()), - ) { - // array length hack - let bytes = { - let mut bytes = [0; 64]; - bytes[0..32].copy_from_slice(&lo[..]); - bytes[32..64].copy_from_slice(&hi[..]); - bytes - }; - - let sig_bytes_from = Signature::::from(bytes); - let sig_bytes_bincode: Signature:: - = bincode::deserialize(&bytes[..]).unwrap(); - - // Check 1: both decoding methods should have the same result. - assert_eq!(sig_bytes_from, sig_bytes_bincode); - - // Check 2: bincode encoding should match original bytes. - let bytes_bincode = bincode::serialize(&sig_bytes_from).unwrap(); - assert_eq!(&bytes[..], &bytes_bincode[..]); - - // Check 3: From encoding should match original bytes. - let bytes_from: [u8; 64] = sig_bytes_bincode.into(); - assert_eq!(&bytes[..], &bytes_from[..]); - } -} diff --git a/frost-redjubjub/tests/frost.rs b/frost-redjubjub/tests/frost.rs deleted file mode 100644 index fa47b76..0000000 --- a/frost-redjubjub/tests/frost.rs +++ /dev/null @@ -1,62 +0,0 @@ -use rand::thread_rng; -use std::collections::HashMap; - -use redjubjub::frost; - -#[test] -fn check_sign_with_dealer() { - let mut rng = thread_rng(); - let numsigners = 5; - let threshold = 3; - let (shares, pubkeys) = frost::keygen_with_dealer(numsigners, threshold, &mut rng).unwrap(); - - let mut nonces: HashMap> = - HashMap::with_capacity(threshold as usize); - let mut commitments: Vec = Vec::with_capacity(threshold as usize); - - // Round 1, generating nonces and signing commitments for each participant. - for participant_index in 1..(threshold + 1) { - // Generate one (1) nonce and one SigningCommitments instance for each - // participant, up to _threshold_. - let (nonce, commitment) = frost::preprocess(1, participant_index as u64, &mut rng); - nonces.insert(participant_index as u64, nonce); - commitments.push(commitment[0]); - } - - // This is what the signature aggregator / coordinator needs to do: - // - decide what message to sign - // - take one (unused) commitment per signing participant - let mut signature_shares: Vec = Vec::with_capacity(threshold as usize); - let message = "message to sign".as_bytes(); - let signing_package = frost::SigningPackage { - message: message.to_vec(), - signing_commitments: commitments, - }; - - // Round 2: each participant generates their signature share - for (participant_index, nonce) in nonces { - let share_package = shares - .iter() - .find(|share| participant_index == share.index) - .unwrap(); - let nonce_to_use = nonce[0]; - // Each participant generates their signature share. - let signature_share = frost::sign(&signing_package, nonce_to_use, share_package).unwrap(); - signature_shares.push(signature_share); - } - - // The aggregator collects the signing shares from all participants and - // generates the final signature. - let group_signature_res = frost::aggregate(&signing_package, &signature_shares[..], &pubkeys); - assert!(group_signature_res.is_ok()); - let group_signature = group_signature_res.unwrap(); - - // Check that the threshold signature can be verified by the group public - // key (aka verification key). - assert!(pubkeys - .group_public - .verify(&message, &group_signature) - .is_ok()); - - // TODO: also check that the SharePackage.group_public also verifies the group signature. -} diff --git a/frost-redjubjub/tests/librustzcash_vectors.rs b/frost-redjubjub/tests/librustzcash_vectors.rs deleted file mode 100644 index 7e2af6c..0000000 --- a/frost-redjubjub/tests/librustzcash_vectors.rs +++ /dev/null @@ -1,1251 +0,0 @@ -use std::convert::TryFrom; - -#[macro_use] -extern crate lazy_static; - -use redjubjub::*; - -#[test] -fn verify_librustzcash_spendauth() { - for (msg, sig, pk_bytes) in LIBRUSTZCASH_SPENDAUTH_SIGS.iter() { - assert!(VerificationKey::try_from(*pk_bytes) - .and_then(|pk| pk.verify(&msg, &sig)) - .is_ok()); - } -} - -#[test] -fn verify_librustzcash_binding() { - for (msg, sig, pk_bytes) in LIBRUSTZCASH_BINDING_SIGS.iter() { - assert!(VerificationKey::try_from(*pk_bytes) - .and_then(|pk| pk.verify(&msg, &sig)) - .is_ok()); - } -} - -lazy_static! { - static ref LIBRUSTZCASH_SPENDAUTH_SIGS: [( - Vec, - Signature, - VerificationKeyBytes - ); 32] = [ - ( - [ - 16, 28, 190, 75, 156, 66, 96, 79, 4, 199, 3, 195, 150, 247, 136, 198, 203, 45, 109, - 125, 88, 244, 84, 48, 177, 46, 178, 237, 214, 64, 7, 108 - ] - .to_vec(), - [ - 184, 72, 147, 0, 184, 42, 112, 23, 132, 161, 146, 154, 96, 228, 121, 19, 57, 57, - 59, 142, 209, 233, 151, 29, 9, 55, 142, 153, 71, 124, 203, 76, 203, 183, 165, 39, - 20, 49, 230, 24, 162, 232, 156, 176, 115, 184, 191, 122, 27, 103, 243, 15, 226, 72, - 177, 219, 67, 176, 95, 27, 108, 40, 69, 10 - ] - .into(), - [ - 181, 241, 137, 93, 46, 42, 77, 236, 42, 240, 254, 156, 102, 146, 236, 44, 166, 93, - 85, 228, 118, 90, 109, 138, 25, 70, 46, 202, 61, 255, 216, 4 - ] - .into(), - ), - ( - [ - 108, 56, 40, 255, 104, 11, 219, 166, 98, 154, 153, 67, 75, 194, 79, 17, 86, 115, - 26, 175, 150, 173, 228, 209, 66, 119, 33, 94, 87, 187, 19, 49 - ] - .to_vec(), - [ - 79, 51, 180, 117, 215, 124, 136, 130, 125, 50, 132, 219, 196, 16, 28, 85, 68, 163, - 54, 62, 86, 36, 115, 180, 28, 35, 105, 224, 1, 31, 165, 186, 26, 50, 252, 46, 139, - 219, 234, 182, 96, 126, 97, 94, 221, 61, 19, 90, 143, 166, 200, 7, 185, 134, 183, - 2, 81, 255, 168, 130, 34, 25, 142, 12 - ] - .into(), - [ - 32, 138, 141, 49, 232, 43, 241, 22, 66, 21, 45, 171, 245, 191, 115, 78, 218, 71, - 232, 16, 49, 246, 189, 199, 239, 171, 119, 186, 146, 179, 252, 155 - ] - .into(), - ), - ( - [ - 145, 63, 229, 40, 221, 46, 129, 128, 68, 42, 148, 149, 87, 96, 109, 94, 188, 197, - 117, 95, 73, 255, 11, 214, 198, 41, 249, 226, 22, 130, 163, 215 - ] - .to_vec(), - [ - 72, 6, 48, 149, 135, 161, 137, 34, 233, 249, 121, 150, 228, 0, 165, 120, 106, 27, - 21, 249, 158, 109, 128, 193, 73, 236, 14, 86, 21, 248, 160, 44, 27, 223, 183, 139, - 19, 121, 238, 236, 194, 40, 243, 249, 223, 15, 191, 65, 182, 7, 23, 61, 76, 70, 37, - 11, 45, 98, 208, 218, 81, 97, 67, 12 - ] - .into(), - [ - 209, 140, 211, 141, 81, 2, 124, 211, 60, 118, 106, 253, 141, 253, 192, 30, 2, 216, - 130, 239, 243, 55, 48, 65, 33, 4, 110, 71, 247, 172, 6, 65 - ] - .into(), - ), - ( - [ - 208, 243, 205, 249, 49, 107, 35, 33, 206, 165, 99, 248, 160, 186, 39, 50, 71, 156, - 226, 164, 9, 17, 162, 158, 198, 154, 10, 123, 189, 221, 247, 116 - ] - .to_vec(), - [ - 96, 38, 240, 221, 163, 157, 103, 24, 101, 88, 180, 51, 66, 149, 94, 187, 20, 236, - 117, 125, 118, 174, 22, 98, 249, 46, 76, 86, 183, 87, 138, 29, 38, 103, 100, 29, - 156, 175, 232, 144, 186, 10, 98, 237, 220, 98, 116, 83, 230, 58, 38, 91, 241, 162, - 38, 216, 38, 248, 51, 35, 116, 229, 245, 1 - ] - .into(), - [ - 19, 244, 2, 26, 154, 118, 210, 35, 37, 167, 110, 77, 38, 171, 92, 151, 150, 251, - 63, 160, 138, 203, 225, 171, 44, 47, 186, 127, 26, 94, 145, 69 - ] - .into(), - ), - ( - [ - 73, 53, 27, 188, 30, 74, 75, 136, 216, 22, 115, 179, 41, 12, 101, 135, 241, 208, - 177, 226, 3, 109, 120, 48, 2, 120, 150, 27, 29, 59, 61, 180 - ] - .to_vec(), - [ - 203, 244, 129, 94, 156, 32, 138, 223, 81, 124, 198, 181, 173, 91, 243, 132, 223, - 81, 53, 71, 49, 159, 197, 177, 192, 2, 36, 14, 165, 50, 88, 158, 211, 201, 110, - 119, 247, 80, 67, 71, 53, 170, 20, 67, 1, 67, 47, 73, 19, 253, 251, 175, 121, 94, - 162, 58, 126, 42, 13, 85, 33, 134, 4, 2 - ] - .into(), - [ - 47, 222, 182, 103, 31, 179, 90, 219, 250, 195, 128, 213, 41, 186, 62, 232, 156, 68, - 205, 52, 43, 71, 73, 212, 6, 108, 217, 73, 156, 166, 145, 102 - ] - .into(), - ), - ( - [ - 158, 55, 154, 163, 138, 43, 56, 169, 209, 184, 225, 86, 39, 131, 0, 194, 62, 122, - 84, 176, 197, 115, 88, 216, 47, 127, 36, 131, 215, 205, 251, 69 - ] - .to_vec(), - [ - 253, 159, 166, 4, 58, 37, 220, 26, 159, 123, 69, 114, 202, 2, 113, 136, 103, 251, - 181, 27, 143, 135, 117, 89, 251, 177, 67, 86, 26, 39, 64, 194, 194, 16, 19, 242, - 189, 157, 128, 9, 17, 6, 148, 194, 43, 164, 238, 156, 15, 135, 62, 99, 247, 58, - 246, 104, 162, 24, 205, 152, 193, 214, 118, 5 - ] - .into(), - [ - 17, 132, 1, 251, 36, 233, 78, 198, 122, 35, 231, 247, 175, 15, 214, 37, 37, 18, - 247, 20, 16, 165, 66, 133, 243, 75, 69, 78, 5, 101, 42, 174 - ] - .into(), - ), - ( - [ - 217, 101, 76, 11, 40, 202, 129, 190, 187, 84, 92, 68, 181, 190, 66, 89, 233, 122, - 72, 49, 98, 38, 40, 129, 112, 67, 119, 39, 61, 230, 140, 107 - ] - .to_vec(), - [ - 94, 211, 95, 97, 114, 31, 97, 88, 94, 137, 189, 186, 206, 228, 157, 10, 148, 94, - 114, 109, 178, 182, 138, 199, 223, 55, 230, 174, 76, 199, 187, 28, 250, 221, 85, - 96, 100, 217, 24, 129, 219, 27, 10, 97, 195, 112, 148, 210, 62, 188, 61, 93, 90, - 185, 107, 58, 177, 123, 81, 220, 219, 199, 119, 0 - ] - .into(), - [ - 244, 173, 81, 29, 254, 24, 62, 207, 198, 165, 40, 87, 251, 222, 99, 74, 26, 190, - 240, 181, 176, 132, 16, 109, 149, 143, 130, 140, 15, 151, 79, 108 - ] - .into(), - ), - ( - [ - 10, 212, 76, 139, 47, 234, 73, 233, 131, 223, 100, 101, 161, 23, 26, 161, 12, 107, - 27, 76, 50, 232, 165, 234, 34, 170, 126, 169, 179, 7, 168, 216 - ] - .to_vec(), - [ - 139, 199, 128, 202, 224, 132, 196, 210, 244, 72, 85, 142, 184, 248, 176, 86, 173, - 70, 205, 224, 161, 234, 51, 253, 239, 182, 81, 171, 192, 201, 180, 134, 212, 132, - 101, 145, 250, 244, 18, 252, 14, 150, 26, 140, 197, 241, 209, 226, 217, 98, 82, - 135, 131, 167, 91, 146, 190, 125, 147, 152, 175, 221, 232, 3 - ] - .into(), - [ - 68, 179, 107, 23, 199, 215, 237, 215, 12, 78, 92, 244, 133, 177, 115, 46, 167, 114, - 174, 10, 70, 38, 232, 102, 4, 27, 229, 238, 5, 128, 86, 155 - ] - .into(), - ), - ( - [ - 7, 121, 157, 250, 188, 252, 108, 217, 56, 87, 183, 45, 98, 129, 233, 210, 121, 143, - 173, 195, 172, 2, 154, 125, 176, 148, 3, 234, 3, 250, 127, 116 - ] - .to_vec(), - [ - 200, 10, 84, 163, 98, 111, 226, 140, 225, 250, 208, 165, 104, 197, 0, 68, 118, 236, - 77, 160, 142, 38, 137, 192, 73, 143, 48, 192, 131, 2, 212, 217, 190, 212, 114, 106, - 232, 178, 156, 18, 25, 116, 101, 150, 208, 248, 222, 183, 159, 19, 181, 83, 211, - 153, 122, 105, 92, 118, 10, 208, 109, 14, 14, 10 - ] - .into(), - [ - 111, 10, 31, 231, 161, 58, 10, 220, 2, 11, 155, 212, 150, 68, 103, 109, 227, 82, - 36, 22, 102, 4, 3, 56, 64, 4, 34, 171, 198, 46, 102, 161 - ] - .into(), - ), - ( - [ - 161, 98, 15, 93, 184, 31, 193, 208, 84, 234, 38, 229, 208, 207, 27, 172, 152, 170, - 39, 138, 187, 88, 195, 82, 253, 108, 101, 128, 110, 86, 114, 242 - ] - .to_vec(), - [ - 18, 41, 243, 39, 192, 12, 24, 229, 74, 197, 174, 162, 214, 152, 159, 92, 220, 52, - 175, 178, 170, 145, 240, 21, 161, 10, 133, 49, 216, 192, 232, 28, 119, 245, 163, - 58, 63, 207, 253, 42, 134, 12, 204, 25, 169, 223, 66, 152, 132, 178, 190, 255, 1, - 193, 120, 237, 17, 164, 1, 172, 146, 11, 176, 2 - ] - .into(), - [ - 29, 23, 116, 183, 78, 100, 121, 77, 61, 83, 68, 115, 247, 127, 102, 90, 216, 110, - 86, 250, 43, 110, 250, 34, 97, 132, 99, 182, 146, 45, 84, 75 - ] - .into(), - ), - ( - [ - 123, 7, 11, 119, 243, 237, 229, 160, 242, 163, 173, 216, 117, 94, 8, 29, 112, 178, - 23, 50, 180, 75, 18, 189, 215, 221, 21, 8, 86, 209, 177, 87 - ] - .to_vec(), - [ - 86, 236, 148, 81, 183, 70, 209, 165, 2, 184, 111, 25, 206, 21, 195, 112, 16, 99, - 185, 161, 2, 19, 27, 53, 80, 133, 39, 39, 227, 103, 94, 140, 0, 10, 28, 243, 255, - 131, 163, 170, 206, 229, 116, 99, 153, 52, 99, 205, 177, 133, 247, 63, 43, 78, 154, - 105, 161, 55, 68, 177, 211, 17, 132, 10 - ] - .into(), - [ - 29, 230, 209, 28, 238, 102, 138, 220, 223, 130, 169, 79, 197, 133, 90, 183, 214, - 204, 190, 100, 0, 89, 221, 164, 60, 131, 235, 21, 68, 150, 204, 174 - ] - .into(), - ), - ( - [ - 181, 94, 198, 199, 78, 194, 64, 118, 146, 51, 79, 70, 73, 206, 87, 51, 96, 13, 145, - 198, 78, 245, 179, 182, 169, 147, 95, 137, 77, 33, 247, 4 - ] - .to_vec(), - [ - 236, 92, 56, 252, 142, 62, 64, 84, 192, 160, 2, 119, 164, 201, 38, 248, 102, 22, - 225, 65, 13, 211, 236, 96, 223, 56, 108, 205, 49, 55, 177, 22, 11, 66, 165, 120, - 114, 57, 144, 81, 170, 50, 119, 41, 138, 151, 109, 248, 211, 141, 208, 110, 241, - 74, 89, 83, 44, 229, 150, 19, 22, 20, 87, 14 - ] - .into(), - [ - 148, 203, 97, 110, 231, 9, 144, 249, 147, 244, 215, 94, 152, 157, 76, 192, 180, 57, - 176, 250, 88, 62, 162, 242, 207, 194, 43, 31, 224, 131, 21, 60 - ] - .into(), - ), - ( - [ - 108, 144, 146, 213, 254, 69, 48, 80, 172, 3, 26, 161, 90, 132, 50, 0, 192, 101, 98, - 65, 167, 199, 175, 147, 29, 177, 217, 226, 72, 233, 93, 118 - ] - .to_vec(), - [ - 56, 134, 173, 220, 187, 159, 248, 241, 192, 65, 91, 20, 145, 141, 192, 118, 101, - 83, 180, 225, 148, 168, 3, 234, 209, 34, 73, 8, 8, 234, 82, 191, 135, 191, 151, 1, - 205, 158, 224, 35, 144, 77, 131, 209, 80, 26, 118, 189, 39, 76, 246, 20, 37, 26, - 16, 70, 36, 69, 253, 26, 251, 230, 155, 10 - ] - .into(), - [ - 173, 141, 143, 17, 147, 238, 245, 194, 249, 178, 20, 48, 35, 192, 16, 157, 150, 22, - 130, 105, 149, 14, 242, 169, 63, 116, 193, 121, 41, 196, 140, 50 - ] - .into(), - ), - ( - [ - 106, 232, 15, 114, 137, 49, 56, 62, 28, 42, 176, 201, 156, 86, 109, 234, 3, 191, - 44, 231, 22, 110, 103, 24, 204, 71, 207, 80, 255, 34, 150, 208 - ] - .to_vec(), - [ - 111, 66, 64, 152, 248, 159, 2, 254, 64, 180, 110, 136, 157, 80, 123, 138, 169, 106, - 86, 180, 105, 131, 109, 52, 252, 70, 48, 86, 230, 35, 181, 88, 158, 173, 73, 67, - 200, 96, 243, 192, 24, 34, 242, 54, 113, 199, 214, 118, 39, 244, 142, 254, 143, - 188, 217, 138, 190, 137, 201, 249, 154, 116, 129, 10 - ] - .into(), - [ - 43, 53, 235, 27, 103, 60, 163, 115, 78, 225, 5, 178, 113, 55, 93, 90, 210, 191, 0, - 249, 175, 80, 72, 140, 22, 173, 81, 237, 10, 176, 48, 20 - ] - .into(), - ), - ( - [ - 115, 113, 54, 112, 20, 175, 145, 55, 156, 102, 8, 55, 94, 188, 73, 151, 45, 250, - 55, 84, 176, 22, 100, 238, 102, 177, 44, 154, 49, 69, 93, 64 - ] - .to_vec(), - [ - 50, 60, 156, 134, 29, 212, 219, 84, 244, 133, 219, 209, 173, 253, 95, 255, 33, 237, - 112, 125, 118, 237, 53, 93, 136, 130, 244, 81, 208, 90, 39, 202, 152, 111, 35, 218, - 255, 167, 173, 5, 160, 80, 97, 104, 109, 174, 255, 108, 171, 192, 91, 209, 108, - 211, 145, 157, 160, 72, 3, 137, 176, 59, 241, 13 - ] - .into(), - [ - 59, 231, 146, 62, 217, 119, 251, 42, 75, 155, 214, 126, 56, 81, 69, 171, 74, 233, - 46, 25, 1, 115, 192, 232, 135, 133, 182, 16, 6, 255, 185, 143 - ] - .into(), - ), - ( - [ - 93, 203, 169, 70, 124, 231, 163, 178, 40, 136, 241, 181, 37, 231, 93, 208, 80, 45, - 166, 216, 63, 169, 147, 117, 109, 223, 26, 76, 4, 125, 65, 115 - ] - .to_vec(), - [ - 50, 143, 129, 178, 231, 153, 77, 215, 240, 11, 70, 238, 116, 184, 15, 53, 241, 64, - 218, 248, 113, 64, 112, 68, 44, 253, 43, 176, 149, 190, 198, 31, 159, 23, 55, 150, - 205, 228, 255, 194, 176, 93, 150, 100, 254, 82, 5, 105, 47, 204, 171, 137, 210, - 184, 133, 234, 41, 242, 21, 221, 226, 3, 96, 5 - ] - .into(), - [ - 223, 237, 26, 32, 148, 201, 169, 138, 2, 140, 193, 114, 251, 9, 165, 58, 162, 221, - 21, 86, 227, 81, 70, 110, 73, 26, 60, 174, 201, 202, 155, 8 - ] - .into(), - ), - ( - [ - 10, 18, 144, 141, 46, 99, 152, 10, 220, 179, 10, 31, 65, 109, 230, 15, 245, 46, - 235, 2, 149, 188, 163, 203, 110, 98, 125, 129, 101, 155, 205, 189 - ] - .to_vec(), - [ - 197, 92, 160, 39, 41, 130, 79, 201, 86, 5, 94, 19, 212, 221, 176, 36, 85, 10, 10, - 233, 57, 235, 195, 79, 236, 245, 170, 80, 10, 165, 163, 162, 9, 166, 219, 231, 132, - 233, 78, 252, 87, 160, 104, 37, 36, 66, 252, 8, 39, 130, 227, 91, 215, 255, 167, - 111, 182, 21, 143, 220, 88, 233, 72, 10 - ] - .into(), - [ - 102, 59, 228, 88, 48, 218, 240, 208, 210, 166, 88, 74, 248, 76, 3, 159, 248, 34, - 163, 166, 251, 51, 150, 127, 247, 151, 82, 124, 167, 104, 89, 186 - ] - .into(), - ), - ( - [ - 188, 253, 211, 252, 199, 54, 126, 222, 14, 31, 80, 124, 161, 10, 199, 39, 248, 45, - 154, 68, 162, 227, 125, 107, 172, 41, 41, 151, 234, 171, 164, 136 - ] - .to_vec(), - [ - 105, 147, 47, 0, 211, 122, 10, 13, 159, 118, 59, 227, 149, 223, 237, 2, 225, 167, - 66, 17, 49, 217, 15, 139, 210, 153, 215, 249, 168, 178, 156, 61, 128, 100, 72, 84, - 108, 84, 245, 17, 123, 78, 64, 220, 253, 63, 114, 157, 176, 1, 3, 87, 36, 121, 246, - 244, 88, 153, 84, 173, 143, 170, 27, 2 - ] - .into(), - [ - 75, 29, 132, 106, 68, 195, 233, 158, 128, 93, 96, 70, 99, 43, 43, 19, 126, 162, - 176, 32, 72, 79, 194, 8, 59, 203, 16, 219, 85, 226, 17, 198 - ] - .into(), - ), - ( - [ - 226, 227, 113, 72, 108, 239, 130, 37, 21, 121, 69, 158, 159, 30, 187, 20, 25, 129, - 18, 211, 152, 237, 217, 225, 103, 173, 225, 84, 130, 14, 98, 152 - ] - .to_vec(), - [ - 237, 88, 120, 116, 191, 17, 131, 145, 14, 29, 52, 144, 131, 236, 139, 72, 220, 147, - 29, 218, 137, 162, 242, 146, 103, 115, 140, 233, 68, 111, 36, 156, 179, 18, 92, - 188, 154, 211, 159, 152, 76, 56, 48, 11, 53, 67, 249, 47, 236, 72, 54, 90, 145, 13, - 112, 129, 201, 234, 39, 40, 94, 110, 181, 2 - ] - .into(), - [ - 71, 123, 7, 83, 166, 112, 96, 41, 72, 21, 124, 204, 220, 242, 114, 18, 136, 114, - 188, 3, 109, 89, 207, 142, 211, 220, 75, 170, 138, 159, 91, 65 - ] - .into(), - ), - ( - [ - 225, 242, 213, 131, 75, 206, 121, 1, 11, 169, 169, 241, 41, 113, 255, 138, 109, - 216, 145, 166, 98, 81, 85, 105, 178, 76, 8, 213, 3, 25, 15, 164 - ] - .to_vec(), - [ - 218, 39, 132, 40, 46, 40, 16, 196, 214, 110, 211, 229, 200, 208, 146, 67, 169, 158, - 66, 110, 184, 166, 117, 120, 16, 27, 105, 176, 36, 74, 187, 103, 245, 186, 59, 233, - 171, 172, 120, 25, 182, 219, 84, 55, 219, 242, 39, 138, 89, 74, 1, 193, 184, 194, - 188, 190, 113, 136, 30, 158, 182, 91, 215, 0 - ] - .into(), - [ - 111, 220, 167, 18, 14, 97, 147, 165, 160, 155, 21, 255, 127, 176, 119, 237, 210, - 112, 99, 193, 66, 166, 167, 180, 108, 198, 153, 227, 94, 85, 232, 13 - ] - .into(), - ), - ( - [ - 225, 47, 87, 102, 125, 86, 130, 79, 147, 184, 26, 138, 230, 229, 254, 180, 191, - 252, 9, 107, 29, 126, 101, 54, 98, 134, 228, 105, 109, 143, 118, 42 - ] - .to_vec(), - [ - 197, 43, 231, 143, 82, 220, 24, 243, 80, 117, 1, 39, 150, 133, 77, 40, 26, 178, 95, - 158, 79, 60, 194, 143, 98, 128, 244, 255, 65, 191, 239, 179, 92, 159, 105, 207, - 138, 161, 38, 24, 201, 232, 230, 204, 200, 157, 93, 195, 178, 71, 88, 242, 173, 77, - 0, 56, 16, 165, 227, 188, 40, 49, 155, 7 - ] - .into(), - [ - 251, 172, 204, 143, 30, 134, 108, 243, 119, 104, 161, 93, 43, 50, 86, 5, 110, 151, - 249, 48, 103, 221, 89, 79, 235, 116, 245, 103, 94, 170, 172, 227 - ] - .into(), - ), - ( - [ - 208, 177, 124, 14, 226, 70, 2, 251, 231, 125, 90, 16, 123, 73, 47, 104, 159, 135, - 54, 131, 77, 244, 234, 106, 178, 9, 156, 169, 107, 233, 234, 187 - ] - .to_vec(), - [ - 1, 233, 198, 32, 153, 142, 54, 180, 79, 77, 194, 197, 49, 31, 59, 191, 245, 228, - 202, 195, 97, 67, 182, 115, 151, 80, 207, 183, 198, 87, 179, 129, 8, 92, 28, 164, - 209, 203, 46, 58, 160, 26, 157, 8, 149, 163, 214, 113, 127, 37, 212, 125, 179, 177, - 95, 244, 189, 21, 246, 72, 183, 184, 185, 9 - ] - .into(), - [ - 246, 252, 81, 48, 0, 123, 41, 78, 72, 116, 61, 73, 248, 229, 4, 234, 152, 149, 48, - 198, 137, 14, 231, 240, 242, 205, 159, 99, 9, 183, 104, 31 - ] - .into(), - ), - ( - [ - 71, 61, 57, 222, 190, 1, 120, 139, 238, 48, 237, 151, 52, 201, 242, 21, 200, 29, - 54, 2, 193, 153, 8, 73, 78, 186, 156, 183, 224, 126, 164, 52 - ] - .to_vec(), - [ - 209, 4, 57, 213, 70, 129, 222, 208, 129, 130, 35, 133, 204, 89, 47, 250, 107, 176, - 210, 179, 51, 173, 240, 112, 146, 112, 138, 1, 244, 87, 116, 144, 250, 178, 27, - 125, 61, 125, 186, 206, 249, 173, 60, 142, 188, 89, 96, 102, 246, 43, 184, 96, 157, - 190, 240, 123, 169, 191, 249, 8, 183, 64, 170, 12 - ] - .into(), - [ - 243, 221, 190, 199, 165, 66, 152, 23, 26, 31, 188, 218, 196, 35, 177, 38, 169, 55, - 212, 132, 148, 172, 124, 129, 232, 238, 162, 154, 224, 80, 154, 109 - ] - .into(), - ), - ( - [ - 88, 104, 132, 39, 159, 181, 16, 226, 167, 230, 84, 135, 90, 15, 145, 23, 88, 99, - 83, 19, 224, 144, 136, 116, 8, 33, 201, 84, 20, 31, 189, 203 - ] - .to_vec(), - [ - 198, 23, 212, 133, 252, 186, 229, 167, 235, 162, 178, 212, 131, 110, 44, 140, 219, - 147, 61, 202, 117, 207, 65, 200, 234, 244, 31, 94, 126, 125, 73, 129, 119, 15, 241, - 221, 212, 70, 245, 188, 178, 112, 3, 245, 89, 109, 193, 44, 0, 195, 97, 51, 167, - 147, 58, 75, 170, 172, 57, 217, 159, 38, 218, 7 - ] - .into(), - [ - 110, 105, 34, 78, 21, 10, 22, 184, 31, 158, 81, 25, 80, 20, 80, 134, 249, 158, 153, - 79, 235, 183, 66, 227, 204, 37, 48, 98, 90, 16, 176, 177 - ] - .into(), - ), - ( - [ - 234, 4, 248, 40, 225, 229, 244, 118, 26, 187, 63, 246, 11, 176, 53, 108, 51, 54, 2, - 132, 191, 16, 8, 85, 111, 150, 228, 94, 80, 192, 144, 159 - ] - .to_vec(), - [ - 218, 62, 49, 124, 86, 4, 230, 89, 33, 189, 120, 96, 24, 96, 252, 254, 143, 23, 237, - 110, 139, 76, 156, 136, 19, 227, 27, 95, 35, 27, 139, 41, 7, 137, 94, 250, 244, - 182, 21, 18, 179, 83, 149, 0, 217, 26, 254, 153, 10, 124, 163, 238, 174, 97, 247, - 27, 25, 122, 23, 217, 151, 174, 175, 4 - ] - .into(), - [ - 24, 112, 210, 128, 205, 41, 123, 217, 111, 198, 27, 183, 47, 137, 121, 176, 224, - 199, 232, 150, 60, 2, 61, 77, 173, 222, 150, 210, 111, 117, 114, 41 - ] - .into(), - ), - ( - [ - 188, 124, 52, 209, 210, 48, 97, 114, 229, 41, 172, 41, 106, 43, 131, 106, 26, 107, - 32, 24, 108, 47, 188, 99, 255, 193, 23, 43, 140, 103, 188, 88 - ] - .to_vec(), - [ - 37, 194, 31, 193, 246, 146, 76, 202, 97, 55, 83, 155, 34, 170, 227, 154, 233, 129, - 3, 185, 171, 72, 145, 76, 41, 81, 48, 56, 191, 105, 136, 58, 131, 113, 119, 246, - 112, 224, 61, 98, 22, 194, 40, 197, 166, 146, 250, 12, 181, 35, 169, 216, 80, 209, - 245, 244, 85, 242, 74, 236, 97, 194, 68, 12 - ] - .into(), - [ - 169, 123, 177, 52, 156, 222, 254, 190, 143, 121, 35, 177, 170, 147, 58, 246, 210, - 32, 213, 223, 102, 205, 179, 158, 7, 55, 113, 112, 36, 65, 202, 110 - ] - .into(), - ), - ( - [ - 17, 95, 185, 175, 219, 86, 64, 58, 174, 21, 201, 150, 129, 250, 36, 20, 195, 110, - 0, 113, 182, 24, 206, 73, 68, 16, 116, 151, 217, 0, 183, 164 - ] - .to_vec(), - [ - 9, 110, 191, 175, 105, 143, 76, 125, 98, 79, 34, 200, 167, 236, 63, 108, 131, 130, - 245, 74, 214, 68, 138, 239, 163, 250, 49, 52, 34, 188, 67, 2, 119, 229, 90, 91, - 153, 236, 151, 216, 105, 48, 164, 148, 165, 209, 106, 20, 20, 22, 237, 200, 103, - 194, 62, 55, 190, 28, 26, 210, 183, 197, 167, 1 - ] - .into(), - [ - 206, 64, 12, 105, 63, 20, 210, 176, 8, 212, 248, 201, 164, 150, 222, 49, 166, 39, - 119, 217, 70, 248, 8, 110, 185, 11, 69, 69, 36, 71, 244, 51 - ] - .into(), - ), - ( - [ - 237, 133, 151, 46, 146, 77, 61, 123, 70, 133, 58, 223, 107, 97, 229, 81, 87, 62, - 207, 195, 97, 170, 15, 82, 211, 5, 20, 89, 163, 217, 128, 35 - ] - .to_vec(), - [ - 231, 246, 248, 149, 194, 92, 119, 254, 228, 30, 210, 128, 15, 253, 106, 166, 147, - 225, 234, 233, 237, 43, 36, 251, 10, 165, 108, 167, 232, 223, 25, 48, 47, 106, 238, - 79, 44, 147, 10, 185, 132, 95, 41, 145, 246, 136, 218, 229, 196, 167, 150, 183, 19, - 31, 12, 166, 186, 121, 95, 255, 144, 25, 145, 6 - ] - .into(), - [ - 75, 0, 191, 179, 0, 38, 200, 103, 240, 232, 146, 127, 48, 255, 143, 78, 126, 37, - 225, 254, 192, 232, 53, 173, 108, 253, 215, 87, 105, 175, 132, 65 - ] - .into(), - ), - ( - [ - 109, 96, 113, 89, 67, 135, 43, 157, 40, 37, 177, 153, 123, 63, 40, 163, 123, 81, - 136, 113, 150, 209, 88, 176, 208, 58, 208, 160, 86, 26, 225, 66 - ] - .to_vec(), - [ - 75, 105, 202, 118, 233, 163, 238, 49, 119, 252, 136, 92, 19, 145, 50, 165, 182, - 178, 187, 249, 59, 201, 146, 191, 137, 65, 18, 72, 116, 85, 97, 186, 74, 17, 104, - 200, 141, 102, 38, 80, 13, 68, 231, 138, 76, 14, 32, 167, 62, 37, 156, 126, 23, 81, - 76, 227, 70, 246, 11, 187, 144, 151, 242, 8 - ] - .into(), - [ - 179, 224, 82, 251, 155, 17, 16, 45, 185, 115, 203, 211, 196, 116, 225, 39, 224, 18, - 222, 193, 92, 208, 170, 176, 232, 53, 34, 151, 235, 167, 237, 33 - ] - .into(), - ), - ( - [ - 216, 78, 65, 19, 9, 23, 203, 211, 17, 208, 180, 215, 155, 65, 140, 75, 188, 241, - 162, 82, 190, 215, 90, 217, 220, 160, 31, 168, 221, 172, 182, 129 - ] - .to_vec(), - [ - 80, 223, 42, 239, 232, 12, 152, 95, 94, 83, 91, 78, 234, 167, 180, 158, 3, 179, - 180, 66, 38, 57, 135, 13, 48, 35, 33, 46, 126, 202, 192, 84, 76, 31, 156, 164, 157, - 134, 187, 206, 16, 241, 165, 166, 99, 70, 150, 62, 233, 42, 181, 123, 68, 253, 219, - 241, 90, 65, 24, 22, 19, 248, 102, 10 - ] - .into(), - [ - 242, 136, 176, 89, 81, 79, 168, 124, 193, 245, 92, 245, 54, 59, 132, 221, 149, 60, - 59, 239, 141, 207, 146, 80, 131, 218, 22, 9, 26, 44, 78, 217 - ] - .into(), - ), - ( - [ - 113, 173, 51, 242, 20, 55, 96, 26, 102, 45, 249, 157, 86, 94, 171, 22, 215, 33, - 156, 121, 103, 97, 95, 98, 87, 226, 153, 54, 60, 83, 140, 122 - ] - .to_vec(), - [ - 245, 115, 96, 107, 149, 128, 251, 197, 15, 162, 231, 250, 22, 228, 83, 221, 99, - 198, 55, 58, 252, 150, 167, 83, 47, 227, 226, 48, 32, 245, 112, 226, 156, 79, 128, - 147, 171, 72, 104, 101, 111, 241, 233, 80, 37, 163, 13, 64, 72, 124, 68, 78, 67, - 204, 190, 119, 81, 119, 228, 238, 191, 126, 50, 5 - ] - .into(), - [ - 243, 223, 148, 190, 197, 217, 142, 40, 5, 20, 215, 119, 252, 195, 180, 3, 47, 186, - 57, 72, 136, 28, 143, 75, 213, 11, 238, 183, 105, 249, 0, 238 - ] - .into(), - ), - ( - [ - 49, 72, 74, 103, 248, 213, 54, 113, 74, 246, 9, 23, 71, 53, 169, 246, 99, 224, 151, - 195, 252, 116, 201, 4, 137, 105, 42, 92, 70, 108, 150, 227 - ] - .to_vec(), - [ - 176, 80, 159, 43, 192, 138, 206, 126, 251, 224, 143, 144, 99, 140, 182, 171, 242, - 189, 90, 83, 4, 85, 210, 211, 44, 62, 235, 229, 119, 240, 73, 56, 167, 44, 29, 148, - 110, 104, 58, 89, 132, 146, 38, 163, 44, 21, 148, 15, 248, 91, 85, 100, 23, 71, - 140, 45, 34, 193, 6, 248, 100, 1, 140, 5 - ] - .into(), - [ - 66, 17, 61, 186, 34, 197, 117, 75, 215, 64, 48, 114, 168, 139, 201, 95, 250, 32, - 242, 102, 65, 198, 97, 157, 250, 228, 211, 122, 140, 107, 22, 73 - ] - .into(), - ), - ]; - static ref LIBRUSTZCASH_BINDING_SIGS: [(Vec, Signature, VerificationKeyBytes); 32] = [ - ( - [ - 16, 28, 190, 75, 156, 66, 96, 79, 4, 199, 3, 195, 150, 247, 136, 198, 203, 45, 109, - 125, 88, 244, 84, 48, 177, 46, 178, 237, 214, 64, 7, 108 - ] - .to_vec(), - [ - 237, 87, 106, 226, 60, 11, 207, 242, 46, 84, 76, 231, 183, 226, 137, 168, 172, 81, - 133, 166, 208, 118, 55, 133, 102, 155, 236, 16, 30, 208, 68, 84, 22, 83, 106, 161, - 209, 8, 179, 99, 82, 239, 252, 99, 238, 87, 130, 246, 133, 95, 231, 43, 122, 10, - 251, 88, 227, 199, 85, 210, 70, 164, 190, 13 - ] - .into(), - [ - 231, 192, 142, 217, 209, 34, 78, 213, 129, 213, 83, 32, 218, 125, 131, 62, 236, - 189, 238, 23, 236, 235, 101, 182, 241, 2, 117, 248, 83, 18, 94, 133 - ] - .into(), - ), - ( - [ - 108, 56, 40, 255, 104, 11, 219, 166, 98, 154, 153, 67, 75, 194, 79, 17, 86, 115, - 26, 175, 150, 173, 228, 209, 66, 119, 33, 94, 87, 187, 19, 49 - ] - .to_vec(), - [ - 25, 185, 147, 122, 61, 235, 191, 32, 59, 56, 250, 154, 49, 19, 148, 205, 195, 201, - 60, 131, 133, 238, 221, 50, 237, 81, 7, 211, 116, 217, 205, 115, 236, 103, 208, 32, - 75, 8, 47, 250, 144, 184, 131, 108, 140, 53, 151, 106, 128, 163, 19, 69, 15, 42, - 82, 114, 234, 34, 191, 159, 57, 241, 36, 9 - ] - .into(), - [ - 21, 9, 29, 239, 240, 242, 41, 16, 105, 198, 200, 212, 207, 17, 76, 88, 75, 79, 223, - 157, 217, 114, 102, 78, 169, 140, 244, 4, 152, 73, 216, 47 - ] - .into(), - ), - ( - [ - 145, 63, 229, 40, 221, 46, 129, 128, 68, 42, 148, 149, 87, 96, 109, 94, 188, 197, - 117, 95, 73, 255, 11, 214, 198, 41, 249, 226, 22, 130, 163, 215 - ] - .to_vec(), - [ - 151, 162, 38, 68, 132, 8, 213, 252, 81, 56, 12, 242, 57, 61, 182, 221, 111, 66, - 218, 143, 184, 210, 235, 125, 18, 226, 157, 128, 213, 96, 89, 84, 208, 167, 64, 60, - 57, 240, 43, 230, 124, 148, 16, 233, 41, 194, 218, 171, 10, 250, 25, 93, 243, 71, - 213, 87, 74, 250, 214, 223, 30, 52, 193, 3 - ] - .into(), - [ - 208, 32, 161, 164, 158, 193, 116, 72, 31, 83, 149, 118, 131, 138, 140, 54, 21, 92, - 188, 31, 124, 204, 144, 72, 186, 253, 87, 4, 193, 138, 130, 157 - ] - .into(), - ), - ( - [ - 208, 243, 205, 249, 49, 107, 35, 33, 206, 165, 99, 248, 160, 186, 39, 50, 71, 156, - 226, 164, 9, 17, 162, 158, 198, 154, 10, 123, 189, 221, 247, 116 - ] - .to_vec(), - [ - 129, 23, 184, 104, 87, 77, 84, 102, 62, 149, 61, 114, 220, 195, 21, 194, 115, 44, - 26, 30, 72, 30, 86, 61, 179, 74, 70, 16, 192, 0, 220, 195, 129, 209, 112, 61, 226, - 172, 132, 127, 52, 103, 213, 217, 213, 42, 202, 6, 179, 184, 7, 17, 29, 5, 28, 24, - 189, 18, 135, 5, 58, 118, 93, 4 - ] - .into(), - [ - 15, 202, 69, 167, 230, 248, 5, 36, 71, 19, 94, 186, 96, 22, 6, 232, 59, 99, 131, - 148, 100, 216, 51, 195, 129, 89, 238, 56, 81, 50, 245, 220 - ] - .into(), - ), - ( - [ - 73, 53, 27, 188, 30, 74, 75, 136, 216, 22, 115, 179, 41, 12, 101, 135, 241, 208, - 177, 226, 3, 109, 120, 48, 2, 120, 150, 27, 29, 59, 61, 180 - ] - .to_vec(), - [ - 158, 145, 214, 27, 179, 127, 199, 48, 80, 13, 226, 197, 111, 19, 72, 183, 73, 51, - 34, 147, 241, 236, 21, 160, 99, 218, 202, 73, 231, 123, 62, 243, 148, 119, 42, 185, - 145, 225, 239, 177, 132, 157, 101, 0, 210, 63, 72, 22, 62, 130, 52, 222, 36, 13, - 124, 0, 208, 141, 234, 3, 38, 207, 72, 13 - ] - .into(), - [ - 13, 167, 148, 29, 141, 128, 10, 130, 105, 36, 188, 29, 169, 176, 172, 169, 162, 21, - 90, 3, 180, 221, 68, 90, 252, 154, 62, 61, 20, 47, 119, 145 - ] - .into(), - ), - ( - [ - 158, 55, 154, 163, 138, 43, 56, 169, 209, 184, 225, 86, 39, 131, 0, 194, 62, 122, - 84, 176, 197, 115, 88, 216, 47, 127, 36, 131, 215, 205, 251, 69 - ] - .to_vec(), - [ - 244, 19, 20, 115, 160, 228, 19, 65, 61, 5, 118, 252, 98, 166, 95, 8, 152, 88, 170, - 220, 129, 233, 169, 252, 99, 157, 119, 63, 243, 158, 82, 170, 248, 192, 197, 111, - 151, 237, 195, 54, 128, 105, 62, 34, 177, 118, 224, 123, 185, 188, 212, 14, 56, 56, - 177, 208, 159, 190, 229, 97, 43, 231, 65, 7 - ] - .into(), - [ - 89, 97, 162, 229, 121, 16, 170, 148, 38, 103, 34, 212, 200, 198, 164, 51, 143, 191, - 7, 42, 178, 208, 97, 236, 230, 113, 1, 197, 82, 39, 203, 83 - ] - .into(), - ), - ( - [ - 217, 101, 76, 11, 40, 202, 129, 190, 187, 84, 92, 68, 181, 190, 66, 89, 233, 122, - 72, 49, 98, 38, 40, 129, 112, 67, 119, 39, 61, 230, 140, 107 - ] - .to_vec(), - [ - 218, 247, 117, 213, 208, 142, 220, 44, 216, 96, 137, 132, 148, 31, 152, 156, 113, - 69, 28, 193, 149, 80, 30, 133, 55, 153, 151, 101, 55, 180, 57, 222, 123, 37, 88, 7, - 15, 26, 6, 186, 101, 236, 56, 130, 31, 172, 73, 71, 16, 248, 103, 15, 141, 24, 57, - 119, 157, 228, 42, 253, 120, 43, 98, 1 - ] - .into(), - [ - 122, 178, 202, 205, 106, 145, 155, 121, 178, 142, 171, 204, 133, 94, 219, 185, 58, - 222, 73, 44, 245, 198, 158, 142, 246, 214, 29, 113, 110, 55, 234, 95 - ] - .into(), - ), - ( - [ - 10, 212, 76, 139, 47, 234, 73, 233, 131, 223, 100, 101, 161, 23, 26, 161, 12, 107, - 27, 76, 50, 232, 165, 234, 34, 170, 126, 169, 179, 7, 168, 216 - ] - .to_vec(), - [ - 48, 232, 149, 96, 68, 229, 204, 221, 41, 15, 163, 211, 84, 69, 221, 144, 189, 141, - 144, 1, 47, 243, 97, 195, 247, 246, 120, 43, 220, 114, 88, 95, 94, 191, 240, 214, - 205, 145, 222, 102, 134, 72, 175, 115, 87, 216, 118, 1, 122, 112, 186, 41, 167, - 179, 167, 120, 59, 222, 49, 226, 201, 166, 210, 5 - ] - .into(), - [ - 176, 34, 144, 56, 153, 248, 153, 225, 109, 38, 93, 184, 90, 94, 254, 213, 242, 15, - 245, 212, 5, 200, 50, 48, 195, 249, 197, 75, 249, 58, 59, 65 - ] - .into(), - ), - ( - [ - 7, 121, 157, 250, 188, 252, 108, 217, 56, 87, 183, 45, 98, 129, 233, 210, 121, 143, - 173, 195, 172, 2, 154, 125, 176, 148, 3, 234, 3, 250, 127, 116 - ] - .to_vec(), - [ - 236, 49, 41, 146, 67, 207, 165, 207, 121, 176, 150, 26, 46, 207, 118, 112, 226, 31, - 19, 98, 57, 97, 183, 215, 227, 144, 101, 255, 163, 15, 186, 104, 231, 212, 237, - 159, 240, 78, 188, 177, 74, 109, 117, 211, 2, 2, 88, 98, 208, 83, 235, 61, 194, - 114, 178, 8, 215, 207, 175, 206, 156, 183, 212, 4 - ] - .into(), - [ - 114, 45, 120, 112, 212, 36, 97, 130, 84, 73, 186, 171, 73, 208, 112, 166, 193, 161, - 139, 138, 33, 191, 122, 112, 173, 253, 115, 135, 25, 216, 165, 128 - ] - .into(), - ), - ( - [ - 161, 98, 15, 93, 184, 31, 193, 208, 84, 234, 38, 229, 208, 207, 27, 172, 152, 170, - 39, 138, 187, 88, 195, 82, 253, 108, 101, 128, 110, 86, 114, 242 - ] - .to_vec(), - [ - 250, 82, 164, 64, 95, 96, 202, 190, 186, 124, 162, 48, 64, 185, 207, 25, 159, 197, - 148, 50, 180, 55, 10, 11, 1, 34, 219, 194, 215, 160, 187, 204, 161, 176, 232, 43, - 129, 43, 17, 183, 80, 223, 55, 39, 58, 160, 120, 162, 247, 92, 64, 233, 145, 81, - 136, 129, 158, 168, 47, 193, 17, 243, 141, 0 - ] - .into(), - [ - 51, 144, 219, 246, 218, 85, 243, 42, 222, 208, 32, 16, 237, 244, 131, 139, 69, 139, - 164, 231, 14, 239, 64, 94, 192, 127, 86, 97, 228, 50, 123, 65 - ] - .into(), - ), - ( - [ - 123, 7, 11, 119, 243, 237, 229, 160, 242, 163, 173, 216, 117, 94, 8, 29, 112, 178, - 23, 50, 180, 75, 18, 189, 215, 221, 21, 8, 86, 209, 177, 87 - ] - .to_vec(), - [ - 25, 68, 135, 235, 188, 239, 156, 9, 63, 43, 65, 178, 241, 114, 230, 156, 94, 118, - 114, 97, 121, 71, 206, 185, 144, 55, 241, 233, 254, 111, 209, 39, 206, 8, 217, 109, - 180, 71, 175, 235, 226, 39, 101, 241, 231, 147, 14, 121, 250, 107, 212, 228, 201, - 63, 134, 232, 110, 101, 43, 40, 209, 83, 254, 10 - ] - .into(), - [ - 196, 239, 106, 25, 44, 155, 136, 240, 60, 108, 136, 236, 150, 16, 37, 71, 89, 205, - 31, 166, 13, 136, 31, 105, 126, 55, 63, 223, 79, 123, 41, 144 - ] - .into(), - ), - ( - [ - 181, 94, 198, 199, 78, 194, 64, 118, 146, 51, 79, 70, 73, 206, 87, 51, 96, 13, 145, - 198, 78, 245, 179, 182, 169, 147, 95, 137, 77, 33, 247, 4 - ] - .to_vec(), - [ - 201, 195, 83, 81, 83, 219, 229, 100, 171, 188, 138, 28, 52, 163, 215, 12, 33, 12, - 163, 52, 146, 64, 74, 212, 148, 195, 255, 242, 96, 87, 106, 212, 174, 204, 31, 138, - 144, 32, 191, 21, 193, 63, 4, 204, 126, 248, 171, 61, 19, 156, 114, 244, 46, 18, - 160, 156, 211, 83, 216, 156, 222, 131, 105, 6 - ] - .into(), - [ - 170, 211, 15, 217, 62, 99, 68, 140, 87, 122, 65, 150, 24, 91, 62, 183, 205, 43, - 222, 241, 69, 89, 213, 235, 51, 214, 156, 238, 67, 119, 239, 62 - ] - .into(), - ), - ( - [ - 108, 144, 146, 213, 254, 69, 48, 80, 172, 3, 26, 161, 90, 132, 50, 0, 192, 101, 98, - 65, 167, 199, 175, 147, 29, 177, 217, 226, 72, 233, 93, 118 - ] - .to_vec(), - [ - 85, 140, 40, 250, 36, 52, 31, 161, 79, 218, 140, 106, 155, 15, 129, 202, 227, 206, - 72, 110, 176, 134, 218, 71, 19, 139, 164, 230, 148, 55, 34, 6, 245, 17, 95, 19, - 253, 21, 21, 156, 119, 213, 25, 201, 31, 130, 28, 215, 2, 0, 120, 56, 248, 134, - 224, 82, 138, 50, 150, 134, 144, 86, 176, 2 - ] - .into(), - [ - 5, 132, 40, 151, 157, 13, 233, 182, 145, 5, 148, 185, 157, 60, 26, 187, 1, 142, 87, - 236, 45, 171, 63, 192, 150, 27, 3, 65, 129, 120, 47, 137 - ] - .into(), - ), - ( - [ - 106, 232, 15, 114, 137, 49, 56, 62, 28, 42, 176, 201, 156, 86, 109, 234, 3, 191, - 44, 231, 22, 110, 103, 24, 204, 71, 207, 80, 255, 34, 150, 208 - ] - .to_vec(), - [ - 76, 143, 197, 238, 95, 10, 247, 248, 222, 235, 98, 201, 131, 124, 227, 105, 9, 253, - 233, 16, 51, 122, 62, 96, 253, 17, 146, 247, 90, 90, 226, 45, 0, 148, 219, 178, - 245, 188, 14, 131, 241, 153, 54, 65, 124, 176, 112, 161, 117, 130, 154, 212, 169, - 222, 227, 123, 23, 159, 43, 212, 240, 195, 105, 2 - ] - .into(), - [ - 129, 237, 183, 32, 252, 37, 62, 9, 191, 183, 110, 221, 208, 147, 195, 155, 170, 90, - 165, 62, 148, 239, 184, 96, 5, 193, 251, 175, 104, 22, 86, 20 - ] - .into(), - ), - ( - [ - 115, 113, 54, 112, 20, 175, 145, 55, 156, 102, 8, 55, 94, 188, 73, 151, 45, 250, - 55, 84, 176, 22, 100, 238, 102, 177, 44, 154, 49, 69, 93, 64 - ] - .to_vec(), - [ - 173, 45, 205, 174, 114, 159, 62, 74, 64, 1, 168, 92, 241, 121, 55, 124, 160, 55, - 250, 71, 230, 228, 135, 71, 28, 232, 153, 135, 249, 105, 179, 85, 169, 85, 150, - 126, 168, 172, 253, 116, 217, 80, 179, 39, 245, 185, 138, 144, 204, 111, 7, 194, - 185, 241, 184, 6, 166, 103, 210, 97, 27, 24, 83, 2 - ] - .into(), - [ - 102, 255, 40, 224, 138, 207, 8, 238, 77, 169, 100, 66, 36, 118, 240, 162, 156, 55, - 103, 103, 65, 234, 190, 160, 149, 137, 75, 180, 194, 77, 163, 102 - ] - .into(), - ), - ( - [ - 93, 203, 169, 70, 124, 231, 163, 178, 40, 136, 241, 181, 37, 231, 93, 208, 80, 45, - 166, 216, 63, 169, 147, 117, 109, 223, 26, 76, 4, 125, 65, 115 - ] - .to_vec(), - [ - 229, 204, 69, 161, 126, 241, 215, 126, 254, 103, 223, 201, 45, 103, 237, 217, 74, - 150, 218, 24, 154, 200, 249, 94, 241, 88, 231, 134, 242, 211, 12, 78, 99, 31, 12, - 60, 63, 235, 62, 5, 147, 224, 243, 161, 46, 209, 65, 113, 105, 220, 49, 153, 213, - 16, 244, 133, 36, 110, 201, 30, 35, 129, 4, 7 - ] - .into(), - [ - 206, 114, 177, 72, 56, 89, 233, 157, 190, 23, 239, 84, 26, 103, 247, 220, 31, 117, - 100, 129, 54, 116, 9, 254, 141, 21, 69, 145, 40, 247, 240, 109 - ] - .into(), - ), - ( - [ - 10, 18, 144, 141, 46, 99, 152, 10, 220, 179, 10, 31, 65, 109, 230, 15, 245, 46, - 235, 2, 149, 188, 163, 203, 110, 98, 125, 129, 101, 155, 205, 189 - ] - .to_vec(), - [ - 176, 119, 123, 137, 30, 22, 101, 77, 181, 10, 152, 72, 84, 223, 25, 119, 147, 186, - 213, 209, 251, 176, 185, 110, 74, 111, 62, 51, 91, 85, 209, 158, 201, 200, 44, 28, - 235, 76, 102, 83, 228, 57, 246, 69, 127, 114, 203, 202, 6, 106, 44, 94, 153, 66, - 230, 238, 30, 44, 159, 31, 19, 151, 110, 12 - ] - .into(), - [ - 64, 131, 183, 133, 193, 39, 56, 61, 212, 66, 113, 5, 204, 197, 56, 160, 202, 240, - 50, 93, 214, 52, 90, 201, 106, 70, 190, 136, 73, 153, 110, 8 - ] - .into(), - ), - ( - [ - 188, 253, 211, 252, 199, 54, 126, 222, 14, 31, 80, 124, 161, 10, 199, 39, 248, 45, - 154, 68, 162, 227, 125, 107, 172, 41, 41, 151, 234, 171, 164, 136 - ] - .to_vec(), - [ - 17, 154, 126, 54, 92, 150, 140, 160, 171, 95, 141, 143, 250, 132, 59, 14, 50, 54, - 116, 195, 157, 200, 83, 83, 53, 167, 141, 93, 125, 64, 197, 95, 95, 14, 230, 27, 2, - 137, 105, 185, 52, 223, 164, 48, 90, 134, 63, 185, 32, 204, 11, 147, 124, 216, 235, - 239, 228, 145, 48, 40, 141, 163, 98, 0 - ] - .into(), - [ - 68, 208, 194, 182, 6, 214, 24, 148, 56, 42, 161, 152, 138, 217, 59, 172, 193, 119, - 237, 56, 238, 225, 133, 77, 224, 14, 75, 145, 53, 5, 142, 101 - ] - .into(), - ), - ( - [ - 226, 227, 113, 72, 108, 239, 130, 37, 21, 121, 69, 158, 159, 30, 187, 20, 25, 129, - 18, 211, 152, 237, 217, 225, 103, 173, 225, 84, 130, 14, 98, 152 - ] - .to_vec(), - [ - 246, 81, 2, 59, 76, 187, 86, 118, 239, 175, 45, 169, 81, 49, 216, 203, 99, 159, - 145, 134, 248, 26, 79, 247, 17, 49, 133, 39, 73, 106, 60, 173, 37, 129, 155, 148, - 224, 137, 174, 230, 242, 206, 205, 1, 254, 247, 32, 212, 34, 154, 21, 145, 54, 173, - 234, 52, 104, 40, 106, 6, 242, 69, 96, 10 - ] - .into(), - [ - 49, 83, 150, 31, 12, 102, 183, 80, 9, 184, 33, 207, 190, 17, 184, 63, 229, 152, - 183, 90, 179, 119, 135, 199, 193, 61, 251, 141, 132, 254, 53, 19 - ] - .into(), - ), - ( - [ - 225, 242, 213, 131, 75, 206, 121, 1, 11, 169, 169, 241, 41, 113, 255, 138, 109, - 216, 145, 166, 98, 81, 85, 105, 178, 76, 8, 213, 3, 25, 15, 164 - ] - .to_vec(), - [ - 144, 121, 70, 141, 125, 29, 95, 18, 88, 111, 23, 199, 155, 19, 207, 156, 118, 120, - 148, 46, 38, 254, 235, 48, 228, 123, 158, 166, 63, 244, 228, 4, 202, 228, 160, 81, - 68, 19, 187, 107, 109, 149, 80, 238, 223, 104, 91, 210, 115, 22, 217, 74, 43, 239, - 186, 194, 133, 90, 224, 160, 220, 38, 140, 13 - ] - .into(), - [ - 138, 225, 61, 235, 12, 42, 193, 198, 100, 212, 166, 123, 121, 117, 207, 170, 164, - 30, 120, 74, 16, 151, 239, 199, 48, 11, 36, 162, 187, 205, 70, 147 - ] - .into(), - ), - ( - [ - 225, 47, 87, 102, 125, 86, 130, 79, 147, 184, 26, 138, 230, 229, 254, 180, 191, - 252, 9, 107, 29, 126, 101, 54, 98, 134, 228, 105, 109, 143, 118, 42 - ] - .to_vec(), - [ - 68, 166, 113, 4, 147, 21, 5, 61, 112, 131, 210, 120, 128, 9, 14, 44, 10, 108, 23, - 196, 44, 185, 172, 243, 180, 73, 220, 122, 240, 52, 94, 86, 65, 85, 132, 140, 74, - 17, 172, 85, 19, 230, 180, 79, 34, 166, 24, 180, 131, 97, 102, 44, 208, 99, 236, - 107, 124, 2, 199, 192, 241, 229, 106, 2 - ] - .into(), - [ - 125, 43, 204, 57, 195, 59, 117, 225, 126, 221, 27, 33, 79, 38, 139, 176, 186, 47, - 7, 150, 242, 182, 218, 190, 23, 94, 132, 3, 140, 245, 239, 18 - ] - .into(), - ), - ( - [ - 208, 177, 124, 14, 226, 70, 2, 251, 231, 125, 90, 16, 123, 73, 47, 104, 159, 135, - 54, 131, 77, 244, 234, 106, 178, 9, 156, 169, 107, 233, 234, 187 - ] - .to_vec(), - [ - 152, 136, 190, 89, 167, 242, 143, 37, 179, 64, 119, 195, 44, 125, 172, 222, 184, - 49, 95, 18, 64, 121, 3, 211, 213, 191, 252, 187, 60, 81, 12, 137, 228, 95, 216, 32, - 78, 235, 209, 241, 2, 228, 161, 132, 75, 203, 49, 154, 81, 66, 14, 78, 205, 123, - 249, 65, 106, 43, 72, 208, 183, 158, 178, 9 - ] - .into(), - [ - 114, 113, 231, 198, 235, 57, 190, 236, 51, 245, 171, 233, 225, 34, 227, 33, 144, - 210, 9, 70, 101, 117, 163, 244, 82, 164, 70, 162, 164, 202, 249, 173 - ] - .into(), - ), - ( - [ - 71, 61, 57, 222, 190, 1, 120, 139, 238, 48, 237, 151, 52, 201, 242, 21, 200, 29, - 54, 2, 193, 153, 8, 73, 78, 186, 156, 183, 224, 126, 164, 52 - ] - .to_vec(), - [ - 198, 185, 85, 138, 190, 54, 233, 102, 247, 52, 43, 110, 176, 53, 49, 66, 65, 165, - 166, 130, 43, 157, 250, 149, 135, 102, 253, 98, 31, 205, 62, 88, 70, 37, 179, 241, - 29, 57, 104, 204, 159, 111, 28, 249, 250, 38, 13, 101, 60, 101, 47, 48, 193, 114, - 223, 36, 51, 45, 33, 150, 219, 69, 193, 2 - ] - .into(), - [ - 250, 27, 172, 162, 248, 64, 155, 57, 38, 153, 71, 119, 202, 180, 187, 215, 160, 63, - 243, 69, 10, 226, 114, 197, 154, 168, 127, 211, 82, 53, 5, 91 - ] - .into(), - ), - ( - [ - 88, 104, 132, 39, 159, 181, 16, 226, 167, 230, 84, 135, 90, 15, 145, 23, 88, 99, - 83, 19, 224, 144, 136, 116, 8, 33, 201, 84, 20, 31, 189, 203 - ] - .to_vec(), - [ - 24, 190, 145, 96, 30, 91, 86, 153, 77, 234, 166, 254, 76, 245, 157, 23, 152, 129, - 141, 84, 0, 105, 92, 100, 108, 196, 197, 126, 156, 15, 209, 230, 50, 216, 235, 177, - 223, 116, 54, 192, 134, 106, 33, 82, 110, 136, 54, 47, 198, 141, 123, 47, 191, 163, - 129, 176, 165, 224, 121, 158, 119, 168, 219, 6 - ] - .into(), - [ - 205, 92, 57, 103, 120, 65, 0, 136, 125, 30, 25, 141, 176, 72, 191, 198, 200, 70, 9, - 5, 52, 155, 123, 23, 16, 196, 109, 169, 146, 225, 165, 171 - ] - .into(), - ), - ( - [ - 234, 4, 248, 40, 225, 229, 244, 118, 26, 187, 63, 246, 11, 176, 53, 108, 51, 54, 2, - 132, 191, 16, 8, 85, 111, 150, 228, 94, 80, 192, 144, 159 - ] - .to_vec(), - [ - 13, 69, 57, 44, 76, 45, 23, 39, 17, 117, 23, 6, 98, 211, 163, 51, 119, 240, 48, 2, - 88, 73, 205, 190, 4, 203, 4, 250, 75, 134, 75, 82, 5, 89, 255, 171, 109, 22, 83, - 76, 177, 99, 224, 243, 84, 192, 83, 127, 105, 61, 96, 247, 107, 67, 78, 144, 206, - 56, 230, 210, 55, 150, 3, 0 - ] - .into(), - [ - 7, 46, 165, 146, 105, 160, 80, 138, 114, 236, 217, 138, 9, 100, 41, 231, 215, 92, - 215, 229, 24, 32, 129, 25, 16, 1, 243, 176, 0, 204, 147, 35 - ] - .into(), - ), - ( - [ - 188, 124, 52, 209, 210, 48, 97, 114, 229, 41, 172, 41, 106, 43, 131, 106, 26, 107, - 32, 24, 108, 47, 188, 99, 255, 193, 23, 43, 140, 103, 188, 88 - ] - .to_vec(), - [ - 115, 233, 189, 93, 167, 14, 110, 88, 157, 118, 162, 29, 195, 11, 250, 122, 252, - 224, 68, 12, 243, 10, 159, 127, 50, 65, 235, 115, 91, 120, 47, 211, 89, 0, 180, 99, - 140, 182, 215, 120, 146, 16, 247, 74, 149, 104, 13, 30, 64, 239, 55, 77, 204, 75, - 94, 231, 232, 217, 60, 7, 53, 133, 124, 4 - ] - .into(), - [ - 251, 201, 115, 163, 5, 40, 10, 63, 211, 146, 80, 78, 1, 16, 107, 199, 146, 72, 180, - 141, 183, 19, 199, 93, 33, 229, 205, 70, 32, 143, 163, 54 - ] - .into(), - ), - ( - [ - 17, 95, 185, 175, 219, 86, 64, 58, 174, 21, 201, 150, 129, 250, 36, 20, 195, 110, - 0, 113, 182, 24, 206, 73, 68, 16, 116, 151, 217, 0, 183, 164 - ] - .to_vec(), - [ - 5, 171, 71, 27, 104, 155, 152, 225, 171, 250, 77, 64, 133, 52, 21, 11, 195, 1, 249, - 69, 239, 136, 150, 180, 164, 139, 50, 132, 81, 146, 130, 39, 115, 69, 122, 24, 113, - 125, 135, 202, 222, 68, 56, 18, 111, 90, 170, 209, 231, 75, 90, 125, 210, 192, 36, - 168, 7, 253, 154, 47, 142, 204, 253, 12 - ] - .into(), - [ - 228, 135, 125, 188, 76, 87, 101, 6, 105, 175, 105, 96, 87, 202, 53, 118, 51, 202, - 103, 210, 10, 155, 106, 16, 142, 210, 53, 248, 207, 131, 121, 51 - ] - .into(), - ), - ( - [ - 237, 133, 151, 46, 146, 77, 61, 123, 70, 133, 58, 223, 107, 97, 229, 81, 87, 62, - 207, 195, 97, 170, 15, 82, 211, 5, 20, 89, 163, 217, 128, 35 - ] - .to_vec(), - [ - 94, 58, 85, 222, 114, 105, 9, 111, 156, 63, 24, 17, 189, 80, 195, 29, 204, 168, 0, - 170, 46, 12, 220, 2, 27, 31, 178, 205, 217, 146, 221, 242, 32, 34, 62, 194, 157, - 102, 152, 161, 12, 11, 220, 49, 126, 197, 57, 143, 98, 24, 127, 211, 128, 189, 79, - 65, 75, 88, 157, 47, 67, 40, 95, 6 - ] - .into(), - [ - 204, 43, 68, 82, 129, 227, 172, 253, 204, 243, 143, 138, 221, 73, 236, 38, 143, 9, - 41, 52, 38, 227, 152, 202, 198, 118, 237, 255, 65, 5, 251, 229 - ] - .into(), - ), - ( - [ - 109, 96, 113, 89, 67, 135, 43, 157, 40, 37, 177, 153, 123, 63, 40, 163, 123, 81, - 136, 113, 150, 209, 88, 176, 208, 58, 208, 160, 86, 26, 225, 66 - ] - .to_vec(), - [ - 78, 191, 253, 51, 223, 212, 196, 105, 82, 191, 242, 41, 117, 77, 104, 209, 172, - 202, 40, 253, 38, 157, 54, 13, 235, 157, 47, 31, 88, 249, 2, 196, 88, 126, 211, - 173, 47, 13, 111, 53, 112, 179, 185, 203, 119, 4, 74, 67, 53, 11, 245, 184, 42, - 160, 147, 154, 209, 242, 196, 248, 159, 150, 142, 1 - ] - .into(), - [ - 120, 105, 195, 25, 208, 187, 21, 168, 238, 79, 44, 94, 96, 0, 112, 179, 221, 190, - 141, 53, 19, 61, 42, 48, 175, 210, 148, 183, 79, 40, 7, 45 - ] - .into(), - ), - ( - [ - 216, 78, 65, 19, 9, 23, 203, 211, 17, 208, 180, 215, 155, 65, 140, 75, 188, 241, - 162, 82, 190, 215, 90, 217, 220, 160, 31, 168, 221, 172, 182, 129 - ] - .to_vec(), - [ - 153, 116, 51, 238, 50, 167, 226, 181, 122, 111, 73, 88, 42, 159, 251, 212, 194, 20, - 98, 43, 48, 125, 80, 116, 7, 243, 13, 203, 169, 71, 111, 165, 16, 236, 122, 203, 4, - 125, 111, 20, 96, 233, 121, 71, 138, 215, 169, 154, 134, 205, 9, 68, 197, 236, 179, - 102, 229, 168, 162, 245, 111, 85, 106, 3 - ] - .into(), - [ - 48, 161, 121, 172, 29, 185, 169, 8, 50, 189, 168, 130, 140, 254, 197, 6, 188, 93, - 253, 67, 198, 198, 185, 212, 42, 224, 217, 195, 129, 84, 230, 5 - ] - .into(), - ), - ( - [ - 113, 173, 51, 242, 20, 55, 96, 26, 102, 45, 249, 157, 86, 94, 171, 22, 215, 33, - 156, 121, 103, 97, 95, 98, 87, 226, 153, 54, 60, 83, 140, 122 - ] - .to_vec(), - [ - 235, 56, 216, 155, 20, 252, 54, 184, 249, 162, 116, 122, 221, 112, 171, 18, 182, - 233, 210, 116, 84, 216, 69, 75, 219, 2, 138, 87, 172, 233, 50, 200, 135, 188, 136, - 55, 81, 43, 101, 66, 176, 248, 24, 208, 106, 131, 44, 240, 166, 159, 162, 107, 58, - 126, 190, 11, 22, 56, 17, 96, 27, 179, 173, 9 - ] - .into(), - [ - 87, 69, 133, 181, 55, 135, 65, 98, 105, 71, 175, 166, 169, 105, 11, 82, 66, 250, - 166, 198, 232, 223, 130, 20, 236, 2, 0, 207, 179, 65, 151, 72 - ] - .into(), - ), - ( - [ - 49, 72, 74, 103, 248, 213, 54, 113, 74, 246, 9, 23, 71, 53, 169, 246, 99, 224, 151, - 195, 252, 116, 201, 4, 137, 105, 42, 92, 70, 108, 150, 227 - ] - .to_vec(), - [ - 138, 52, 43, 171, 87, 79, 36, 251, 109, 39, 155, 54, 200, 106, 231, 234, 75, 234, - 140, 168, 179, 68, 180, 227, 220, 212, 43, 44, 175, 177, 75, 108, 47, 216, 185, 32, - 126, 143, 204, 58, 46, 123, 85, 224, 214, 181, 247, 48, 252, 37, 5, 186, 193, 168, - 142, 205, 97, 153, 36, 161, 178, 162, 152, 3 - ] - .into(), - [ - 75, 64, 164, 20, 239, 96, 148, 68, 235, 208, 11, 77, 136, 192, 177, 116, 193, 84, - 44, 205, 239, 143, 46, 162, 51, 228, 61, 95, 160, 21, 200, 102 - ] - .into(), - ), - ]; -} diff --git a/frost-redjubjub/tests/proptests.proptest-regressions b/frost-redjubjub/tests/proptests.proptest-regressions deleted file mode 100644 index 41c883a..0000000 --- a/frost-redjubjub/tests/proptests.proptest-regressions +++ /dev/null @@ -1,8 +0,0 @@ -# Seeds for failure cases proptest has generated in the past. It is -# automatically read and these particular cases re-run before any -# novel cases are generated. -# -# It is recommended to check this file in to source control so that -# everyone who runs the test benefits from these saved cases. -cc 25716e9dc4549b01b395fca1fc076fc34300ad972ac59c5e098f7ec90a03446b # shrinks to tweaks = [ChangePubkey], rng_seed = 946433020594646748 -cc ddb674b23f131d33cdbe34f3959f7fc076f4815a12ad5d6f741ae38d2689d1c2 # shrinks to tweaks = [ChangePubkey, ChangePubkey, ChangePubkey, ChangePubkey], rng_seed = 8346595811973717667 diff --git a/frost-redjubjub/tests/proptests.rs b/frost-redjubjub/tests/proptests.rs deleted file mode 100644 index f03fbbc..0000000 --- a/frost-redjubjub/tests/proptests.rs +++ /dev/null @@ -1,153 +0,0 @@ -use std::convert::TryFrom; - -use proptest::prelude::*; -use rand_core::{CryptoRng, RngCore}; - -use redjubjub::*; - -/// A signature test-case, containing signature data and expected validity. -#[derive(Clone, Debug)] -struct SignatureCase { - msg: Vec, - sig: Signature, - pk_bytes: VerificationKeyBytes, - invalid_pk_bytes: VerificationKeyBytes, - is_valid: bool, -} - -/// A modification to a test-case. -#[derive(Copy, Clone, Debug)] -enum Tweak { - /// No-op, used to check that unchanged cases verify. - None, - /// Change the message the signature is defined for, invalidating the signature. - ChangeMessage, - /// Change the public key the signature is defined for, invalidating the signature. - ChangePubkey, - /* XXX implement this -- needs to regenerate a custom signature because the - nonce commitment is fed into the hash, so it has to have torsion at signing - time. - /// Change the case to have a torsion component in the signature's `r` value. - AddTorsion, - */ - /* XXX implement this -- needs custom handling of field arithmetic. - /// Change the signature's `s` scalar to be unreduced (mod L), invalidating the signature. - UnreducedScalar, - */ -} - -impl SignatureCase { - fn new(mut rng: R, msg: Vec) -> Self { - let sk = SigningKey::new(&mut rng); - let sig = sk.sign(&mut rng, &msg); - let pk_bytes = VerificationKey::from(&sk).into(); - let invalid_pk_bytes = VerificationKey::from(&SigningKey::new(&mut rng)).into(); - Self { - msg, - sig, - pk_bytes, - invalid_pk_bytes, - is_valid: true, - } - } - - // Check that signature verification succeeds or fails, as expected. - fn check(&self) -> bool { - // The signature data is stored in (refined) byte types, but do a round trip - // conversion to raw bytes to exercise those code paths. - let sig = { - let bytes: [u8; 64] = self.sig.into(); - Signature::::from(bytes) - }; - let pk_bytes = { - let bytes: [u8; 32] = self.pk_bytes.into(); - VerificationKeyBytes::::from(bytes) - }; - - // Check that the verification key is a valid RedJubjub verification key. - let pub_key = VerificationKey::try_from(pk_bytes) - .expect("The test verification key to be well-formed."); - - // Check that signature validation has the expected result. - self.is_valid == pub_key.verify(&self.msg, &sig).is_ok() - } - - fn apply_tweak(&mut self, tweak: &Tweak) { - match tweak { - Tweak::None => {} - Tweak::ChangeMessage => { - // Changing the message makes the signature invalid. - self.msg.push(90); - self.is_valid = false; - } - Tweak::ChangePubkey => { - // Changing the public key makes the signature invalid. - self.pk_bytes = self.invalid_pk_bytes; - self.is_valid = false; - } - } - } -} - -fn tweak_strategy() -> impl Strategy { - prop_oneof![ - 10 => Just(Tweak::None), - 1 => Just(Tweak::ChangeMessage), - 1 => Just(Tweak::ChangePubkey), - ] -} - -use rand_chacha::ChaChaRng; -use rand_core::SeedableRng; - -proptest! { - - #[test] - fn tweak_signature( - tweaks in prop::collection::vec(tweak_strategy(), (0,5)), - rng_seed in prop::array::uniform32(any::()), - ) { - // Use a deterministic RNG so that test failures can be reproduced. - // Seeding with 64 bits of entropy is INSECURE and this code should - // not be copied outside of this test! - let mut rng = ChaChaRng::from_seed(rng_seed); - - // Create a test case for each signature type. - let msg = b"test message for proptests"; - let mut binding = SignatureCase::::new(&mut rng, msg.to_vec()); - let mut spendauth = SignatureCase::::new(&mut rng, msg.to_vec()); - - // Apply tweaks to each case. - for t in &tweaks { - binding.apply_tweak(t); - spendauth.apply_tweak(t); - } - - assert!(binding.check()); - assert!(spendauth.check()); - } - - #[test] - fn randomization_commutes_with_pubkey_homomorphism(rng_seed in prop::array::uniform32(any::())) { - // Use a deterministic RNG so that test failures can be reproduced. - let mut rng = ChaChaRng::from_seed(rng_seed); - - let r = { - // XXX-jubjub: better API for this - let mut bytes = [0; 64]; - rng.fill_bytes(&mut bytes[..]); - Randomizer::from_bytes_wide(&bytes) - }; - - let sk = SigningKey::::new(&mut rng); - let pk = VerificationKey::from(&sk); - - let sk_r = sk.randomize(&r); - let pk_r = pk.randomize(&r); - - let pk_r_via_sk_rand: [u8; 32] = VerificationKeyBytes::from(VerificationKey::from(&sk_r)).into(); - let pk_r_via_pk_rand: [u8; 32] = VerificationKeyBytes::from(pk_r).into(); - - assert_eq!(pk_r_via_pk_rand, pk_r_via_sk_rand); - } -} diff --git a/frost-redjubjub/tests/smallorder.rs b/frost-redjubjub/tests/smallorder.rs deleted file mode 100644 index 019068e..0000000 --- a/frost-redjubjub/tests/smallorder.rs +++ /dev/null @@ -1,24 +0,0 @@ -use std::convert::TryFrom; - -use jubjub::{AffinePoint, Fq}; - -use redjubjub::*; - -#[test] -fn identity_publickey_passes() { - let identity = AffinePoint::identity(); - assert_eq!(::from(identity.is_small_order()), true); - let bytes = identity.to_bytes(); - let pk_bytes = VerificationKeyBytes::::from(bytes); - assert!(VerificationKey::::try_from(pk_bytes).is_ok()); -} - -#[test] -fn smallorder_publickey_passes() { - // (1,0) is a point of order 4 on any Edwards curve - let order4 = AffinePoint::from_raw_unchecked(Fq::one(), Fq::zero()); - assert_eq!(::from(order4.is_small_order()), true); - let bytes = order4.to_bytes(); - let pk_bytes = VerificationKeyBytes::::from(bytes); - assert!(VerificationKey::::try_from(pk_bytes).is_ok()); -} diff --git a/frost-redjubjub/zcash-frost-audit-report-20210323.pdf b/zcash-frost-audit-report-20210323.pdf similarity index 100% rename from frost-redjubjub/zcash-frost-audit-report-20210323.pdf rename to zcash-frost-audit-report-20210323.pdf