|
| 1 | +#[derive(Debug, Copy, Clone, PartialEq)] |
| 2 | +#[repr(u8)] |
| 3 | +/// Status is pre-auth layer for any interaction with [`DBState`] |
| 4 | +// DEV: partial type-state pattern might be considered |
| 5 | +pub enum Status { |
| 6 | + // Fresh is the state all nodes start in - both pre-genesis, and if the network is running but they aren't |
| 7 | + // yet participating |
| 8 | + Fresh, |
| 9 | + // Proposed implies somebody else has sent me a proposal |
| 10 | + Proposed, |
| 11 | + // Proposing implies I have sent the others in the network a proposal |
| 12 | + Proposing, |
| 13 | + // Accepted means I have accepted a proposal received from somebody else |
| 14 | + // note Joiners do not accept/reject proposals |
| 15 | + Accepted, |
| 16 | + // Rejected means I have rejected a proposal received from somebody else |
| 17 | + // it doesn't automatically abort the DKG, but the leader is advised to abort and suggest some new terms |
| 18 | + Rejected, |
| 19 | + // Aborted means the leader has told the network to abort the proposal; a node may have rejected, |
| 20 | + // they may have found an error in the proposal, or any other reason could have occurred |
| 21 | + Aborted, |
| 22 | + // Executing means the leader has reviewed accepts/rejects and decided to go ahead with the DKG |
| 23 | + // this implies that the Kyber DKG process has been started |
| 24 | + Executing, |
| 25 | + // Complete means the DKG has finished and a new group file has been created successfully |
| 26 | + Complete, |
| 27 | + // TimedOut means the proposal timeout has been reached without entering the `Executing` state |
| 28 | + // any node can trigger this for themselves should they identify timeout has been reached |
| 29 | + // it does _not_ guarantee that other nodes have also timed out - a network error or something else |
| 30 | + // could have occurred. If the rest of the network continues, our node will likely transition to `Evicted` |
| 31 | + TimedOut, |
| 32 | + // Joined is the state a new proposed group member enters when they have been proposed a DKG and they run the |
| 33 | + // `join` DKG command to signal their acceptance to join the network |
| 34 | + Joined, |
| 35 | + // Left is used when a node has left the network by their own choice after a DKG. It's not entirely necessary, |
| 36 | + // an operator could just turn their node off. It's used to determine if an existing state is the current state |
| 37 | + // of the network, or whether epochs have happened in between times |
| 38 | + Left, |
| 39 | + // Failed signals that a key sharing execution was attempted, but this node did not see it complete successfully. |
| 40 | + // This could be either due to it being evicted or the DKG not completing for the whole network. Operators should |
| 41 | + // check the node and network status, and manually transition the node to `Left` or create a new proposal depending |
| 42 | + // on the outcome of the DKG |
| 43 | + Failed, |
| 44 | +} |
| 45 | + |
| 46 | +#[derive(thiserror::Error, Debug)] |
| 47 | +pub enum StateError { |
| 48 | + #[error("invalid transition attempt from {from} to {to}")] |
| 49 | + InvalidStateChange { from: Status, to: Status }, |
| 50 | + #[error("impossible DKG state received: {0}")] |
| 51 | + ImpossibleDkgState(u32), |
| 52 | +} |
| 53 | + |
| 54 | +impl TryFrom<u32> for Status { |
| 55 | + type Error = StateError; |
| 56 | + |
| 57 | + fn try_from(value: u32) -> Result<Self, Self::Error> { |
| 58 | + match value { |
| 59 | + 0 => Ok(Status::Fresh), |
| 60 | + 1 => Ok(Status::Proposed), |
| 61 | + 2 => Ok(Status::Proposing), |
| 62 | + 3 => Ok(Status::Accepted), |
| 63 | + 4 => Ok(Status::Rejected), |
| 64 | + 5 => Ok(Status::Aborted), |
| 65 | + 6 => Ok(Status::Executing), |
| 66 | + 7 => Ok(Status::Complete), |
| 67 | + 8 => Ok(Status::TimedOut), |
| 68 | + 9 => Ok(Status::Joined), |
| 69 | + 10 => Ok(Status::Left), |
| 70 | + 11 => Ok(Status::Failed), |
| 71 | + _ => Err(StateError::ImpossibleDkgState(value)), |
| 72 | + } |
| 73 | + } |
| 74 | +} |
| 75 | + |
| 76 | +impl std::fmt::Display for Status { |
| 77 | + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| 78 | + write!(f, "{self:?}") |
| 79 | + } |
| 80 | +} |
0 commit comments