consolidate arbitrary impls to one file in zebra-chain (#553)

* consolidate arbitrary impls to one file in zebra-chain

* move the ones I missed

* move test-vectors

Co-authored-by: Jane Lusby <jane@zfnd.org>
This commit is contained in:
Jane Lusby 2020-06-30 14:23:38 -07:00 committed by GitHub
parent 7245d91fe9
commit 6cbb6d4574
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 231 additions and 239 deletions

View File

@ -8,8 +8,6 @@ mod serialize;
mod shielded_data; mod shielded_data;
mod transparent; mod transparent;
#[cfg(test)]
mod test_vectors;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;

View File

@ -1,8 +1,5 @@
#[cfg(test)]
use proptest::{array, collection::vec, prelude::*};
use serde::{Deserialize, Serialize};
use crate::{ed25519_zebra, notes::sprout, proofs::ZkSnarkProof}; use crate::{ed25519_zebra, notes::sprout, proofs::ZkSnarkProof};
use serde::{Deserialize, Serialize};
/// A _JoinSplit Description_, as described in [protocol specification §7.2][ps]. /// A _JoinSplit Description_, as described in [protocol specification §7.2][ps].
/// ///
@ -70,56 +67,6 @@ impl<P: ZkSnarkProof> PartialEq for JoinSplit<P> {
// Because x25519_dalek::PublicKey does not impl Eq // Because x25519_dalek::PublicKey does not impl Eq
impl<P: ZkSnarkProof> Eq for JoinSplit<P> {} impl<P: ZkSnarkProof> Eq for JoinSplit<P> {}
#[cfg(test)]
impl<P: ZkSnarkProof + Arbitrary + 'static> Arbitrary for JoinSplit<P> {
type Parameters = ();
fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
(
any::<u64>(),
any::<u64>(),
array::uniform32(any::<u8>()),
array::uniform2(array::uniform32(any::<u8>())),
array::uniform2(array::uniform32(any::<u8>())),
array::uniform32(any::<u8>()),
array::uniform32(any::<u8>()),
array::uniform2(array::uniform32(any::<u8>())),
any::<P>(),
array::uniform2(any::<sprout::EncryptedCiphertext>()),
)
.prop_map(
|(
vpub_old,
vpub_new,
anchor,
nullifiers,
commitments,
ephemeral_key_bytes,
random_seed,
vmacs,
zkproof,
enc_ciphertexts,
)| {
Self {
vpub_old,
vpub_new,
anchor,
nullifiers,
commitments,
ephemeral_key: x25519_dalek::PublicKey::from(ephemeral_key_bytes),
random_seed,
vmacs,
zkproof,
enc_ciphertexts,
}
},
)
.boxed()
}
type Strategy = BoxedStrategy<Self>;
}
/// A bundle of JoinSplit descriptions and signature data. /// A bundle of JoinSplit descriptions and signature data.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct JoinSplitData<P: ZkSnarkProof> { pub struct JoinSplitData<P: ZkSnarkProof> {
@ -157,30 +104,3 @@ impl<P: ZkSnarkProof> JoinSplitData<P> {
std::iter::once(&self.first).chain(self.rest.iter()) std::iter::once(&self.first).chain(self.rest.iter())
} }
} }
#[cfg(test)]
impl<P: ZkSnarkProof + Arbitrary + 'static> Arbitrary for JoinSplitData<P> {
type Parameters = ();
fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
(
any::<JoinSplit<P>>(),
vec(any::<JoinSplit<P>>(), 0..10),
array::uniform32(any::<u8>()),
vec(any::<u8>(), 64),
)
.prop_map(|(first, rest, pub_key_bytes, sig_bytes)| Self {
first,
rest,
pub_key: ed25519_zebra::VerificationKeyBytes::from(pub_key_bytes),
sig: ed25519_zebra::Signature::from({
let mut b = [0u8; 64];
b.copy_from_slice(sig_bytes.as_slice());
b
}),
})
.boxed()
}
type Strategy = BoxedStrategy<Self>;
}

View File

