Align output of `tx simulate` with other Aiken's commands.

And also return a structured output as JSON, so it's more easily used
  by other tools.

  ```
       Parsing script context
    Simulating 78ec148ea647cf9969446891af31939c5d57b275a2455706782c6183ef0b62f1
      Redeemer Spend → 0

  {"mem":151993,"cpu":58180696}
  ```
This commit is contained in:
KtorZ 2023-02-14 16:49:13 +01:00
parent a3078adce8
commit 428b5f2b37
No known key found for this signature in database
GPG Key ID: 33173CB6F77F4277
4 changed files with 50 additions and 13 deletions

View File

@ -1,11 +1,11 @@
use miette::IntoDiagnostic; use miette::IntoDiagnostic;
use owo_colors::OwoColorize;
use pallas_primitives::{ use pallas_primitives::{
babbage::{TransactionInput, TransactionOutput}, babbage::{Redeemer, TransactionInput, TransactionOutput},
Fragment, Fragment,
}; };
use pallas_traverse::{Era, MultiEraTx}; use pallas_traverse::{Era, MultiEraTx};
use std::fs; use std::{fmt, fs, path::PathBuf, process};
use std::path::PathBuf;
use uplc::{ use uplc::{
machine::cost_model::ExBudget, machine::cost_model::ExBudget,
tx::{ tx::{
@ -54,6 +54,8 @@ pub fn exec(
zero_slot, zero_slot,
}: Args, }: Args,
) -> miette::Result<()> { ) -> miette::Result<()> {
eprintln!("{} script context", " Parsing".bold().purple(),);
let (tx_bytes, inputs_bytes, outputs_bytes) = if cbor { let (tx_bytes, inputs_bytes, outputs_bytes) = if cbor {
( (
fs::read(input).into_diagnostic()?, fs::read(input).into_diagnostic()?,
@ -76,6 +78,8 @@ pub fn exec(
.or_else(|_| MultiEraTx::decode(Era::Alonzo, &tx_bytes)) .or_else(|_| MultiEraTx::decode(Era::Alonzo, &tx_bytes))
.into_diagnostic()?; .into_diagnostic()?;
eprintln!("{} {}", " Simulating".bold().purple(), tx.hash());
let inputs = Vec::<TransactionInput>::decode_fragment(&inputs_bytes).unwrap(); let inputs = Vec::<TransactionInput>::decode_fragment(&inputs_bytes).unwrap();
let outputs = Vec::<TransactionOutput>::decode_fragment(&outputs_bytes).unwrap(); let outputs = Vec::<TransactionOutput>::decode_fragment(&outputs_bytes).unwrap();
@ -88,8 +92,6 @@ pub fn exec(
}) })
.collect(); .collect();
println!("Simulating: {}", tx.hash());
if let Some(tx_babbage) = tx.as_babbage() { if let Some(tx_babbage) = tx.as_babbage() {
let slot_config = SlotConfig { let slot_config = SlotConfig {
zero_time, zero_time,
@ -97,13 +99,27 @@ pub fn exec(
slot_length, slot_length,
}; };
let result = let with_redeemer = |redeemer: &Redeemer| {
tx::eval_phase_two(tx_babbage, &resolved_inputs, None, None, &slot_config, true); 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 { match result {
Ok(redeemers) => { Ok(redeemers) => {
println!("\nTotal Budget Used\n-----------------\n");
let total_budget_used = let total_budget_used =
redeemers redeemers
.iter() .iter()
@ -112,11 +128,16 @@ pub fn exec(
cpu: accum.cpu + curr.ex_units.steps as i64, cpu: accum.cpu + curr.ex_units.steps as i64,
}); });
println!("mem: {}", total_budget_used.mem); println!(
println!("cpu: {}", total_budget_used.cpu); "\n{}",
serde_json::to_string(&total_budget_used)
.map_err(|_| fmt::Error)
.into_diagnostic()?
);
} }
Err(err) => { Err(err) => {
eprintln!("\nError\n-----\n\n{err}\n"); eprintln!("{} {}", " Error".bold().red(), err.red());
process::exit(1);
} }
} }
} }

View File

@ -18,7 +18,7 @@ macro_rules! hashmap {
} }
/// Can be negative /// Can be negative
#[derive(Debug, Clone, PartialEq, Eq, Copy)] #[derive(Debug, Clone, PartialEq, Eq, Copy, serde::Serialize)]
pub struct ExBudget { pub struct ExBudget {
pub mem: i64, pub mem: i64,
pub cpu: i64, pub cpu: i64,

View File

@ -35,6 +35,7 @@ pub fn eval_phase_two(
initial_budget: Option<&ExBudget>, initial_budget: Option<&ExBudget>,
slot_config: &SlotConfig, slot_config: &SlotConfig,
run_phase_one: bool, run_phase_one: bool,
with_redeemer: fn(&Redeemer) -> (),
) -> Result<Vec<Redeemer>, Error> { ) -> Result<Vec<Redeemer>, Error> {
let redeemers = tx.transaction_witness_set.redeemer.as_ref(); 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()); let mut remaining_budget = *initial_budget.unwrap_or(&ExBudget::default());
for redeemer in rs.iter() { for redeemer in rs.iter() {
with_redeemer(redeemer);
let redeemer = eval::eval_redeemer( let redeemer = eval::eval_redeemer(
tx, tx,
utxos, utxos,
@ -87,6 +90,7 @@ pub fn eval_phase_two_raw(
initial_budget: (u64, u64), initial_budget: (u64, u64),
slot_config: (u64, u64, u32), slot_config: (u64, u64, u32),
run_phase_one: bool, run_phase_one: bool,
with_redeemer: fn(&Redeemer) -> (),
) -> Result<Vec<Vec<u8>>, Error> { ) -> Result<Vec<Vec<u8>>, Error> {
let multi_era_tx = MultiEraTx::decode(Era::Babbage, tx_bytes) let multi_era_tx = MultiEraTx::decode(Era::Babbage, tx_bytes)
.or_else(|_| MultiEraTx::decode(Era::Alonzo, tx_bytes))?; .or_else(|_| MultiEraTx::decode(Era::Alonzo, tx_bytes))?;
@ -122,6 +126,7 @@ pub fn eval_phase_two_raw(
Some(&budget), Some(&budget),
&sc, &sc,
run_phase_one, run_phase_one,
with_redeemer,
) { ) {
Ok(redeemers) => Ok(redeemers Ok(redeemers) => Ok(redeemers
.iter() .iter()

View File

@ -246,6 +246,7 @@ fn test_eval() {
Some(&initial_budget), Some(&initial_budget),
&slot_config, &slot_config,
false, false,
|_| (),
) )
.unwrap(); .unwrap();
@ -516,6 +517,7 @@ fn test_eval_1() {
Some(&initial_budget), Some(&initial_budget),
&slot_config, &slot_config,
false, false,
|_| (),
) )
.unwrap(); .unwrap();
@ -621,6 +623,7 @@ fn test_eval_2() {
Some(&initial_budget), Some(&initial_budget),
&slot_config, &slot_config,
false, false,
|_| (),
) )
.unwrap(); .unwrap();
@ -885,6 +888,7 @@ fn test_eval_3() {
Some(&initial_budget), Some(&initial_budget),
&slot_config, &slot_config,
false, false,
|_| (),
) )
.unwrap(); .unwrap();
@ -987,6 +991,7 @@ fn test_eval_4() {
Some(&initial_budget), Some(&initial_budget),
&slot_config, &slot_config,
false, false,
|_| (),
) )
.is_err()); .is_err());
} }
@ -1069,6 +1074,7 @@ fn test_eval_5() {
Some(&initial_budget), Some(&initial_budget),
&slot_config, &slot_config,
false, false,
|_| (),
) )
.unwrap(); .unwrap();
@ -1173,6 +1179,7 @@ fn test_eval_6() {
Some(&initial_budget), Some(&initial_budget),
&slot_config, &slot_config,
false, false,
|_| (),
) )
.unwrap(); .unwrap();
@ -1277,6 +1284,7 @@ fn test_eval_7() {
Some(&initial_budget), Some(&initial_budget),
&slot_config, &slot_config,
false, false,
|_| (),
) )
.unwrap(); .unwrap();
@ -1532,6 +1540,7 @@ fn test_eval_8() {
Some(&initial_budget), Some(&initial_budget),
&slot_config, &slot_config,
false, false,
|_| (),
) )
.unwrap(); .unwrap();
@ -1632,6 +1641,7 @@ fn eval_missing_redeemer() {
Some(&initial_budget), Some(&initial_budget),
&slot_config, &slot_config,
false, false,
|_| (),
) )
.unwrap(); .unwrap();
} }
@ -1711,6 +1721,7 @@ fn eval_extraneous_redeemer() {
Some(&initial_budget), Some(&initial_budget),
&slot_config, &slot_config,
false, false,
|_| (),
) )
.is_err()); .is_err());
} }