From 4adf6f27ad394b8a48f5565be7dfb26a9c26ce5a Mon Sep 17 00:00:00 2001 From: Pi Lanningham Date: Mon, 17 Feb 2025 15:55:33 -0500 Subject: [PATCH] Avoid wiping out traces when accessing logs The clones are cheap enough here that we likely don't need to worry about the cost of cloning; and this removes a significant foot-gun where you can wipe out the logs/labels by accessing the other field. --- crates/aiken-lang/src/test_framework.rs | 8 ++++---- crates/aiken/src/cmd/uplc/eval.rs | 2 +- crates/uplc/src/machine/eval_result.rs | 18 ++++++++++-------- crates/uplc/src/tx/eval.rs | 2 +- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/crates/aiken-lang/src/test_framework.rs b/crates/aiken-lang/src/test_framework.rs index ab23ec0a..295dee81 100644 --- a/crates/aiken-lang/src/test_framework.rs +++ b/crates/aiken-lang/src/test_framework.rs @@ -222,7 +222,7 @@ unsafe impl Send for UnitTest {} impl UnitTest { pub fn run(self, plutus_version: &PlutusVersion) -> UnitTestResult<(Constant, Rc)> { - let mut eval_result = Program::::try_from(self.program.clone()) + let eval_result = Program::::try_from(self.program.clone()) .unwrap() .eval_version(ExBudget::max(), &plutus_version.into()); @@ -384,7 +384,7 @@ impl PropertyTest { .sample(&self.fuzzer.program)? .expect("A seeded PRNG returned 'None' which indicates a fuzzer is ill-formed and implemented wrongly; please contact library's authors."); - let mut result = self.eval(&value, plutus_version); + let result = self.eval(&value, plutus_version); for label in result.labels() { // NOTE: There may be other log outputs that interefere with labels. So *by @@ -536,7 +536,7 @@ impl Benchmark { Ok(Some((new_prng, value))) => { prng = new_prng; - let mut result = self.eval(&value, plutus_version); + let result = self.eval(&value, plutus_version); match result.result() { Ok(_) => measures.push((size, result.cost())), Err(uplc_error) => { @@ -664,7 +664,7 @@ impl Prng { fuzzer: &Program, ) -> Result, FuzzerError> { let program = Program::::try_from(fuzzer.apply_data(self.uplc())).unwrap(); - let mut result = program.eval(ExBudget::max()); + let result = program.eval(ExBudget::max()); result .result() .map_err(|uplc_error| FuzzerError { diff --git a/crates/aiken/src/cmd/uplc/eval.rs b/crates/aiken/src/cmd/uplc/eval.rs index b59fec23..61f4a81f 100644 --- a/crates/aiken/src/cmd/uplc/eval.rs +++ b/crates/aiken/src/cmd/uplc/eval.rs @@ -77,7 +77,7 @@ pub fn exec( let program = Program::::try_from(program).into_diagnostic()?; - let mut eval_result = if debug { + let eval_result = if debug { program.eval_debug(ExBudget::default(), &Language::PlutusV3) } else { program.eval(budget) diff --git a/crates/uplc/src/machine/eval_result.rs b/crates/uplc/src/machine/eval_result.rs index 9fbddceb..b6679e4b 100644 --- a/crates/uplc/src/machine/eval_result.rs +++ b/crates/uplc/src/machine/eval_result.rs @@ -31,20 +31,22 @@ impl EvalResult { self.initial_budget - self.remaining_budget } - pub fn traces(&mut self) -> Vec { - std::mem::take(&mut self.traces) + pub fn traces(&self) -> Vec { + self.traces.clone() } - pub fn logs(&mut self) -> Vec { - std::mem::take(&mut self.traces) - .into_iter() + pub fn logs(&self) -> Vec { + self.traces + .iter() + .cloned() .filter_map(Trace::unwrap_log) .collect() } - pub fn labels(&mut self) -> Vec { - std::mem::take(&mut self.traces) - .into_iter() + pub fn labels(&self) -> Vec { + self.traces + .iter() + .cloned() .filter_map(Trace::unwrap_label) .collect() } diff --git a/crates/uplc/src/tx/eval.rs b/crates/uplc/src/tx/eval.rs index b1259d9c..25f3a4f7 100644 --- a/crates/uplc/src/tx/eval.rs +++ b/crates/uplc/src/tx/eval.rs @@ -49,7 +49,7 @@ pub fn eval_redeemer( ScriptContext::V3 { .. } => program.apply_data(script_context.to_plutus_data()), }; - let mut eval_result = if let Some(costs) = cost_mdl_opt { + let eval_result = if let Some(costs) = cost_mdl_opt { program.eval_as(lang, costs, Some(initial_budget)) } else { program.eval_version(ExBudget::default(), lang)