1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
mod prover;
mod verifier;

pub use prover::ProverTranscript;
pub use verifier::VerifierTranscriptOnline;
pub use verifier::VerifierTranscriptPreprocess;

use crate::algebra::Domain;
use crate::crypto::hash::{Hash, Hasher};
use crate::crypto::prg::{Key, KEY_SIZE, PRG};
use crate::generator::ShareGen;
use crate::interpreter::Wire;
use crate::{PACKED, PLAYERS};

pub trait Transcript<D: Domain> {
    const IS_PROVER: bool = false;

    // Different instances:
    //
    // - Proving   : input is the next input value
    // - Verifying : input is unused bogus value a
    fn input(&mut self) -> Wire<D>;

    /// Reconstructs the share:
    ///
    /// # Proving
    ///
    /// The transcript records the mask (each share send by each party)
    ///
    /// # Verifying (Online)
    ///
    /// The transcript adds the missing share for the unopened players
    ///
    /// # Verifying (Preprocessing)
    ///
    /// Nop, just return zero.
    fn reconstruct(&mut self, mask: D::Share) -> D::Recon;

    /// Record correction:
    ///
    /// # Proving
    ///
    /// The transcript records the correction
    ///
    /// # Verifying (Online)
    ///
    /// The transcript provides the next correction (ignoring the input)
    ///
    /// # Verifying (Preprocessing)
    ///
    /// The transcript records the correction
    fn correction(&mut self, corr: D::Recon) -> D::Recon;

    /// Record if the reconstructed value is zero
    ///
    /// # Proving
    ///
    /// Check if zero: if not the witness was invalid and the prover aborts
    ///
    /// # Verifying (Online)
    ///
    /// Check if zero: if zero the proof is invalid.
    ///
    /// # Verifying (Preprocessing)
    ///
    /// Nop. Ignore the input.
    fn zero_check(&mut self, recon: D::Recon);

    fn new_mask(&mut self) -> D::Share;

    /// Return the commitment to the online phase
    fn online_hash(&self) -> [Hash; PACKED];

    /// Return the commitment to the preprocessing phase
    fn preprocess_hash(&self) -> [Hash; PACKED];

    fn hash(&self) -> [Hash; PACKED] {
        fn hash_join(preprocess: &Hash, online: &Hash) -> Hash {
            let mut hasher = Hasher::new();
            hasher.update(preprocess.as_bytes());
            hasher.update(online.as_bytes());
            hasher.finalize()
        }
        let online_hashes = self.online_hash();
        let preprocess_hashes = self.preprocess_hash();
        [
            hash_join(&preprocess_hashes[0], &online_hashes[0]),
            hash_join(&preprocess_hashes[1], &online_hashes[1]),
            hash_join(&preprocess_hashes[2], &online_hashes[2]),
            hash_join(&preprocess_hashes[3], &online_hashes[3]),
            hash_join(&preprocess_hashes[4], &online_hashes[4]),
            hash_join(&preprocess_hashes[5], &online_hashes[5]),
            hash_join(&preprocess_hashes[6], &online_hashes[6]),
            hash_join(&preprocess_hashes[7], &online_hashes[7]),
        ]
    }
}

fn expand_seed(seed: Key) -> [Key; PLAYERS] {
    let mut prg = PRG::new(&seed);
    let mut keys = [[0u8; KEY_SIZE]; PLAYERS];
    for key in keys.iter_mut() {
        prg.gen(key);
    }
    keys
}

fn share_gen_from_rep_seeds<D: Domain>(seeds: &[Key; PACKED]) -> Box<ShareGen<D>> {
    Box::new(ShareGen::new(
        &[
            expand_seed(seeds[0]),
            expand_seed(seeds[1]),
            expand_seed(seeds[2]),
            expand_seed(seeds[3]),
            expand_seed(seeds[4]),
            expand_seed(seeds[5]),
            expand_seed(seeds[6]),
            expand_seed(seeds[7]),
        ],
        [PLAYERS; PACKED],
    ))
}