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#[derive(Clone, Debug, BorshSerialize, BorshDeserialize)]
154pub struct GameContext {
155 pub(crate) game_addr: Addr,
156 pub(crate) access_version: u64,
159 pub(crate) settle_version: u64,
162 pub(crate) transactor_addr: Addr,
164 pub(crate) status: GameStatus,
165 pub(crate) players: Vec<Player>,
167 pub(crate) servers: Vec<Server>,
169 pub(crate) dispatch: Option<DispatchEvent>,
170 pub(crate) handler_state: Vec<u8>,
171 pub(crate) timestamp: u64,
172 pub(crate) allow_exit: bool,
174 pub(crate) random_states: Vec<RandomState>,
176 pub(crate) decision_states: Vec<DecisionState>,
178 pub(crate) settles: Option<Vec<Settle>>,
180 pub(crate) transfers: Option<Vec<Transfer>>,
182 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 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 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 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 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 pub fn set_game_status(&mut self, status: GameStatus) {
478 self.status = status;
479 }
480
481 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 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 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 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 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 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 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 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}