zebra/zebra-chain/src/transaction/tests/arbitrary.rs

228 lines
6.9 KiB
Rust

use crate::{
note_commitment_tree::SaplingNoteTreeRootHash,
notes::{sapling, sprout},
proofs::{Groth16Proof, ZkSnarkProof},
transaction::{
CoinbaseData, JoinSplit, JoinSplitData, OutPoint, Output, ShieldedData, Spend, Transaction,
TransparentInput,
},
types::{
amount::{Amount, NonNegative},
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::<Amount<NonNegative>>(),
any::<Amount<NonNegative>>(),
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>;
}