use group::{ff::PrimeField, prime::PrimeCurveAffine}; use halo2::{arithmetic::FieldExt, pasta::pallas}; use proptest::{arbitrary::any, array, collection::vec, prelude::*}; use crate::primitives::redpallas::{Signature, SpendAuth, VerificationKey, VerificationKeyBytes}; use super::{ keys, note, tree, Action, Address, AuthorizedAction, Diversifier, Flags, NoteCommitment, ValueCommitment, }; use std::{ convert::{TryFrom, TryInto}, marker::PhantomData, }; impl Arbitrary for Action { type Parameters = (); fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy { ( any::(), any::>(), any::(), any::(), ) .prop_map(|(nullifier, rk, enc_ciphertext, out_ciphertext)| Self { cv: ValueCommitment(pallas::Affine::identity()), nullifier, rk, cm_x: NoteCommitment(pallas::Affine::identity()).extract_x(), ephemeral_key: keys::EphemeralPublicKey(pallas::Affine::generator()), enc_ciphertext, out_ciphertext, }) .boxed() } type Strategy = BoxedStrategy; } impl Arbitrary for note::Nullifier { type Parameters = (); fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy { (vec(any::(), 64)) .prop_map(|bytes| { let bytes = bytes.try_into().expect("vec is the correct length"); Self::try_from(pallas::Scalar::from_bytes_wide(&bytes).to_repr()) .expect("a valid generated nullifier") }) .boxed() } type Strategy = BoxedStrategy; } impl Arbitrary for AuthorizedAction { type Parameters = (); fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy { (any::(), any::>()) .prop_map(|(action, spend_auth_sig)| Self { action, spend_auth_sig, }) .boxed() } type Strategy = BoxedStrategy; } impl Arbitrary for Signature { type Parameters = (); fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy { (array::uniform32(any::()), array::uniform32(any::())) .prop_map(|(r_bytes, s_bytes)| Self { r_bytes, s_bytes, _marker: PhantomData, }) .boxed() } type Strategy = BoxedStrategy; } impl Arbitrary for VerificationKeyBytes { type Parameters = (); fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy { (vec(any::(), 64)) .prop_map(|bytes| { let bytes = bytes.try_into().expect("vec is the correct length"); let sk = pallas::Scalar::from_bytes_wide(&bytes); let pk = VerificationKey::from_scalar(&sk); pk.into() }) .boxed() } type Strategy = BoxedStrategy; } impl Arbitrary for Flags { type Parameters = (); fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy { (any::()).prop_map(Self::from_bits_truncate).boxed() } type Strategy = BoxedStrategy; } impl Arbitrary for tree::Root { type Parameters = (); fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy { (vec(any::(), 64)) .prop_map(|bytes| { let bytes = bytes.try_into().expect("vec is the correct length"); Self::try_from(pallas::Base::from_bytes_wide(&bytes).to_repr()) .expect("a valid generated Orchard note commitment tree root") }) .boxed() } type Strategy = BoxedStrategy; } impl Arbitrary for keys::TransmissionKey { type Parameters = (); fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy { (any::()) .prop_map(|spending_key| { let full_viewing_key = keys::FullViewingKey::from(spending_key); let diversifier_key = keys::DiversifierKey::from(full_viewing_key); let diversifier = Diversifier::from(diversifier_key); let incoming_viewing_key = keys::IncomingViewingKey::from(full_viewing_key); Self::from((incoming_viewing_key, diversifier)) }) .boxed() } type Strategy = BoxedStrategy; } impl Arbitrary for Address { type Parameters = (); fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy { (any::(), any::()) .prop_map(|(diversifier, transmission_key)| Self { diversifier, transmission_key, }) .boxed() } type Strategy = BoxedStrategy; }