penumbra_sct/component/
clock.rsuse crate::{epoch::Epoch, state_key};
use anyhow::{anyhow, Context, Result};
use async_trait::async_trait;
use cnidarium::{StateRead, StateWrite};
use penumbra_proto::{StateReadProto, StateWriteProto};
use std::str::FromStr;
#[async_trait]
pub trait EpochRead: StateRead {
async fn get_block_height(&self) -> Result<u64> {
self.get_proto(state_key::block_manager::block_height())
.await?
.ok_or_else(|| anyhow!("Missing block_height"))
}
async fn get_current_block_timestamp(&self) -> Result<tendermint::Time> {
let timestamp_string: String = self
.get_proto(state_key::block_manager::current_block_timestamp())
.await?
.ok_or_else(|| anyhow!("Missing current_block_timestamp"))?;
Ok(tendermint::Time::from_str(×tamp_string)
.context("current_block_timestamp was an invalid RFC3339 time string")?)
}
async fn get_block_timestamp(&self, height: u64) -> Result<tendermint::Time> {
let timestamp_string: String = self
.nonverifiable_get_proto(&state_key::block_manager::block_timestamp(height).as_bytes())
.await?
.ok_or_else(|| anyhow!("Missing block_timestamp for height {}", height))?;
Ok(
tendermint::Time::from_str(×tamp_string).context(format!(
"block_timestamp for height {} was an invalid RFC3339 time string",
height
))?,
)
}
async fn get_current_epoch(&self) -> Result<Epoch> {
let height = self.get_block_height().await?;
self.get(&state_key::epoch_manager::epoch_by_height(height))
.await?
.ok_or_else(|| anyhow!("missing epoch for current height: {height}"))
}
async fn get_epoch_by_height(&self, height: u64) -> Result<Epoch> {
self.get(&state_key::epoch_manager::epoch_by_height(height))
.await?
.ok_or_else(|| anyhow!("missing epoch for height"))
}
async fn is_epoch_ending_early(&self) -> bool {
self.object_get(state_key::epoch_manager::end_epoch_early())
.unwrap_or(false)
}
}
impl<T: StateRead + ?Sized> EpochRead for T {}
#[async_trait]
pub trait EpochManager: StateWrite {
fn put_block_timestamp(&mut self, height: u64, timestamp: tendermint::Time) {
self.put_proto(
state_key::block_manager::current_block_timestamp().into(),
timestamp.to_rfc3339(),
);
self.nonverifiable_put_proto(
state_key::block_manager::block_timestamp(height).into(),
timestamp.to_rfc3339(),
);
}
fn set_end_epoch_flag(&mut self) {
self.object_put(state_key::epoch_manager::end_epoch_early(), true)
}
fn put_block_height(&mut self, height: u64) {
self.put_proto(state_key::block_manager::block_height().to_string(), height)
}
fn put_epoch_by_height(&mut self, height: u64, epoch: Epoch) {
self.put(state_key::epoch_manager::epoch_by_height(height), epoch)
}
}
impl<T: StateWrite + ?Sized> EpochManager for T {}