ab_client_proof_of_time/source/
timekeeper.rs1use crate::source::state::PotState;
2use crate::verifier::PotVerifier;
3use ab_core_primitives::pot::{PotCheckpoints, PotSeed, SlotNumber};
4use ab_proof_of_time::PotError;
5use futures::SinkExt;
6use futures::channel::mpsc;
7use futures::executor::block_on;
8use std::num::NonZeroU32;
9use std::sync::Arc;
10use tracing::{debug, trace};
11
12#[derive(Debug, Copy, Clone)]
14pub struct TimekeeperProof {
15 pub slot: SlotNumber,
17 pub seed: PotSeed,
19 pub slot_iterations: NonZeroU32,
21 pub checkpoints: PotCheckpoints,
23}
24
25#[derive(Debug)]
27#[must_use = "Doesn't do anything unless run() method is called"]
28pub struct Timekeeper {
29 state: Arc<PotState>,
30 pot_verifier: PotVerifier,
31 proof_sender: mpsc::Sender<TimekeeperProof>,
32}
33
34impl Timekeeper {
35 pub fn new(
37 state: Arc<PotState>,
38 pot_verifier: PotVerifier,
39 ) -> (Self, mpsc::Receiver<TimekeeperProof>) {
40 let (proof_sender, proof_receiver) = mpsc::channel(1);
41
42 (
43 Self {
44 state,
45 pot_verifier,
46 proof_sender,
47 },
48 proof_receiver,
49 )
50 }
51
52 pub fn run(self) -> Result<(), PotError> {
56 let Self {
57 state,
58 pot_verifier,
59 mut proof_sender,
60 } = self;
61
62 let mut next_slot_input = state.next_slot_input();
63
64 loop {
65 trace!(
66 "Proving for slot {} with {} iterations",
67 next_slot_input.slot, next_slot_input.slot_iterations
68 );
69 let checkpoints =
70 ab_proof_of_time::prove(next_slot_input.seed, next_slot_input.slot_iterations)?;
71
72 let proof = TimekeeperProof {
73 seed: next_slot_input.seed,
74 slot_iterations: next_slot_input.slot_iterations,
75 slot: next_slot_input.slot,
76 checkpoints,
77 };
78
79 pot_verifier.inject_verified_checkpoints(
80 next_slot_input.seed,
81 next_slot_input.slot_iterations,
82 checkpoints,
83 );
84
85 next_slot_input = state
86 .try_extend(
87 next_slot_input,
88 next_slot_input.slot,
89 checkpoints.output(),
90 None,
91 )
92 .unwrap_or_else(|next_slot_input| next_slot_input);
93
94 if let Err(error) = proof_sender.try_send(proof)
95 && let Err(error) = block_on(proof_sender.send(error.into_inner()))
96 {
97 debug!(%error, "Couldn't send proof, the channel is closed");
98 return Ok(());
99 }
100 }
101 }
102}