sc_proof_of_time/source/
timekeeper.rs

1use crate::source::state::PotState;
2use crate::verifier::PotVerifier;
3use futures::SinkExt;
4use futures::channel::mpsc;
5use futures::executor::block_on;
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, next_slot_input.slot_iterations
37        );
38        let checkpoints =
39            subspace_proof_of_time::prove(next_slot_input.seed, next_slot_input.slot_iterations)?;
40
41        let proof = TimekeeperProof {
42            seed: next_slot_input.seed,
43            slot_iterations: next_slot_input.slot_iterations,
44            slot: next_slot_input.slot,
45            checkpoints,
46        };
47
48        pot_verifier.inject_verified_checkpoints(
49            next_slot_input.seed,
50            next_slot_input.slot_iterations,
51            checkpoints,
52        );
53
54        next_slot_input = state
55            .try_extend(
56                next_slot_input,
57                next_slot_input.slot,
58                checkpoints.output(),
59                None,
60            )
61            .unwrap_or_else(|next_slot_input| next_slot_input);
62
63        if let Err(error) = proofs_sender.try_send(proof)
64            && let Err(error) = block_on(proofs_sender.send(error.into_inner()))
65        {
66            debug!(%error, "Couldn't send checkpoints, channel is closed");
67            return Ok(());
68        }
69    }
70}