@ -1,14 +1,10 @@
use futures::future::Either;
#[cfg(test)]
use proptest::{arbitrary::Arbitrary, array, collection::vec, prelude::*};
// XXX this name seems too long? // XXX this name seems too long?
use crate::note_commitment_tree::SaplingNoteTreeRootHash; use crate::note_commitment_tree::SaplingNoteTreeRootHash;
use crate::notes::sapling; use crate::notes::sapling;
use crate::proofs::Groth16Proof; use crate::proofs::Groth16Proof;
use crate::redjubjub::{self, Binding, SpendAuth}; use crate::redjubjub::{self, Binding, SpendAuth};
use crate::serde_helpers; use crate::serde_helpers;
use futures::future::Either;
/// A _Spend Description_, as described in [protocol specification §7.3][ps]. /// A _Spend Description_, as described in [protocol specification §7.3][ps].
/// ///
@ -33,39 +29,6 @@ pub struct Spend {
pub spend_auth_sig: redjubjub::Signature<SpendAuth>, pub spend_auth_sig: redjubjub::Signature<SpendAuth>,
} }
#[cfg(test)]
impl Arbitrary for Spend {
type Parameters = ();
fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
(
array::uniform32(any::<u8>()),
any::<SaplingNoteTreeRootHash>(),
array::uniform32(any::<u8>()),
array::uniform32(any::<u8>()),
any::<Groth16Proof>(),
vec(any::<u8>(), 64),
)
.prop_map(
|(cv_bytes, anchor, nullifier_bytes, rpk_bytes, proof, sig_bytes)| Self {
anchor,
cv: cv_bytes,
nullifier: nullifier_bytes,
rk: redjubjub::PublicKeyBytes::from(rpk_bytes),
zkproof: proof,
spend_auth_sig: redjubjub::Signature::from({
let mut b = [0u8; 64];
b.copy_from_slice(sig_bytes.as_slice());
b
}),
},
)
.boxed()
}
type Strategy = BoxedStrategy<Self>;
}
/// A _Output Description_, as described in [protocol specification §7.4][ps]. /// A _Output Description_, as described in [protocol specification §7.4][ps].
/// ///
/// [ps]: https://zips.z.cash/protocol/protocol.pdf#outputencoding /// [ps]: https://zips.z.cash/protocol/protocol.pdf#outputencoding
@ -92,37 +55,6 @@ pub struct Output {
impl Eq for Output {} impl Eq for Output {}
#[cfg(test)]
impl Arbitrary for Output {
type Parameters = ();
fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
(
array::uniform32(any::<u8>()),
array::uniform32(any::<u8>()),
array::uniform32(any::<u8>()).prop_filter("Valid jubjub::AffinePoint", |b| {
jubjub::AffinePoint::from_bytes(*b).is_some().unwrap_u8() == 1
}),
any::<sapling::EncryptedCiphertext>(),
any::<sapling::OutCiphertext>(),
any::<Groth16Proof>(),
)
.prop_map(
|(cv, cmu, ephemeral_key_bytes, enc_ciphertext, out_ciphertext, zkproof)| Self {
cv,
cmu,
ephemeral_key: jubjub::AffinePoint::from_bytes(ephemeral_key_bytes).unwrap(),
enc_ciphertext,
out_ciphertext,
zkproof,
},
)
.boxed()
}
type Strategy = BoxedStrategy<Self>;
}
/// Sapling-on-Groth16 spend and output descriptions. /// Sapling-on-Groth16 spend and output descriptions.
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ShieldedData { pub struct ShieldedData {
@ -197,33 +129,3 @@ impl std::cmp::PartialEq for ShieldedData {
} }
impl std::cmp::Eq for ShieldedData {} impl std::cmp::Eq for ShieldedData {}
#[cfg(test)]
impl Arbitrary for ShieldedData {
type Parameters = ();
fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
(
prop_oneof![
any::<Spend>().prop_map(Either::Left),
any::<Output>().prop_map(Either::Right)
],
vec(any::<Spend>(), 0..10),
vec(any::<Output>(), 0..10),
vec(any::<u8>(), 64),
)
.prop_map(|(first, rest_spends, rest_outputs, sig_bytes)| Self {
first,
rest_spends,
rest_outputs,
binding_sig: redjubjub::Signature::from({
let mut b = [0u8; 64];
b.copy_from_slice(sig_bytes.as_slice());
b
}),
})
.boxed()
}
type Strategy = BoxedStrategy<Self>;
}

View File

