Skip to main content

race_core/
context.rs

1use std::collections::HashMap;
2
3use crate::types::GameAccount;
4use borsh::{BorshDeserialize, BorshSerialize};
5use race_api::decision::DecisionState;
6use race_api::effect::{Ask, Assign, Effect, Release, Reveal};
7use race_api::engine::GameHandler;
8use race_api::error::{Error, Result};
9use race_api::event::{CustomEvent, Event};
10use race_api::random::{RandomSpec, RandomState, RandomStatus};
11use race_api::types::{
12    Addr, Ciphertext, DecisionId, GameStatus, PlayerJoin, RandomId, SecretDigest, SecretShare,
13    ServerJoin, Settle, SettleOp, Transfer,
14};
15#[cfg(feature = "serde")]
16use serde::{Deserialize, Serialize};
17
18const OPERATION_TIMEOUT: u64 = 15_000;
19
20#[derive(Debug, BorshSerialize, BorshDeserialize, PartialEq, Eq, Clone)]
21#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
22#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
23pub enum NodeStatus {
24    Pending(u64),
25    Confirming,
26    Ready,
27    Disconnected,
28}
29
30impl std::fmt::Display for NodeStatus {
31    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32        match self {
33            NodeStatus::Pending(access_version) => write!(f, "pending[{}]", access_version),
34            NodeStatus::Confirming => write!(f, "confirming"),
35            NodeStatus::Ready => write!(f, "ready"),
36            NodeStatus::Disconnected => write!(f, "disconnected"),
37        }
38    }
39}
40
41#[derive(Debug, BorshSerialize, BorshDeserialize, PartialEq, Eq, Clone)]
42#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
43#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
44pub struct Player {
45    pub addr: String,
46    pub position: usize,
47    pub status: NodeStatus,
48    pub balance: u64,
49}
50
51impl From<PlayerJoin> for Player {
52    fn from(new_player: PlayerJoin) -> Self {
53        Self {
54            addr: new_player.addr,
55            position: new_player.position as _,
56            status: NodeStatus::Ready,
57            balance: new_player.balance,
58        }
59    }
60}
61
62impl Player {
63    pub fn new_pending(addr: String, balance: u64, position: usize, access_version: u64) -> Self {
64        Self {
65            addr,
66            balance,
67            position,
68            status: NodeStatus::Pending(access_version),
69        }
70    }
71
72    pub fn new<S: Into<String>>(addr: S, balance: u64, position: usize) -> Self {
73        Self {
74            addr: addr.into(),
75            status: NodeStatus::Ready,
76            balance,
77            position,
78        }
79    }
80}
81
82#[derive(Clone, Debug, BorshSerialize, BorshDeserialize)]
83pub struct Server {
84    pub addr: String,
85    pub status: NodeStatus,
86    pub endpoint: String,
87}
88
89impl From<ServerJoin> for Server {
90    fn from(new_server: ServerJoin) -> Self {
91        Self {
92            addr: new_server.addr,
93            status: NodeStatus::Ready,
94            endpoint: new_server.endpoint,
95        }
96    }
97}
98
99impl Server {
100    pub fn new_pending<S: Into<String>>(addr: S, endpoint: String, access_version: u64) -> Self {
101        Server {
102            addr: addr.into(),
103            endpoint,
104            status: NodeStatus::Pending(access_version),
105        }
106    }
107
108    pub fn new<S: Into<String>>(addr: S, endpoint: String) -> Self {
109        Server {
110            addr: addr.into(),
111            endpoint,
112            status: NodeStatus::Ready,
113        }
114    }
115}
116
117#[derive(Clone, Debug, BorshSerialize, BorshDeserialize, PartialEq, Eq)]
118pub struct DispatchEvent {
119    pub timeout: u64,
120    pub event: Event,
121}
122
123impl DispatchEvent {
124    pub fn new(event: Event, timeout: u64) -> Self {
125        Self { timeout, event }
126    }
127}
128
129/// The context for public data.
130///
131/// This information is not transmitted over the network, instead it's
132/// calculated independently at each node.  This struct will neither
133/// be passed into the WASM runtime, instead [`Effect`] will be used.
134///
135/// # Access Version and Settle Version
136///
137/// Version numbers used in synchronization with on-chain data.  Every
138/// time a settlement is made, the `settle_version` will increase by
139/// 1.
140///
141/// # Handler State
142///
143/// The state of game handler will be serialized as JSON string, and stored.
144/// It will be passed into the WASM runtime, and get deseralized inside.
145///
146/// # Player Exiting
147///
148/// Players are not always allowed to leave a game.  When leaving,
149/// the player will be ejected from the game account, and assets will
150/// be paid out.  The property `allow_exit` decides whether leaving is
151/// allowed at the moment.  If it's disabled, leaving event will be
152/// rejected.
153#[derive(Clone, Debug, BorshSerialize, BorshDeserialize)]
154pub struct GameContext {
155    pub(crate) game_addr: Addr,
156    /// Version numbers for player/server access.  This number will be
157    /// increased whenever a new player joins or a server gets attached.
158    pub(crate) access_version: u64,
159    /// Version number for transactor settlement.  This number will be
160    /// increased whenever a transaction is sent.
161    pub(crate) settle_version: u64,
162    /// Current transactor's address
163    pub(crate) transactor_addr: Addr,
164    pub(crate) status: GameStatus,
165    /// List of players playing in this game
166    pub(crate) players: Vec<Player>,
167    /// List of validators serving this game
168    pub(crate) servers: Vec<Server>,
169    pub(crate) dispatch: Option<DispatchEvent>,
170    pub(crate) handler_state: Vec<u8>,
171    pub(crate) timestamp: u64,
172    /// Whether a player can leave or not
173    pub(crate) allow_exit: bool,
174    /// All runtime random states, each stores the ciphers and assignments.
175    pub(crate) random_states: Vec<RandomState>,
176    /// All runtime decision states, each stores the answer.
177    pub(crate) decision_states: Vec<DecisionState>,
178    /// Settles, if is not None, will be handled by event loop.
179    pub(crate) settles: Option<Vec<Settle>>,
180    /// Transfers, if is not None, will be handled by event loop.
181    pub(crate) transfers: Option<Vec<Transfer>>,
182    /// The latest checkpoint state
183    pub(crate) checkpoint: Option<Vec<u8>>,
184}
185
186impl GameContext {
187    pub fn try_new(game_account: &GameAccount) -> Result<Self> {
188        let transactor_addr = game_account
189            .transactor_addr
190            .as_ref()
191            .ok_or(Error::GameNotServed)?;
192
193        let players = game_account
194            .players
195            .iter()
196            .map(|p| {
197                Player::new_pending(p.addr.clone(), p.balance, p.position as _, p.access_version)
198            })
199            .collect();
200
201        let servers = game_account
202            .servers
203            .iter()
204            .map(|s| Server::new_pending(s.addr.clone(), s.endpoint.clone(), s.access_version))
205            .collect();
206
207        Ok(Self {
208            game_addr: game_account.addr.clone(),
209            access_version: game_account.access_version,
210            settle_version: game_account.settle_version,
211            transactor_addr: transactor_addr.to_owned(),
212            status: GameStatus::Uninit,
213            players,
214            servers,
215            dispatch: None,
216            timestamp: 0,
217            allow_exit: false,
218            random_states: vec![],
219            decision_states: vec![],
220            settles: None,
221            transfers: None,
222            handler_state: "".into(),
223            checkpoint: None,
224        })
225    }
226
227    pub fn set_timestamp(&mut self, timestamp: u64) {
228        self.timestamp = timestamp;
229    }
230
231    pub fn is_allow_exit(&self) -> bool {
232        self.allow_exit
233    }
234
235    pub fn get_handler_state_raw(&self) -> &Vec<u8> {
236        &self.handler_state
237    }
238
239    pub fn set_handler_state_raw(&mut self, state: Vec<u8>) {
240        self.handler_state = state;
241    }
242
243    pub fn get_handler_state<H>(&self) -> H
244    where
245        H: GameHandler,
246    {
247        H::try_from_slice(&self.handler_state).unwrap()
248    }
249
250    pub fn get_checkpoint(&self) -> Option<Vec<u8>> {
251        self.checkpoint.clone()
252    }
253
254    pub fn set_handler_state<H>(&mut self, handler: &H)
255    where
256        H: GameHandler,
257    {
258        self.handler_state = handler.try_to_vec().unwrap()
259    }
260
261    pub fn get_servers(&self) -> &Vec<Server> {
262        &self.servers
263    }
264
265    pub fn get_game_addr(&self) -> &str {
266        &self.game_addr
267    }
268
269    pub fn get_transactor_addr(&self) -> &str {
270        &self.transactor_addr
271    }
272
273    pub fn get_player_by_index(&self, index: usize) -> Option<&Player> {
274        self.players.get(index)
275    }
276
277    pub fn get_player_mut_by_index(&mut self, index: usize) -> Option<&mut Player> {
278        self.players.get_mut(index)
279    }
280
281    pub fn get_player_by_address(&self, addr: &str) -> Option<&Player> {
282        self.players.iter().find(|p| p.addr.eq(addr))
283    }
284
285    pub fn get_player_mut_by_address(&mut self, addr: &str) -> Option<&mut Player> {
286        self.players.iter_mut().find(|p| p.addr.eq(addr))
287    }
288
289    pub fn count_players(&self) -> u16 {
290        self.players.len() as u16
291    }
292
293    pub fn count_servers(&self) -> u16 {
294        self.servers.len() as u16
295    }
296
297    pub fn gen_start_game_event(&self) -> Event {
298        Event::GameStart {
299            access_version: self.access_version,
300        }
301    }
302
303    pub fn get_server_by_address(&self, addr: &str) -> Option<&Server> {
304        self.servers.iter().find(|s| s.addr.eq(addr))
305    }
306
307    pub fn get_transactor_server(&self) -> &Server {
308        self.get_server_by_address(&self.transactor_addr).unwrap()
309    }
310
311    pub fn dispatch_event(&mut self, event: Event, timeout: u64) {
312        self.dispatch = Some(DispatchEvent::new(event, self.timestamp + timeout));
313    }
314
315    pub fn dispatch_event_instantly(&mut self, event: Event) {
316        self.dispatch_event(event, 0);
317    }
318
319    pub fn wait_timeout(&mut self, timeout: u64) {
320        self.dispatch = Some(DispatchEvent::new(
321            Event::WaitingTimeout,
322            self.timestamp + timeout,
323        ));
324    }
325
326    pub fn action_timeout(&mut self, player_addr: String, timeout: u64) {
327        self.dispatch = Some(DispatchEvent::new(
328            Event::ActionTimeout { player_addr },
329            self.timestamp + timeout,
330        ));
331    }
332
333    pub fn start_game(&mut self) {
334        self.random_states.clear();
335        self.dispatch = Some(DispatchEvent::new(self.gen_start_game_event(), 0));
336    }
337
338    pub fn shutdown_game(&mut self) {
339        self.dispatch = Some(DispatchEvent::new(Event::Shutdown, 0));
340    }
341
342    pub fn dispatch_custom<E>(&mut self, e: &E, timeout: u64)
343    where
344        E: CustomEvent,
345    {
346        let event = Event::custom(self.transactor_addr.to_owned(), e);
347        self.dispatch_event(event, timeout);
348    }
349
350    pub fn get_players(&self) -> &Vec<Player> {
351        &self.players
352    }
353
354    pub fn get_timestamp(&self) -> u64 {
355        self.timestamp
356    }
357
358    pub fn is_checkpoint(&self) -> bool {
359        self.checkpoint.is_some()
360    }
361
362    pub fn get_status(&self) -> GameStatus {
363        self.status
364    }
365
366    // pub(crate) fn set_players(&mut self, players: Vec<Player>) {
367    //     self.players = players;
368    // }
369
370    pub fn list_random_states(&self) -> &Vec<RandomState> {
371        &self.random_states
372    }
373
374    pub fn list_random_states_mut(&mut self) -> &mut Vec<RandomState> {
375        &mut self.random_states
376    }
377
378    pub fn list_decision_states(&self) -> &Vec<DecisionState> {
379        &self.decision_states
380    }
381
382    pub fn get_dispatch(&self) -> &Option<DispatchEvent> {
383        &self.dispatch
384    }
385
386    pub fn cancel_dispatch(&mut self) {
387        self.dispatch = None;
388    }
389
390    pub fn get_access_version(&self) -> u64 {
391        self.access_version
392    }
393
394    pub fn get_settle_version(&self) -> u64 {
395        self.settle_version
396    }
397
398    /// Get the random state by its id.
399    pub fn get_random_state(&self, id: RandomId) -> Result<&RandomState> {
400        if id == 0 {
401            return Err(Error::RandomStateNotFound(id));
402        }
403        if let Some(rnd_st) = self.random_states.get(id as usize - 1) {
404            Ok(rnd_st)
405        } else {
406            Err(Error::RandomStateNotFound(id))
407        }
408    }
409
410    pub fn get_random_state_unchecked(&self, id: RandomId) -> &RandomState {
411        &self.random_states[id as usize - 1]
412    }
413
414    pub fn get_decision_state_mut(&mut self, id: DecisionId) -> Result<&mut DecisionState> {
415        if id == 0 {
416            return Err(Error::InvalidDecisionId);
417        }
418        if let Some(st) = self.decision_states.get_mut(id as usize - 1) {
419            Ok(st)
420        } else {
421            Err(Error::InvalidDecisionId)
422        }
423    }
424    /// Get the mutable random state by its id.
425    pub fn get_random_state_mut(&mut self, id: RandomId) -> Result<&mut RandomState> {
426        if id == 0 {
427            return Err(Error::RandomStateNotFound(id));
428        }
429        if let Some(rnd_st) = self.random_states.get_mut(id as usize - 1) {
430            Ok(rnd_st)
431        } else {
432            Err(Error::RandomStateNotFound(id))
433        }
434    }
435
436    /// Assign random item to a player
437    pub fn assign<S: Into<String>>(
438        &mut self,
439        random_id: RandomId,
440        player_addr: S,
441        indexes: Vec<usize>,
442    ) -> Result<()> {
443        let rnd_st = self.get_random_state_mut(random_id)?;
444        rnd_st.assign(player_addr.into(), indexes)?;
445        Ok(())
446    }
447
448    pub fn reveal(&mut self, random_id: RandomId, indexes: Vec<usize>) -> Result<()> {
449        let rnd_st = self.get_random_state_mut(random_id)?;
450        rnd_st.reveal(indexes)?;
451        Ok(())
452    }
453
454    pub fn release(&mut self, decision_id: DecisionId) -> Result<()> {
455        let state = self.get_decision_state_mut(decision_id)?;
456        state.release()?;
457        Ok(())
458    }
459
460    pub fn is_random_ready(&self, random_id: RandomId) -> bool {
461        match self.get_random_state(random_id) {
462            Ok(rnd) => matches!(
463                rnd.status,
464                RandomStatus::Ready | RandomStatus::WaitingSecrets
465            ),
466            Err(_) => false,
467        }
468    }
469
470    pub fn is_secrets_ready(&self) -> bool {
471        self.random_states
472            .iter()
473            .all(|st| st.status == RandomStatus::Ready)
474    }
475
476    /// Set game status
477    pub fn set_game_status(&mut self, status: GameStatus) {
478        self.status = status;
479    }
480
481    /// Set player status by address.
482    /// Using it in custom event handler is not allowed.
483    pub fn set_player_status(&mut self, addr: &str, status: NodeStatus) -> Result<()> {
484        if let Some(p) = self.players.iter_mut().find(|p| p.addr.eq(&addr)) {
485            p.status = status;
486        } else {
487            return Err(Error::InvalidPlayerAddress);
488        }
489        Ok(())
490    }
491
492    /// Add player to the game.
493    pub fn add_player(&mut self, player: &PlayerJoin) -> Result<()> {
494        if let Some(p) = self
495            .players
496            .iter()
497            .find(|p| p.addr.eq(&player.addr) || p.position == player.position as usize)
498        {
499            if p.position == player.position as usize {
500                Err(Error::PositionOccupied(p.position))
501            } else {
502                Err(Error::PlayerAlreadyJoined(player.addr.clone()))
503            }
504        } else {
505            self.players.push(Player::new(
506                player.addr.clone(),
507                player.balance,
508                player.position as _,
509            ));
510            Ok(())
511        }
512    }
513
514    /// Add server to the game.
515    pub fn add_server(&mut self, server: &ServerJoin) -> Result<()> {
516        if self
517            .servers
518            .iter()
519            .find(|s| s.addr.eq(&server.addr))
520            .is_some()
521        {
522            Err(Error::ServerAlreadyJoined(server.addr.clone()))
523        } else {
524            self.servers
525                .push(Server::new(server.addr.clone(), server.endpoint.clone()));
526            Ok(())
527        }
528    }
529
530    pub fn set_access_version(&mut self, access_version: u64) {
531        self.access_version = access_version;
532    }
533
534    pub fn set_allow_exit(&mut self, allow_exit: bool) {
535        self.allow_exit = allow_exit;
536    }
537
538    /// Remove player from the game.
539    pub fn remove_player(&mut self, addr: &str) -> Result<()> {
540        let orig_len = self.players.len();
541        if self.allow_exit {
542            self.players.retain(|p| p.addr.ne(&addr));
543            if orig_len == self.players.len() {
544                Err(Error::PlayerNotInGame)
545            } else {
546                Ok(())
547            }
548        } else {
549            Err(Error::CantLeave)
550        }
551    }
552
553    /// Dispatch an event if there's none
554    pub fn dispatch_safe(&mut self, event: Event, timeout: u64) {
555        if self.dispatch.is_none() {
556            self.dispatch = Some(DispatchEvent::new(event, timeout + self.timestamp));
557        }
558    }
559
560    /// Dispatch event after timeout.
561    pub fn dispatch(&mut self, event: Event, timeout: u64) -> Result<()> {
562        if self.dispatch.is_some() {
563            return Err(Error::DuplicatedEventDispatching);
564        }
565        self.dispatch = Some(DispatchEvent::new(event, timeout));
566        Ok(())
567    }
568
569    pub fn init_random_state(&mut self, spec: RandomSpec) -> Result<RandomId> {
570        let random_id = self.random_states.len() + 1;
571        let owners: Vec<String> = self
572            .servers
573            .iter()
574            .filter_map(|s| {
575                if s.status == NodeStatus::Ready {
576                    Some(s.addr.clone())
577                } else {
578                    None
579                }
580            })
581            .collect();
582
583        // The only failure case is that when there are not enough owners.
584        // Here we know the game is served, so the servers must not be empty.
585        let random_state = RandomState::try_new(random_id, spec, &owners)?;
586
587        self.random_states.push(random_state);
588        Ok(random_id)
589    }
590
591    pub fn add_shared_secrets(&mut self, _addr: &str, shares: Vec<SecretShare>) -> Result<()> {
592        for share in shares.into_iter() {
593            match share {
594                SecretShare::Random {
595                    from_addr,
596                    to_addr,
597                    random_id,
598                    index,
599                    secret,
600                } => {
601                    self.get_random_state_mut(random_id)?
602                        .add_secret(from_addr, to_addr, index, secret)?;
603                }
604                SecretShare::Answer {
605                    from_addr,
606                    decision_id,
607                    secret,
608                } => {
609                    self.get_decision_state_mut(decision_id)?
610                        .add_secret(&from_addr, secret)?;
611                }
612            }
613        }
614        Ok(())
615    }
616
617    pub fn randomize_and_mask(
618        &mut self,
619        addr: &str,
620        random_id: RandomId,
621        ciphertexts: Vec<Ciphertext>,
622    ) -> Result<()> {
623        let rnd_st = self.get_random_state_mut(random_id)?;
624        rnd_st.mask(addr, ciphertexts)?;
625        self.dispatch_randomization_timeout(random_id)
626    }
627
628    pub fn lock(
629        &mut self,
630        addr: &str,
631        random_id: RandomId,
632        ciphertexts_and_tests: Vec<(Ciphertext, Ciphertext)>,
633    ) -> Result<()> {
634        let rnd_st = self.get_random_state_mut(random_id)?;
635        rnd_st.lock(addr, ciphertexts_and_tests)?;
636        self.dispatch_randomization_timeout(random_id)
637    }
638
639    pub fn dispatch_randomization_timeout(&mut self, random_id: RandomId) -> Result<()> {
640        let no_dispatch = self.dispatch.is_none();
641        let rnd_st = self.get_random_state_mut(random_id)?;
642        match &rnd_st.status {
643            RandomStatus::Shared => {}
644            RandomStatus::Ready => {
645                self.dispatch_event_instantly(Event::RandomnessReady { random_id });
646            }
647            RandomStatus::Locking(ref addr) => {
648                let addr = addr.to_owned();
649                if no_dispatch {
650                    self.dispatch_event(
651                        Event::OperationTimeout { addrs: vec![addr] },
652                        OPERATION_TIMEOUT,
653                    );
654                }
655            }
656            RandomStatus::Masking(ref addr) => {
657                let addr = addr.to_owned();
658                if no_dispatch {
659                    self.dispatch_event(
660                        Event::OperationTimeout { addrs: vec![addr] },
661                        OPERATION_TIMEOUT,
662                    );
663                }
664            }
665            RandomStatus::WaitingSecrets => {
666                if no_dispatch {
667                    let addrs = rnd_st.list_operating_addrs();
668                    self.dispatch_event(Event::OperationTimeout { addrs }, OPERATION_TIMEOUT);
669                }
670            }
671        }
672        Ok(())
673    }
674
675    pub fn settle(&mut self, settles: Vec<Settle>) {
676        self.settles = Some(settles);
677    }
678
679    pub fn transfer(&mut self, transfers: Vec<Transfer>) {
680        self.transfers = Some(transfers);
681    }
682
683    pub fn get_settles(&self) -> &Option<Vec<Settle>> {
684        &self.settles
685    }
686
687    pub fn bump_settle_version(&mut self) {
688        self.settle_version += 1;
689    }
690
691    pub fn take_settles_and_transfers(
692        &mut self,
693    ) -> Result<Option<(Vec<Settle>, Vec<Transfer>, Vec<u8>)>> {
694        if let Some(checkpoint) = self.get_checkpoint() {
695            let mut settles = None;
696            std::mem::swap(&mut settles, &mut self.settles);
697
698            if let Some(settles) = settles.as_mut() {
699                settles.sort_by_key(|s| match s.op {
700                    SettleOp::Add(_) => 0,
701                    SettleOp::Sub(_) => 1,
702                    SettleOp::Eject => 2,
703                    SettleOp::AssignSlot(_) => 3,
704                })
705            }
706
707            for s in settles.as_ref().unwrap().iter() {
708                match s.op {
709                    SettleOp::Eject => {
710                        self.players.retain(|p| p.addr.ne(&s.addr));
711                    }
712                    SettleOp::Add(amount) => {
713                        let p =
714                            self.get_player_mut_by_address(&s.addr)
715                                .ok_or(Error::InvalidSettle(format!(
716                                    "Invalid player address: {}",
717                                    s.addr
718                                )))?;
719                        p.balance =
720                            p.balance
721                                .checked_add(amount)
722                                .ok_or(Error::InvalidSettle(format!(
723                                    "Settle amount overflow (add): balance {}, change {}",
724                                    p.balance, amount,
725                                )))?;
726                    }
727                    SettleOp::Sub(amount) => {
728                        let p =
729                            self.get_player_mut_by_address(&s.addr)
730                                .ok_or(Error::InvalidSettle(format!(
731                                    "Invalid player address: {}",
732                                    s.addr
733                                )))?;
734                        p.balance =
735                            p.balance
736                                .checked_sub(amount)
737                                .ok_or(Error::InvalidSettle(format!(
738                                    "Settle amount overflow (sub): balance {}, change {}",
739                                    p.balance, amount,
740                                )))?;
741                    }
742                    SettleOp::AssignSlot(_) => {}
743                }
744            }
745
746            let mut transfers = None;
747            std::mem::swap(&mut transfers, &mut self.transfers);
748            self.bump_settle_version();
749
750            Ok(Some((
751                settles.unwrap_or(vec![]),
752                transfers.unwrap_or(vec![]),
753                checkpoint,
754            )))
755        } else {
756            Ok(None)
757        }
758    }
759
760    pub fn add_settle(&mut self, settle: Settle) {
761        if let Some(ref mut settles) = self.settles {
762            settles.push(settle);
763        } else {
764            self.settles = Some(vec![settle]);
765        }
766    }
767
768    pub fn add_revealed_random(
769        &mut self,
770        random_id: RandomId,
771        revealed: HashMap<usize, String>,
772    ) -> Result<()> {
773        let rnd_st = self.get_random_state_mut(random_id)?;
774        rnd_st
775            .add_revealed(revealed)
776            .map_err(|e| Error::InvalidDecryptedValue(e.to_string()))
777    }
778
779    pub fn add_revealed_answer(&mut self, decision_id: DecisionId, revealed: String) -> Result<()> {
780        let st = self.get_decision_state_mut(decision_id)?;
781        st.add_released(revealed)
782    }
783
784    pub fn ask(&mut self, owner: String) -> DecisionId {
785        let id = self.decision_states.len() + 1;
786        let st = DecisionState::new(id, owner);
787        self.decision_states.push(st);
788        id
789    }
790
791    pub fn answer_decision(
792        &mut self,
793        id: DecisionId,
794        owner: &str,
795        ciphertext: Ciphertext,
796        digest: SecretDigest,
797    ) -> Result<()> {
798        let st = self.get_decision_state_mut(id)?;
799        st.answer(owner, ciphertext, digest)
800    }
801
802    pub fn get_revealed(&self, random_id: RandomId) -> Result<&HashMap<usize, String>> {
803        let rnd_st = self.get_random_state(random_id)?;
804        Ok(&rnd_st.revealed)
805    }
806
807    pub fn derive_effect(&self) -> Effect {
808        let revealed = self
809            .list_random_states()
810            .iter()
811            .map(|st| (st.id, st.revealed.clone()))
812            .collect();
813        let answered = self
814            .list_decision_states()
815            .iter()
816            .filter_map(|st| {
817                if let Some(a) = st.get_revealed() {
818                    Some((st.id, a.to_owned()))
819                } else {
820                    None
821                }
822            })
823            .collect();
824
825        Effect {
826            start_game: false,
827            stop_game: false,
828            cancel_dispatch: false,
829            action_timeout: None,
830            wait_timeout: None,
831            timestamp: self.timestamp,
832            curr_random_id: self.list_random_states().len() + 1,
833            curr_decision_id: self.list_decision_states().len() + 1,
834            players_count: self.count_players(),
835            servers_count: self.count_servers(),
836            asks: Vec::new(),
837            assigns: Vec::new(),
838            reveals: Vec::new(),
839            releases: Vec::new(),
840            init_random_states: Vec::new(),
841            revealed,
842            answered,
843            is_checkpoint: false,
844            checkpoint: None,
845            settles: Vec::new(),
846            handler_state: Some(self.handler_state.clone()),
847            error: None,
848            allow_exit: self.allow_exit,
849            transfers: Vec::new(),
850        }
851    }
852
853    pub fn apply_effect(&mut self, effect: Effect) -> Result<()> {
854        let Effect {
855            action_timeout,
856            wait_timeout,
857            start_game,
858            stop_game,
859            cancel_dispatch,
860            asks,
861            assigns,
862            reveals,
863            releases,
864            init_random_states,
865            settles,
866            transfers,
867            handler_state,
868            allow_exit,
869            checkpoint,
870            ..
871        } = effect;
872
873        // Handle dispatching
874        if start_game {
875            self.start_game();
876        } else if stop_game {
877            self.shutdown_game();
878        } else if let Some(t) = action_timeout {
879            self.action_timeout(t.player_addr, t.timeout);
880        } else if let Some(t) = wait_timeout {
881            self.wait_timeout(t);
882        } else if cancel_dispatch {
883            self.cancel_dispatch();
884        }
885
886        self.set_allow_exit(allow_exit);
887
888        for Assign {
889            random_id,
890            indexes,
891            player_addr,
892        } in assigns.into_iter()
893        {
894            self.assign(random_id, player_addr, indexes)?;
895        }
896
897        for Reveal { random_id, indexes } in reveals.into_iter() {
898            self.reveal(random_id, indexes)?;
899        }
900
901        for Release { decision_id } in releases.into_iter() {
902            self.release(decision_id)?;
903        }
904
905        for Ask { player_addr } in asks.into_iter() {
906            self.ask(player_addr);
907        }
908
909        for spec in init_random_states.into_iter() {
910            self.init_random_state(spec)?;
911        }
912
913        if let Some(checkpoint_state) = checkpoint {
914            self.checkpoint = Some(checkpoint_state);
915            self.settle(settles);
916            self.transfer(transfers);
917        } else {
918            if (!settles.is_empty()) || (!transfers.is_empty()) {
919                return Err(Error::SettleWithoutCheckpoint);
920            }
921        }
922
923        if let Some(state) = handler_state {
924            self.handler_state = state;
925        }
926
927        Ok(())
928    }
929
930    pub fn set_node_ready(&mut self, access_version: u64) {
931        for s in self.servers.iter_mut() {
932            if let NodeStatus::Pending(a) = s.status {
933                if a <= access_version {
934                    s.status = NodeStatus::Ready
935                }
936            }
937        }
938        for p in self.players.iter_mut() {
939            if let NodeStatus::Pending(a) = p.status {
940                if a <= access_version {
941                    p.status = NodeStatus::Ready
942                }
943            }
944        }
945    }
946
947    pub fn apply_checkpoint(&mut self, access_version: u64, settle_version: u64) -> Result<()> {
948        if self.settle_version != settle_version {
949            return Err(Error::InvalidCheckpoint);
950        }
951
952        self.players.retain(|p| match p.status {
953            NodeStatus::Pending(v) => v <= access_version,
954            NodeStatus::Confirming => true,
955            NodeStatus::Ready => true,
956            NodeStatus::Disconnected => true,
957        });
958
959        self.servers.retain(|s| match s.status {
960            NodeStatus::Pending(v) => v <= access_version || s.addr.eq(&self.transactor_addr),
961            NodeStatus::Confirming => true,
962            NodeStatus::Ready => true,
963            NodeStatus::Disconnected => true,
964        });
965
966        self.access_version = access_version;
967
968        Ok(())
969    }
970
971    pub fn prepare_for_next_event(&mut self, timestamp: u64) {
972        self.set_timestamp(timestamp);
973        self.checkpoint = None;
974    }
975}
976
977impl Default for GameContext {
978    fn default() -> Self {
979        Self {
980            game_addr: "".into(),
981            access_version: 0,
982            settle_version: 0,
983            transactor_addr: "".into(),
984            status: GameStatus::Uninit,
985            players: Vec::new(),
986            servers: Vec::new(),
987            dispatch: None,
988            handler_state: "".into(),
989            timestamp: 0,
990            allow_exit: false,
991            random_states: Vec::new(),
992            decision_states: Vec::new(),
993            settles: None,
994            transfers: None,
995            checkpoint: None,
996        }
997    }
998}