sc_proof_of_time/source/
timekeeper.rs

1use crate::source::state::PotState;
2use crate::verifier::PotVerifier;
3use futures::channel::mpsc;
4use futures::executor::block_on;
5use futures::SinkExt;
6use sp_consensus_slots::Slot;
7use std::num::NonZeroU32;
8use std::sync::Arc;
9use subspace_core_primitives::pot::{PotCheckpoints, PotSeed};
10use subspace_proof_of_time::PotError;
11use tracing::{debug, trace};
12
13/// Proof of time slot information
14pub(super) struct TimekeeperProof {
15    /// Slot number
16    pub(super) slot: Slot,
17    /// Proof of time seed
18    pub(super) seed: PotSeed,
19    /// Iterations per slot
20    pub(super) slot_iterations: NonZeroU32,
21    /// Proof of time checkpoints
22    pub(super) checkpoints: PotCheckpoints,
23}
24
25/// Runs timekeeper, must be running on a fast dedicated CPU core
26pub(super) fn run_timekeeper(
27    state: Arc<PotState>,
28    pot_verifier: PotVerifier,
29    mut proofs_sender: mpsc::Sender<TimekeeperProof>,
30) -> Result<(), PotError> {
31    let mut next_slot_input = state.next_slot_input();
32
33    loop {
34        trace!(
35            "Proving for slot {} with {} iterations",
36            next_slot_input.slot,
37            next_slot_input.slot_iterations
38        );
39        let checkpoints =
40            subspace_proof_of_time::prove(next_slot_input.seed, next_slot_input.slot_iterations)?;
41
42        let proof = TimekeeperProof {
43            seed: next_slot_input.seed,
44            slot_iterations: next_slot_input.slot_iterations,
45            slot: next_slot_input.slot,
46            checkpoints,
47        };
48
49        pot_verifier.inject_verified_checkpoints(
50            next_slot_input.seed,
51            next_slot_input.slot_iterations,
52            checkpoints,
53        );
54
55        next_slot_input = state
56            .try_extend(
57                next_slot_input,
58                next_slot_input.slot,
59                checkpoints.output(),
60                None,
61            )
62            .unwrap_or_else(|next_slot_input| next_slot_input);
63
64        if let Err(error) = proofs_sender.try_send(proof) {
65            if let Err(error) = block_on(proofs_sender.send(error.into_inner())) {
66                debug!(%error, "Couldn't send checkpoints, channel is closed");
67                return Ok(());
68            }
69        }
70    }
71}