@ -1,18 +1,15 @@
use proptest::{ use proptest::{arbitrary::any, collection::vec, option, prelude::*};
arbitrary::{any, Arbitrary},
collection::vec,
option,
prelude::*,
};
use crate::{ use crate::{
serialization::{ZcashDeserialize, ZcashSerialize}, serialization::{ZcashDeserialize, ZcashSerialize},
types::{LockTime, Script}, types::LockTime,
}; };
use super::*; use super::*;
#[cfg(test)] mod arbitrary;
mod test_vectors;
impl Transaction { impl Transaction {
pub fn v1_strategy() -> impl Strategy<Value = Self> { pub fn v1_strategy() -> impl Strategy<Value = Self> {
( (
@ -99,54 +96,6 @@ impl Transaction {
} }
} }
#[cfg(test)]
impl Arbitrary for Transaction {
type Parameters = ();
fn arbitrary_with(_args: ()) -> Self::Strategy {
prop_oneof![
Self::v1_strategy(),
Self::v2_strategy(),
Self::v3_strategy(),
Self::v4_strategy()
]
.boxed()
}
type Strategy = BoxedStrategy<Self>;
}
#[cfg(test)]
impl Arbitrary for TransparentInput {
type Parameters = ();
fn arbitrary_with(_args: ()) -> Self::Strategy {
prop_oneof![
(any::<OutPoint>(), any::<Script>(), any::<u32>())
.prop_map(|(outpoint, script, sequence)| {
TransparentInput::PrevOut {
outpoint,
script,
sequence,
}
})
.boxed(),
(any::<BlockHeight>(), vec(any::<u8>(), 0..95), any::<u32>())
.prop_map(|(height, data, sequence)| {
TransparentInput::Coinbase {
height,
data: CoinbaseData(data),
sequence,
}
})
.boxed(),
]
.boxed()
}
type Strategy = BoxedStrategy<Self>;
}
#[test] #[test]
fn librustzcash_tx_deserialize_and_round_trip() { fn librustzcash_tx_deserialize_and_round_trip() {
let tx = Transaction::zcash_deserialize(&test_vectors::GENERIC_TESTNET_TX[..]) let tx = Transaction::zcash_deserialize(&test_vectors::GENERIC_TESTNET_TX[..])
@ -158,7 +107,6 @@ fn librustzcash_tx_deserialize_and_round_trip() {
assert_eq!(&test_vectors::GENERIC_TESTNET_TX[..], &data2[..]); assert_eq!(&test_vectors::GENERIC_TESTNET_TX[..], &data2[..]);
} }
#[cfg(test)]
proptest! { proptest! {
#[test] #[test]

View File

@ -0,0 +1,224 @@
use crate::{
note_commitment_tree::SaplingNoteTreeRootHash,
notes::{sapling, sprout},
proofs::{Groth16Proof, ZkSnarkProof},
transaction::{
CoinbaseData, JoinSplit, JoinSplitData, OutPoint, Output, ShieldedData, Spend, Transaction,
TransparentInput,
},
types::{BlockHeight, Script},
};
use futures::future::Either;
use proptest::{array, collection::vec, prelude::*};
impl<P: ZkSnarkProof + Arbitrary + 'static> Arbitrary for JoinSplit<P> {
type Parameters = ();
fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
(
any::<u64>(),
any::<u64>(),
array::uniform32(any::<u8>()),
array::uniform2(array::uniform32(any::<u8>())),
array::uniform2(array::uniform32(any::<u8>())),
array::uniform32(any::<u8>()),
array::uniform32(any::<u8>()),
array::uniform2(array::uniform32(any::<u8>())),
any::<P>(),
array::uniform2(any::<sprout::EncryptedCiphertext>()),
)
.prop_map(
|(
vpub_old,
vpub_new,
anchor,
nullifiers,
commitments,
ephemeral_key_bytes,
random_seed,
vmacs,
zkproof,
enc_ciphertexts,
)| {
Self {
vpub_old,
vpub_new,
anchor,
nullifiers,
commitments,
ephemeral_key: x25519_dalek::PublicKey::from(ephemeral_key_bytes),
random_seed,
vmacs,
zkproof,
enc_ciphertexts,
}
},
)
.boxed()
}
type Strategy = BoxedStrategy<Self>;
}
impl<P: ZkSnarkProof + Arbitrary + 'static> Arbitrary for JoinSplitData<P> {
type Parameters = ();
fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
(
any::<JoinSplit<P>>(),
vec(any::<JoinSplit<P>>(), 0..10),
array::uniform32(any::<u8>()),
vec(any::<u8>(), 64),
)
.prop_map(|(first, rest, pub_key_bytes, sig_bytes)| Self {
first,
rest,
pub_key: ed25519_zebra::VerificationKeyBytes::from(pub_key_bytes),
sig: ed25519_zebra::Signature::from({
let mut b = [0u8; 64];
b.copy_from_slice(sig_bytes.as_slice());
b
}),
})
.boxed()
}
type Strategy = BoxedStrategy<Self>;
}
impl Arbitrary for Output {
type Parameters = ();
fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
(
array::uniform32(any::<u8>()),
array::uniform32(any::<u8>()),
array::uniform32(any::<u8>()).prop_filter("Valid jubjub::AffinePoint", |b| {
jubjub::AffinePoint::from_bytes(*b).is_some().unwrap_u8() == 1
}),
any::<sapling::EncryptedCiphertext>(),
any::<sapling::OutCiphertext>(),
any::<Groth16Proof>(),
)
.prop_map(
|(cv, cmu, ephemeral_key_bytes, enc_ciphertext, out_ciphertext, zkproof)| Self {
cv,
cmu,
ephemeral_key: jubjub::AffinePoint::from_bytes(ephemeral_key_bytes).unwrap(),
enc_ciphertext,
out_ciphertext,
zkproof,
},
)
.boxed()
}
type Strategy = BoxedStrategy<Self>;
}
impl Arbitrary for ShieldedData {
type Parameters = ();
fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
(
prop_oneof![
any::<Spend>().prop_map(Either::Left),
any::<Output>().prop_map(Either::Right)
],
vec(any::<Spend>(), 0..10),
vec(any::<Output>(), 0..10),
vec(any::<u8>(), 64),
)
.prop_map(|(first, rest_spends, rest_outputs, sig_bytes)| Self {
first,
rest_spends,
rest_outputs,
binding_sig: redjubjub::Signature::from({
let mut b = [0u8; 64];
b.copy_from_slice(sig_bytes.as_slice());
b
}),
})
.boxed()
}
type Strategy = BoxedStrategy<Self>;
}
impl Arbitrary for Spend {
type Parameters = ();
fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
(
array::uniform32(any::<u8>()),
any::<SaplingNoteTreeRootHash>(),
array::uniform32(any::<u8>()),
array::uniform32(any::<u8>()),
any::<Groth16Proof>(),
vec(any::<u8>(), 64),
)
.prop_map(
|(cv_bytes, anchor, nullifier_bytes, rpk_bytes, proof, sig_bytes)| Self {
anchor,
cv: cv_bytes,
nullifier: nullifier_bytes,
rk: redjubjub::PublicKeyBytes::from(rpk_bytes),
zkproof: proof,
spend_auth_sig: redjubjub::Signature::from({
let mut b = [0u8; 64];
b.copy_from_slice(sig_bytes.as_slice());
b
}),
},
)
.boxed()
}
type Strategy = BoxedStrategy<Self>;
}
impl Arbitrary for Transaction {
type Parameters = ();
fn arbitrary_with(_args: ()) -> Self::Strategy {
prop_oneof![
Self::v1_strategy(),
Self::v2_strategy(),
Self::v3_strategy(),
Self::v4_strategy()
]
.boxed()
}
type Strategy = BoxedStrategy<Self>;
}
impl Arbitrary for TransparentInput {
type Parameters = ();
fn arbitrary_with(_args: ()) -> Self::Strategy {
prop_oneof![
(any::<OutPoint>(), any::<Script>(), any::<u32>())
.prop_map(|(outpoint, script, sequence)| {
TransparentInput::PrevOut {
outpoint,
script,
sequence,
}
})
.boxed(),
(any::<BlockHeight>(), vec(any::<u8>(), 0..95), any::<u32>())
.prop_map(|(height, data, sequence)| {
TransparentInput::Coinbase {
height,
data: CoinbaseData(data),
sequence,
}
})
.boxed(),
]
.boxed()
}
type Strategy = BoxedStrategy<Self>;
}