Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds serialize and deserialize to Network types #450

Merged
merged 17 commits into from Oct 20, 2021
Merged
6 changes: 4 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions algorithms/Cargo.toml
Expand Up @@ -114,6 +114,9 @@ version = "2"
[dependencies.digest]
version = "0.9"

[dependencies.hex]
version = "0.4.3"

[dependencies.itertools]
version = "0.10.1"

Expand All @@ -139,13 +142,21 @@ default-features = false
[dependencies.rayon]
version = "1"

[dependencies.serde]
version = "1.0"
default-features = false
features = ["derive"]

[dependencies.sha2]
version = "0.9"
default-features = false

[dependencies.thiserror]
version = "1.0"

[dev-dependencies.bincode]
version = "1"

[dev-dependencies.criterion]
version = "0.3.5"

Expand Down
76 changes: 63 additions & 13 deletions algorithms/src/signature/aleo.rs
Expand Up @@ -31,19 +31,24 @@ use snarkvm_curves::{
};
use snarkvm_fields::{ConstraintFieldError, Field, FieldParameters, PrimeField, ToConstraintField};
use snarkvm_utilities::{
fmt,
io::{Read, Result as IoResult, Write},
ops::Mul,
rand::UniformRand,
serialize::*,
str::FromStr,
FromBits,
FromBytes,
FromBytesDeserializer,
ToBits,
ToBytes,
ToBytesSerializer,
};

use anyhow::Result;
use itertools::Itertools;
use rand::{CryptoRng, Rng};
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};

#[derive(Derivative)]
#[derivative(
Expand All @@ -62,6 +67,11 @@ pub struct AleoSignature<TE: TwistedEdwardsParameters> {
}

impl<TE: TwistedEdwardsParameters> AleoSignature<TE> {
#[inline]
pub fn size() -> usize {
2 * TE::ScalarField::SERIALIZED_SIZE + 2 * TE::BaseField::SERIALIZED_SIZE
}

#[inline]
pub fn root_public_key(&self) -> Result<TEAffine<TE>> {
if let Some(element) = TEAffine::<TE>::from_x_coordinate(self.root_public_key, true) {
Expand Down Expand Up @@ -97,16 +107,6 @@ impl<TE: TwistedEdwardsParameters> AleoSignature<TE> {
}
}

impl<TE: TwistedEdwardsParameters> ToBytes for AleoSignature<TE> {
#[inline]
fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
self.prover_response.write_le(&mut writer)?;
self.verifier_challenge.write_le(&mut writer)?;
self.root_public_key.write_le(&mut writer)?;
self.root_randomizer.write_le(&mut writer)
}
}

impl<TE: TwistedEdwardsParameters> FromBytes for AleoSignature<TE> {
#[inline]
fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
Expand All @@ -124,6 +124,56 @@ impl<TE: TwistedEdwardsParameters> FromBytes for AleoSignature<TE> {
}
}

impl<TE: TwistedEdwardsParameters> ToBytes for AleoSignature<TE> {
#[inline]
fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
self.prover_response.write_le(&mut writer)?;
self.verifier_challenge.write_le(&mut writer)?;
self.root_public_key.write_le(&mut writer)?;
self.root_randomizer.write_le(&mut writer)
}
}

impl<TE: TwistedEdwardsParameters> FromStr for AleoSignature<TE> {
type Err = anyhow::Error;

#[inline]
fn from_str(signature_hex: &str) -> Result<Self, Self::Err> {
Self::from_bytes_le(&hex::decode(signature_hex)?)
}
}

impl<TE: TwistedEdwardsParameters> fmt::Display for AleoSignature<TE> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let signature_hex = hex::encode(self.to_bytes_le().expect("Failed to convert signature to bytes"));
write!(f, "{}", signature_hex)
}
}

impl<TE: TwistedEdwardsParameters> Serialize for AleoSignature<TE> {
#[inline]
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
match serializer.is_human_readable() {
true => serializer.collect_str(self),
false => ToBytesSerializer::serialize(self, serializer),
}
}
}

impl<'de, TE: TwistedEdwardsParameters> Deserialize<'de> for AleoSignature<TE> {
#[inline]
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
match deserializer.is_human_readable() {
true => {
let s: String = Deserialize::deserialize(deserializer)?;
FromStr::from_str(&s).map_err(de::Error::custom)
}
false => FromBytesDeserializer::<Self>::deserialize(deserializer, "signature", Self::size()),
}
}
}

