use core::fmt;
use std::error;
const MAX_CELLS: usize = 2 * 1024 * 1024 * 1024 - 1;
const MAX_FRAMES: usize = 1024 * 1024;
#[non_exhaustive]
#[derive(Clone, Debug)]
pub enum LimitError {
MaxCellsExceeded {
got: usize,
max: usize,
bound: &'static str,
},
MaxFramesExceeded {
got: usize,
max: usize,
bound: &'static str,
},
}
impl fmt::Display for LimitError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let (limit, got, max, bound) = match self {
LimitError::MaxCellsExceeded { got, max, bound } => ("cells", got, max, bound),
LimitError::MaxFramesExceeded { got, max, bound } => ("frames", got, max, bound),
};
write!(
f,
"maximum number of {} exceeded (needed {}, maximum {}) (bound: {})",
limit, got, max, bound,
)
}
}
impl error::Error for LimitError {}
impl LimitError {
fn check_max_cells(got: usize, bound: &'static str) -> Result<(), Self> {
if got > MAX_CELLS {
Err(Self::MaxCellsExceeded {
got,
max: MAX_CELLS,
bound,
})
} else {
Ok(())
}
}
fn check_max_frames(got: usize, bound: &'static str) -> Result<(), Self> {
if got > MAX_FRAMES {
Err(Self::MaxFramesExceeded {
got,
max: MAX_CELLS,
bound,
})
} else {
Ok(())
}
}
pub(super) fn check_program<J: crate::jet::Jet>(
program: &crate::RedeemNode<J>,
) -> Result<(), Self> {
let source_ty_width = program.arrow().source.bit_width();
let target_ty_width = program.arrow().target.bit_width();
let bounds = program.bounds();
Self::check_max_cells(source_ty_width, "source type width")?;
Self::check_max_cells(target_ty_width, "target type width")?;
Self::check_max_cells(bounds.extra_cells, "extra cells")?;
Self::check_max_cells(
source_ty_width + target_ty_width,
"source + target type widths",
)?;
Self::check_max_cells(
source_ty_width + target_ty_width + bounds.extra_cells,
"source + target type widths + extra cells",
)?;
Self::check_max_frames(bounds.extra_frames, "extra frames")?;
Self::check_max_frames(
bounds.extra_frames + crate::analysis::IO_EXTRA_FRAMES,
"extra frames + fixed overhead",
)?;
Ok(())
}
}