diff --git a/crates/uplc/src/machine.rs b/crates/uplc/src/machine.rs index 6efbdf3e..1e54f9e6 100644 --- a/crates/uplc/src/machine.rs +++ b/crates/uplc/src/machine.rs @@ -320,7 +320,7 @@ impl Machine { } fn eval_builtin_app(&mut self, runtime: BuiltinRuntime) -> Result { - let cost = runtime.to_ex_budget(&self.costs.builtin_costs); + let cost = runtime.to_ex_budget(&self.costs.builtin_costs)?; self.spend_budget(cost)?; diff --git a/crates/uplc/src/machine/cost_model.rs b/crates/uplc/src/machine/cost_model.rs index e2a1503a..9eb8124d 100644 --- a/crates/uplc/src/machine/cost_model.rs +++ b/crates/uplc/src/machine/cost_model.rs @@ -1,5 +1,6 @@ -use super::Value; +use super::{runtime, Error, Value}; use crate::builtins::DefaultFunction; +use num_bigint::BigInt; use pallas_primitives::conway::Language; use std::collections::HashMap; @@ -1741,8 +1742,8 @@ impl Default for BuiltinCosts { } impl BuiltinCosts { - pub fn to_ex_budget(&self, fun: DefaultFunction, args: &[Value]) -> ExBudget { - match fun { + pub fn to_ex_budget(&self, fun: DefaultFunction, args: &[Value]) -> Result { + Ok(match fun { DefaultFunction::AddInteger => ExBudget { mem: self .add_integer @@ -2307,18 +2308,31 @@ impl BuiltinCosts { .cpu .cost(args[0].to_ex_mem(), args[1].to_ex_mem()), }, - DefaultFunction::IntegerToByteString => ExBudget { - mem: self.integer_to_byte_string.mem.cost( - args[0].to_ex_mem(), - args[1].to_ex_mem(), - args[2].to_ex_mem(), - ), - cpu: self.integer_to_byte_string.cpu.cost( - args[0].to_ex_mem(), - args[1].to_ex_mem(), - args[2].to_ex_mem(), - ), - }, + DefaultFunction::IntegerToByteString => { + let uplc_int = args[1].unwrap_integer()?; + + if uplc_int > &BigInt::from(runtime::INTEGER_TO_BYTE_STRING_MAXIMUM_OUTPUT_LENGTH) { + return Err(Error::IntegerToByteStringSizeTooBig( + uplc_int.clone(), + runtime::INTEGER_TO_BYTE_STRING_MAXIMUM_OUTPUT_LENGTH, + )); + } + + let arg1 = u64::try_from(uplc_int).unwrap().try_into().unwrap(); + + ExBudget { + mem: self.integer_to_byte_string.mem.cost( + args[0].to_ex_mem(), + arg1, + args[2].to_ex_mem(), + ), + cpu: self.integer_to_byte_string.cpu.cost( + args[0].to_ex_mem(), + arg1, + args[2].to_ex_mem(), + ), + } + } DefaultFunction::ByteStringToInteger => ExBudget { mem: self .byte_string_to_integer @@ -2329,7 +2343,7 @@ impl BuiltinCosts { .cpu .cost(args[0].to_ex_mem(), args[1].to_ex_mem()), }, - } + }) } } diff --git a/crates/uplc/src/machine/runtime.rs b/crates/uplc/src/machine/runtime.rs index c69bd038..25387f12 100644 --- a/crates/uplc/src/machine/runtime.rs +++ b/crates/uplc/src/machine/runtime.rs @@ -31,7 +31,7 @@ const BLST_P1_COMPRESSED_SIZE: usize = 48; const BLST_P2_COMPRESSED_SIZE: usize = 96; -const INTEGER_TO_BYTE_STRING_MAXIMUM_OUTPUT_LENGTH: i64 = 8192; +pub const INTEGER_TO_BYTE_STRING_MAXIMUM_OUTPUT_LENGTH: i64 = 8192; //#[derive(std::cmp::PartialEq)] //pub enum EvalMode { @@ -96,7 +96,7 @@ impl BuiltinRuntime { Ok(()) } - pub fn to_ex_budget(&self, costs: &BuiltinCosts) -> ExBudget { + pub fn to_ex_budget(&self, costs: &BuiltinCosts) -> Result { costs.to_ex_budget(self.fun, &self.args) } } @@ -1388,12 +1388,13 @@ impl DefaultFunction { return Err(Error::IntegerToByteStringNegativeSize(size.clone())); } - if size > &INTEGER_TO_BYTE_STRING_MAXIMUM_OUTPUT_LENGTH.into() { - return Err(Error::IntegerToByteStringSizeTooBig( - size.clone(), - INTEGER_TO_BYTE_STRING_MAXIMUM_OUTPUT_LENGTH, - )); - } + // Since this is checked at cost time it is no longer needed + // if size > &INTEGER_TO_BYTE_STRING_MAXIMUM_OUTPUT_LENGTH.into() { + // return Err(Error::IntegerToByteStringSizeTooBig( + // size.clone(), + // INTEGER_TO_BYTE_STRING_MAXIMUM_OUTPUT_LENGTH, + // )); + // } if size.is_zero() && integer_log2(input.clone())