#[derive(Derivative)]
#[derivative(
Clone(bound = "TE: TwistedEdwardsParameters"),
Expand All @@ -135,7 +185,7 @@ pub struct AleoSignatureScheme<TE: TwistedEdwardsParameters>
where
TE::BaseField: PoseidonDefaultParametersField,
{
pub g_bases: Vec<TEProjective<TE>>,
g_bases: Vec<TEProjective<TE>>,
crypto_hash: PoseidonCryptoHash<TE::BaseField, 4, false>,
}

Expand Down Expand Up @@ -171,8 +221,8 @@ where
Self { g_bases, crypto_hash }
}

fn parameters(&self) -> Self::Parameters {
self.g_bases.clone()
fn parameters(&self) -> &Self::Parameters {
&self.g_bases
}

///
Expand Down
63 changes: 58 additions & 5 deletions algorithms/src/signature/tests.rs
Expand Up @@ -17,11 +17,10 @@
use crate::SignatureScheme;
use snarkvm_utilities::FromBytes;

use rand::SeedableRng;
use rand_chacha::ChaChaRng;
use rand::thread_rng;

fn sign_and_verify<S: SignatureScheme>(message: &[u8]) {
let rng = &mut ChaChaRng::seed_from_u64(1231275789u64);
let rng = &mut thread_rng();
let signature_scheme = S::setup("sign_and_verify");

let private_key = signature_scheme.generate_private_key(rng);
Expand All @@ -31,7 +30,7 @@ fn sign_and_verify<S: SignatureScheme>(message: &[u8]) {
}

fn failed_verification<S: SignatureScheme>(message: &[u8], bad_message: &[u8]) {
let rng = &mut ChaChaRng::seed_from_u64(1231275789u64);
let rng = &mut thread_rng();
let signature_scheme = S::setup("failed_verification");

let private_key = signature_scheme.generate_private_key(rng);
Expand All @@ -48,11 +47,12 @@ fn signature_scheme_serialization<S: SignatureScheme>() {

mod aleo {
use super::*;
use crate::signature::AleoSignatureScheme;
use crate::signature::{AleoSignature, AleoSignatureScheme};
use snarkvm_curves::{
edwards_bls12::EdwardsParameters as EdwardsBls12,
edwards_bw6::EdwardsParameters as EdwardsBW6,
};
use snarkvm_utilities::{str::FromStr, FromBytes, ToBytes};

#[test]
fn test_aleo_signature_on_edwards_bls12_377() {
Expand All @@ -77,4 +77,57 @@ mod aleo {
signature_scheme_serialization::<AleoSignatureScheme<EdwardsBls12>>();
signature_scheme_serialization::<AleoSignatureScheme<EdwardsBW6>>();
}

#[test]
fn test_serde_json() {
type TestSignature = AleoSignatureScheme<EdwardsBls12>;

let expected_signature = {
let rng = &mut thread_rng();
let signature_scheme = TestSignature::setup("test_serde_json");
let private_key = signature_scheme.generate_private_key(rng);
let message = b"Hi, I am an Aleo signature!";
signature_scheme.sign(&private_key, message, rng).unwrap()
};

// Serialize
let expected_string = &expected_signature.to_string();
let candidate_string = serde_json::to_string(&expected_signature).unwrap();
assert_eq!(258, candidate_string.len(), "Update me if serialization has changed");
assert_eq!(
expected_string,
serde_json::Value::from_str(&candidate_string)
.unwrap()
.as_str()
.unwrap()
);

// Deserialize
assert_eq!(expected_signature, serde_json::from_str(&candidate_string).unwrap());
assert_eq!(expected_signature, AleoSignature::from_str(&expected_string).unwrap());
}

#[test]
fn test_bincode() {
type TestSignature = AleoSignatureScheme<EdwardsBls12>;

let expected_signature = {
let rng = &mut thread_rng();
let signature_scheme = TestSignature::setup("test_bincode");
let private_key = signature_scheme.generate_private_key(rng);
let message = b"Hi, I am an Aleo signature!";
signature_scheme.sign(&private_key, message, rng).unwrap()
};

// Serialize
let expected_bytes = expected_signature.to_bytes_le().unwrap();
assert_eq!(
&expected_bytes[..],
&bincode::serialize(&expected_signature).unwrap()[..]
);

// Deserialize
assert_eq!(expected_signature, bincode::deserialize(&expected_bytes[..]).unwrap());
assert_eq!(expected_signature, AleoSignature::read_le(&expected_bytes[..]).unwrap());
}
}