3838
3939mod decoding;
4040
41+ use anyhow:: ensure;
4142use rand_core:: CryptoRngCore ;
4243
4344use crate :: {
4445 crypto:: {
4546 default_rng,
46- ed25519:: { sign, PrivateKey , PublicKey , Signature } ,
47+ ed25519:: { sign, verify_signature , PrivateKey , PublicKey , Signature } ,
4748 hash:: { digest:: Digest , Blake2b256Hasher , Blake2b512Hasher } ,
4849 } ,
4950 vote_protocol:: {
5051 committee:: ElectionPublicKey ,
5152 voter:: {
5253 encrypt_vote_with_default_rng,
53- proof:: { generate_voter_proof, VoterProof , VoterProofCommitment } ,
54+ proof:: { generate_voter_proof, verify_voter_proof , VoterProof , VoterProofCommitment } ,
5455 EncryptedVote , Vote ,
5556 } ,
5657 } ,
@@ -154,22 +155,64 @@ impl Tx {
154155 } )
155156 }
156157
158+ /// Verify transaction signature and underlying proof for public vote
159+ ///
160+ /// # Errors
161+ /// - Invalid signature
162+ /// - Invalid proof
163+ pub fn verify ( & self , election_public_key : & ElectionPublicKey ) -> anyhow:: Result < ( ) > {
164+ let bytes = Self :: bytes_to_sign (
165+ & self . vote_plan_id ,
166+ self . proposal_index ,
167+ & self . vote ,
168+ & self . public_key ,
169+ ) ;
170+ ensure ! (
171+ verify_signature( & self . public_key, & bytes, & self . signature) ,
172+ "Invalid signature."
173+ ) ;
174+
175+ if let VotePayload :: Private ( encrypted_vote, proof) = & self . vote {
176+ let vote_plan_id_hash = Blake2b512Hasher :: new ( ) . chain_update ( self . vote_plan_id ) ;
177+ let commitment = VoterProofCommitment :: from_hash ( vote_plan_id_hash) ;
178+ ensure ! (
179+ verify_voter_proof(
180+ encrypted_vote. clone( ) ,
181+ election_public_key,
182+ & commitment,
183+ proof,
184+ ) ,
185+ "Invalid proof."
186+ ) ;
187+ }
188+
189+ Ok ( ( ) )
190+ }
191+
157192 /// Generate transaction signature
158193 fn sign (
159194 vote_plan_id : & [ u8 ; 32 ] , proposal_index : u8 , vote : & VotePayload , private_key : & PrivateKey ,
160195 ) -> Signature {
161- let mut bytes = Vec :: new ( ) ;
162- Self :: bytes_to_sign (
196+ let bytes = Self :: bytes_to_sign (
163197 vote_plan_id,
164198 proposal_index,
165199 vote,
166200 & private_key. public_key ( ) ,
167- & mut bytes,
168201 ) ;
169- let msg = Blake2b256Hasher :: new ( )
202+ sign ( private_key, & bytes)
203+ }
204+
205+ /// Generate bytes to be signed.
206+ /// A Blake2b256 hash of the transaction body
207+ fn bytes_to_sign (
208+ vote_plan_id : & [ u8 ; 32 ] , proposal_index : u8 , vote : & VotePayload , public_key : & PublicKey ,
209+ ) -> Vec < u8 > {
210+ let mut bytes = Vec :: new ( ) ;
211+ Self :: tx_body_decode ( vote_plan_id, proposal_index, vote, public_key, & mut bytes) ;
212+ Blake2b256Hasher :: new ( )
170213 . chain_update ( bytes. as_slice ( ) )
171- . finalize ( ) ;
172- sign ( private_key , msg . as_slice ( ) )
214+ . finalize ( )
215+ . to_vec ( )
173216 }
174217}
175218
@@ -205,6 +248,27 @@ impl VotePayload {
205248
206249 Ok ( Self :: Private ( encrypted_vote, voter_proof) )
207250 }
251+
252+ // #[allow(clippy::cast_possible_truncation, dead_code)]
253+ // fn choice(&self, secret_key: &ElectionSecretKey) -> anyhow::Result<u8> {
254+ // match self {
255+ // Self::Public(choice) => Ok(*choice),
256+ // Self::Private(vote, _) => {
257+ // // Making a tally and decryption tally procedure on one vote to retrieve
258+ // the // original voting choice.
259+ // // Assuming that the voting power argument must be equals to 1.
260+ // let setup = DecryptionTallySetup::new(1)?;
261+ // for voting_option in 0..vote.voting_options() {
262+ // let tally = tally(voting_option, &[vote.clone()], &[1])?;
263+ // let choice_for_voting_option = decrypt_tally(&tally, secret_key,
264+ // &setup)?; if choice_for_voting_option == 1 {
265+ // return Ok(voting_option as u8);
266+ // }
267+ // }
268+ // bail!("Invalid encrypted vote, not a unit vector");
269+ // },
270+ // }
271+ // }
208272}
209273
210274#[ cfg( test) ]
@@ -216,22 +280,23 @@ mod tests {
216280
217281 #[ proptest]
218282 fn tx_test (
219- vote_plan_id : [ u8 ; 32 ] , proposal_index : u8 , #[ strategy( 1u8 ..) ] voting_options : u8 ,
283+ vote_plan_id : [ u8 ; 32 ] , proposal_index : u8 , #[ strategy( 1u8 ..5 ) ] voting_options : u8 ,
220284 #[ strategy( 0 ..#voting_options) ] choice : u8 , users_private_key : PrivateKey ,
221285 election_secret_key : ElectionSecretKey ,
222286 ) {
223287 let election_public_key = election_secret_key. public_key ( ) ;
224288
225- let _tx = Tx :: new_public (
289+ let tx = Tx :: new_public (
226290 vote_plan_id,
227291 proposal_index,
228292 voting_options,
229293 choice,
230294 & users_private_key,
231295 )
232296 . unwrap ( ) ;
297+ tx. verify ( & election_public_key) . unwrap ( ) ;
233298
234- let _tx = Tx :: new_private_with_default_rng (
299+ let tx = Tx :: new_private_with_default_rng (
235300 vote_plan_id,
236301 proposal_index,
237302 voting_options,
@@ -240,5 +305,6 @@ mod tests {
240305 & users_private_key,
241306 )
242307 . unwrap ( ) ;
308+ tx. verify ( & election_public_key) . unwrap ( ) ;
243309 }
244310}
0 commit comments