From 9776bfb0b059f65417094e83d23b473044de537e Mon Sep 17 00:00:00 2001 From: aniampio Date: Wed, 23 Mar 2022 17:34:39 +0000 Subject: [PATCH] Copy and adjust aggregation of verification keys from coconut --- Cargo.lock | 113 +++++++++++++- common/nym-compact-ecash/Cargo.toml | 3 +- common/nym-compact-ecash/src/error.rs | 3 + common/nym-compact-ecash/src/lib.rs | 22 ++- .../src/scheme/aggregation.rs | 133 ++++++++++++++++ common/nym-compact-ecash/src/scheme/keygen.rs | 147 +++++++++++++++++- common/nym-compact-ecash/src/scheme/mod.rs | 102 ++++++++++++ .../src/scheme/withdrawal.rs | 2 +- common/nym-compact-ecash/src/tests/e2e.rs | 12 +- common/nym-compact-ecash/src/traits.rs | 22 +++ common/nymcoconut/src/lib.rs | 11 ++ 11 files changed, 556 insertions(+), 14 deletions(-) create mode 100644 common/nym-compact-ecash/src/traits.rs diff --git a/Cargo.lock b/Cargo.lock index 26ecc4a3b9..dd5fbb2312 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1345,6 +1345,17 @@ dependencies = [ "zeroize", ] +[[package]] +name = "clap" +version = "2.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "bitflags 1.3.2", + "textwrap 0.11.0", + "unicode-width", +] + [[package]] name = "clap" version = "3.2.25" @@ -1354,7 +1365,7 @@ dependencies = [ "bitflags 1.3.2", "clap_lex 0.2.4", "indexmap 1.9.3", - "textwrap", + "textwrap 0.16.0", ] [[package]] @@ -1800,6 +1811,32 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "criterion" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b01d6de93b2b6c65e17c634a26653a29d107b3c98c607c765bf38d041531cd8f" +dependencies = [ + "atty", + "cast", + "clap 2.34.0", + "criterion-plot 0.4.5", + "csv", + "itertools 0.10.5", + "lazy_static", + "num-traits", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_cbor", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", +] + [[package]] name = "criterion" version = "0.4.0" @@ -1811,7 +1848,7 @@ dependencies = [ "cast", "ciborium", "clap 3.2.25", - "criterion-plot", + "criterion-plot 0.5.0", "itertools 0.10.5", "lazy_static", "num-traits", @@ -1826,6 +1863,16 @@ dependencies = [ "walkdir", ] +[[package]] +name = "criterion-plot" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2673cc8207403546f45f5fd319a974b1e6983ad1a3ee7e6041650013be041876" +dependencies = [ + "cast", + "itertools 0.10.5", +] + [[package]] name = "criterion-plot" version = "0.5.0" @@ -1975,6 +2022,27 @@ dependencies = [ "subtle 2.4.1", ] +[[package]] +name = "csv" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" +dependencies = [ + "memchr", +] + [[package]] name = "ctor" version = "0.1.26" @@ -6259,7 +6327,7 @@ version = "0.5.0" dependencies = [ "bls12_381 0.6.0", "bs58 0.4.0", - "criterion", + "criterion 0.4.0", "digest 0.9.0", "doc-comment", "ff 0.11.1", @@ -6308,6 +6376,22 @@ dependencies = [ "thiserror", ] +[[package]] +name = "nym-compact-ecash" +version = "0.1.0" +dependencies = [ + "bls12_381 0.5.0", + "bs58 0.4.0", + "criterion 0.3.6", + "digest 0.9.0", + "ff 0.10.1", + "group 0.10.0", + "itertools 0.10.5", + "rand 0.8.5", + "sha2 0.9.9", + "thiserror", +] + [[package]] name = "nym-config" version = "0.1.0" @@ -6408,7 +6492,7 @@ dependencies = [ "bitvec", "bls12_381 0.6.0", "bs58 0.4.0", - "criterion", + "criterion 0.4.0", "ff 0.11.1", "group 0.11.0", "lazy_static", @@ -7007,7 +7091,7 @@ dependencies = [ "blake3", "chacha20 0.9.1", "chacha20poly1305 0.10.1", - "criterion", + "criterion 0.4.0", "curve25519-dalek 3.2.0", "fastrand 1.9.0", "getrandom 0.2.10", @@ -9755,6 +9839,16 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_cbor" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" +dependencies = [ + "half", + "serde", +] + [[package]] name = "serde_derive" version = "1.0.189" @@ -10753,6 +10847,15 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + [[package]] name = "textwrap" version = "0.16.0" diff --git a/common/nym-compact-ecash/Cargo.toml b/common/nym-compact-ecash/Cargo.toml index b88d710ad2..de68b93011 100644 --- a/common/nym-compact-ecash/Cargo.toml +++ b/common/nym-compact-ecash/Cargo.toml @@ -8,12 +8,13 @@ edition = "2021" [dependencies] bls12_381 = { version = "0.5", default-features = false, features = ["pairings", "alloc", "experimental"] } -nymcoconut = { path = "../nymcoconut" } itertools = "0.10" digest = "0.9" rand = "0.8" thiserror = "1.0" sha2 = "0.9" +bs58 = "0.4.0" + [dev-dependencies] criterion = { version = "0.3", features = ["html_reports"] } diff --git a/common/nym-compact-ecash/src/error.rs b/common/nym-compact-ecash/src/error.rs index 9057472934..6a63548a91 100644 --- a/common/nym-compact-ecash/src/error.rs +++ b/common/nym-compact-ecash/src/error.rs @@ -7,6 +7,9 @@ pub enum CompactEcashError { #[error("Setup error: {0}")] Setup(String), + #[error("Aggregation error: {0}")] + Aggregation(String), + #[error("Withdrawal Request Verification related error: {0}")] WithdrawalRequestVerification(String), diff --git a/common/nym-compact-ecash/src/lib.rs b/common/nym-compact-ecash/src/lib.rs index 58c2380165..4cf720a0e7 100644 --- a/common/nym-compact-ecash/src/lib.rs +++ b/common/nym-compact-ecash/src/lib.rs @@ -1,8 +1,28 @@ -pub use nymcoconut::*; +use std::convert::TryInto; + +use bls12_381::Scalar; + +pub use traits::Base58; + +use crate::error::CompactEcashError; +use crate::traits::Bytable; mod error; mod proofs; mod scheme; #[cfg(test)] mod tests; +mod traits; mod utils; + +pub type Attribute = Scalar; + +impl Bytable for Attribute { + fn to_byte_vec(&self) -> Vec { + self.to_bytes().to_vec() + } + + fn try_from_byte_slice(slice: &[u8]) -> Result { + Ok(Attribute::from_bytes(slice.try_into().unwrap()).unwrap()) + } +} \ No newline at end of file diff --git a/common/nym-compact-ecash/src/scheme/aggregation.rs b/common/nym-compact-ecash/src/scheme/aggregation.rs index 8b13789179..6d529f9868 100644 --- a/common/nym-compact-ecash/src/scheme/aggregation.rs +++ b/common/nym-compact-ecash/src/scheme/aggregation.rs @@ -1 +1,134 @@ +use core::iter::Sum; +use core::ops::Mul; +use bls12_381::{G2Prepared, G2Projective, Scalar}; +use group::Curve; +use itertools::Itertools; + +use crate::Attribute; +use crate::error::{CompactEcashError, Result}; +use crate::scheme::{PartialSignature, Signature, SignatureShare, SignerIndex}; +use crate::scheme::keygen::VerificationKeyAuth; +use crate::scheme::setup::Parameters; +use crate::utils::{check_bilinear_pairing, perform_lagrangian_interpolation_at_origin}; + +pub(crate) trait Aggregatable: Sized { + fn aggregate(aggregatable: &[Self], indices: Option<&[SignerIndex]>) -> Result; + + fn check_unique_indices(indices: &[SignerIndex]) -> bool { + // if aggregation is a threshold one, all indices should be unique + indices.iter().unique_by(|&index| index).count() == indices.len() + } +} + +impl Aggregatable for T + where + T: Sum, + for<'a> T: Sum<&'a T>, + for<'a> &'a T: Mul, +{ + fn aggregate(aggregatable: &[T], indices: Option<&[u64]>) -> Result { + if aggregatable.is_empty() { + return Err(CompactEcashError::Aggregation("Empty set of values".to_string())); + } + + if let Some(indices) = indices { + if !Self::check_unique_indices(indices) { + return Err(CompactEcashError::Aggregation("Non-unique indices".to_string())); + } + perform_lagrangian_interpolation_at_origin(indices, aggregatable) + } else { + // non-threshold + Ok(aggregatable.iter().sum()) + } + } +} + +impl Aggregatable for PartialSignature { + fn aggregate(sigs: &[PartialSignature], indices: Option<&[u64]>) -> Result { + let h = sigs + .get(0) + .ok_or_else(|| CompactEcashError::Aggregation("Empty set of signatures".to_string()))? + .sig1(); + + // TODO: is it possible to avoid this allocation? + let sigmas = sigs.iter().map(|sig| *sig.sig2()).collect::>(); + let aggr_sigma = Aggregatable::aggregate(&sigmas, indices)?; + + Ok(Signature(*h, aggr_sigma)) + } +} + +/// Ensures all provided verification keys were generated to verify the same number of attributes. +fn check_same_key_size(keys: &[VerificationKeyAuth]) -> bool { + keys.iter().map(|vk| vk.beta_g1.len()).all_equal() + && keys.iter().map(|vk| vk.beta_g2.len()).all_equal() +} + +pub fn aggregate_verification_keys( + keys: &[VerificationKeyAuth], + indices: Option<&[SignerIndex]>, +) -> Result { + if !check_same_key_size(keys) { + return Err(CompactEcashError::Aggregation( + "Verification keys are of different sizes".to_string(), + )); + } + Aggregatable::aggregate(keys, indices) +} + +pub fn aggregate_signature_shares( + params: &Parameters, + verification_key: &VerificationKeyAuth, + attributes: &[Attribute], + shares: &[SignatureShare], +) -> Result { + let (signatures, indices): (Vec<_>, Vec<_>) = shares + .iter() + .map(|share| (*share.signature(), share.index())) + .unzip(); + + aggregate_signatures( + params, + verification_key, + attributes, + &signatures, + Some(&indices), + ) +} + +pub fn aggregate_signatures( + params: &Parameters, + verification_key: &VerificationKeyAuth, + attributes: &[Attribute], + signatures: &[PartialSignature], + indices: Option<&[SignerIndex]>, +) -> Result { + // aggregate the signature + + let signature = match Aggregatable::aggregate(signatures, indices) { + Ok(res) => res, + Err(err) => return Err(err), + }; + + // Verify the signature + let alpha = verification_key.alpha; + + let tmp = attributes + .iter() + .zip(verification_key.beta_g2.iter()) + .map(|(attr, beta_i)| beta_i * attr) + .sum::(); + + if !check_bilinear_pairing( + &signature.0.to_affine(), + &G2Prepared::from((alpha + tmp).to_affine()), + &signature.1.to_affine(), + params.prepared_miller_g2(), + ) { + return Err(CompactEcashError::Aggregation( + "Verification of the aggregated signature failed".to_string(), + )); + } + Ok(signature) +} \ No newline at end of file diff --git a/common/nym-compact-ecash/src/scheme/keygen.rs b/common/nym-compact-ecash/src/scheme/keygen.rs index e23b65ad61..124ea0c828 100644 --- a/common/nym-compact-ecash/src/scheme/keygen.rs +++ b/common/nym-compact-ecash/src/scheme/keygen.rs @@ -1,16 +1,21 @@ +use core::borrow::Borrow; +use core::iter::Sum; +use core::ops::{Add, Mul}; use std::convert::TryFrom; use std::convert::TryInto; use bls12_381::{G1Projective, G2Projective, Scalar}; +use group::Curve; use crate::error::{CompactEcashError, Result}; +use crate::scheme::aggregation::aggregate_verification_keys; use crate::scheme::setup::Parameters; use crate::scheme::SignerIndex; -use crate::utils::Polynomial; use crate::utils::{ try_deserialize_g1_projective, try_deserialize_g2_projective, try_deserialize_scalar, try_deserialize_scalar_vec, }; +use crate::utils::Polynomial; #[derive(Debug, PartialEq, Clone)] pub struct SecretKeyAuth { @@ -173,6 +178,146 @@ impl TryFrom<&[u8]> for VerificationKeyAuth { } } +impl<'b> Add<&'b VerificationKeyAuth> for VerificationKeyAuth { + type Output = VerificationKeyAuth; + + #[inline] + fn add(self, rhs: &'b VerificationKeyAuth) -> VerificationKeyAuth { + // If you're trying to add two keys together that were created + // for different number of attributes, just panic as it's a + // nonsense operation. + assert_eq!( + self.beta_g1.len(), + rhs.beta_g1.len(), + "trying to add verification keys generated for different number of attributes [G1]" + ); + + assert_eq!( + self.beta_g2.len(), + rhs.beta_g2.len(), + "trying to add verification keys generated for different number of attributes [G2]" + ); + + assert_eq!( + self.beta_g1.len(), + self.beta_g2.len(), + "this key is incorrect - the number of elements G1 and G2 does not match" + ); + + assert_eq!( + rhs.beta_g1.len(), + rhs.beta_g2.len(), + "they key you want to add is incorrect - the number of elements G1 and G2 does not match" + ); + + VerificationKeyAuth { + alpha: self.alpha + rhs.alpha, + beta_g1: self + .beta_g1 + .iter() + .zip(rhs.beta_g1.iter()) + .map(|(self_beta_g1, rhs_beta_g1)| self_beta_g1 + rhs_beta_g1) + .collect(), + beta_g2: self + .beta_g2 + .iter() + .zip(rhs.beta_g2.iter()) + .map(|(self_beta_g2, rhs_beta_g2)| self_beta_g2 + rhs_beta_g2) + .collect(), + } + } +} + +impl<'a> Mul for &'a VerificationKeyAuth { + type Output = VerificationKeyAuth; + + #[inline] + fn mul(self, rhs: Scalar) -> Self::Output { + VerificationKeyAuth { + alpha: self.alpha * rhs, + beta_g1: self.beta_g1.iter().map(|b_i| b_i * rhs).collect(), + beta_g2: self.beta_g2.iter().map(|b_i| b_i * rhs).collect(), + } + } +} + +impl Sum for VerificationKeyAuth + where + T: Borrow, +{ + #[inline] + fn sum(iter: I) -> Self + where + I: Iterator, + { + let mut peekable = iter.peekable(); + let head_attributes = match peekable.peek() { + Some(head) => head.borrow().beta_g2.len(), + None => { + // TODO: this is a really weird edge case. You're trying to sum an EMPTY iterator + // of VerificationKey. So should it panic here or just return some nonsense value? + return VerificationKeyAuth::identity(0); + } + }; + + peekable.fold(VerificationKeyAuth::identity(head_attributes), |acc, item| { + acc + item.borrow() + }) + } +} + +impl VerificationKeyAuth { + /// Create a (kinda) identity verification key using specified + /// number of 'beta' elements + pub(crate) fn identity(beta_size: usize) -> Self { + VerificationKeyAuth { + alpha: G2Projective::identity(), + beta_g1: vec![G1Projective::identity(); beta_size], + beta_g2: vec![G2Projective::identity(); beta_size], + } + } + + pub fn aggregate(sigs: &[Self], indices: Option<&[SignerIndex]>) -> Result { + aggregate_verification_keys(sigs, indices) + } + + pub fn alpha(&self) -> &G2Projective { + &self.alpha + } + + pub fn beta_g1(&self) -> &Vec { + &self.beta_g1 + } + + pub fn beta_g2(&self) -> &Vec { + &self.beta_g2 + } + + pub fn to_bytes(&self) -> Vec { + let beta_g1_len = self.beta_g1.len(); + let beta_g2_len = self.beta_g2.len(); + let mut bytes = Vec::with_capacity(96 + 8 + beta_g1_len * 48 + beta_g2_len * 96); + + bytes.extend_from_slice(&self.alpha.to_affine().to_compressed()); + + bytes.extend_from_slice(&beta_g1_len.to_le_bytes()); + + for beta_g1 in self.beta_g1.iter() { + bytes.extend_from_slice(&beta_g1.to_affine().to_compressed()) + } + + for beta_g2 in self.beta_g2.iter() { + bytes.extend_from_slice(&beta_g2.to_affine().to_compressed()) + } + + bytes + } + + pub fn from_bytes(bytes: &[u8]) -> Result { + VerificationKeyAuth::try_from(bytes) + } +} + #[derive(Debug, PartialEq, Clone)] pub struct SecretKeyUser { pub(crate) sk: Scalar, diff --git a/common/nym-compact-ecash/src/scheme/mod.rs b/common/nym-compact-ecash/src/scheme/mod.rs index 60d7b99528..b0f59670b6 100644 --- a/common/nym-compact-ecash/src/scheme/mod.rs +++ b/common/nym-compact-ecash/src/scheme/mod.rs @@ -1,4 +1,13 @@ +use std::convert::TryFrom; +use std::convert::TryInto; + use bls12_381::{G1Projective, Scalar}; +use group::Curve; + +use crate::error::{CompactEcashError, Result}; +use crate::scheme::setup::Parameters; +use crate::traits::Bytable; +use crate::utils::try_deserialize_g1_projective; pub mod aggregation; pub mod keygen; @@ -12,10 +21,103 @@ pub type SignerIndex = u64; #[cfg_attr(test, derive(PartialEq))] pub struct Signature(pub(crate) G1Projective, pub(crate) G1Projective); +pub type PartialSignature = Signature; + +impl TryFrom<&[u8]> for Signature { + type Error = CompactEcashError; + + fn try_from(bytes: &[u8]) -> Result { + if bytes.len() != 96 { + return Err(CompactEcashError::Deserialization(format!( + "Signature must be exactly 96 bytes, got {}", + bytes.len() + ))); + } + + let sig1_bytes: &[u8; 48] = &bytes[..48].try_into().expect("Slice size != 48"); + let sig2_bytes: &[u8; 48] = &bytes[48..].try_into().expect("Slice size != 48"); + + let sig1 = try_deserialize_g1_projective( + sig1_bytes, + CompactEcashError::Deserialization("Failed to deserialize compressed sig1".to_string()), + )?; + + let sig2 = try_deserialize_g1_projective( + sig2_bytes, + CompactEcashError::Deserialization("Failed to deserialize compressed sig2".to_string()), + )?; + + Ok(Signature(sig1, sig2)) + } +} + +impl Signature { + pub(crate) fn sig1(&self) -> &G1Projective { + &self.0 + } + + pub(crate) fn sig2(&self) -> &G1Projective { + &self.1 + } + + pub fn randomise(&self, params: &Parameters) -> (Signature, Scalar) { + let r = params.random_scalar(); + let r_prime = params.random_scalar(); + let h_prime = self.0 * r_prime; + let s_prime = (self.1 * r_prime) + (h_prime * r); + (Signature(h_prime, s_prime), r) + } + + pub fn to_bytes(self) -> [u8; 96] { + let mut bytes = [0u8; 96]; + bytes[..48].copy_from_slice(&self.0.to_affine().to_compressed()); + bytes[48..].copy_from_slice(&self.1.to_affine().to_compressed()); + bytes + } + + pub fn from_bytes(bytes: &[u8]) -> Result { + Signature::try_from(bytes) + } +} + +impl Bytable for Signature { + fn to_byte_vec(&self) -> Vec { + self.to_bytes().to_vec() + } + + fn try_from_byte_slice(slice: &[u8]) -> Result { + Signature::from_bytes(slice) + } +} + + #[derive(Debug)] #[cfg_attr(test, derive(PartialEq))] pub struct BlindedSignature(G1Projective, G1Projective); +pub struct SignatureShare { + signature: Signature, + index: SignerIndex, +} + +impl SignatureShare { + pub fn new(signature: Signature, index: SignerIndex) -> Self { + SignatureShare { signature, index } + } + + pub fn signature(&self) -> &Signature { + &self.signature + } + + pub fn index(&self) -> SignerIndex { + self.index + } + + // pub fn aggregate(shares: &[Self]) -> Result { + // aggregate_signature_shares(shares) + // } +} + pub struct Wallet { sig: Signature, v: Scalar, diff --git a/common/nym-compact-ecash/src/scheme/withdrawal.rs b/common/nym-compact-ecash/src/scheme/withdrawal.rs index 214578b4ee..1bf44a5159 100644 --- a/common/nym-compact-ecash/src/scheme/withdrawal.rs +++ b/common/nym-compact-ecash/src/scheme/withdrawal.rs @@ -154,7 +154,6 @@ pub fn issue_verify( let unblinded_c = c - blinding_removers; - // Verify the signature correctness on the wallet share let attr = vec![sk_user.sk, req_info.v, req_info.t]; let signed_attributes = attr @@ -163,6 +162,7 @@ pub fn issue_verify( .map(|(attr, beta_i)| beta_i * attr) .sum::(); + // Verify the signature correctness on the wallet share if !check_bilinear_pairing( &h.to_affine(), &G2Prepared::from((vk_auth.alpha + signed_attributes).to_affine()), diff --git a/common/nym-compact-ecash/src/tests/e2e.rs b/common/nym-compact-ecash/src/tests/e2e.rs index 3e83442d86..080067d5f4 100644 --- a/common/nym-compact-ecash/src/tests/e2e.rs +++ b/common/nym-compact-ecash/src/tests/e2e.rs @@ -1,13 +1,13 @@ use itertools::izip; use crate::error::CompactEcashError; +use crate::scheme::aggregation::aggregate_verification_keys; use crate::scheme::keygen::{ - generate_keypair_user, ttp_keygen, PublicKeyUser, SecretKeyUser, VerificationKeyAuth, + generate_keypair_user, PublicKeyUser, SecretKeyUser, ttp_keygen, VerificationKeyAuth, }; use crate::scheme::setup::Parameters; -use crate::scheme::withdrawal::{issue_verify, issue_wallet, withdrawal_request}; use crate::scheme::Wallet; -use crate::VerificationKey; +use crate::scheme::withdrawal::{issue_verify, issue_wallet, withdrawal_request}; #[test] fn main() -> Result<(), CompactEcashError> { @@ -22,6 +22,8 @@ fn main() -> Result<(), CompactEcashError> { .map(|keypair| keypair.verification_key()) .collect(); + let verification_key = aggregate_verification_keys(&verification_keys_auth, Some(&[1, 2, 3]))?; + let mut wallet_blinded_signatures = Vec::new(); for auth_keypair in authorities_keypairs { let blind_signature = issue_wallet( @@ -37,8 +39,8 @@ fn main() -> Result<(), CompactEcashError> { wallet_blinded_signatures.iter(), verification_keys_auth.iter() ) - .map(|(w, vk)| issue_verify(¶ms, vk, &user_keypair.secret_key(), w, &req_info).unwrap()) - .collect(); + .map(|(w, vk)| issue_verify(¶ms, vk, &user_keypair.secret_key(), w, &req_info).unwrap()) + .collect(); Ok(()) } diff --git a/common/nym-compact-ecash/src/traits.rs b/common/nym-compact-ecash/src/traits.rs new file mode 100644 index 0000000000..c2e93142f6 --- /dev/null +++ b/common/nym-compact-ecash/src/traits.rs @@ -0,0 +1,22 @@ +use crate::CompactEcashError; + +pub trait Bytable + where + Self: Sized, +{ + fn to_byte_vec(&self) -> Vec; + + fn try_from_byte_slice(slice: &[u8]) -> Result; +} + +pub trait Base58 + where + Self: Bytable, +{ + fn try_from_bs58>(x: S) -> Result { + Self::try_from_byte_slice(&bs58::decode(x.as_ref()).into_vec().unwrap()) + } + fn to_bs58(&self) -> String { + bs58::encode(self.to_byte_vec()).into_string() + } +} diff --git a/common/nymcoconut/src/lib.rs b/common/nymcoconut/src/lib.rs index 38846c1e79..add9f081eb 100644 --- a/common/nymcoconut/src/lib.rs +++ b/common/nymcoconut/src/lib.rs @@ -39,8 +39,19 @@ pub use scheme::verification::prove_bandwidth_credential; pub use scheme::verification::verify_credential; pub use scheme::verification::Theta; pub use scheme::BlindedSignature; +pub use scheme::issuance::blind_sign; +pub use scheme::issuance::BlindSignRequest; +pub use scheme::issuance::prepare_blind_sign; +pub use scheme::keygen::KeyPair; +pub use scheme::keygen::ttp_keygen; +pub use scheme::keygen::VerificationKey; +pub use scheme::setup::Parameters; +pub use scheme::setup::setup; pub use scheme::Signature; pub use scheme::SignatureShare; +pub use scheme::verification::prove_bandwidth_credential; +pub use scheme::verification::Theta; +pub use scheme::verification::verify_credential; pub use traits::Base58; pub use utils::hash_to_scalar;