Skip to content
Closed
7,301 changes: 0 additions & 7,301 deletions Cargo.lock

This file was deleted.

67 changes: 41 additions & 26 deletions src/checks/block.rs
Original file line number Diff line number Diff line change
@@ -1,34 +1,49 @@
use anyhow::anyhow;
use crate::state::State;
use anyhow::{anyhow, Ok};

#[derive(Clone, Debug, Default)]
pub struct BlockHeigtCheck {}

impl BlockHeigtCheck {
pub async fn run(
&self,
pre_state: &crate::state::State,
post_state: &crate::state::State,
) -> anyhow::Result<()> {
match (
pre_state.latest_block_height,
post_state.latest_block_height,
) {
(None, None) => Ok(()), // nothing happen yet
(None, Some(_)) => Ok(()), // first block
(Some(pre_block_height), None) => Err(anyhow!(
"Invalid state: pre {} -> post None",
pre_block_height
)), // should never happen
(Some(pre_block_height), Some(post_block_height)) => {
if pre_block_height < post_block_height {
Ok(())
} else {
Err(anyhow!(
"Invalid block height: pre {} -> post {}",
pre_block_height,
post_block_height
))
}
pub async fn run(&self, pre_state: &State, post_state: &State) -> anyhow::Result<()> {
let pre_block = pre_state.get_last_block();
let post_block = post_state.get_last_block();
if pre_block.height + 1 != post_block.height {
Err(anyhow!(
"Blocks are not consecutive: pre {} -> post {}",
pre_block.height,
post_block.height
))
} else {
Ok(())
}
}
}

pub struct BlockTimeCheck {
max_time: u64,
}
impl BlockTimeCheck {
pub async fn run(&self, pre_state: &State, post_state: &State) -> anyhow::Result<()> {
let pre_block = pre_state.get_last_block();
let post_block = post_state.get_last_block();
let max_estimated_block_time = pre_state.get_max_block_time_estimate() as u64;
if max_estimated_block_time > self.max_time {
Err(anyhow!(
"Max estimated block time is too high: {}",
max_estimated_block_time
))
} else {
let estimated_post_time = pre_state.max_next_block_timestamp_estimate();
if estimated_post_time < post_block.timestamp {
Err(anyhow!(
"Block at height {} took too long to be produced {} (vs {:?})",
post_block.height,
post_block.timestamp - pre_block.timestamp,
pre_state.get_max_block_time_estimate()
))
} else {
Ok(())
}
}
}
Expand Down
34 changes: 12 additions & 22 deletions src/checks/epoch.rs
Original file line number Diff line number Diff line change
@@ -1,31 +1,21 @@
use crate::state::State;
use anyhow::anyhow;

#[derive(Clone, Debug, Default)]
pub struct EpochCheck {}

impl EpochCheck {
pub async fn run(
&self,
pre_state: &crate::state::State,
post_state: &crate::state::State,
) -> anyhow::Result<()> {
match (pre_state.latest_epoch, post_state.latest_epoch) {
(None, None) => Ok(()), // nothing happen yet
(None, Some(_)) => Ok(()), // first epoch
(Some(pre_epoch), None) => {
Err(anyhow!("Invalid state: pre {} -> post None", pre_epoch))
} // should never happen
(Some(pre_epoch), Some(post_epoch)) => {
if pre_epoch <= post_epoch {
Ok(())
} else {
Err(anyhow!(
"Invalid epoch: pre {} -> post {}",
pre_epoch,
post_epoch
))
}
}
pub async fn run(&self, pre_state: &State, post_state: &State) -> anyhow::Result<()> {
let pre_epoch = pre_state.get_last_block().epoch;
let post_epoch = post_state.get_last_block().epoch;
if pre_epoch == post_epoch || pre_epoch.checked_add(1).unwrap_or_default() == post_epoch {
Ok(())
} else {
Err(anyhow!(
"Invalid epoch: pre {} -> post {}",
pre_epoch,
post_epoch
))
}
}
}
10 changes: 8 additions & 2 deletions src/checks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,29 @@ pub mod epoch;
pub mod total_supply_native;
pub mod tx_size;

use crate::config::AppConfig;
use block::BlockHeigtCheck;
use block::BlockTimeCheck;
use epoch::EpochCheck;
use total_supply_native::TotalSupplyNativeCheck;
use tx_size::TxSizeCheck;

pub enum Checks {
BlockHeightCheck(BlockHeigtCheck),
BlockTimeCheck(BlockTimeCheck),
EpochCheck(EpochCheck),
TotalSupplyNative(TotalSupplyNativeCheck),
TxSize(TxSizeCheck),
}

pub fn all_checks() -> Vec<Checks> {
pub fn all_checks(config: &AppConfig) -> Vec<Checks> {
vec![
Checks::BlockHeightCheck(BlockHeigtCheck::default()),
Checks::EpochCheck(EpochCheck::default()),
Checks::TotalSupplyNative(TotalSupplyNativeCheck::default()),
Checks::TxSize(TxSizeCheck::default()),
Checks::TxSize(TxSizeCheck::new(
config.max_tx_size,
config.max_tx_inner_len,
)),
]
}
47 changes: 20 additions & 27 deletions src/checks/total_supply_native.rs
Original file line number Diff line number Diff line change
@@ -1,35 +1,28 @@
use crate::{shared::namada::Address, state::State};
use anyhow::anyhow;

#[derive(Clone, Debug, Default)]
pub struct TotalSupplyNativeCheck {}
pub struct TotalSupplyNativeCheck {
token: Address,
}

impl TotalSupplyNativeCheck {
pub async fn run(
&self,
pre_state: &crate::state::State,
post_state: &crate::state::State,
) -> anyhow::Result<()> {
match (
pre_state.latest_total_supply_native,
post_state.latest_total_supply_native,
) {
(None, None) => Ok(()), // nothing happen yet
(None, Some(_)) => Ok(()), // first epoch
(Some(pre_total_supply), None) => Err(anyhow!(
"Invalid state: pre {} -> post None",
pre_total_supply
)), // should never happen
(Some(pre_total_supply), Some(post_total_supply)) => {
if pre_total_supply <= post_total_supply {
Ok(())
} else {
Err(anyhow!(
"Invalid total supply: pre {} -> post {}. Could be valid in case of slashes or rejected governance proposal.",
pre_total_supply,
post_total_supply
))
}
}
pub fn new(token: Address) -> Self {
Self { token }
}

pub async fn run(&self, pre_state: &State, post_state: &State) -> anyhow::Result<()> {
let pre_total_supply = pre_state.get_total_supply(&self.token).unwrap_or_default();
let post_total_supply = post_state.get_total_supply(&self.token).unwrap_or_default();

if pre_total_supply <= post_total_supply {
Ok(())
} else {
Err(anyhow!(
"Invalid total supply: pre {} -> post {}. Could be valid in case of slashes or rejected governance proposal.",
pre_total_supply,
post_total_supply
))
}
}
}
39 changes: 32 additions & 7 deletions src/checks/tx_size.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,37 @@
#[derive(Clone, Debug, Default)]
pub struct TxSizeCheck {}
use crate::state::State;
use anyhow::anyhow;

#[derive(Clone, Debug)]
pub struct TxSizeCheck {
max_tx_size: u64,
max_inner_len: u64,
}

impl TxSizeCheck {
pub async fn run(
&self,
pre_state: &crate::state::State,
post_state: &crate::state::State,
) -> anyhow::Result<()> {
pub fn new(max_tx_size: u64, max_inner_len: u64) -> Self {
Self {
max_tx_size,
max_inner_len,
}
}

pub async fn run(&self, _pre_state: &State, post_state: &State) -> anyhow::Result<()> {
for tx in &post_state.get_last_block().transactions {
if tx.inners.len() > self.max_inner_len as usize {
return Err(anyhow!(
"Transaction inner length is too large: {}",
tx.inners.len()
));
}
for inner in &tx.inners {
if inner.kind.size() > self.max_tx_size as usize {
return Err(anyhow!(
"Transaction size is too large: {}",
inner.kind.size()
));
}
}
}
Ok(())
}
}
12 changes: 10 additions & 2 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::u64;

use crate::log::LogConfig;

#[derive(clap::Parser)]
Expand All @@ -17,12 +19,18 @@ pub struct AppConfig {
#[clap(long, env, default_value_t = 9184)]
pub prometheus_port: u64,

#[clap(long, env, default_value_t = 1)]
#[clap(long, env, default_value_t = u64::MAX)]
pub initial_block_height: u64,

#[clap(long, env, default_value_t = 5)]
#[clap(long, env, default_value_t = 1000)]
pub sleep_for: u64,

#[clap(flatten)]
pub log: LogConfig,

#[clap(long, env, default_value_t = 100000)]
pub max_tx_size: u64,

#[clap(long, env, default_value_t = 100)]
pub max_tx_inner_len: u64,
}
Loading
Loading