use crate::{
asm::{self, Word},
Stack,
};
use core::fmt;
use thiserror::Error;
pub type CheckResult<T> = Result<T, CheckError>;
#[derive(Debug, Error)]
pub enum CheckError {
#[error("errors occurred while executing one or more constraints: {0}")]
ConstraintErrors(#[from] ConstraintErrors),
#[error("one or more constraints were unsatisfied: {0}")]
ConstraintsUnsatisfied(#[from] ConstraintsUnsatisfied),
}
#[derive(Debug, Error)]
pub struct ConstraintErrors(pub Vec<(usize, ConstraintError)>);
#[derive(Debug, Error)]
pub struct ConstraintsUnsatisfied(pub Vec<usize>);
pub type ConstraintResult<T> = Result<T, ConstraintError>;
#[derive(Debug, Error)]
pub enum ConstraintError {
#[error(
"invalid constraint evaluation result\n \
expected: [0] (false) or [1] (true)\n \
found: {0:?}"
)]
InvalidEvaluation(Stack),
#[error("operation at index {0} failed: {1}")]
Op(usize, OpError),
}
pub type OpResult<T> = Result<T, OpError>;
#[derive(Debug, Error)]
pub enum OpError {
#[error("access operation error: {0}")]
Access(#[from] AccessError),
#[error("ALU operation error: {0}")]
Alu(#[from] AluError),
#[error("crypto operation error: {0}")]
Crypto(#[from] CryptoError),
#[error("stack operation error: {0}")]
Stack(#[from] StackError),
#[error("repeat operation error: {0}")]
Repeat(#[from] RepeatError),
#[error("total control flow operation error: {0}")]
TotalControlFlow(#[from] TotalControlFlowError),
#[error("temporary operation error: {0}")]
Temporary(#[from] TemporaryError),
#[error("bytecode error: {0}")]
FromBytes(#[from] asm::FromBytesError),
#[error("PC counter overflowed")]
PcOverflow,
}
#[derive(Debug, Error)]
pub enum AccessError {
#[error("decision variable slot out of bounds")]
DecisionSlotOutOfBounds,
#[error("decision variable slot index out of bounds")]
DecisionIndexOutOfBounds,
#[error("the length of a decision variable slot is too large: {0}")]
DecisionLengthTooLarge(usize),
#[error("solution data index out of bounds")]
SolutionDataOutOfBounds,
#[error("transient data index out of bounds")]
TransientDataOutOfBounds,
#[error("transient data key out of bounds")]
TransientDataKeyOutOfBounds,
#[error("state slot out of bounds")]
StateSlotOutOfBounds,
#[error("invalid state slot delta: expected `0` or `1`, found {0}")]
InvalidStateSlotDelta(Word),
}
#[derive(Debug, Error)]
pub enum AluError {
#[error("word overflow")]
Overflow,
#[error("word underflow")]
Underflow,
#[error("attempted to divide by zero")]
DivideByZero,
}
#[derive(Debug, Error)]
pub enum CryptoError {
#[error("failed to verify ed25519 signature: {0}")]
Ed25519(#[from] ed25519_dalek::ed25519::Error),
#[error("failed to recover secp256k1 public key: {0}")]
Secp256k1(#[from] secp256k1::Error),
#[error("failed to parse secp256k1 recovery id")]
Secp256k1RecoveryId,
}
pub type StackResult<T> = Result<T, StackError>;
#[derive(Debug, Error)]
pub enum StackError {
#[error("attempted to pop an empty stack")]
Empty,
#[error("indexed stack out of bounds")]
IndexOutOfBounds,
#[error("the {}-word stack size limit was exceeded", crate::Stack::SIZE_LIMIT)]
Overflow,
#[error(
"invalid condition\n \
expected: [0] (false) or [1] (true)\n \
found: {0}"
)]
InvalidCondition(Word),
}
pub type RepeatResult<T> = Result<T, RepeatError>;
#[derive(Debug, Error)]
pub enum RepeatError {
#[error("attempted to repeat to empty stack")]
Empty,
#[error("attempted to access repeat counter with empty stack")]
NoCounter,
#[error("The count direction must be 0 or 1")]
InvalidCountDirection,
#[error("the {}-word stack size limit was exceeded", crate::Stack::SIZE_LIMIT)]
Overflow,
}
pub type TotalControlFlowResult<T> = Result<T, TotalControlFlowError>;
#[derive(Debug, Error)]
pub enum TotalControlFlowError {
#[error("jump forward if requires a boolean condition")]
InvalidJumpForwardIfCondition,
#[error("jump forward if requires to jump at least one instruction")]
JumpedToSelf,
#[error("halt if requires a boolean condition")]
InvalidHaltIfCondition,
}
pub type TemporaryResult<T> = Result<T, TemporaryError>;
#[derive(Debug, Error)]
pub enum TemporaryError {
#[error("attempted to pop an empty memory")]
Empty,
#[error("indexed memory out of bounds")]
IndexOutOfBounds,
#[error("the {}-word stack size limit was exceeded", crate::Memory::SIZE_LIMIT)]
Overflow,
}
impl fmt::Display for ConstraintErrors {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("the constraints at the following indices failed: \n")?;
for (ix, err) in &self.0 {
f.write_str(&format!(" {ix}: {err}\n"))?;
}
Ok(())
}
}
impl fmt::Display for ConstraintsUnsatisfied {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("the constraints at the following indices returned false: \n")?;
for ix in &self.0 {
f.write_str(&format!(" {ix}\n"))?;
}
Ok(())
}
}
impl From<core::convert::Infallible> for OpError {
fn from(err: core::convert::Infallible) -> Self {
match err {}
}
}