minsc 0.2.0

A Miniscript-based high-level scripting language for Bitcoin contracts
Documentation
use lalrpop_util::ParseError;
use std::fmt;

use miniscript::bitcoin::hashes;
use miniscript::descriptor::DescriptorKeyParseError;
use miniscript::policy::compiler::CompilerError;

use crate::ast::Ident;
use crate::runtime::Value;

pub type Result<T> = std::result::Result<T, Error>;

#[derive(thiserror::Error, Debug)]
pub enum Error {
    #[error("Assigned variable name already exists: {0}")]
    AssignedVariableExists(Ident),

    #[error("Missing expected return value, set a final expression or a main() function")]
    NoReturnValue,

    #[error("Undefined function: {0}")]
    FnNotFound(Ident),

    #[error("Undefined variable: {0}")]
    VarNotFound(Ident),

    #[error("Expected a function, not {0:?}")]
    NotFn(Value),

    #[error("Expected an array, not {0:?}")]
    NotArray(Value),

    #[error("Expected a number, not {0:?}")]
    NotNumber(Value),

    #[error("Expected a pubkey, not {0:?}")]
    NotPubKey(Value),

    #[error("Expected an hash, not {0:?}")]
    NotHash(Value),

    #[error("Expected a network type, not {0:?}")]
    NotNetwork(Value),

    #[error("Expected a policy or array of policies, not {0:?}")]
    NotPolicyLike(Value),

    #[error("Expected a miniscript or policy, not {0:?}")]
    NotMiniscriptLike(Value),

    #[error("Expected a descriptor, policy or miniscript, not {0:?}")]
    NotDescriptorLike(Value),

    #[error("Array index out of range")]
    ArrayIndexOutOfRange,

    #[error("Function {0} expected {1} arguments, not {2}")]
    ArgumentMismatch(Ident, usize, usize),

    #[error("Invalid datetime string: {0}")]
    InvalidDateTime(chrono::ParseError),

    #[error("Absolute by-blocktime timelock out of range, supported up to 2106")]
    InvalidDateTimeOutOfRange,

    #[error("Heightwise duration must be divisible by 10 minutes")]
    InvalidDurationHeightwise,

    #[error("Relative by-blockheight timelocks are only supported for up to 65535 blocks (roughly 455 days)")]
    InvalidDurationBlocksOutOfRange,

    #[error("Relative by-blocktime timelocks are only supported for up to 33553920 seconds (roughly 1 year)")]
    InvalidDurationTimeOutOfRange,

    #[error("Parser error: {0}")]
    ParseError(String),

    #[error("Invalid arguments")]
    InvalidArguments,

    #[error("Descriptors can only be derived with a single child code and without '/*'")]
    InvalidDescriptorDerivation,

    #[error("Standalone single keys cannot be derived")]
    InvalidSingleDerivation,

    #[error("sh() can only wrap wsh() or wpkh()")]
    InvalidShUse,

    #[error("in {0}(): {1}")]
    CallError(Ident, Box<Error>),

    #[error("Descriptor key parse error: {0}")]
    DescriptorKeyParseError(DescriptorKeyParseError),

    #[error("Miniscript compiler error: {0}")]
    MiniscriptCompilerError(CompilerError),

    #[error("Hash error: {0}")]
    HashError(hashes::Error),

    #[error("Invalid hex: {0}")]
    HexError(hashes::hex::Error),

    #[error("IO error: {0:?}")]
    Io(std::io::Error),
}

impl<L, T, E> From<ParseError<L, T, E>> for Error
where
    L: fmt::Display,
    T: fmt::Display,
    E: fmt::Display,
{
    fn from(err: ParseError<L, T, E>) -> Self {
        Error::ParseError(err.to_string())
    }
}

impl_from_variant!(DescriptorKeyParseError, Error);
impl_from_variant!(CompilerError, Error, MiniscriptCompilerError);
impl_from_variant!(hashes::Error, Error, HashError);
impl_from_variant!(hashes::hex::Error, Error, HexError);
impl_from_variant!(chrono::ParseError, Error, InvalidDateTime);
impl_from_variant!(std::io::Error, Error, Io);