From 84df3be139deb3562a413a1950d75616cf1ebc55 Mon Sep 17 00:00:00 2001 From: Kasey White Date: Tue, 12 Jul 2022 23:50:25 -0400 Subject: [PATCH] start filling in builtin cost model Co-authored-by: rvcas --- crates/uplc/src/ast.rs | 4 +- crates/uplc/src/machine.rs | 15 +- crates/uplc/src/machine/cost_model.rs | 356 +++++++++++++++++++++++++- 3 files changed, 364 insertions(+), 11 deletions(-) diff --git a/crates/uplc/src/ast.rs b/crates/uplc/src/ast.rs index b2f18355..48177a28 100644 --- a/crates/uplc/src/ast.rs +++ b/crates/uplc/src/ast.rs @@ -4,7 +4,7 @@ use crate::{ builtins::DefaultFunction, debruijn::{self, Converter}, machine::{ - cost_model::{ExBudget, MachineCosts}, + cost_model::{ExBudget, CostModel}, Machine, }, }; @@ -407,7 +407,7 @@ impl From> for Term { impl Program { pub fn eval(&self) -> Result, crate::machine::Error> { - let mut machine = Machine::new(MachineCosts::default(), ExBudget::default(), 200); + let mut machine = Machine::new(CostModel::default(), ExBudget::default(), 200); let (term, _, _) = machine.run(&self.term)?; diff --git a/crates/uplc/src/machine.rs b/crates/uplc/src/machine.rs index e6f61836..e111c99a 100644 --- a/crates/uplc/src/machine.rs +++ b/crates/uplc/src/machine.rs @@ -7,13 +7,13 @@ pub mod cost_model; mod error; mod runtime; -use cost_model::{ExBudget, MachineCosts, StepKind}; +use cost_model::{ExBudget, StepKind}; pub use error::Error; -use self::runtime::BuiltinRuntime; +use self::{cost_model::CostModel, runtime::BuiltinRuntime}; pub struct Machine { - costs: MachineCosts, + costs: CostModel, ex_budget: ExBudget, frames: Vec, slippage: u32, @@ -22,7 +22,7 @@ pub struct Machine { } impl Machine { - pub fn new(costs: MachineCosts, initial_budget: ExBudget, slippage: u32) -> Machine { + pub fn new(costs: CostModel, initial_budget: ExBudget, slippage: u32) -> Machine { Machine { costs, ex_budget: initial_budget, @@ -37,7 +37,7 @@ impl Machine { &mut self, term: &Term, ) -> Result<(Term, usize, Vec), Error> { - let startup_budget = self.costs.get(StepKind::StartUp); + let startup_budget = self.costs.machine_costs.get(StepKind::StartUp); self.spend_budget(startup_budget)?; @@ -244,7 +244,7 @@ impl Machine { runtime: BuiltinRuntime, ) -> Result { if runtime.is_ready() { - self.spend_budget(ExBudget::default())?; + self.spend_budget(todo!())?; runtime.call() } else { @@ -281,7 +281,8 @@ impl Machine { fn spend_unbudgeted_steps(&mut self) -> Result<(), Error> { for i in 0..self.unbudgeted_steps.len() - 1 { - let mut unspent_step_budget = self.costs.get(StepKind::try_from(i as u8)?); + let mut unspent_step_budget = + self.costs.machine_costs.get(StepKind::try_from(i as u8)?); unspent_step_budget.occurences(self.unbudgeted_steps[i] as i32); diff --git a/crates/uplc/src/machine/cost_model.rs b/crates/uplc/src/machine/cost_model.rs index 1fb5ec94..8a08bdd3 100644 --- a/crates/uplc/src/machine/cost_model.rs +++ b/crates/uplc/src/machine/cost_model.rs @@ -11,14 +11,14 @@ impl ExBudget { self.cpu *= n; } } - +#[derive(Default)] pub struct CostModel { pub machine_costs: MachineCosts, + pub builtin_costs: BuiltinCosts, } /// There's no entry for Error since we'll be exiting anyway; also, what would /// happen if calling 'Error' caused the budget to be exceeded? -#[derive(Default)] pub struct MachineCosts { startup: ExBudget, var: ExBudget, @@ -47,6 +47,42 @@ impl MachineCosts { } } +impl Default for MachineCosts { + fn default() -> Self { + Self { + startup: ExBudget { mem: 100, cpu: 100 }, + var: ExBudget { + mem: 100, + cpu: 23000, + }, + constant: ExBudget { + mem: 100, + cpu: 23000, + }, + lambda: ExBudget { + mem: 100, + cpu: 23000, + }, + delay: ExBudget { + mem: 100, + cpu: 23000, + }, + force: ExBudget { + mem: 100, + cpu: 23000, + }, + apply: ExBudget { + mem: 100, + cpu: 23000, + }, + builtin: ExBudget { + mem: 100, + cpu: 23000, + }, + } + } +} + pub struct BuiltinCosts { pub add_integer: CostingFun, pub subtract_integer: CostingFun, @@ -114,6 +150,322 @@ pub struct BuiltinCosts { pub serialise_data: CostingFun, } +impl Default for BuiltinCosts { + fn default() -> Self { + Self { + add_integer: CostingFun { + memory: TwoArguments::MaxSize(MaxSize { + intercept: 1, + slope: 1, + }), + cpu: TwoArguments::MaxSize(MaxSize { + intercept: 205665, + slope: 812, + }), + }, + subtract_integer: CostingFun { + memory: TwoArguments::MaxSize(MaxSize { + intercept: 1, + slope: 1, + }), + cpu: TwoArguments::MaxSize(MaxSize { + intercept: 205665, + slope: 812, + }), + }, + multiply_integer: CostingFun { + memory: TwoArguments::AddedSizes(AddedSizes { + intercept: 0, + slope: 1, + }), + + cpu: TwoArguments::AddedSizes(AddedSizes { + intercept: 69522, + slope: 11687, + }), + }, + divide_integer: CostingFun { + memory: TwoArguments::SubtractedSizes(SubtractedSizes { + intercept: 0, + slope: 1, + minimum: 1, + }), + cpu: TwoArguments::ConstAboveDiagonal(ConstantOrTwoArguments { + constant: 196500, + model: Box::new(TwoArguments::MultipliedSizes(MultipliedSizes { + intercept: 453240, + slope: 220, + })), + }), + }, + quotient_integer: CostingFun { + memory: TwoArguments::SubtractedSizes(SubtractedSizes { + intercept: 0, + slope: 1, + minimum: 1, + }), + cpu: TwoArguments::ConstAboveDiagonal(ConstantOrTwoArguments { + constant: 196500, + model: Box::new(TwoArguments::MultipliedSizes(MultipliedSizes { + intercept: 453240, + slope: 220, + })), + }), + }, + remainder_integer: CostingFun { + memory: TwoArguments::SubtractedSizes(SubtractedSizes { + intercept: 0, + slope: 1, + minimum: 1, + }), + cpu: TwoArguments::ConstAboveDiagonal(ConstantOrTwoArguments { + constant: 196500, + model: Box::new(TwoArguments::MultipliedSizes(MultipliedSizes { + intercept: 453240, + slope: 220, + })), + }), + }, + mod_integer: CostingFun { + memory: TwoArguments::SubtractedSizes(SubtractedSizes { + intercept: 0, + slope: 1, + minimum: 1, + }), + cpu: TwoArguments::ConstAboveDiagonal(ConstantOrTwoArguments { + constant: 196500, + model: Box::new(TwoArguments::MultipliedSizes(MultipliedSizes { + intercept: 453240, + slope: 220, + })), + }), + }, + equals_integer: CostingFun { + memory: TwoArguments::ConstantCost(1), + cpu: TwoArguments::MinSize(MinSize { + intercept: 208512, + slope: 421, + }), + }, + less_than_integer: CostingFun { + memory: TwoArguments::ConstantCost(1), + cpu: TwoArguments::MinSize(MinSize { + intercept: 208896, + slope: 511, + }), + }, + less_than_equals_integer: CostingFun { + memory: TwoArguments::ConstantCost(1), + cpu: TwoArguments::MinSize(MinSize { + intercept: 204924, + slope: 473, + }), + }, + append_byte_string: CostingFun { + memory: TwoArguments::AddedSizes(AddedSizes { + intercept: 1000, + slope: 571, + }), + cpu: TwoArguments::AddedSizes(AddedSizes { + intercept: 0, + slope: 1, + }), + }, + cons_byte_string: CostingFun { + memory: TwoArguments::AddedSizes(AddedSizes { + intercept: 0, + slope: 1, + }), + cpu: TwoArguments::LinearInY(LinearSize { + intercept: 221973, + slope: 511, + }), + }, + slice_byte_string: CostingFun { + memory: ThreeArguments::LinearInZ(LinearSize { + intercept: 4, + slope: 0, + }), + cpu: ThreeArguments::LinearInZ(LinearSize { + intercept: 265318, + slope: 0, + }), + }, + length_of_byte_string: CostingFun { + memory: OneArgument::ConstantCost(10), + cpu: OneArgument::ConstantCost(1000), + }, + index_byte_string: CostingFun { + memory: TwoArguments::ConstantCost(4), + cpu: TwoArguments::ConstantCost(57667), + }, + equals_byte_string: CostingFun { + memory: TwoArguments::ConstantCost(1), + cpu: TwoArguments::LinearOnDiagonal(ConstantOrLinear { + constant: 245000, + intercept: 216773, + slope: 62, + }), + }, + less_than_byte_string: CostingFun { + memory: TwoArguments::ConstantCost(1), + cpu: TwoArguments::MinSize(MinSize { + intercept: 197145, + slope: 156, + }), + }, + less_than_equals_byte_string: CostingFun { + memory: todo!(), + cpu: todo!(), + }, + sha2_256: CostingFun { + memory: todo!(), + cpu: todo!(), + }, + sha3_256: CostingFun { + memory: todo!(), + cpu: todo!(), + }, + blake2b_256: CostingFun { + memory: todo!(), + cpu: todo!(), + }, + verify_ed25519_signature: CostingFun { + memory: todo!(), + cpu: todo!(), + }, + verify_ecdsa_secp256k1_signature: CostingFun { + memory: todo!(), + cpu: todo!(), + }, + verify_schnorr_secp256k1_signature: CostingFun { + memory: todo!(), + cpu: todo!(), + }, + append_string: CostingFun { + memory: todo!(), + cpu: todo!(), + }, + equals_string: CostingFun { + memory: todo!(), + cpu: todo!(), + }, + encode_utf8: CostingFun { + memory: todo!(), + cpu: todo!(), + }, + decode_utf8: CostingFun { + memory: todo!(), + cpu: todo!(), + }, + if_then_else: CostingFun { + memory: todo!(), + cpu: todo!(), + }, + choose_unit: CostingFun { + memory: todo!(), + cpu: todo!(), + }, + trace: CostingFun { + memory: todo!(), + cpu: todo!(), + }, + fst_pair: CostingFun { + memory: todo!(), + cpu: todo!(), + }, + snd_pair: CostingFun { + memory: todo!(), + cpu: todo!(), + }, + choose_list: CostingFun { + memory: todo!(), + cpu: todo!(), + }, + mk_cons: CostingFun { + memory: todo!(), + cpu: todo!(), + }, + head_list: CostingFun { + memory: todo!(), + cpu: todo!(), + }, + tail_list: CostingFun { + memory: todo!(), + cpu: todo!(), + }, + null_list: CostingFun { + memory: todo!(), + cpu: todo!(), + }, + choose_data: CostingFun { + memory: todo!(), + cpu: todo!(), + }, + constr_data: CostingFun { + memory: todo!(), + cpu: todo!(), + }, + map_data: CostingFun { + memory: todo!(), + cpu: todo!(), + }, + list_data: CostingFun { + memory: todo!(), + cpu: todo!(), + }, + i_data: CostingFun { + memory: todo!(), + cpu: todo!(), + }, + b_data: CostingFun { + memory: todo!(), + cpu: todo!(), + }, + un_constr_data: CostingFun { + memory: todo!(), + cpu: todo!(), + }, + un_map_data: CostingFun { + memory: todo!(), + cpu: todo!(), + }, + un_list_data: CostingFun { + memory: todo!(), + cpu: todo!(), + }, + un_i_data: CostingFun { + memory: todo!(), + cpu: todo!(), + }, + un_b_data: CostingFun { + memory: todo!(), + cpu: todo!(), + }, + equals_data: CostingFun { + memory: todo!(), + cpu: todo!(), + }, + mk_pair_data: CostingFun { + memory: todo!(), + cpu: todo!(), + }, + mk_nil_data: CostingFun { + memory: todo!(), + cpu: todo!(), + }, + mk_nil_pair_data: CostingFun { + memory: todo!(), + cpu: todo!(), + }, + serialise_data: CostingFun { + memory: todo!(), + cpu: todo!(), + }, + } + } +} + pub struct CostingFun { pub memory: T, pub cpu: T,