diff --git a/ergo-lib/src/chain/transaction/reduced.rs b/ergo-lib/src/chain/transaction/reduced.rs index 4e2c542b9..c3a19a98c 100644 --- a/ergo-lib/src/chain/transaction/reduced.rs +++ b/ergo-lib/src/chain/transaction/reduced.rs @@ -123,7 +123,11 @@ impl SigmaSerializable for ReducedTransaction { let cost = r.get_u64()?; let extension = input.spending_proof.extension; let reduced_input = ReducedInput { - reduction_result: ReductionResult { sigma_prop, cost }, + reduction_result: ReductionResult { + sigma_prop, + cost, + env: Env::empty(), + }, extension: extension.clone(), }; let unsigned_input = UnsignedInput { @@ -167,6 +171,7 @@ pub mod arbitrary { reduction_result: ReductionResult { sigma_prop: sb.clone(), cost: 0, + env: Env::empty(), }, extension: unsigned_input.extension, }), diff --git a/ergotree-interpreter/src/contracts.rs b/ergotree-interpreter/src/contracts.rs index a1c27154f..b3e47cc07 100644 --- a/ergotree-interpreter/src/contracts.rs +++ b/ergotree-interpreter/src/contracts.rs @@ -213,11 +213,9 @@ mod tests { let encoder = AddressEncoder::new(NetworkPrefix::Mainnet); let addr = encoder.parse_address_from_str(p2s_addr_str).unwrap(); assert!(addr.script().unwrap().proposition().is_ok()); - let _script = addr.script().unwrap().proposition().unwrap(); + // let script = addr.script().unwrap().proposition().unwrap(); // dbg!(&script); - // let res: bool = eval_out_wo_ctx::(script.as_ref()) - // .try_into() - // .unwrap(); + // let res: bool = eval_out_wo_ctx::(&script).try_into().unwrap(); // assert!(!res); } @@ -227,12 +225,9 @@ mod tests { let p2s_addr_str = "cLPHJ3MHuKAHoCUwGhcEFw5sWJqvPwFyKxTRj1aUoMwgAz78Fg3zLXRhBup9Te1WLau1gZXNmXvUmeXGCd7QLeqB7ArrT3v5cg26piEtqymM6j2SkgYVCobgoAGKeTf6nMLxv1uVrLdjt1GnPxG1MuWj7Es7Dfumotbx9YEaxwqtTUC5SKsJc9LCpAmNWRAQbU6tVVEvmfwWivrGoZ3L5C4DMisxN3U"; let encoder = AddressEncoder::new(NetworkPrefix::Mainnet); let addr = encoder.parse_address_from_str(p2s_addr_str).unwrap(); - let _script = addr.script().unwrap().proposition().unwrap(); - // dbg!(&script); - // let res: bool = eval_out_wo_ctx::(script.as_ref()) - // .try_into() - // .unwrap(); - // assert!(!res); + let _ = addr.script().unwrap().proposition().unwrap(); + // let ctx = Rc::new(force_any_val::()); + // let _ = reduce_to_crypto(&script, &Env::empty(), ctx).unwrap(); } #[test] @@ -284,6 +279,15 @@ mod tests { let encoder = AddressEncoder::new(NetworkPrefix::Mainnet); let addr = encoder.parse_address_from_str(p2s_str).unwrap(); - let _script = addr.script().unwrap().proposition().unwrap(); + let _ = addr.script().unwrap().proposition().unwrap(); + // let ctx = Rc::new(force_any_val::()); + // let res = reduce_to_crypto(&script, &Env::empty(), ctx).unwrap(); + // match res.sigma_prop { + // SigmaBoolean::TrivialProp(b) => assert!(b), + // SigmaBoolean::ProofOfKnowledge(_) => { + // todo!() + // } + // SigmaBoolean::SigmaConjecture(_) => todo!(), + // } } } diff --git a/ergotree-interpreter/src/eval.rs b/ergotree-interpreter/src/eval.rs index f201a74f9..8202cd5c3 100644 --- a/ergotree-interpreter/src/eval.rs +++ b/ergotree-interpreter/src/eval.rs @@ -155,6 +155,14 @@ pub enum EvalError { /// Scorex serialization parsing error #[error("Serialization parsing error: {0}")] ScorexParsingError(#[from] ScorexParsingError), + /// Wrapped eval error with environment after evaluation + #[error("eval error: {error}, env: {env:?}")] + WrappedWithEnvError { + /// eval error + error: Box, + /// environment after evaluation + env: Env, + }, } /// Result of expression reduction procedure (see `reduce_to_crypto`). @@ -164,31 +172,39 @@ pub struct ReductionResult { pub sigma_prop: SigmaBoolean, /// estimated cost of expression evaluation pub cost: u64, - // pub env: Env, + /// environment after the evaluation + pub env: Env, } /// Evaluate the given expression by reducing it to SigmaBoolean value. pub fn reduce_to_crypto( expr: &Expr, - env: &mut Env, + env: &Env, ctx: Rc, ) -> Result { let cost_accum = CostAccumulator::new(0, None); let mut ectx = EvalContext::new(ctx, cost_accum); - expr.eval(env, &mut ectx) + let mut env_mut = env.clone(); + expr.eval(&mut env_mut, &mut ectx) .and_then(|v| -> Result { match v { Value::Boolean(b) => Ok(ReductionResult { sigma_prop: SigmaBoolean::TrivialProp(b), cost: 0, + env: env_mut.clone(), }), Value::SigmaProp(sp) => Ok(ReductionResult { sigma_prop: sp.value().clone(), cost: 0, + env: env_mut.clone(), }), _ => Err(EvalError::InvalidResultType), } }) + .map_err(|e| EvalError::WrappedWithEnvError { + error: Box::new(e), + env: env_mut, + }) } /// Expects SigmaProp constant value and returns it's value. Otherwise, returns an error. diff --git a/ergotree-interpreter/src/sigma_protocol/prover.rs b/ergotree-interpreter/src/sigma_protocol/prover.rs index 8549baeac..2b210f76f 100644 --- a/ergotree-interpreter/src/sigma_protocol/prover.rs +++ b/ergotree-interpreter/src/sigma_protocol/prover.rs @@ -144,9 +144,8 @@ pub trait Prover { ) -> Result { let expr = tree.proposition()?; let ctx_ext = ctx.extension.clone(); - let mut env_mut = env.clone(); let reduction_result = - reduce_to_crypto(&expr, &mut env_mut, ctx).map_err(ProverError::EvalError)?; + reduce_to_crypto(&expr, env, ctx).map_err(ProverError::EvalError)?; self.generate_proof(reduction_result.sigma_prop, message, hints_bag) .map(|p| ProverResult { diff --git a/ergotree-interpreter/src/sigma_protocol/verifier.rs b/ergotree-interpreter/src/sigma_protocol/verifier.rs index 8101cbbc9..7219b9e68 100644 --- a/ergotree-interpreter/src/sigma_protocol/verifier.rs +++ b/ergotree-interpreter/src/sigma_protocol/verifier.rs @@ -66,8 +66,7 @@ pub trait Verifier { message: &[u8], ) -> Result { let expr = tree.proposition()?; - let mut env_mut = env.clone(); - let cprop = reduce_to_crypto(&expr, &mut env_mut, ctx)?.sigma_prop; + let cprop = reduce_to_crypto(&expr, env, ctx)?.sigma_prop; let res: bool = match cprop { SigmaBoolean::TrivialProp(b) => b, sb => { diff --git a/ergotree-ir/src/mir/val_def.rs b/ergotree-ir/src/mir/val_def.rs index 4858c5ad0..d213359f5 100644 --- a/ergotree-ir/src/mir/val_def.rs +++ b/ergotree-ir/src/mir/val_def.rs @@ -9,6 +9,7 @@ use crate::types::stype::SType; use super::expr::Expr; extern crate derive_more; +use derive_more::Display; use derive_more::From; use crate::has_opcode::HasStaticOpCode; @@ -16,7 +17,7 @@ use crate::has_opcode::HasStaticOpCode; use proptest_derive::Arbitrary; /// Variable id -#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy, From)] +#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy, From, Display)] #[cfg_attr(feature = "arbitrary", derive(Arbitrary))] pub struct ValId(pub u32);