Add a debug flag for uplc eval
This commit is contained in:
@@ -30,7 +30,7 @@ patricia_tree = "0.8.0"
|
||||
petgraph = "0.6.3"
|
||||
pretty = "0.12.3"
|
||||
serde = { version = "1.0.197", features = ["derive", "rc"] }
|
||||
strum = "0.24.1"
|
||||
strum = { version = "0.26.3", features = ["derive"] }
|
||||
thiserror = "1.0.39"
|
||||
uplc = { path = '../uplc', version = "1.1.10" }
|
||||
vec1 = "1.10.1"
|
||||
|
||||
@@ -12,9 +12,11 @@ use crate::{
|
||||
},
|
||||
IdGenerator,
|
||||
};
|
||||
|
||||
use indexmap::IndexMap;
|
||||
use std::{collections::HashMap, rc::Rc};
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
use uplc::{
|
||||
builder::{CONSTR_FIELDS_EXPOSER, CONSTR_INDEX_EXPOSER},
|
||||
builtins::DefaultFunction,
|
||||
|
||||
@@ -45,6 +45,7 @@ pallas-traverse.workspace = true
|
||||
rand = "0.8.5"
|
||||
regex = "1.7.1"
|
||||
serde_json = "1.0.94"
|
||||
strum = { version = "0.26.3", features = ["derive"] }
|
||||
thiserror = "1.0.39"
|
||||
uplc = { path = '../uplc', version = "1.1.10" }
|
||||
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
use miette::IntoDiagnostic;
|
||||
use pallas_primitives::conway::Language;
|
||||
use serde_json::json;
|
||||
use std::{path::PathBuf, process};
|
||||
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
use uplc::{
|
||||
ast::{FakeNamedDeBruijn, Name, NamedDeBruijn, Program, Term},
|
||||
machine::cost_model::ExBudget,
|
||||
builtins::DefaultFunction,
|
||||
machine::{
|
||||
cost_model::{ExBudget, StepKind},
|
||||
TERM_COUNT,
|
||||
},
|
||||
parser,
|
||||
};
|
||||
|
||||
@@ -18,6 +26,9 @@ pub struct Args {
|
||||
#[clap(short, long)]
|
||||
cbor: bool,
|
||||
|
||||
#[clap(short, long, default_value_t = false)]
|
||||
debug: bool,
|
||||
|
||||
/// Arguments to pass to the UPLC program
|
||||
args: Vec<String>,
|
||||
}
|
||||
@@ -27,6 +38,7 @@ pub fn exec(
|
||||
script,
|
||||
flat,
|
||||
args,
|
||||
debug,
|
||||
cbor,
|
||||
}: Args,
|
||||
) -> miette::Result<()> {
|
||||
@@ -65,7 +77,11 @@ pub fn exec(
|
||||
|
||||
let program = Program::<NamedDeBruijn>::try_from(program).into_diagnostic()?;
|
||||
|
||||
let mut eval_result = program.eval(budget);
|
||||
let mut eval_result = if debug {
|
||||
program.eval_debug(ExBudget::default(), &Language::PlutusV3)
|
||||
} else {
|
||||
program.eval(budget)
|
||||
};
|
||||
|
||||
let cost = eval_result.cost();
|
||||
let logs = eval_result.logs();
|
||||
@@ -85,6 +101,43 @@ pub fn exec(
|
||||
serde_json::to_string_pretty(&output).into_diagnostic()?
|
||||
);
|
||||
|
||||
if debug {
|
||||
println!("---------------DEBUG------------------");
|
||||
let costs = eval_result.debug_cost().unwrap();
|
||||
|
||||
let mut output = json!([]);
|
||||
for step in StepKind::iter() {
|
||||
if matches!(step, StepKind::StartUp) {
|
||||
continue;
|
||||
}
|
||||
let i = step as usize * 2;
|
||||
|
||||
if costs[i + 1] != 0 || costs[i] != 0 {
|
||||
output.as_array_mut().unwrap().push(json!({
|
||||
"step": step.to_string(),
|
||||
"cpu": costs[i+1],
|
||||
"mem": costs[i],
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
for fun in DefaultFunction::iter() {
|
||||
let i = (fun as usize + TERM_COUNT) * 2;
|
||||
if costs[i + 1] != 0 || costs[i] != 0 {
|
||||
output.as_array_mut().unwrap().push(json!({
|
||||
"fun": fun.to_string(),
|
||||
"cpu": costs[i+1],
|
||||
"mem": costs[i],
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
println!(
|
||||
"{}",
|
||||
serde_json::to_string_pretty(&output).into_diagnostic()?
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Err(err) => {
|
||||
|
||||
@@ -28,8 +28,7 @@ peg = "0.8.1"
|
||||
pretty = "0.11.3"
|
||||
serde = { version = "1.0.152", features = ["derive"] }
|
||||
serde_json = "1.0.94"
|
||||
strum = "0.24.1"
|
||||
strum_macros = "0.24.3"
|
||||
strum = { version = "0.26.3", features = ["derive"] }
|
||||
thiserror = "1.0.39"
|
||||
blst = "0.3.11"
|
||||
once_cell = "1.18.0"
|
||||
|
||||
@@ -844,7 +844,7 @@ impl From<Term<FakeNamedDeBruijn>> for Term<NamedDeBruijn> {
|
||||
impl Program<NamedDeBruijn> {
|
||||
pub fn eval(self, initial_budget: ExBudget) -> EvalResult {
|
||||
let mut machine = Machine::new(
|
||||
Language::PlutusV2,
|
||||
Language::PlutusV3,
|
||||
CostModel::default(),
|
||||
initial_budget,
|
||||
200,
|
||||
@@ -852,7 +852,13 @@ impl Program<NamedDeBruijn> {
|
||||
|
||||
let term = machine.run(self.term);
|
||||
|
||||
EvalResult::new(term, machine.ex_budget, initial_budget, machine.logs)
|
||||
EvalResult::new(
|
||||
term,
|
||||
machine.ex_budget,
|
||||
initial_budget,
|
||||
machine.logs,
|
||||
machine.spend_counter.map(|i| i.into()),
|
||||
)
|
||||
}
|
||||
|
||||
/// Evaluate a Program as a specific PlutusVersion
|
||||
@@ -861,7 +867,13 @@ impl Program<NamedDeBruijn> {
|
||||
|
||||
let term = machine.run(self.term);
|
||||
|
||||
EvalResult::new(term, machine.ex_budget, initial_budget, machine.logs)
|
||||
EvalResult::new(
|
||||
term,
|
||||
machine.ex_budget,
|
||||
initial_budget,
|
||||
machine.logs,
|
||||
machine.spend_counter.map(|i| i.into()),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn eval_as(
|
||||
@@ -881,7 +893,32 @@ impl Program<NamedDeBruijn> {
|
||||
|
||||
let term = machine.run(self.term);
|
||||
|
||||
EvalResult::new(term, machine.ex_budget, budget, machine.logs)
|
||||
EvalResult::new(
|
||||
term,
|
||||
machine.ex_budget,
|
||||
budget,
|
||||
machine.logs,
|
||||
machine.spend_counter.map(|i| i.into()),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn eval_debug(self, initial_budget: ExBudget, version: &Language) -> EvalResult {
|
||||
let mut machine = Machine::new_debug(
|
||||
version.clone(),
|
||||
CostModel::default(),
|
||||
initial_budget,
|
||||
200, //slippage
|
||||
);
|
||||
|
||||
let term = machine.run(self.term);
|
||||
|
||||
EvalResult::new(
|
||||
term,
|
||||
machine.ex_budget,
|
||||
initial_budget,
|
||||
machine.logs,
|
||||
machine.spend_counter.map(|i| i.into()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::ast::Term;
|
||||
use pallas_codec::flat::de;
|
||||
use std::{fmt::Display, rc::Rc, str::FromStr};
|
||||
use strum_macros::EnumIter;
|
||||
use strum::EnumIter;
|
||||
|
||||
/// All the possible builtin functions in Untyped Plutus Core.
|
||||
#[repr(u8)]
|
||||
|
||||
@@ -42,11 +42,15 @@ enum Context {
|
||||
NoFrame,
|
||||
}
|
||||
|
||||
pub const TERM_COUNT: usize = 9;
|
||||
pub const BUILTIN_COUNT: usize = 87;
|
||||
|
||||
pub struct Machine {
|
||||
costs: CostModel,
|
||||
pub ex_budget: ExBudget,
|
||||
slippage: u32,
|
||||
unbudgeted_steps: [u32; 10],
|
||||
pub spend_counter: Option<[i64; (TERM_COUNT + BUILTIN_COUNT) * 2]>,
|
||||
pub logs: Vec<String>,
|
||||
version: Language,
|
||||
}
|
||||
@@ -63,6 +67,24 @@ impl Machine {
|
||||
ex_budget: initial_budget,
|
||||
slippage,
|
||||
unbudgeted_steps: [0; 10],
|
||||
spend_counter: None,
|
||||
logs: vec![],
|
||||
version,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_debug(
|
||||
version: Language,
|
||||
costs: CostModel,
|
||||
initial_budget: ExBudget,
|
||||
slippage: u32,
|
||||
) -> Machine {
|
||||
Machine {
|
||||
costs,
|
||||
ex_budget: initial_budget,
|
||||
slippage,
|
||||
unbudgeted_steps: [0; 10],
|
||||
spend_counter: Some([0; (TERM_COUNT + BUILTIN_COUNT) * 2]),
|
||||
logs: vec![],
|
||||
version,
|
||||
}
|
||||
@@ -324,6 +346,13 @@ impl Machine {
|
||||
|
||||
self.spend_budget(cost)?;
|
||||
|
||||
if let Some(counter) = &mut self.spend_counter {
|
||||
let i = (runtime.fun as usize + TERM_COUNT) * 2;
|
||||
|
||||
counter[i] += cost.mem;
|
||||
counter[i + 1] += cost.cpu;
|
||||
}
|
||||
|
||||
runtime.call(&self.version, &mut self.logs)
|
||||
}
|
||||
|
||||
@@ -355,6 +384,11 @@ impl Machine {
|
||||
self.spend_budget(unspent_step_budget)?;
|
||||
|
||||
self.unbudgeted_steps[i] = 0;
|
||||
|
||||
if let Some(counter) = &mut self.spend_counter {
|
||||
counter[i * 2] += unspent_step_budget.mem;
|
||||
counter[i * 2 + 1] += unspent_step_budget.cpu;
|
||||
}
|
||||
}
|
||||
|
||||
self.unbudgeted_steps[9] = 0;
|
||||
|
||||
@@ -4,6 +4,8 @@ use num_traits::Signed;
|
||||
use pallas_primitives::conway::Language;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use strum::{Display, EnumIter};
|
||||
|
||||
macro_rules! hashmap {
|
||||
// map-like
|
||||
($($k:expr => $v:expr),* $(,)?) => {{
|
||||
@@ -5345,6 +5347,7 @@ pub struct TwoArgumentsQuadraticFunction {
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, EnumIter, Display, Clone, Copy)]
|
||||
pub enum StepKind {
|
||||
Constant = 0,
|
||||
Var = 1,
|
||||
|
||||
@@ -7,6 +7,7 @@ pub struct EvalResult {
|
||||
remaining_budget: ExBudget,
|
||||
initial_budget: ExBudget,
|
||||
logs: Vec<String>,
|
||||
debug_cost: Option<Vec<i64>>,
|
||||
}
|
||||
|
||||
impl EvalResult {
|
||||
@@ -15,12 +16,14 @@ impl EvalResult {
|
||||
remaining_budget: ExBudget,
|
||||
initial_budget: ExBudget,
|
||||
logs: Vec<String>,
|
||||
debug_cost: Option<Vec<i64>>,
|
||||
) -> EvalResult {
|
||||
EvalResult {
|
||||
result,
|
||||
remaining_budget,
|
||||
initial_budget,
|
||||
logs,
|
||||
debug_cost,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +50,10 @@ impl EvalResult {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn debug_cost(&self) -> Option<Vec<i64>> {
|
||||
self.debug_cost.clone()
|
||||
}
|
||||
|
||||
#[allow(clippy::result_unit_err)]
|
||||
pub fn unwrap_constant(self) -> Result<Constant, ()> {
|
||||
match self.result {
|
||||
|
||||
@@ -53,7 +53,7 @@ impl From<&Language> for BuiltinSemantics {
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct BuiltinRuntime {
|
||||
pub(super) args: Vec<Value>,
|
||||
fun: DefaultFunction,
|
||||
pub fun: DefaultFunction,
|
||||
pub(super) forces: u32,
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user