ab_client_proof_of_time/source/
state.rs1use crate::PotNextSlotInput;
2use crate::verifier::PotVerifier;
3use ab_core_primitives::pot::{PotOutput, PotParametersChange, SlotNumber};
4use parking_lot::Mutex;
5
6#[derive(Debug, Copy, Clone, Eq, PartialEq)]
7struct InnerState {
8 next_slot_input: PotNextSlotInput,
9 parameters_change: Option<PotParametersChange>,
10}
11
12impl InnerState {
13 fn update(
14 mut self,
15 mut slot: SlotNumber,
16 mut output: PotOutput,
17 maybe_updated_parameters_change: Option<Option<PotParametersChange>>,
18 pot_verifier: &PotVerifier,
19 ) -> Self {
20 if let Some(updated_parameters_change) = maybe_updated_parameters_change {
21 self.parameters_change = updated_parameters_change;
22 }
23
24 loop {
25 self.next_slot_input = PotNextSlotInput::derive(
26 self.next_slot_input.slot_iterations,
27 slot,
28 output,
29 &self.parameters_change,
30 );
31
32 if let Some(checkpoints) = pot_verifier.try_get_checkpoints(
34 self.next_slot_input.slot_iterations,
35 self.next_slot_input.seed,
36 ) {
37 slot = self.next_slot_input.slot;
38 output = checkpoints.output();
39 } else {
40 break;
41 }
42 }
43
44 self
45 }
46}
47
48#[derive(Debug)]
50pub enum PotStateSetOutcome {
51 NoChange,
53 Extension {
55 from: PotNextSlotInput,
56 to: PotNextSlotInput,
57 },
58 Reorg {
60 from: PotNextSlotInput,
61 to: PotNextSlotInput,
62 },
63}
64
65#[derive(Debug)]
69pub struct PotState {
70 inner_state: Mutex<InnerState>,
71 verifier: PotVerifier,
72}
73
74impl PotState {
75 pub fn new(
77 next_slot_input: PotNextSlotInput,
78 parameters_change: Option<PotParametersChange>,
79 verifier: PotVerifier,
80 ) -> Self {
81 let inner = InnerState {
82 next_slot_input,
83 parameters_change,
84 };
85
86 Self {
87 inner_state: Mutex::new(inner),
88 verifier,
89 }
90 }
91
92 pub fn next_slot_input(&self) -> PotNextSlotInput {
94 self.inner_state.lock().next_slot_input
95 }
96
97 pub fn try_extend(
102 &self,
103 expected_existing_next_slot_input: PotNextSlotInput,
104 best_slot: SlotNumber,
105 best_output: PotOutput,
106 maybe_updated_parameters_change: Option<Option<PotParametersChange>>,
107 ) -> Result<PotNextSlotInput, PotNextSlotInput> {
108 let mut existing_inner_state = self.inner_state.lock();
109 if expected_existing_next_slot_input != existing_inner_state.next_slot_input {
110 return Err(existing_inner_state.next_slot_input);
111 }
112
113 *existing_inner_state = existing_inner_state.update(
114 best_slot,
115 best_output,
116 maybe_updated_parameters_change,
117 &self.verifier,
118 );
119
120 Ok(existing_inner_state.next_slot_input)
121 }
122
123 pub fn set_known_good_output(
129 &self,
130 slot: SlotNumber,
131 output: PotOutput,
132 updated_parameters_change: Option<PotParametersChange>,
133 ) -> PotStateSetOutcome {
134 let previous_best_state;
135 let new_best_state;
136 {
137 let mut inner_state = self.inner_state.lock();
138 previous_best_state = *inner_state;
139 new_best_state = previous_best_state.update(
140 slot,
141 output,
142 Some(updated_parameters_change),
143 &self.verifier,
144 );
145 *inner_state = new_best_state;
146 }
147
148 if previous_best_state.next_slot_input == new_best_state.next_slot_input {
149 return PotStateSetOutcome::NoChange;
150 }
151
152 if previous_best_state.next_slot_input.slot < new_best_state.next_slot_input.slot {
153 let mut slot_iterations = previous_best_state.next_slot_input.slot_iterations;
154 let mut seed = previous_best_state.next_slot_input.seed;
155
156 for slot in
157 previous_best_state.next_slot_input.slot..new_best_state.next_slot_input.slot
158 {
159 let Some(checkpoints) = self.verifier.try_get_checkpoints(slot_iterations, seed)
160 else {
161 break;
162 };
163
164 let pot_input = PotNextSlotInput::derive(
165 slot_iterations,
166 slot,
167 checkpoints.output(),
168 &updated_parameters_change,
169 );
170
171 let next_slot = slot + SlotNumber::ONE;
174 slot_iterations = pot_input.slot_iterations;
175 seed = pot_input.seed;
176
177 if next_slot == new_best_state.next_slot_input.slot
178 && slot_iterations == new_best_state.next_slot_input.slot_iterations
179 && seed == new_best_state.next_slot_input.seed
180 {
181 return PotStateSetOutcome::Extension {
182 from: previous_best_state.next_slot_input,
183 to: new_best_state.next_slot_input,
184 };
185 }
186 }
187 }
188
189 PotStateSetOutcome::Reorg {
190 from: previous_best_state.next_slot_input,
191 to: new_best_state.next_slot_input,
192 }
193 }
194}