penumbra_sdk_sct/component/
sct.rs1use std::sync::Arc;
2
3use anyhow::{anyhow, Result};
4use async_trait::async_trait;
5use cnidarium::{StateRead, StateWrite};
6use cnidarium_component::Component;
7use penumbra_sdk_proto::{StateReadProto, StateWriteProto};
8use tendermint::v0_37::abci;
9use tracing::instrument;
10
11use crate::{epoch::Epoch, genesis, params::SctParameters, state_key};
12
13use super::clock::EpochManager;
14
15pub struct Sct {}
16
17#[async_trait]
18impl Component for Sct {
19 type AppState = genesis::Content;
20
21 #[instrument(name = "sct_component", skip(state, app_state))]
22 async fn init_chain<S: StateWrite>(mut state: S, app_state: Option<&Self::AppState>) {
23 match app_state {
24 Some(genesis) => {
25 state.put_sct_params(genesis.sct_params.clone());
26 state.put_block_height(0);
27 state.put_epoch_by_height(
28 0,
29 Epoch {
30 index: 0,
31 start_height: 0,
32 },
33 );
34
35 state.put_epoch_by_height(
38 1,
39 Epoch {
40 index: 0,
41 start_height: 0,
42 },
43 );
44 }
45 None => { }
46 }
47 }
48
49 #[instrument(name = "sct_component", skip(state, begin_block))]
50 async fn begin_block<S: StateWrite + 'static>(
51 state: &mut Arc<S>,
52 begin_block: &abci::request::BeginBlock,
53 ) {
54 let state = Arc::get_mut(state).expect("there's only one reference to the state");
55 state.put_block_height(begin_block.header.height.into());
56 state.put_block_timestamp(begin_block.header.height.into(), begin_block.header.time);
57 }
58
59 #[instrument(name = "sct_component", skip(_state, _end_block))]
60 async fn end_block<S: StateWrite + 'static>(
61 _state: &mut Arc<S>,
62 _end_block: &abci::request::EndBlock,
63 ) {
64 }
65
66 #[instrument(name = "sct_component", skip(_state))]
67 async fn end_epoch<S: StateWrite + 'static>(_state: &mut Arc<S>) -> anyhow::Result<()> {
68 Ok(())
69 }
70}
71
72#[async_trait]
74pub trait StateReadExt: StateRead {
75 async fn get_sct_params(&self) -> Result<SctParameters> {
77 self.get(state_key::config::sct_params())
78 .await?
79 .ok_or_else(|| anyhow!("Missing SctParameters"))
80 }
81
82 async fn get_epoch_duration_parameter(&self) -> Result<u64> {
87 self.get_sct_params()
88 .await
89 .map(|params| params.epoch_duration)
90 }
91}
92
93impl<T: StateRead + ?Sized> StateReadExt for T {}
94
95#[async_trait]
97pub trait StateWriteExt: StateWrite {
98 fn put_sct_params(&mut self, params: SctParameters) {
99 self.put(state_key::config::sct_params().to_string(), params);
100 }
101}
102
103impl<T: StateWrite + ?Sized> StateWriteExt for T {}