griffin_core/uplc/machine/
error.rs

1use super::{ExBudget, Value};
2use crate::uplc::ast::{NamedDeBruijn, Term, Type};
3use alloc::{
4    string::{FromUtf8Error, String, ToString},
5    vec::Vec,
6};
7use num_bigint::BigInt;
8
9#[derive(Debug, Clone, PartialEq, thiserror_no_std::Error)]
10pub enum Error {
11    #[error("execution went over budget\n{:>13} {}\n{:>13} {}", "Mem", .0.mem, "CPU", .0.cpu)]
12    OutOfExError(ExBudget),
13    #[error("invalid step kind: {0}")]
14    InvalidStepKind(u8),
15    #[error(
16        "cannot evaluate an open term:\n{:>13} {}",
17        "Term",
18        indent(redacted(.0.to_string(), 10)),
19    )]
20    OpenTermEvaluated(Term<NamedDeBruijn>),
21    #[error("the validator crashed / exited prematurely")]
22    EvaluationFailure,
23    #[error(
24        "attempted to instantiate a non-polymorphic term\n{:>13} {}",
25        "Term",
26        indent(redacted(format!("{:#?}", .0), 10)),
27    )]
28    NonPolymorphicInstantiation(Value),
29    #[error(
30      "attempted to apply an argument to a non-function\n{:>13} {}\n{:>13} {}",
31      "Thing",
32      indent(redacted(format!("{:#?}", .0), 5)),
33      "Argument",
34      indent(redacted(format!("{:#?}", .1), 5)),
35    )]
36    NonFunctionalApplication(Value, Value),
37    #[error(
38        "attempted to case a non-const\n{:>13} {}",
39        "Value",
40        indent(redacted(format!("{:#?}", .0), 10)),
41    )]
42    NonConstrScrutinized(Value),
43    #[error("Cases: {0:#?}\n\n are missing branch for constr:\n\n{1:#?}")]
44    MissingCaseBranch(Vec<Term<NamedDeBruijn>>, Value),
45    #[error("type mismatch\n{:>13} {0}\n{:>13} {1}", "Expected", "Got")]
46    TypeMismatch(Type, Type),
47    #[error("type mismatch\n{:>13} (list a)\n{:>13} {0}", "Expected", "Got")]
48    ListTypeMismatch(Type),
49    #[error("type mismatch\n{:>13}(pair a b)\n{:>13} {0}", "Expected", "Got")]
50    PairTypeMismatch(Type),
51    #[error(
52        "unexpected empty list\n{:>13} {}",
53        "List",
54        indent(redacted(format!("{:#?}", .0), 10)),
55    )]
56    EmptyList(Value),
57    #[error(
58        "a builtin received a term argument when something else was expected\n{:>13} {}\n{:>13} You probably forgot to wrap the builtin with a force.",
59        "Term",
60        indent(redacted(format!("{:#?}", .0), 10)),
61        "Hint"
62    )]
63    UnexpectedBuiltinTermArgument(Term<NamedDeBruijn>),
64    #[error(
65        "a builtin expected a term argument, but something else was received:\n{:>13} {}\n{:>13} You probably have an extra force wrapped around a builtin",
66        "Term",
67        indent(redacted(format!("{:#?}", .0), 10)),
68        "Hint"
69    )]
70    BuiltinTermArgumentExpected(Term<NamedDeBruijn>),
71    #[error(
72        "Unable to unlift value because it is not a constant\n{:>13} {}",
73        "Value",
74        indent(redacted(format!("{:#?}", .0), 10)),
75    )]
76    NotAConstant(Value),
77    #[error("The evaluation never reached a final state")]
78    MachineNeverReachedDone,
79    #[error("integerToByteString encountered negative size\n{:>13} {0}", "Size")]
80    IntegerToByteStringNegativeSize(BigInt),
81    #[error("replicateByte encountered negative size\n{:>13} {0}", "Size")]
82    ReplicateByteNegativeSize(BigInt),
83    #[error("integerToByteString encountered negative input\n{:>13} {0}", "Input")]
84    IntegerToByteStringNegativeInput(BigInt),
85    #[error(
86        "bytes size beyond limit when converting from integer\n{:>13} {0}\n{:>13} {1}",
87        "Size",
88        "Maximum"
89    )]
90    IntegerToByteStringSizeTooBig(BigInt, i64),
91    #[error(
92        "bytes size beyond limit when replicate byte\n{:>13} {0}\n{:>13} {1}",
93        "Size",
94        "Maximum"
95    )]
96    ReplicateByteSizeTooBig(BigInt, i64),
97    #[error(
98        "bytes size below limit when converting from integer\n{:>13} {0}\n{:>13} {1}",
99        "Size",
100        "Minimum"
101    )]
102    IntegerToByteStringSizeTooSmall(BigInt, usize),
103    #[error("Decoding utf8")]
104    Utf8(#[from] FromUtf8Error),
105    #[error(
106        "Out of Bounds\n{:>13} {}\nb{:>13} {}\n{:>13} 0 - {}",
107        "Index",
108        .0,
109        "ByteArray",
110        hex::encode(.1),
111        "Allowed",
112        .1.len() - 1
113    )]
114    ByteStringOutOfBounds(BigInt, Vec<u8>),
115    #[error(
116        "attempt to consByteString something than isn't a byte between [0-255]\n{:>13} {0}",
117        "Found"
118    )]
119    ByteStringConsNotAByte(BigInt),
120    #[error("divide By Zero: {0} / {1}")]
121    DivideByZero(BigInt, BigInt),
122    #[error("Ed25519S PublicKey should be 32 bytes but it was {0}")]
123    UnexpectedEd25519PublicKeyLength(usize),
124    #[error("Ed25519S Signature should be 64 bytes but it was {0}")]
125    UnexpectedEd25519SignatureLength(usize),
126    #[error(
127      "failed to deserialise PlutusData using {0}\n{:>13} {}",
128      "Value",
129      indent(redacted(format!("{:#?}", .1), 10)),
130    )]
131    DeserialisationError(String, Value),
132    #[error("integer overflow")]
133    OverflowError,
134    #[error("{0} is not within the bounds of a Natural")]
135    OutsideNaturalBounds(BigInt),
136    #[error("{0} is not within the bounds of a Byte")]
137    OutsideByteBounds(BigInt),
138    #[error("readBit: index out of bounds")]
139    ReadBitOutOfBounds,
140    #[error("writeBits: index out of bounds")]
141    WriteBitsOutOfBounds,
142    #[error("illegal operation on empty ByteArray")]
143    EmptyByteArray,
144    #[error("blst error {0:?}")]
145    Blst(blst::BLST_ERROR),
146    #[error("blst::hashToGroup")]
147    HashToCurveDstTooBig,
148    #[cfg(not(target_family = "wasm"))]
149    #[error(transparent)]
150    Secp256k1(#[from] secp256k1::Error),
151    #[cfg(target_family = "wasm")]
152    #[error("{0}")]
153    K256Error(String),
154}
155
156#[cfg(target_family = "wasm")]
157impl From<k256::ecdsa::Error> for Error {
158    fn from(error: k256::ecdsa::Error) -> Error {
159        Error::K256Error(format!("K256 error: {}", error))
160    }
161}
162
163/// Print only the first n lines of possibly long output, and redact the rest if longer.
164fn redacted(s: String, max_rows: usize) -> String {
165    let rows = s.lines();
166
167    if rows.count() > max_rows {
168        let last_line = s.lines().last().unwrap();
169        let mut s = s.lines().take(max_rows).collect::<Vec<_>>().join("\n");
170        s.push_str(&format!("\n    ...redacted...\n{last_line}"));
171        s
172    } else {
173        s
174    }
175}
176
177fn indent(s: String) -> String {
178    s.lines().collect::<Vec<_>>().join(&format!("\n{:>14}", ""))
179}