//! Randomised data generation for Orchard types. use std::marker::PhantomData; 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, AuthorizedAction, Flags, NoteCommitment, ValueCommitment, }; 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: 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: r_bytes.into(), s_bytes: s_bytes.into(), _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; }