1use std::{
2 collections::{BTreeSet, HashMap},
3 sync::Arc,
4};
5
6use race_api::error::{Error, Result};
7use race_api::event::{CustomEvent, Event};
8use race_api::random::{RandomState, RandomStatus};
9use race_api::types::SecretShare;
10
11use race_core::{
12 connection::ConnectionT,
13 context::GameContext,
14 encryptor::EncryptorT,
15 secret::SecretState,
16 types::{
17 AttachGameParams, Ciphertext, ClientMode, DecisionId, RandomId, SecretIdent, SecretKey,
18 SubmitEventParams,
19 },
20};
21
22use race_core::transport::TransportT;
23
24#[derive(PartialEq, Eq, PartialOrd, Ord)]
29pub enum OpIdent {
30 RandomSecret {
31 random_id: RandomId,
32 to_addr: Option<String>,
33 index: usize,
34 },
35 AnswerSecret {
36 decision_id: DecisionId,
37 },
38 Lock {
39 random_id: RandomId,
40 },
41 Mask {
42 random_id: RandomId,
43 },
44}
45
46pub struct Client {
62 pub encryptor: Arc<dyn EncryptorT>,
63 pub transport: Arc<dyn TransportT>,
64 pub connection: Arc<dyn ConnectionT>,
65 pub game_addr: String,
66 pub addr: String,
68 pub mode: ClientMode,
72 pub op_hist: BTreeSet<OpIdent>,
73 pub secret_state: SecretState,
74}
75
76impl Client {
77 pub fn new(
78 addr: String,
79 game_addr: String,
80 mode: ClientMode,
81 transport: Arc<dyn TransportT>,
82 encryptor: Arc<dyn EncryptorT>,
83 connection: Arc<dyn ConnectionT>,
84 ) -> Self {
85 Self {
86 addr,
87 game_addr,
88 mode,
89 op_hist: BTreeSet::new(),
90 secret_state: SecretState::new(encryptor.clone()),
91 transport,
92 encryptor,
93 connection,
94 }
95 }
96
97 pub async fn attach_game(&self) -> Result<()> {
98 let key = self.encryptor.export_public_key(None)?;
99 self.connection
100 .attach_game(
101 &self.game_addr,
102 AttachGameParams {
103 key,
104 signer: self.addr.clone(),
105 },
106 )
107 .await
108 }
109
110 pub async fn submit_event(&self, event: Event) -> Result<()> {
111 self.connection
112 .submit_event(&self.game_addr, SubmitEventParams { event })
113 .await
114 }
115
116 pub async fn submit_custom_event<S: CustomEvent>(&self, custom_event: S) -> Result<()> {
117 let event = Event::custom(&self.game_addr, &custom_event);
118 self.connection
119 .submit_event(&self.addr, SubmitEventParams { event })
120 .await
121 }
122
123 pub fn load_random_states(&mut self, game_context: &GameContext) -> Result<()> {
124 for random_state in game_context.list_random_states().iter() {
125 if !self.secret_state.is_random_loaded(random_state.id) {
126 self.secret_state
127 .gen_random_secrets(random_state.id, random_state.size);
128 }
129 }
130 Ok(())
131 }
132
133 pub fn answer_event(&mut self, decision_id: DecisionId, value: String) -> Result<Event> {
134 let (ciphertext, digest) = self.secret_state.encrypt_answer(decision_id, value)?;
135 Ok(Event::AnswerDecision {
136 sender: self.addr.clone(),
137 decision_id,
138 ciphertext,
139 digest,
140 })
141 }
142
143 pub async fn answer(&mut self, decision_id: DecisionId, value: String) -> Result<()> {
144 let event = self.answer_event(decision_id, value)?;
145 self.connection
146 .submit_event(&self.game_addr, SubmitEventParams { event })
147 .await?;
148 Ok(())
149 }
150
151 pub fn handle_decision(&mut self, game_context: &GameContext) -> Result<Vec<Event>> {
152 let mut shares = Vec::new();
153
154 for state in game_context.list_decision_states() {
155 println!("[CLET] Decision state {:?}", state);
156 if state.get_owner().eq(&self.addr) {
157 let secret = self
158 .secret_state
159 .get_decision_secret(state.id)
160 .ok_or(Error::MissingDecisionSecret(state.id))?;
161 shares.push(SecretShare::new_for_answer(
162 state.id,
163 self.addr.clone(),
164 secret,
165 ));
166 }
167 }
168 if shares.is_empty() {
169 Ok(vec![])
170 } else {
171 Ok(vec![Event::ShareSecrets {
172 sender: self.addr.clone(),
173 shares,
174 }])
175 }
176 }
177
178 pub fn handle_random_waiting(&mut self, random_state: &RandomState) -> Result<Option<Event>> {
179 let required_idents: Vec<SecretIdent> = random_state
180 .list_required_secrets_by_from_addr(&self.addr)
181 .into_iter()
182 .filter_map(|idt| {
183 let op_ident = OpIdent::RandomSecret {
184 random_id: idt.random_id,
185 to_addr: idt.to_addr.clone(),
186 index: idt.index,
187 };
188 if self.op_hist.contains(&op_ident) {
189 None
190 } else {
191 Some(idt)
192 }
193 })
194 .collect();
195
196 let mut op_hist = Vec::new();
197
198 let shares = required_idents
199 .into_iter()
200 .map(|idt| {
201 let secret = self
202 .secret_state
203 .get_random_lock(idt.random_id, idt.index)?;
204 op_hist.push(OpIdent::RandomSecret {
205 random_id: random_state.id,
206 index: idt.index,
207 to_addr: idt.to_addr.clone(),
208 });
209 Ok(SecretShare::new_for_random(
210 idt.random_id,
211 idt.index,
212 self.addr.clone(),
213 idt.to_addr,
214 secret,
215 ))
216 })
217 .collect::<Result<Vec<SecretShare>>>()?;
218
219 if shares.is_empty() {
220 Ok(None)
221 } else {
222 let event = Event::ShareSecrets {
223 sender: self.addr.clone(),
224 shares,
225 };
226 self.op_hist.extend(op_hist);
227 Ok(Some(event))
228 }
229 }
230
231 pub fn handle_random_masking(&mut self, random_state: &RandomState) -> Result<Option<Event>> {
232 let op_ident = OpIdent::Mask {
233 random_id: random_state.id,
234 };
235
236 if self.op_hist.contains(&op_ident) {
237 return Ok(None);
238 }
239
240 let origin = random_state
241 .ciphertexts
242 .iter()
243 .map(|c| c.ciphertext().to_owned())
244 .collect();
245
246 let mut masked = self
247 .secret_state
248 .mask(random_state.id, origin)
249 .map_err(|e| Error::RandomizationError(e.to_string()))?;
250
251 self.encryptor.shuffle(&mut masked);
252
253 let event = Event::Mask {
254 sender: self.addr.clone(),
255 random_id: random_state.id,
256 ciphertexts: masked,
257 };
258
259 self.op_hist.insert(op_ident);
260
261 Ok(Some(event))
262 }
263
264 pub fn handle_random_locking(&mut self, random_state: &RandomState) -> Result<Option<Event>> {
265 let op_ident = OpIdent::Lock {
266 random_id: random_state.id,
267 };
268
269 if self.op_hist.contains(&op_ident) {
270 return Ok(None);
271 }
272
273 let origin = random_state
274 .ciphertexts
275 .iter()
276 .map(|c| c.ciphertext().to_owned())
277 .collect();
278
279 let unmasked = self
280 .secret_state
281 .unmask(random_state.id, origin)
282 .map_err(|e| Error::RandomizationError(e.to_string()))?;
283
284 let locked = self
285 .secret_state
286 .lock(random_state.id, unmasked)
287 .map_err(|e| Error::RandomizationError(e.to_string()))?;
288
289 let event = Event::Lock {
290 sender: self.addr.clone(),
291 random_id: random_state.id,
292 ciphertexts_and_digests: locked,
293 };
294
295 self.op_hist.insert(op_ident);
296
297 Ok(Some(event))
298 }
299
300 pub fn handle_randomization(&mut self, game_context: &GameContext) -> Result<Vec<Event>> {
301 let mut events = vec![];
302 for random_state in game_context.list_random_states().iter() {
303 match random_state.status {
304 RandomStatus::Ready => (),
305 RandomStatus::Shared => (),
306 RandomStatus::WaitingSecrets => {
307 if let Some(event) = self.handle_random_waiting(random_state)? {
308 events.push(event);
309 }
310 }
311 RandomStatus::Locking(ref addr) => {
312 if self.addr.eq(addr) {
313 if let Some(event) = self.handle_random_locking(random_state)? {
314 events.push(event);
315 }
316 }
317 }
318 RandomStatus::Masking(ref addr) => {
319 if self.addr.eq(addr) {
320 if let Some(event) = self.handle_random_masking(random_state)? {
321 events.push(event);
322 }
323 }
324 }
325 }
326 }
327
328 Ok(events)
329 }
330
331 pub fn handle_updated_context(&mut self, ctx: &GameContext) -> Result<Vec<Event>> {
332 let events = match self.mode {
333 ClientMode::Player => {
334 self.load_random_states(ctx)?;
335 self.handle_decision(ctx)?
336 }
337 ClientMode::Transactor | ClientMode::Validator => {
338 self.load_random_states(ctx)?;
339 self.handle_randomization(ctx)?
340 }
341 };
342 Ok(events)
343 }
344
345 pub fn flush_secret_states(&mut self) {
346 self.secret_state.clear();
347 self.op_hist.clear();
348 }
349
350 pub fn decrypt(
353 &self,
354 ctx: &GameContext,
355 random_id: RandomId,
356 ) -> Result<HashMap<usize, String>> {
357 let random_state = ctx.get_random_state(random_id)?;
358 let options = &random_state.options;
359
360 let mut revealed = decrypt_with_secrets(
361 &*self.encryptor,
362 random_state.list_revealed_ciphertexts(),
363 random_state.list_revealed_secrets()?,
364 options,
365 )?;
366
367 if self.mode == ClientMode::Player {
368 let assigned = decrypt_with_secrets(
369 &*self.encryptor,
370 random_state.list_assigned_ciphertexts(&self.addr),
371 random_state.list_shared_secrets(&self.addr)?,
372 options,
373 )?;
374 revealed.extend(assigned);
375 }
376
377 Ok(revealed)
378 }
379}
380
381fn decrypt_with_secrets(
382 encryptor: &dyn EncryptorT,
383 ciphertext_map: HashMap<usize, Ciphertext>,
384 mut secret_map: HashMap<usize, Vec<SecretKey>>,
385 options: &[String],
386) -> Result<HashMap<usize, String>> {
387 let mut ret = HashMap::new();
388 for (i, mut buf) in ciphertext_map.into_iter() {
389 if let Some(secrets) = secret_map.remove(&i) {
390 encryptor.apply_multi(secrets, &mut buf);
391 let value = String::from_utf8(buf).or(Err(Error::DecryptionFailed))?;
392 if !options.contains(&value) {
393 return Err(Error::InvalidDecryptedValue(value))?;
394 }
395 ret.insert(i, value);
396 } else {
397 return Err(Error::MissingSecret);
398 }
399 }
400 Ok(ret)
401}