Commit 06d4ba57 authored by Stephane Glondu's avatar Stephane Glondu

Add ELECTION.process_ballots

parent 195f31a3
Pipeline #67650 passed with stages
in 16 minutes and 58 seconds
......@@ -189,6 +189,14 @@ module Shape = struct
| SAtomic of 'a
| SArray of 'a t array
let to_array = function
| SAtomic _ -> invalid_arg "Shape.to_array"
| SArray xs ->
Array.map (function
| SAtomic x -> x
| SArray _ -> invalid_arg "Shape.to_array"
) xs
let of_array_array x =
SArray (
Array.map (fun x ->
......
......@@ -65,6 +65,7 @@ module Shape : sig
type 'a t =
| SAtomic of 'a
| SArray of 'a t array
val to_array : 'a t -> 'a array
val of_array_array : 'a array array -> 'a t
val to_array_array : 'a t -> 'a array array
val map : ('a -> 'b) -> 'a t -> 'b t
......
......@@ -68,7 +68,6 @@ module Make (W : ELECTION_DATA) (M : RANDOM) = struct
let ( / ) x y = x *~ invert y
type ciphertext = elt Serializable_t.ciphertext array array
let dummy_ciphertext =
{
......@@ -83,15 +82,6 @@ module Make (W : ELECTION_DATA) (M : RANDOM) = struct
beta = c1.beta *~ c2.beta;
}
let neutral_ciphertext () =
Array.map Question.neutral_shape election.e_params.e_questions
|> Array.map (Option.map (Array.map (fun () -> dummy_ciphertext)))
|> Array.to_list
|> List.filter_map (fun x -> x)
|> Array.of_list
let combine_ciphertexts = Array.mmap2 eg_combine
type plaintext = int array array
type ballot = elt Serializable_t.ballot
......@@ -126,7 +116,7 @@ module Make (W : ELECTION_DATA) (M : RANDOM) = struct
List.flatten (
List.map (fun {alpha; beta} ->
[alpha; beta]
) (Array.to_list (Q.extract_ciphertexts a))
) (Array.to_list (Shape.to_array (Q.extract_ciphertexts a)))
)
) (Array.to_list answers)
) |> Array.of_list
......@@ -182,8 +172,20 @@ module Make (W : ELECTION_DATA) (M : RANDOM) = struct
in ok &&
Array.forall2 (verify_answer p.e_public_key zkp) p.e_questions b.answers
let extract_ciphertext b =
Array.map Q.extract_ciphertexts b.answers
let process_ballots bs =
let bs = Array.map (fun b -> Array.map Q.extract_ciphertexts b.answers) bs in
SArray (
Array.mapi (fun i q ->
match Question.neutral_shape q with
| Some s ->
let s = Shape.map (fun _ -> dummy_ciphertext) s in
Array.fold_left (fun accu b ->
Shape.map2 eg_combine accu b.(i)
) s bs
| None ->
SArray (Array.map (fun b -> b.(i)) bs)
) election.e_params.e_questions
)
type factor = elt partial_decryption
......
......@@ -30,7 +30,7 @@ let read_question l b = Standard (Question_std_j.read_question l b)
let write_question b (Standard q) = Question_std_j.write_question b q
let neutral_shape = function
| Standard q -> Some (Array.make (Question_std.question_length q) ())
| Standard q -> Some (SArray (Array.make (Question_std.question_length q) (SAtomic ())))
let erase_question = function
| Standard q ->
......@@ -50,7 +50,7 @@ module type S = sig
val create_answer : question -> public_key:elt -> prefix:string -> int array -> Yojson.Safe.json m
val verify_answer : question -> public_key:elt -> prefix:string -> Yojson.Safe.json -> bool
val extract_ciphertexts : Yojson.Safe.json -> elt ciphertext array
val extract_ciphertexts : Yojson.Safe.json -> elt ciphertext shape
val compute_result : num_tallied:int -> question -> elt shape -> int shape
val check_result : question -> elt shape -> int shape -> bool
......
......@@ -29,7 +29,7 @@ type question =
val read_question : Yojson.Safe.lexer_state -> Lexing.lexbuf -> question
val write_question : Bi_outbuf.t -> question -> unit
val neutral_shape : question -> unit array option
val neutral_shape : question -> unit shape option
val erase_question : question -> question
module type S = sig
......@@ -39,7 +39,7 @@ module type S = sig
val create_answer : question -> public_key:elt -> prefix:string -> int array -> Yojson.Safe.json m
val verify_answer : question -> public_key:elt -> prefix:string -> Yojson.Safe.json -> bool
val extract_ciphertexts : Yojson.Safe.json -> elt ciphertext array
val extract_ciphertexts : Yojson.Safe.json -> elt ciphertext shape
val compute_result : num_tallied:int -> question -> elt shape -> int shape
val check_result : question -> elt shape -> int shape -> bool
......
......@@ -42,7 +42,7 @@ module type S = sig
val create_answer : question -> public_key:elt -> prefix:string -> int array -> elt answer m
val verify_answer : question -> public_key:elt -> prefix:string -> elt answer -> bool
val extract_ciphertexts : elt answer -> elt ciphertext array
val extract_ciphertexts : elt answer -> elt ciphertext shape
val compute_result : num_tallied:int -> question -> elt shape -> int shape
val check_result : question -> elt shape -> int shape -> bool
......@@ -421,7 +421,8 @@ module Make (M : RANDOM) (G : GROUP) = struct
eg_disj_verify y d zkp a.overall_proof sumc
| _, _ -> false
let extract_ciphertexts a = a.choices
let extract_ciphertexts a =
SArray (Array.map (fun x -> SAtomic x) a.choices)
let compute_result ~num_tallied =
let log =
......
......@@ -32,7 +32,7 @@ module type S = sig
val create_answer : question -> public_key:elt -> prefix:string -> int array -> elt answer m
val verify_answer : question -> public_key:elt -> prefix:string -> elt answer -> bool
val extract_ciphertexts : elt answer -> elt ciphertext array
val extract_ciphertexts : elt answer -> elt ciphertext shape
val compute_result : num_tallied:int -> question -> elt shape -> int shape
val check_result : question -> elt shape -> int shape -> bool
......
......@@ -76,18 +76,6 @@ module type ELECTION = sig
type private_key = Z.t
type public_key = elt
(** {2 Ciphertexts} *)
type ciphertext = elt Serializable_t.ciphertext array array
(** A ciphertext that can be homomorphically combined. *)
val neutral_ciphertext : unit -> ciphertext
(** The neutral element for [combine_ciphertext] below. *)
val combine_ciphertexts : ciphertext -> ciphertext -> ciphertext
(** Combine two ciphertexts. The encrypted tally of an election is
the combination of all ciphertexts of valid cast ballots. *)
(** {2 Ballots} *)
type plaintext = Serializable_t.plaintext
......@@ -110,8 +98,9 @@ module type ELECTION = sig
(** [check_ballot b] checks all the cryptographic proofs in [b]. All
ballots produced by [create_ballot] should pass this check. *)
val extract_ciphertext : ballot -> ciphertext
(** Extract the ciphertext from a ballot. *)
(** {2 Tally} *)
val process_ballots : ballot array -> elt Serializable_t.ciphertext shape
(** {2 Partial decryptions} *)
......
......@@ -147,13 +147,9 @@ module Make (P : PARSED_PARAMS) : S = struct
match Lazy.force ballots with
| None -> failwith "ballots.jsons is missing"
| Some ballots ->
let tally =
List.fold_left (fun accu (b, _) ->
E.combine_ciphertexts (E.extract_ciphertext b) accu
) (E.neutral_ciphertext ()) ballots
in
Shape.of_array_array tally,
List.length ballots
let ballots = Array.map fst (Array.of_list ballots) in
E.process_ballots ballots,
Array.length ballots
)
let vote privcred ballot =
......
......@@ -363,14 +363,9 @@ let compute_encrypted_tally uuid =
let module W = (val Election.get_group election) in
let module E = Election.Make (W) (LwtRandom) in
let%lwt ballots = load_ballots uuid in
let num_tallied, tally =
List.fold_left (fun (n, accu) rawballot ->
let ballot = ballot_of_string E.G.read rawballot in
let ciphertext = E.extract_ciphertext ballot in
n + 1, E.combine_ciphertexts accu ciphertext
) (0, E.neutral_ciphertext ()) ballots
in
let tally = Shape.of_array_array tally in
let ballots = Array.map (ballot_of_string E.G.read) (Array.of_list ballots) in
let tally = E.process_ballots ballots in
let num_tallied = Array.length ballots in
let tally = string_of_encrypted_tally E.G.write tally in
let%lwt () = write_file ~uuid (string_of_election_file ESETally) [tally] in
return (Some (num_tallied, sha256_b64 tally, tally))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment