Skip to content

Commit 51f0dc4

Browse files
committed
added double_vote test
1 parent f21b55d commit 51f0dc4

File tree

2 files changed

+133
-15
lines changed

2 files changed

+133
-15
lines changed
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
use std::collections::HashMap;
2+
3+
use catalyst_signed_doc::{
4+
DocumentRef,
5+
catalyst_id::{CatalystId, role_index::RoleId},
6+
tests_utils::{create_dummy_key_pair, create_key_pair_and_publish},
7+
};
8+
use catalyst_voting::vote_protocol::committee::ElectionSecretKey;
9+
use proptest::{
10+
prelude::{ProptestConfig, prop::array},
11+
property_test,
12+
};
13+
14+
use crate::tally::{
15+
contest_tally,
16+
provider::tests::TestTallyProvider,
17+
tests::{
18+
PROPOSALS_AMOUNT, VOTING_OPTIONS, Voter, assert_contest_tally_result, expected_tally,
19+
prepare_contest, publish_ballot,
20+
},
21+
};
22+
23+
#[property_test(config = ProptestConfig::with_cases(1))]
24+
fn double_vote_test(
25+
voting_power: u32,
26+
#[strategy = array::uniform(0..VOTING_OPTIONS)] first_choices: [usize; PROPOSALS_AMOUNT],
27+
#[strategy = array::uniform(0..VOTING_OPTIONS)] second_choices: [usize; PROPOSALS_AMOUNT],
28+
anonymous: bool,
29+
options: [String; VOTING_OPTIONS],
30+
) {
31+
let election_secret_key = ElectionSecretKey::random_with_default_rng();
32+
let mut p = TestTallyProvider::default();
33+
34+
let (contest_parameters, proposals_refs) = prepare_contest(
35+
&options,
36+
PROPOSALS_AMOUNT,
37+
&election_secret_key.public_key(),
38+
&mut p.p,
39+
)
40+
.unwrap();
41+
assert_eq!(proposals_refs.len(), PROPOSALS_AMOUNT);
42+
43+
let (sk, kid) = create_key_pair_and_publish(&mut p.p, || create_dummy_key_pair(RoleId::Role0));
44+
let voter = Voter {
45+
voting_power,
46+
anonymous,
47+
choices: first_choices,
48+
};
49+
let sk = sk.into();
50+
publish_ballot(
51+
(&voter, kid.clone(), &sk),
52+
&contest_parameters,
53+
&proposals_refs,
54+
&mut p,
55+
)
56+
.unwrap();
57+
// double vote, which must superceed the previous one
58+
std::thread::sleep(std::time::Duration::from_secs(1));
59+
let voter = Voter {
60+
voting_power,
61+
anonymous,
62+
choices: second_choices,
63+
};
64+
let ballot = publish_ballot(
65+
(&voter, kid.clone(), &sk),
66+
&contest_parameters,
67+
&proposals_refs,
68+
&mut p,
69+
)
70+
.unwrap();
71+
72+
let exp_tally = expected_tally(&contest_parameters, &proposals_refs, &[voter]);
73+
let exp_participants: HashMap<CatalystId, (u64, DocumentRef)> =
74+
[(kid, (voting_power.into(), ballot.doc_ref().unwrap()))]
75+
.into_iter()
76+
.collect();
77+
78+
let res_tally = contest_tally(&contest_parameters, Some(&election_secret_key), &p).unwrap();
79+
assert_contest_tally_result(
80+
&election_secret_key.public_key(),
81+
res_tally,
82+
&contest_parameters,
83+
exp_tally,
84+
exp_participants,
85+
);
86+
}

rust/catalyst-contest/src/tally/tests.rs renamed to rust/catalyst-contest/src/tally/tests/mod.rs

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
mod double_vote;
2+
13
use std::collections::HashMap;
24

