mod node;
mod precompile;
mod precompile_registry;
mod state;
mod wire;
use alloc::boxed::Box;
pub use node::{DataChunk, Digest, Node, NodeType, Payload, TRUE_DIGEST, Tag};
pub use precompile::{Precompile, precompile_id};
pub use precompile_registry::PrecompileRegistry;
pub use state::{DeferredContext, DeferredState};
pub use wire::{DeferredStateWire, IntegrityError, TRUE_INDEX, WireEntry};
use crate::Word;
pub type DeferredRoot = Digest;
pub const DEFERRED_ROOT_DOMAIN: Word = Word::new(Tag::AND.as_word());
pub const DEFAULT_MAX_DEFERRED_ELEMENTS: usize = 1 << 20;
pub fn fold_deferred_root(root: DeferredRoot, statement: Digest) -> DeferredRoot {
Node::and(root, statement).digest()
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub struct DeferredRootTracker {
root: DeferredRoot,
}
impl DeferredRootTracker {
pub fn new() -> Self {
Self::default()
}
pub fn from_root(root: DeferredRoot) -> Self {
Self { root }
}
pub fn root(&self) -> DeferredRoot {
self.root
}
pub fn record_statement(&mut self, statement: Digest) {
self.root = fold_deferred_root(self.root, statement);
}
}
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
pub enum DeferredError {
#[error("invalid or unknown deferred tag")]
InvalidTag,
#[error("referenced digest is not present in deferred state")]
MissingNode,
#[error("conflicting node definition for digest")]
ConflictingNode,
#[error("payload is not valid for the given tag")]
InvalidPayload,
#[error("equality assertion failed")]
AssertionFailed,
#[error("deferred insertion requires {num_elements} elements but only {max} remain")]
DeferredStateTooLarge { num_elements: usize, max: usize },
#[error("operation is not supported by this handler")]
Unsupported,
#[error("invalid deferred root transition: expected {expected:?}, got {actual:?}")]
InvalidDeferredRootTransition { expected: Digest, actual: Digest },
}
#[derive(Debug, Clone, thiserror::Error)]
pub enum PrecompileError {
#[error("deferred DAG is missing a node referenced during evaluation")]
MissingNode,
#[error("node failed precompile validation")]
InvalidNode,
#[error("deferred assertion failed: values disagree")]
AssertionFailed,
#[error(transparent)]
Other(#[from] DeferredError),
#[error("precompile `{name}`: {source}")]
Precompile {
name: &'static str,
source: Box<PrecompileError>,
},
}
impl PrecompileError {
pub fn root(&self) -> &PrecompileError {
match self {
PrecompileError::Precompile { source, .. } => source.root(),
other => other,
}
}
pub(crate) fn with_precompile(name: &'static str, source: PrecompileError) -> Self {
Self::Precompile { name, source: Box::new(source) }
}
}