Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 12 additions & 10 deletions bindings/ergo-lib-wasm/src/wallet.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//! Wallet-like features
use ergo_lib::chain::ergo_box::ErgoBox;
use ergo_lib::chain;
use wasm_bindgen::prelude::*;

use crate::{
Expand Down Expand Up @@ -28,7 +28,9 @@ impl Wallet {
}

/// Sign a transaction:
/// `boxes_to_spend` - unspent boxes [`ErgoBoxCandidate`] used as inputs in the transaction
/// `tx` - transaction to sign
/// `boxes_to_spend` - boxes corresponding to [`UnsignedTransaction::inputs`]
/// `data_boxes` - boxes corresponding to [`UnsignedTransaction::data_inputs`]
#[wasm_bindgen]
pub fn sign_transaction(
&self,
Expand All @@ -37,15 +39,15 @@ impl Wallet {
boxes_to_spend: &ErgoBoxes,
data_boxes: &ErgoBoxes,
) -> Result<Transaction, JsValue> {
let boxes_to_spend: Vec<ErgoBox> = boxes_to_spend.clone().into();
let data_boxes: Vec<ErgoBox> = data_boxes.clone().into();
let boxes_to_spend: Vec<chain::ergo_box::ErgoBox> = boxes_to_spend.clone().into();
let data_boxes: Vec<chain::ergo_box::ErgoBox> = data_boxes.clone().into();
let tx_context = ergo_lib::wallet::signing::TransactionContext {
spending_tx: tx.clone().into(),
boxes_to_spend,
data_boxes,
};
self.0
.sign_transaction(
tx.clone().into(),
boxes_to_spend.as_slice(),
data_boxes.as_slice(),
&_state_context.clone().into(),
)
.sign_transaction(tx_context, &_state_context.clone().into())
.map_err(|e| JsValue::from_str(&format!("{}", e)))
.map(Transaction::from)
}
Expand Down
4 changes: 3 additions & 1 deletion ergo-lib/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

### Changed

- moved and change visibility of various modules(input, data_input, prover_result, etc.) [#135](https://github.com/ergoplatform/sigma-rust/pull/135)
- Moved and changed visibility of various modules(input, data_input, prover_result, etc.) [#135](https://github.com/ergoplatform/sigma-rust/pull/135)
- Added Context parameter to Prover::prove, Verifier::verify [#139](https://github.com/ergoplatform/sigma-rust/pull/139)
- Moved all transaction-related parameters into TransactionContext parameter in Wallet::sign_transaction [#139](https://github.com/ergoplatform/sigma-rust/pull/139)

## [0.3.0] - 2020-11-04

Expand Down
19 changes: 19 additions & 0 deletions ergo-lib/src/ast.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
//! AST for ErgoTree
use crate::eval::cost_accum::CostAccumulator;
use crate::eval::EvalError;
use crate::eval::Evaluable;
use crate::{serialization::op_code::OpCode, types::*};
use core::fmt;
use Expr::*;
Expand Down Expand Up @@ -121,6 +124,22 @@ pub enum ContextMethods {
Inputs,
/// Tx outputs
Outputs,
/// Current blockchain height
Height,
}

impl Evaluable for ContextMethods {
fn eval(
&self,
_env: &crate::eval::Env,
_ca: &mut CostAccumulator,
ctx: &crate::eval::context::Context,
) -> Result<Constant, EvalError> {
match self {
ContextMethods::Height => Ok(ctx.height.clone()),
_ => Err(EvalError::UnexpectedExpr),
}
}
}

#[derive(PartialEq, Eq, Debug, Clone)]
Expand Down
115 changes: 78 additions & 37 deletions ergo-lib/src/eval.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
//! Interpreter
use crate::{
ast::{ops::BinOp, ops::NumOp, Constant, ConstantVal, Expr},
ast::{Constant, ConstantVal, Expr},
sigma_protocol::sigma_boolean::SigmaBoolean,
types::SType,
};

use cost_accum::CostAccumulator;
use thiserror::Error;
use value::Value;

mod cost_accum;
use self::context::Context;

pub(crate) mod context;
pub(crate) mod cost_accum;
mod costs;
mod value;

/// Environment vars for script interpreter
/// Environment for the interpreter
pub struct Env();

impl Env {
Expand All @@ -35,61 +36,101 @@ pub enum EvalError {
UnexpectedExpr,
}

/// Result of ErgoTree reduction procedure (see `reduce_to_crypto`).
/// Result of expression reduction procedure (see `reduce_to_crypto`).
pub struct ReductionResult {
/// value of SigmaProp type which represents a statement verifiable via sigma protocol.
pub sigma_prop: SigmaBoolean,
/// estimated cost of contract execution
/// estimated cost of expression evaluation
pub cost: u64,
}

/// Interpreter
pub trait Evaluator {
/// This method is used in both prover and verifier to compute SigmaBoolean value.
fn reduce_to_crypto(&self, expr: &Expr, env: &Env) -> Result<ReductionResult, EvalError> {
/// Evaluate the given expression by reducing it to SigmaBoolean value.
fn reduce_to_crypto(
&self,
expr: &Expr,
env: &Env,
ctx: &Context,
) -> Result<ReductionResult, EvalError> {
let mut ca = CostAccumulator::new(0, None);
eval(expr, env, &mut ca).and_then(|v| match v {
Value::Boolean(b) => Ok(ReductionResult {
sigma_prop: SigmaBoolean::TrivialProp(b),
cost: 0,
}),
Value::SigmaProp(sb) => Ok(ReductionResult {
sigma_prop: *sb,
cost: 0,
}),
_ => Err(EvalError::InvalidResultType),
eval(expr, env, &mut ca, ctx).and_then(|v| -> Result<ReductionResult, EvalError> {
match v {
Constant {
tpe: SType::SBoolean,
v: ConstantVal::Boolean(b),
} => Ok(ReductionResult {
sigma_prop: SigmaBoolean::TrivialProp(b),
cost: 0,
}),
Constant {
tpe: SType::SSigmaProp,
v: ConstantVal::SigmaProp(sp),
} => Ok(ReductionResult {
sigma_prop: sp.value().clone(),
cost: 0,
}),
_ => Err(EvalError::InvalidResultType),
}
})
}
}

/// Expression evaluation.
/// Should be implemented by every node that can be evaluated.
pub trait Evaluable {
/// Evaluation routine to be implement by each node
fn eval(
&self,
env: &Env,
ca: &mut CostAccumulator,
ctx: &Context,
) -> Result<Constant, EvalError>;
}

#[allow(unconditional_recursion)]
fn eval(expr: &Expr, env: &Env, ca: &mut CostAccumulator) -> Result<Value, EvalError> {
fn eval(
expr: &Expr,
env: &Env,
ca: &mut CostAccumulator,
ctx: &Context,
) -> Result<Constant, EvalError> {
match expr {
Expr::Const(Constant {
tpe: SType::SBoolean,
v: ConstantVal::Boolean(b),
}) => Ok(Value::Boolean(*b)),
Expr::Const(Constant {
tpe: SType::SSigmaProp,
v: ConstantVal::SigmaProp(sp),
}) => Ok(Value::SigmaProp(Box::new((*sp.value()).clone()))),
Expr::Const(c) => Ok(c.clone()),
Expr::Coll { .. } => todo!(),
Expr::Tup { .. } => todo!(),
Expr::PredefFunc(_) => todo!(),
Expr::CollM(_) => todo!(),
Expr::BoxM(_) => todo!(),
Expr::CtxM(_) => todo!(),
Expr::CtxM(v) => v.eval(env, ca, ctx),
Expr::MethodCall { .. } => todo!(),
Expr::BinOp(bin_op, l, r) => {
let v_l = eval(l, env, ca)?;
let v_r = eval(r, env, ca)?;
Expr::BinOp(_bin_op, l, r) => {
let _v_l = eval(l, env, ca, ctx)?;
let _v_r = eval(r, env, ca, ctx)?;
ca.add_cost_of(expr);
Ok(match bin_op {
BinOp::Num(op) => match op {
NumOp::Add => v_l + v_r,
},
})
todo!()
// Ok(match bin_op {
// BinOp::Num(op) => match op {
// NumOp::Add => v_l + v_r,
// },
// })
}
_ => Err(EvalError::UnexpectedExpr),
}
}

#[cfg(test)]
mod tests {
use crate::ast::ContextMethods;
use crate::ast::TryExtractFrom;

use super::*;

#[test]
fn height() {
let expr = Expr::CtxM(ContextMethods::Height);
let mut ca = CostAccumulator::new(0, None);
let res = eval(&expr, &Env::empty(), &mut ca, &Context::dummy()).unwrap();
assert_eq!(i32::try_extract_from(res).unwrap(), 0);
}
}
28 changes: 28 additions & 0 deletions ergo-lib/src/eval/context.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use crate::ast::Constant;
use crate::chain::ergo_state_context::ErgoStateContext;
use crate::wallet::signing::TransactionContext;

#[derive(PartialEq, Eq, Debug, Clone)]
pub struct Context {
pub height: Constant,
}

impl Context {
#[cfg(test)]
pub fn dummy() -> Self {
Context {
height: 0i32.into(),
}
}

pub fn new(
_state_ctx: &ErgoStateContext,
_tx_ctx: &TransactionContext,
_self_index: usize,
) -> Self {
// TODO: implement
Context {
height: 0i32.into(),
}
}
}
35 changes: 0 additions & 35 deletions ergo-lib/src/eval/value.rs

This file was deleted.

20 changes: 16 additions & 4 deletions ergo-lib/src/sigma_protocol/prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use super::{
UncheckedTree, UnprovenLeaf, UnprovenSchnorr, UnprovenTree,
};
use crate::ergo_tree::{ErgoTree, ErgoTreeParsingError};
use crate::eval::context::Context;
use crate::eval::{Env, EvalError, Evaluator};
use thiserror::Error;

Expand Down Expand Up @@ -67,11 +68,12 @@ pub trait Prover: Evaluator {
&self,
tree: &ErgoTree,
env: &Env,
ctx: &Context,
message: &[u8],
) -> Result<ProverResult, ProverError> {
let expr = tree.proposition()?;
let proof = self
.reduce_to_crypto(expr.as_ref(), env)
.reduce_to_crypto(expr.as_ref(), env, ctx)
.map_err(ProverError::EvalError)
.and_then(|v| match v.sigma_prop {
SigmaBoolean::TrivialProp(true) => Ok(UncheckedTree::NoProof),
Expand Down Expand Up @@ -314,7 +316,12 @@ mod tests {
let message = vec![0u8; 100];

let prover = TestProver { secrets: vec![] };
let res = prover.prove(&bool_true_tree, &Env::empty(), message.as_slice());
let res = prover.prove(
&bool_true_tree,
&Env::empty(),
&Context::dummy(),
message.as_slice(),
);
assert!(res.is_ok());
assert_eq!(res.unwrap().proof, ProofBytes::Empty);
}
Expand All @@ -328,7 +335,12 @@ mod tests {
let message = vec![0u8; 100];

let prover = TestProver { secrets: vec![] };
let res = prover.prove(&bool_false_tree, &Env::empty(), message.as_slice());
let res = prover.prove(
&bool_false_tree,
&Env::empty(),
&Context::dummy(),
message.as_slice(),
);
assert!(res.is_err());
assert_eq!(res.err().unwrap(), ProverError::ReducedToFalse);
}
Expand All @@ -346,7 +358,7 @@ mod tests {
let prover = TestProver {
secrets: vec![PrivateInput::DlogProverInput(secret)],
};
let res = prover.prove(&tree, &Env::empty(), message.as_slice());
let res = prover.prove(&tree, &Env::empty(), &Context::dummy(), message.as_slice());
assert!(res.is_ok());
assert_ne!(res.unwrap().proof, ProofBytes::Empty);
}
Expand Down
Loading