35
use catalyst_signed_doc::{
4-
CatalystSignedDocument, DocumentRef, builder,
6+
CatalystSignedDocument, DocumentRef,
7+
builder::{self, ed25519::Ed25519SigningKey},
58
catalyst_id::{CatalystId, role_index::RoleId},
69
providers::tests::TestCatalystProvider,
710
tests_utils::{
@@ -27,7 +30,7 @@ use crate::{
2730
payload::{Choices, ContestBallotPayload},
2831
},
2932
contest_parameters::ContestParameters,
30-
tally::{contest_tally, provider::tests::TestTallyProvider},
33+
tally::{ContestResult, contest_tally, provider::tests::TestTallyProvider},
3134
};
3235

3336
const VOTING_OPTIONS: usize = 3;
@@ -43,6 +46,11 @@ struct Voter {
4346
anonymous: bool,
4447
}
4548

49+
type EncryptedTotalResult = u64;
50+
type ClearTotalResult = u64;
51+
type Participants = HashMap<CatalystId, (u64, DocumentRef)>;
52+
type TallyRes = HashMap<DocumentRef, Vec<(ClearTotalResult, EncryptedTotalResult, String)>>;
53+
4654
#[property_test(config = ProptestConfig::with_cases(1))]
4755
fn tally_test(
4856
voters: [Voter; VOTERS_NUMBER],
@@ -62,10 +70,11 @@ fn tally_test(
6270

6371
let exp_tally = expected_tally(&contest_parameters, &proposals_refs, &voters);
6472

65-
let exp_participant: HashMap<CatalystId, (u64, DocumentRef)> = voters
73+
let exp_participants: Participants = voters
6674
.iter()
6775
.map(|v| {
68-
let ballot = publish_ballot(v, &contest_parameters, &proposals_refs, &mut p).unwrap();
76+
let ballot =
77+
publish_ballot_with_keys(v, &contest_parameters, &proposals_refs, &mut p).unwrap();
6978
let voter = ballot.authors().first().unwrap().clone();
7079
let ballot_ref = ballot.doc_ref().unwrap();
7180

@@ -74,8 +83,24 @@ fn tally_test(
7483
.collect();
7584

7685
let res_tally = contest_tally(&contest_parameters, Some(&election_secret_key), &p).unwrap();
86+
assert_contest_tally_result(
87+
&election_secret_key.public_key(),
88+
res_tally,
89+
&contest_parameters,
90+
exp_tally,
91+
exp_participants,
92+
);
93+
}
94+
95+
fn assert_contest_tally_result(
96+
election_public_key: &ElectionPublicKey,
97+
res_tally: ContestResult,
98+
contest_parameters: &ContestParameters,
99+
exp_tally: TallyRes,
100+
exp_participants: Participants,
101+
) {
77102
assert_eq!(&res_tally.options, contest_parameters.options());
78-
assert_eq!(&res_tally.participants, &exp_participant);
103+
assert_eq!(&res_tally.participants, &exp_participants);
79104

80105
for (p_ref, exp_tally_per_proposal) in exp_tally {
81106
let res_tally_per_proposal = res_tally
@@ -100,7 +125,7 @@ fn tally_test(
100125
assert!(verify_tally_proof(
101126
&res_tally_per_proposal[i].encrypted_tally,
102127
decrypted_tally.tally,
103-
&election_secret_key.public_key(),
128+
&election_public_key,
104129
&decrypted_tally.proof
105130
));
106131
}
@@ -141,22 +166,32 @@ fn prepare_contest(
141166
Ok((ContestParameters::new(&parameters, p)?, proposals_refs))
142167
}
143168

144-
fn publish_ballot(
169+
fn publish_ballot_with_keys(
145170
voter: &Voter,
146171
parameters: &ContestParameters,
147172
proposals_refs: &[DocumentRef],
148173
p: &mut TestTallyProvider,
149174
) -> anyhow::Result<CatalystSignedDocument> {
150175
let (sk, kid) = create_key_pair_and_publish(&mut p.p, || create_dummy_key_pair(RoleId::Role0));
176+
publish_ballot((voter, kid, &sk.into()), parameters, proposals_refs, p)
177+
}
151178

179+
fn publish_ballot(
180+
voter: (&Voter, CatalystId, &Ed25519SigningKey),
181+
parameters: &ContestParameters,
182+
proposals_refs: &[DocumentRef],
183+
p: &mut TestTallyProvider,
184+
) -> anyhow::Result<CatalystSignedDocument> {
152185
// Filling the `TestTallyProvider` with the voter's voting power information
153-
p.voters.insert(kid.clone(), voter.voting_power.into());
186+
p.voters
187+
.insert(voter.1.clone(), voter.0.voting_power.into());
154188

155189
let choices = voter
190+
.0
156191
.choices
157192
.iter()
158193
.map(|choice| {
159-
if voter.anonymous {
194+
if voter.0.anonymous {
160195
let commitment = commitment_key(parameters.doc_ref())?;
161196
Choices::new_encrypted_single(
162197
*choice,
@@ -176,21 +211,18 @@ fn publish_ballot(
176211
proposals_refs,
177212
parameters.doc_ref(),
178213
&payload,
179-
&sk.into(),
180-
kid,
214+
voter.2,
215+
voter.1,
181216
None,
182217
)
183218
})
184219
}
185220

186-
type EncryptedTotalResult = u64;
187-
type ClearTotalResult = u64;
188-
189221
fn expected_tally(
190222
contest_parameters: &ContestParameters,
191223
proposals_refs: &[DocumentRef],
192224
voters: &[Voter],
193-
) -> HashMap<DocumentRef, Vec<(ClearTotalResult, EncryptedTotalResult, String)>> {
225+
) -> TallyRes {
194226
let options = contest_parameters.options().clone();
195227

196228
proposals_refs

0 commit comments

Comments
 (0)