1use std::any::type_name;
2use std::convert::TryFrom;
3use std::mem;
4
5use num_traits::Zero;
6
7use super::*;
8use crate::algebra::{Hashable, Pack, PackSelected};
9use crate::crypto::hash::PackedHasher;
10use crate::generator::ShareGen;
11use crate::proof::{OpenOnline, OpenPreprocessing};
12
13pub struct ProverTranscript<D: Domain, I: Iterator<Item = D::Recon>> {
14 seeds: [[u8; KEY_SIZE]; PACKED],
17
18 witness: I,
20
21 share_gen: Box<ShareGen<D>>,
23
24 hash_online: PackedHasher,
26 hash_preprocess: PackedHasher,
27
28 reconstructions: Vec<D::Share>,
30 corrections: Vec<D::Recon>,
31 inputs: Vec<D::Recon>,
32}
33
34impl<D: Domain, I: Iterator<Item = D::Recon>> ProverTranscript<D, I> {
35 pub fn new(
36 witness: I, seeds: [Key; PACKED], ) -> Self {
39 Self {
40 seeds,
41 share_gen: share_gen_from_rep_seeds(&seeds),
42 witness,
43 hash_online: PackedHasher::new(),
44 hash_preprocess: PackedHasher::new(),
45 reconstructions: vec![],
46 corrections: vec![],
47 inputs: vec![],
48 }
49 }
50
51 pub(crate) fn extract(
58 self, players: [usize; PACKED], ) -> (Vec<OpenOnline>, Vec<OpenPreprocessing>) {
61 let mut dst_recon: [Vec<u8>; PACKED] = [
62 vec![],
63 vec![],
64 vec![],
65 vec![],
66 vec![],
67 vec![],
68 vec![],
69 vec![],
70 ];
71
72 let mut dst_corr: [Vec<u8>; PACKED] = [
73 vec![],
74 vec![],
75 vec![],
76 vec![],
77 vec![],
78 vec![],
79 vec![],
80 vec![],
81 ];
82
83 let mut dst_input: [Vec<u8>; PACKED] = [
84 vec![],
85 vec![],
86 vec![],
87 vec![],
88 vec![],
89 vec![],
90 vec![],
91 vec![],
92 ];
93
94 let selected: Vec<bool> = players.iter().copied().map(|i| i < PLAYERS).collect();
95
96 D::Share::pack_selected(&mut dst_recon, &self.reconstructions[..], players);
98
99 D::Recon::pack(
101 &mut dst_corr,
102 &self.corrections[..],
103 <&[bool; PACKED]>::try_from(&selected[..]).unwrap(),
104 );
105
106 D::Recon::pack(
108 &mut dst_input,
109 &self.inputs[..],
110 <&[bool; PACKED]>::try_from(&selected[..]).unwrap(),
111 );
112
113 let mut open_preprocessing: Vec<OpenPreprocessing> = vec![];
115 let mut open_online: Vec<OpenOnline> = vec![];
116 for rep in 0..PACKED {
117 let omit = players[rep];
118 debug_assert!(omit <= PLAYERS);
119 if omit < PLAYERS {
120 let corrs = mem::take(&mut dst_corr[rep]);
122 let recons = mem::take(&mut dst_recon[rep]);
123 let inputs = mem::take(&mut dst_input[rep]);
124
125 let mut seeds = expand_seed(self.seeds[rep]);
127 seeds[omit] = [0u8; KEY_SIZE];
128
129 open_online.push(OpenOnline {
131 omit: omit as u8,
132 recons,
133 corrs,
134 inputs,
135 seeds,
136 })
137 } else {
138 debug_assert_eq!(omit, PLAYERS);
139 debug_assert_eq!(
140 dst_corr[rep].len(),
141 0,
142 "rep = {}, players = {:?}, {:?}",
143 rep,
144 &players,
145 &dst_corr
146 );
147
148 debug_assert_eq!(
149 dst_recon[rep].len(),
150 0,
151 "rep = {}, players = {:?}, domain = {}, {:?}",
152 rep,
153 &players,
154 type_name::<D>(),
155 &dst_recon
156 );
157
158 debug_assert_eq!(
159 dst_input[rep].len(),
160 0,
161 "rep = {}, players = {:?}, {:?}",
162 rep,
163 &players,
164 &dst_input
165 );
166
167 open_preprocessing.push(OpenPreprocessing {
168 comm_online: self.hash_online[rep].finalize().into(),
169 seed: self.seeds[rep],
170 })
171 }
172 }
173
174 (open_online, open_preprocessing)
175 }
176}
177
178impl<D: Domain, I: Iterator<Item = D::Recon>> Transcript<D> for ProverTranscript<D, I> {
179 const IS_PROVER: bool = true;
180
181 fn input(&mut self) -> Wire<D> {
182 let mask = self.share_gen.next();
184
185 let lambda = D::reconstruct(&mask);
187
188 let input = self.witness.next().expect("witness is too short");
191 let corr = input - lambda;
192
193 corr.hash(&mut self.hash_online);
195
196 self.inputs.push(corr);
198 Wire { mask, corr }
199 }
200
201 fn online_hash(&self) -> [Hash; PACKED] {
202 self.hash_online.finalize()
203 }
204
205 fn preprocess_hash(&self) -> [Hash; PACKED] {
206 self.hash_preprocess.finalize()
207 }
208
209 fn reconstruct(&mut self, mask: D::Share) -> D::Recon {
210 mask.hash(&mut self.hash_online);
211 self.reconstructions.push(mask);
212 D::reconstruct(&mask)
213 }
214
215 fn correction(&mut self, corr: D::Recon) -> D::Recon {
216 corr.hash(&mut self.hash_preprocess);
217 self.corrections.push(corr);
218 corr
219 }
220
221 fn zero_check(&mut self, recon: D::Recon) {
222 assert!(
224 recon.is_zero(),
225 "witness is invalid!. Wire has value {:?}, expected zero.",
226 recon
227 );
228 }
229
230 fn new_mask(&mut self) -> D::Share {
231 self.share_gen.next()
232 }
233}