Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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