diff --git a/crates/aiken/src/cmd/tx/simulate.rs b/crates/aiken/src/cmd/tx/simulate.rs index 2888cf41..ae3a3dda 100644 --- a/crates/aiken/src/cmd/tx/simulate.rs +++ b/crates/aiken/src/cmd/tx/simulate.rs @@ -1,11 +1,11 @@ use miette::IntoDiagnostic; +use owo_colors::OwoColorize; use pallas_primitives::{ - babbage::{TransactionInput, TransactionOutput}, + babbage::{Redeemer, TransactionInput, TransactionOutput}, Fragment, }; use pallas_traverse::{Era, MultiEraTx}; -use std::fs; -use std::path::PathBuf; +use std::{fmt, fs, path::PathBuf, process}; use uplc::{ machine::cost_model::ExBudget, tx::{ @@ -54,6 +54,8 @@ pub fn exec( zero_slot, }: Args, ) -> miette::Result<()> { + eprintln!("{} script context", " Parsing".bold().purple(),); + let (tx_bytes, inputs_bytes, outputs_bytes) = if cbor { ( fs::read(input).into_diagnostic()?, @@ -76,6 +78,8 @@ pub fn exec( .or_else(|_| MultiEraTx::decode(Era::Alonzo, &tx_bytes)) .into_diagnostic()?; + eprintln!("{} {}", " Simulating".bold().purple(), tx.hash()); + let inputs = Vec::::decode_fragment(&inputs_bytes).unwrap(); let outputs = Vec::::decode_fragment(&outputs_bytes).unwrap(); @@ -88,8 +92,6 @@ pub fn exec( }) .collect(); - println!("Simulating: {}", tx.hash()); - if let Some(tx_babbage) = tx.as_babbage() { let slot_config = SlotConfig { zero_time, @@ -97,13 +99,27 @@ pub fn exec( slot_length, }; - let result = - tx::eval_phase_two(tx_babbage, &resolved_inputs, None, None, &slot_config, true); + let with_redeemer = |redeemer: &Redeemer| { + println!( + "{} {:?} → {}", + " Redeemer".bold().purple(), + redeemer.tag, + redeemer.index + ) + }; + + let result = tx::eval_phase_two( + tx_babbage, + &resolved_inputs, + None, + None, + &slot_config, + true, + with_redeemer, + ); match result { Ok(redeemers) => { - println!("\nTotal Budget Used\n-----------------\n"); - let total_budget_used = redeemers .iter() @@ -112,11 +128,16 @@ pub fn exec( cpu: accum.cpu + curr.ex_units.steps as i64, }); - println!("mem: {}", total_budget_used.mem); - println!("cpu: {}", total_budget_used.cpu); + println!( + "\n{}", + serde_json::to_string(&total_budget_used) + .map_err(|_| fmt::Error) + .into_diagnostic()? + ); } Err(err) => { - eprintln!("\nError\n-----\n\n{err}\n"); + eprintln!("{} {}", " Error".bold().red(), err.red()); + process::exit(1); } } } diff --git a/crates/uplc/src/machine/cost_model.rs b/crates/uplc/src/machine/cost_model.rs index 90c03c5b..16c1a62c 100644 --- a/crates/uplc/src/machine/cost_model.rs +++ b/crates/uplc/src/machine/cost_model.rs @@ -18,7 +18,7 @@ macro_rules! hashmap { } /// Can be negative -#[derive(Debug, Clone, PartialEq, Eq, Copy)] +#[derive(Debug, Clone, PartialEq, Eq, Copy, serde::Serialize)] pub struct ExBudget { pub mem: i64, pub cpu: i64, diff --git a/crates/uplc/src/tx.rs b/crates/uplc/src/tx.rs index 31fd50f2..643675be 100644 --- a/crates/uplc/src/tx.rs +++ b/crates/uplc/src/tx.rs @@ -35,6 +35,7 @@ pub fn eval_phase_two( initial_budget: Option<&ExBudget>, slot_config: &SlotConfig, run_phase_one: bool, + with_redeemer: fn(&Redeemer) -> (), ) -> Result, Error> { let redeemers = tx.transaction_witness_set.redeemer.as_ref(); @@ -52,6 +53,8 @@ pub fn eval_phase_two( let mut remaining_budget = *initial_budget.unwrap_or(&ExBudget::default()); for redeemer in rs.iter() { + with_redeemer(redeemer); + let redeemer = eval::eval_redeemer( tx, utxos, @@ -87,6 +90,7 @@ pub fn eval_phase_two_raw( initial_budget: (u64, u64), slot_config: (u64, u64, u32), run_phase_one: bool, + with_redeemer: fn(&Redeemer) -> (), ) -> Result>, Error> { let multi_era_tx = MultiEraTx::decode(Era::Babbage, tx_bytes) .or_else(|_| MultiEraTx::decode(Era::Alonzo, tx_bytes))?; @@ -122,6 +126,7 @@ pub fn eval_phase_two_raw( Some(&budget), &sc, run_phase_one, + with_redeemer, ) { Ok(redeemers) => Ok(redeemers .iter() diff --git a/crates/uplc/src/tx/tests.rs b/crates/uplc/src/tx/tests.rs index 7cfbe1ad..c988122b 100644 --- a/crates/uplc/src/tx/tests.rs +++ b/crates/uplc/src/tx/tests.rs @@ -246,6 +246,7 @@ fn test_eval() { Some(&initial_budget), &slot_config, false, + |_| (), ) .unwrap(); @@ -516,6 +517,7 @@ fn test_eval_1() { Some(&initial_budget), &slot_config, false, + |_| (), ) .unwrap(); @@ -621,6 +623,7 @@ fn test_eval_2() { Some(&initial_budget), &slot_config, false, + |_| (), ) .unwrap(); @@ -885,6 +888,7 @@ fn test_eval_3() { Some(&initial_budget), &slot_config, false, + |_| (), ) .unwrap(); @@ -987,6 +991,7 @@ fn test_eval_4() { Some(&initial_budget), &slot_config, false, + |_| (), ) .is_err()); } @@ -1069,6 +1074,7 @@ fn test_eval_5() { Some(&initial_budget), &slot_config, false, + |_| (), ) .unwrap(); @@ -1173,6 +1179,7 @@ fn test_eval_6() { Some(&initial_budget), &slot_config, false, + |_| (), ) .unwrap(); @@ -1277,6 +1284,7 @@ fn test_eval_7() { Some(&initial_budget), &slot_config, false, + |_| (), ) .unwrap(); @@ -1532,6 +1540,7 @@ fn test_eval_8() { Some(&initial_budget), &slot_config, false, + |_| (), ) .unwrap(); @@ -1632,6 +1641,7 @@ fn eval_missing_redeemer() { Some(&initial_budget), &slot_config, false, + |_| (), ) .unwrap(); } @@ -1711,6 +1721,7 @@ fn eval_extraneous_redeemer() { Some(&initial_budget), &slot_config, false, + |_| (), ) .is_err()); }