Skip to content

Commit

Permalink
feat(rust): Move proptest to dev-dependencies, cleanup prop tests (
Browse files Browse the repository at this point in the history
…#82)

* add vote-tx-v2 crate

* rename jormungandr-vote-tx to vote-tx-v1

* add Vote CBOR encoding/decoding

* wip

* wip

* wip

* wip

* add proptest for Vote type

* replace ciborium usage with minicbor

* add new TxBody struct, cleanup gen_vote_tx.cddl

* add TxBody CBOR decoding/encoding impl

* add Cbor trait

* add GeneralisedTx struct

* wip

* wip

* fix spelling

* fix doctest

* add array lenth validation

* cleanup vote-tx-v1 tests

* cleanup catalyst-voting crate

* wip

* refactor decoding test for v1 Tx

* cleanup vote-tx-v2

* fix
  • Loading branch information
Mr-Leshiy authored Nov 13, 2024
1 parent 9142501 commit 575a153
Show file tree
Hide file tree
Showing 15 changed files with 158 additions and 158 deletions.
2 changes: 1 addition & 1 deletion rust/catalyst-voting/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ curve25519-dalek = { version = "4.1.3", features = ["digest", "rand_core"] }
ed25519-dalek = { version = "2.1.1", features = ["rand_core"] }
blake2b_simd = "1.0.2"
rayon = "1.10.0"
proptest = { version = "1.5.0" }

[dev-dependencies]
criterion = "0.5.1"
proptest = { version = "1.5.0" }
# Potentially it could be replaced with using `proptest::property_test` attribute macro,
# after this PR will be merged https://github.com/proptest-rs/proptest/pull/523
test-strategy = "0.4.0"
8 changes: 7 additions & 1 deletion rust/catalyst-voting/src/crypto/ed25519/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use ed25519_dalek::{
ed25519::signature::Signer, Signature as Ed25519Signature, SigningKey, VerifyingKey,
};

use super::rng::default_rng;
use crate::crypto::rng::rand_core::CryptoRngCore;

/// `Ed25519` private key struct.
Expand All @@ -19,6 +20,11 @@ impl PrivateKey {
Self(SigningKey::generate(rng))
}

/// Randomly generate the `ElectionSecretKey` with the `crypto::default_rng`.
pub fn random_with_default_rng() -> Self {
Self::random(&mut default_rng())
}

/// Get associated `Ed25519` public key.
pub fn public_key(&self) -> PublicKey {
PublicKey(self.0.verifying_key())
Expand Down Expand Up @@ -46,7 +52,7 @@ pub fn verify_signature(pk: &PublicKey, msg: &[u8], sig: &Signature) -> bool {
pk.0.verify_strict(msg, &sig.0).is_ok()
}

#[allow(missing_docs, clippy::missing_docs_in_private_items)]
#[cfg(test)]
mod arbitrary_impl {
use proptest::prelude::{any, Arbitrary, BoxedStrategy, Strategy};

Expand Down
2 changes: 1 addition & 1 deletion rust/catalyst-voting/src/crypto/elgamal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ impl Add<&Ciphertext> for &Ciphertext {
}
}

#[allow(missing_docs, clippy::missing_docs_in_private_items)]
#[cfg(test)]
mod arbitrary_impl {
use proptest::{
arbitrary::any,
Expand Down
2 changes: 1 addition & 1 deletion rust/catalyst-voting/src/crypto/group/ristretto255/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ impl Sub<&GroupElement> for &GroupElement {
}
}

#[allow(missing_docs, clippy::missing_docs_in_private_items)]
#[cfg(test)]
mod arbitrary_impl {
use proptest::{
arbitrary::any,
Expand Down
2 changes: 1 addition & 1 deletion rust/catalyst-voting/src/crypto/zk_unit_vector/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ fn check_2(
&right_1 + &right_2 == left
}

#[allow(missing_docs, clippy::missing_docs_in_private_items)]
#[cfg(test)]
mod arbitrary_impl {
use proptest::{
prelude::{any_with, Arbitrary, BoxedStrategy, Strategy},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ impl ResponseRandomness {
}
}

#[allow(missing_docs, clippy::missing_docs_in_private_items)]
#[cfg(test)]
mod arbitrary_impl {
use proptest::{
arbitrary::any,
Expand Down
2 changes: 1 addition & 1 deletion rust/catalyst-voting/src/vote_protocol/committee/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ impl ElectionSecretKey {
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ElectionPublicKey(pub(crate) GroupElement);

#[allow(missing_docs, clippy::missing_docs_in_private_items)]
#[cfg(test)]
mod arbitrary_impl {
use proptest::prelude::{any, Arbitrary, BoxedStrategy, Strategy};

Expand Down
2 changes: 1 addition & 1 deletion rust/catalyst-voting/src/vote_protocol/voter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ pub fn decrypt_vote(vote: &EncryptedVote, secret_key: &ElectionSecretKey) -> any
bail!("Invalid encrypted vote, not a valid unit vector.")
}

#[allow(missing_docs, clippy::missing_docs_in_private_items)]
#[cfg(test)]
mod arbitrary_impl {
use proptest::{
prelude::{any_with, Arbitrary, BoxedStrategy, Strategy},
Expand Down
2 changes: 1 addition & 1 deletion rust/catalyst-voting/src/vote_protocol/voter/proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ pub fn verify_voter_proof(
verify_unit_vector_proof(&proof.0, encrypted_vote.0, &public_key.0, &commitment.0)
}

#[allow(missing_docs, clippy::missing_docs_in_private_items)]
#[cfg(test)]
mod arbitrary_impl {
use proptest::prelude::{any_with, Arbitrary, BoxedStrategy, Strategy};

Expand Down
2 changes: 1 addition & 1 deletion rust/vote-tx-v1/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ workspace = true
[dependencies]
catalyst-voting = { version = "0.0.1", path = "../catalyst-voting" }
anyhow = "1.0.89"
proptest = { version = "1.5.0" }

[dev-dependencies]
proptest = { version = "1.5.0" }
# Potentially it could be replaced with using `proptest::property_test` attribute macro,
# after this PR will be merged https://github.com/proptest-rs/proptest/pull/523
test-strategy = "0.4.0"
119 changes: 103 additions & 16 deletions rust/vote-tx-v1/src/decoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,12 +216,31 @@ impl Tx {

#[cfg(test)]
mod tests {
use catalyst_voting::{
crypto::{ed25519::PrivateKey, rng::rand_core::OsRng},
vote_protocol::committee::ElectionSecretKey,
};
use test_strategy::proptest;

use super::*;

#[proptest]
fn tx_to_bytes_from_bytes_test(t1: Tx) {
fn tx_public_to_bytes_from_bytes_test(
vote_plan_id: [u8; 32], proposal_index: u8, #[strategy(1u8..5)] voting_options: u8,
#[strategy(0..#voting_options)] choice: u8,
) {
let mut rng = OsRng;
let users_private_key = PrivateKey::random(&mut rng);

let t1 = Tx::new_public(
vote_plan_id,
proposal_index,
voting_options,
choice,
&users_private_key,
)
.unwrap();

let bytes = t1.to_bytes();

let mut reader = bytes.as_slice();
Expand All @@ -242,21 +261,89 @@ mod tests {
assert_eq!(proposal_index, t1.proposal_index);

let vote_tag = read_be_u8(&mut reader).unwrap();
assert!(vote_tag == PUBLIC_VOTE_TAG || vote_tag == PRIVATE_VOTE_TAG);
match vote_tag {
PUBLIC_VOTE_TAG => {
let vote = read_be_u8(&mut reader).unwrap();
assert_eq!(VotePayload::Public(vote), t1.vote);
},
PRIVATE_VOTE_TAG => {
let size = read_be_u8(&mut reader).unwrap();
let vote = EncryptedVote::from_bytes(&mut reader, size.into()).unwrap();
let size = read_be_u8(&mut reader).unwrap();
let proof = VoterProof::from_bytes(&mut reader, size.into()).unwrap();
assert_eq!(VotePayload::Private(vote, proof), t1.vote);
},
_ => {},
}
assert!(vote_tag == PUBLIC_VOTE_TAG);

let vote = read_be_u8(&mut reader).unwrap();
assert_eq!(VotePayload::Public(vote), t1.vote);

let block_date = read_be_u64(&mut reader).unwrap();
assert_eq!(block_date, 0);

let inputs_amount = read_be_u8(&mut reader).unwrap();
assert_eq!(inputs_amount, NUMBER_OF_INPUTS);

let outputs_amount = read_be_u8(&mut reader).unwrap();
assert_eq!(outputs_amount, NUMBER_OF_OUTPUTS);

let input_tag = read_be_u8(&mut reader).unwrap();
assert_eq!(input_tag, INPUT_TAG);

let value = read_be_u64(&mut reader).unwrap();
assert_eq!(value, 0);

let public_key = read_array(&mut reader).unwrap();
assert_eq!(PublicKey::from_bytes(&public_key).unwrap(), t1.public_key);

let witness_tag = read_be_u8(&mut reader).unwrap();
assert_eq!(witness_tag, WITNESS_TAG);

let nonce = read_be_u32(&mut reader).unwrap();
assert_eq!(nonce, 0);

let signature = read_array(&mut reader).unwrap();
assert_eq!(Signature::from_bytes(&signature), t1.signature);

let t2 = Tx::from_bytes(&mut bytes.as_slice()).unwrap();
assert_eq!(t1, t2);
}

#[proptest]
fn tx_private_to_bytes_from_bytes_test(
vote_plan_id: [u8; 32], proposal_index: u8, #[strategy(1u8..5)] voting_options: u8,
#[strategy(0..#voting_options)] choice: u8,
) {
let mut rng = OsRng;
let users_private_key = PrivateKey::random(&mut rng);
let election_secret_key = ElectionSecretKey::random(&mut rng);
let election_public_key = election_secret_key.public_key();

let t1 = Tx::new_private(
vote_plan_id,
proposal_index,
voting_options,
choice,
&election_public_key,
&users_private_key,
&mut rng,
)
.unwrap();

let bytes = t1.to_bytes();

let mut reader = bytes.as_slice();

let size = read_be_u32(&mut reader).unwrap();
assert_eq!(size as usize, bytes.len() - 4);

let padding_tag = read_be_u8(&mut reader).unwrap();
assert_eq!(padding_tag, PADDING_TAG);

let fragment_tag = read_be_u8(&mut reader).unwrap();
assert_eq!(fragment_tag, FRAGMENT_TAG);

let vote_plan_id = read_array(&mut reader).unwrap();
assert_eq!(vote_plan_id, t1.vote_plan_id);

let proposal_index = read_be_u8(&mut reader).unwrap();
assert_eq!(proposal_index, t1.proposal_index);

let vote_tag = read_be_u8(&mut reader).unwrap();
assert!(vote_tag == PRIVATE_VOTE_TAG);
let size = read_be_u8(&mut reader).unwrap();
let vote = EncryptedVote::from_bytes(&mut reader, size.into()).unwrap();
let size = read_be_u8(&mut reader).unwrap();
let proof = VoterProof::from_bytes(&mut reader, size.into()).unwrap();
assert_eq!(VotePayload::Private(vote, proof), t1.vote);

let block_date = read_be_u64(&mut reader).unwrap();
assert_eq!(block_date, 0);
Expand Down
62 changes: 3 additions & 59 deletions rust/vote-tx-v1/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,63 +295,6 @@ impl VotePayload {
}
}

#[allow(missing_docs, clippy::missing_docs_in_private_items)]
mod arbitrary_impl {
use catalyst_voting::crypto::ed25519::PrivateKey;
use proptest::prelude::{any, any_with, Arbitrary, BoxedStrategy, Strategy};

use super::{EncryptedVote, Signature, Tx, VotePayload, VoterProof};

impl Arbitrary for Tx {
type Parameters = ();
type Strategy = BoxedStrategy<Self>;

fn arbitrary_with((): Self::Parameters) -> Self::Strategy {
any::<(
[u8; 32],
u8,
VotePayload,
PrivateKey,
[u8; Signature::BYTES_SIZE],
)>()
.prop_map(
|(vote_plan_id, proposal_index, vote, sk, signature_bytes)| {
Tx {
vote_plan_id,
proposal_index,
vote,
public_key: sk.public_key(),
signature: Signature::from_bytes(&signature_bytes),
}
},
)
.boxed()
}
}

impl Arbitrary for VotePayload {
type Parameters = ();
type Strategy = BoxedStrategy<Self>;

fn arbitrary_with((): Self::Parameters) -> Self::Strategy {
any::<bool>()
.prop_flat_map(|b| {
if b {
any::<u8>().prop_map(VotePayload::Public).boxed()
} else {
any::<(u8, u8)>()
.prop_flat_map(|(s1, s2)| {
any_with::<(EncryptedVote, VoterProof)>((s1.into(), s2.into()))
.prop_map(|(v, p)| VotePayload::Private(v, p))
})
.boxed()
}
})
.boxed()
}
}
}

#[cfg(test)]
mod tests {
use catalyst_voting::{
Expand All @@ -364,9 +307,10 @@ mod tests {
#[proptest]
fn tx_test(
vote_plan_id: [u8; 32], proposal_index: u8, #[strategy(1u8..5)] voting_options: u8,
#[strategy(0..#voting_options)] choice: u8, users_private_key: PrivateKey,
election_secret_key: ElectionSecretKey,
#[strategy(0..#voting_options)] choice: u8,
) {
let users_private_key = PrivateKey::random_with_default_rng();
let election_secret_key = ElectionSecretKey::random_with_default_rng();
let election_public_key = election_secret_key.public_key();

let tx = Tx::new_public(
Expand Down
2 changes: 1 addition & 1 deletion rust/vote-tx-v2/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ workspace = true

[dependencies]
anyhow = "1.0.89"
proptest = { version = "1.5.0" }
minicbor = { version = "0.25.1", features = ["alloc"] }

[dev-dependencies]
proptest = { version = "1.5.0" }
# Potentially it could be replaced with using `proptest::property_test` attribute macro,
# after this PR will be merged https://github.com/proptest-rs/proptest/pull/523
test-strategy = "0.4.0"
Loading

0 comments on commit 575a153

Please sign in to comment.