From 5ea93bb677b80bdf5f76d9a8ed7c4732003fce09 Mon Sep 17 00:00:00 2001 From: schaeff Date: Mon, 20 Jun 2022 17:51:44 +0200 Subject: [PATCH] implement basic log statement --- zokrates_cli/src/ops/compute_witness.rs | 2 +- zokrates_core/src/absy/from_ast.rs | 9 +++++++ zokrates_core/src/absy/mod.rs | 2 ++ zokrates_core/src/flat_absy/mod.rs | 3 +++ zokrates_core/src/flatten/mod.rs | 4 +++ zokrates_core/src/ir/folder.rs | 1 + zokrates_core/src/ir/from_flat.rs | 1 + zokrates_core/src/ir/interpreter.rs | 8 +++++- zokrates_core/src/ir/mod.rs | 2 ++ zokrates_core/src/ir/smtlib2.rs | 1 + zokrates_core/src/ir/visitor.rs | 1 + zokrates_core/src/optimizer/redefinition.rs | 1 + zokrates_core/src/semantics.rs | 1 + .../src/static_analysis/flat_propagation.rs | 1 + .../static_analysis/flatten_complex_types.rs | 1 + zokrates_core/src/typed_absy/mod.rs | 2 ++ zokrates_core/src/zir/folder.rs | 1 + zokrates_core/src/zir/mod.rs | 2 ++ zokrates_core/src/zir/result_folder.rs | 1 + zokrates_parser/src/zokrates.pest | 5 +++- zokrates_pest_ast/src/lib.rs | 27 ++++++++++++++++--- zokrates_test/src/lib.rs | 2 +- 22 files changed, 70 insertions(+), 8 deletions(-) diff --git a/zokrates_cli/src/ops/compute_witness.rs b/zokrates_cli/src/ops/compute_witness.rs index 944451df..52e2f3bd 100644 --- a/zokrates_cli/src/ops/compute_witness.rs +++ b/zokrates_cli/src/ops/compute_witness.rs @@ -159,7 +159,7 @@ fn cli_compute>>( let interpreter = ir::Interpreter::default(); let witness = interpreter - .execute(ir_prog, &arguments.encode()) + .execute(ir_prog, &arguments.encode(), &mut std::io::stdout()) .map_err(|e| format!("Execution failed: {}", e))?; use zokrates_abi::Decode; diff --git a/zokrates_core/src/absy/from_ast.rs b/zokrates_core/src/absy/from_ast.rs index 81b0ccc8..c9535236 100644 --- a/zokrates_core/src/absy/from_ast.rs +++ b/zokrates_core/src/absy/from_ast.rs @@ -256,6 +256,7 @@ fn statements_from_statement(statement: pest::Statement) -> Vec vec![absy::StatementNode::from(s)], pest::Statement::Assertion(s) => vec![absy::StatementNode::from(s)], pest::Statement::Return(s) => vec![absy::StatementNode::from(s)], + pest::Statement::Log(l) => vec![absy::StatementNode::from(l)], } } @@ -351,6 +352,14 @@ fn statements_from_definition(definition: pest::DefinitionStatement) -> Vec From> for absy::StatementNode<'ast> { + fn from(statement: pest::LogStatement<'ast>) -> absy::StatementNode<'ast> { + use crate::absy::NodeValue; + + absy::Statement::Log(statement.content.inner).span(statement.span) + } +} + impl<'ast> From> for absy::StatementNode<'ast> { fn from(statement: pest::ReturnStatement<'ast>) -> absy::StatementNode<'ast> { use crate::absy::NodeValue; diff --git a/zokrates_core/src/absy/mod.rs b/zokrates_core/src/absy/mod.rs index c9caa5dd..7c729566 100644 --- a/zokrates_core/src/absy/mod.rs +++ b/zokrates_core/src/absy/mod.rs @@ -395,6 +395,7 @@ pub enum Statement<'ast> { Vec>, ), MultipleDefinition(Vec>, ExpressionNode<'ast>), + Log(String), } pub type StatementNode<'ast> = Node>; @@ -428,6 +429,7 @@ impl<'ast> fmt::Display for Statement<'ast> { } write!(f, " = {}", rhs) } + Statement::Log(ref l) => write!(f, "log!({})", l), } } } diff --git a/zokrates_core/src/flat_absy/mod.rs b/zokrates_core/src/flat_absy/mod.rs index 01260145..8890c825 100644 --- a/zokrates_core/src/flat_absy/mod.rs +++ b/zokrates_core/src/flat_absy/mod.rs @@ -159,6 +159,7 @@ pub enum FlatStatement { Condition(FlatExpression, FlatExpression, RuntimeError), Definition(FlatVariable, FlatExpression), Directive(FlatDirective), + Log(String), } impl fmt::Display for FlatStatement { @@ -169,6 +170,7 @@ impl fmt::Display for FlatStatement { write!(f, "{} == {} // {}", lhs, rhs, message) } FlatStatement::Directive(ref d) => write!(f, "{}", d), + FlatStatement::Log(ref l) => write!(f, "log!({})", l), } } } @@ -206,6 +208,7 @@ impl FlatStatement { ..d }) } + FlatStatement::Log(l) => FlatStatement::Log(l), } } } diff --git a/zokrates_core/src/flatten/mod.rs b/zokrates_core/src/flatten/mod.rs index 64fc11b5..5cd2bf97 100644 --- a/zokrates_core/src/flatten/mod.rs +++ b/zokrates_core/src/flatten/mod.rs @@ -1234,6 +1234,7 @@ impl<'ast, T: Field> Flattener<'ast, T> { inputs: new_inputs, }) } + FlatStatement::Log(l) => FlatStatement::Log(l), }); statements_flattened.extend(statements); @@ -2572,6 +2573,9 @@ impl<'ast, T: Field> Flattener<'ast, T> { } } } + ZirStatement::Log(l) => { + statements_flattened.push_back(FlatStatement::Log(l)); + } } } diff --git a/zokrates_core/src/ir/folder.rs b/zokrates_core/src/ir/folder.rs index a50c71f6..d4f86ade 100644 --- a/zokrates_core/src/ir/folder.rs +++ b/zokrates_core/src/ir/folder.rs @@ -58,6 +58,7 @@ pub fn fold_statement>(f: &mut F, s: Statement) -> Vec message, )], Statement::Directive(dir) => vec![Statement::Directive(f.fold_directive(dir))], + Statement::Log(l) => vec![Statement::Log(l)], } } diff --git a/zokrates_core/src/ir/from_flat.rs b/zokrates_core/src/ir/from_flat.rs index 640336b3..7dc7f49d 100644 --- a/zokrates_core/src/ir/from_flat.rs +++ b/zokrates_core/src/ir/from_flat.rs @@ -74,6 +74,7 @@ impl From> for Statement { e => Statement::Constraint(LinComb::from(e).into(), var.into(), None), }, FlatStatement::Directive(ds) => Statement::Directive(ds.into()), + FlatStatement::Log(l) => Statement::Log(l), } } } diff --git a/zokrates_core/src/ir/interpreter.rs b/zokrates_core/src/ir/interpreter.rs index 67a91a02..0253f6e3 100644 --- a/zokrates_core/src/ir/interpreter.rs +++ b/zokrates_core/src/ir/interpreter.rs @@ -25,10 +25,11 @@ impl Interpreter { } impl Interpreter { - pub fn execute>>( + pub fn execute>>( &self, program: ProgIterator, inputs: &[T], + log_stream: &mut W, ) -> ExecutionResult { self.check_inputs(&program, inputs)?; let mut witness = BTreeMap::new(); @@ -75,6 +76,9 @@ impl Interpreter { witness.insert(*o, res[i].clone()); } } + Statement::Log(l) => { + writeln!(log_stream, "{}", l).map_err(|_| Error::LogStream)?; + } } } @@ -273,6 +277,7 @@ pub enum Error { UnsatisfiedConstraint { error: Option }, Solver, WrongInputCount { expected: usize, received: usize }, + LogStream, } impl fmt::Display for Error { @@ -305,6 +310,7 @@ impl fmt::Display for Error { received, if received == 1 { "" } else { "s" } ), + Error::LogStream => write!(f, "Error writing a log to the log stream"), } } } diff --git a/zokrates_core/src/ir/mod.rs b/zokrates_core/src/ir/mod.rs index 1b96ea00..ec395f2b 100644 --- a/zokrates_core/src/ir/mod.rs +++ b/zokrates_core/src/ir/mod.rs @@ -26,6 +26,7 @@ pub use self::witness::Witness; pub enum Statement { Constraint(QuadComb, LinComb, Option), Directive(Directive), + Log(String), } impl Statement { @@ -70,6 +71,7 @@ impl fmt::Display for Statement { match *self { Statement::Constraint(ref quad, ref lin, _) => write!(f, "{} == {}", quad, lin), Statement::Directive(ref s) => write!(f, "{}", s), + Statement::Log(ref s) => write!(f, "{}", s), } } } diff --git a/zokrates_core/src/ir/smtlib2.rs b/zokrates_core/src/ir/smtlib2.rs index 560a1b90..f25603b5 100644 --- a/zokrates_core/src/ir/smtlib2.rs +++ b/zokrates_core/src/ir/smtlib2.rs @@ -86,6 +86,7 @@ impl SMTLib2 for Statement { write!(f, " |~prime|))") } Statement::Directive(ref s) => s.to_smtlib2(f), + Statement::Log(_) => write!(f, ""), } } } diff --git a/zokrates_core/src/ir/visitor.rs b/zokrates_core/src/ir/visitor.rs index 236ade45..bcf74f15 100644 --- a/zokrates_core/src/ir/visitor.rs +++ b/zokrates_core/src/ir/visitor.rs @@ -61,6 +61,7 @@ pub fn visit_statement>(f: &mut F, s: &Statement) { } } Statement::Directive(dir) => f.visit_directive(dir), + Statement::Log(_) => {} } } diff --git a/zokrates_core/src/optimizer/redefinition.rs b/zokrates_core/src/optimizer/redefinition.rs index 0d35c5eb..2bacad2f 100644 --- a/zokrates_core/src/optimizer/redefinition.rs +++ b/zokrates_core/src/optimizer/redefinition.rs @@ -168,6 +168,7 @@ impl Folder for RedefinitionOptimizer { } } } + Statement::Log(l) => vec![Statement::Log(l)], } } diff --git a/zokrates_core/src/semantics.rs b/zokrates_core/src/semantics.rs index 7e3c2626..ea721924 100644 --- a/zokrates_core/src/semantics.rs +++ b/zokrates_core/src/semantics.rs @@ -2024,6 +2024,7 @@ impl<'ast, T: Field> Checker<'ast, T> { }), }.map_err(|e| vec![e]) } + Statement::Log(l) => Ok(TypedStatement::Log(l)), } } diff --git a/zokrates_core/src/static_analysis/flat_propagation.rs b/zokrates_core/src/static_analysis/flat_propagation.rs index caa58473..9026b9cb 100644 --- a/zokrates_core/src/static_analysis/flat_propagation.rs +++ b/zokrates_core/src/static_analysis/flat_propagation.rs @@ -75,6 +75,7 @@ impl FlatStatement { .collect(), ..d })), + FlatStatement::Log(l) => Some(FlatStatement::Log(l)), } } } diff --git a/zokrates_core/src/static_analysis/flatten_complex_types.rs b/zokrates_core/src/static_analysis/flatten_complex_types.rs index 1d8ab686..ed1a3771 100644 --- a/zokrates_core/src/static_analysis/flatten_complex_types.rs +++ b/zokrates_core/src/static_analysis/flatten_complex_types.rs @@ -474,6 +474,7 @@ fn fold_statement<'ast, T: Field>( f.fold_expression_list(statements_buffer, elist), )] } + typed_absy::TypedStatement::Log(l) => vec![zir::ZirStatement::Log(l)], typed_absy::TypedStatement::PushCallLog(..) => vec![], typed_absy::TypedStatement::PopCallLog => vec![], }; diff --git a/zokrates_core/src/typed_absy/mod.rs b/zokrates_core/src/typed_absy/mod.rs index c10ebf74..4d46d9e3 100644 --- a/zokrates_core/src/typed_absy/mod.rs +++ b/zokrates_core/src/typed_absy/mod.rs @@ -641,6 +641,7 @@ pub enum TypedStatement<'ast, T> { Vec>, ), MultipleDefinition(Vec>, TypedExpressionList<'ast, T>), + Log(String), // Aux PushCallLog( DeclarationFunctionKey<'ast, T>, @@ -707,6 +708,7 @@ impl<'ast, T: fmt::Display> fmt::Display for TypedStatement<'ast, T> { } write!(f, " = {}", rhs) } + TypedStatement::Log(ref l) => write!(f, "log!({})", l), TypedStatement::PushCallLog(ref key, ref generics) => write!( f, "// PUSH CALL TO {}/{}::<{}>", diff --git a/zokrates_core/src/zir/folder.rs b/zokrates_core/src/zir/folder.rs index cdd4534a..2c1ac297 100644 --- a/zokrates_core/src/zir/folder.rs +++ b/zokrates_core/src/zir/folder.rs @@ -122,6 +122,7 @@ pub fn fold_statement<'ast, T: Field, F: Folder<'ast, T>>( variables.into_iter().map(|v| f.fold_variable(v)).collect(), f.fold_expression_list(elist), ), + ZirStatement::Log(l) => ZirStatement::Log(l), }; vec![res] } diff --git a/zokrates_core/src/zir/mod.rs b/zokrates_core/src/zir/mod.rs index 2f7dcd89..fe6f9039 100644 --- a/zokrates_core/src/zir/mod.rs +++ b/zokrates_core/src/zir/mod.rs @@ -112,6 +112,7 @@ pub enum ZirStatement<'ast, T> { ), Assertion(BooleanExpression<'ast, T>, RuntimeError), MultipleDefinition(Vec>, ZirExpressionList<'ast, T>), + Log(String), } impl<'ast, T: fmt::Display> fmt::Display for ZirStatement<'ast, T> { @@ -161,6 +162,7 @@ impl<'ast, T: fmt::Display> fmt::Display for ZirStatement<'ast, T> { } write!(f, " = {}", rhs) } + ZirStatement::Log(ref l) => write!(f, "log!({})", l), } } } diff --git a/zokrates_core/src/zir/result_folder.rs b/zokrates_core/src/zir/result_folder.rs index d36c7c96..458cf3c0 100644 --- a/zokrates_core/src/zir/result_folder.rs +++ b/zokrates_core/src/zir/result_folder.rs @@ -147,6 +147,7 @@ pub fn fold_statement<'ast, T: Field, F: ResultFolder<'ast, T>>( .collect::>()?, f.fold_expression_list(elist)?, ), + ZirStatement::Log(l) => ZirStatement::Log(l), }; Ok(vec![res]) } diff --git a/zokrates_parser/src/zokrates.pest b/zokrates_parser/src/zokrates.pest index 063424c8..61c7393d 100644 --- a/zokrates_parser/src/zokrates.pest +++ b/zokrates_parser/src/zokrates.pest @@ -53,12 +53,15 @@ vis = { vis_private | vis_public } // Statements statement = { (return_statement // does not require subsequent newline - | (iteration_statement + | (log_statement + | iteration_statement | definition_statement | expression_statement ) ~ NEWLINE ) ~ NEWLINE* } +log_statement = { "log!(\"" ~ log_statement_content ~ "\")"} +log_statement_content = { ASCII_ALPHANUMERIC* } iteration_statement = { "for" ~ ty ~ identifier ~ "in" ~ expression ~ ".." ~ expression ~ "do" ~ NEWLINE* ~ statement* ~ "endfor"} return_statement = { "return" ~ expression_list} definition_statement = { typed_identifier_or_assignee_list ~ "=" ~ expression } // declare and assign, so only identifiers are allowed, unlike `assignment_statement` diff --git a/zokrates_pest_ast/src/lib.rs b/zokrates_pest_ast/src/lib.rs index fc3d62a8..778d895c 100644 --- a/zokrates_pest_ast/src/lib.rs +++ b/zokrates_pest_ast/src/lib.rs @@ -15,10 +15,11 @@ pub use ast::{ File, FromExpression, FunctionDefinition, HexLiteralExpression, HexNumberExpression, IdentifierExpression, IdentifierOrDecimal, IfElseExpression, ImportDirective, ImportSymbol, InlineArrayExpression, InlineStructExpression, InlineStructMember, InlineTupleExpression, - IterationStatement, LiteralExpression, Parameter, PostfixExpression, Range, RangeOrExpression, - ReturnStatement, Span, Spread, SpreadOrExpression, Statement, StructDefinition, StructField, - SymbolDeclaration, TernaryExpression, ToExpression, Type, TypeDefinition, TypedIdentifier, - TypedIdentifierOrAssignee, UnaryExpression, UnaryOperator, Underscore, Visibility, + IterationStatement, LiteralExpression, LogStatement, Parameter, PostfixExpression, Range, + RangeOrExpression, ReturnStatement, Span, Spread, SpreadOrExpression, Statement, + StructDefinition, StructField, SymbolDeclaration, TernaryExpression, ToExpression, Type, + TypeDefinition, TypedIdentifier, TypedIdentifierOrAssignee, UnaryExpression, UnaryOperator, + Underscore, Visibility, }; mod ast { @@ -365,6 +366,24 @@ mod ast { Definition(DefinitionStatement<'ast>), Assertion(AssertionStatement<'ast>), Iteration(IterationStatement<'ast>), + Log(LogStatement<'ast>), + } + + #[derive(Debug, FromPest, PartialEq, Clone)] + #[pest_ast(rule(Rule::log_statement))] + pub struct LogStatement<'ast> { + pub content: LogStatementContent<'ast>, + #[pest_ast(outer())] + pub span: Span<'ast>, + } + + #[derive(Debug, FromPest, PartialEq, Clone)] + #[pest_ast(rule(Rule::log_statement_content))] + pub struct LogStatementContent<'ast> { + #[pest_ast(outer(with(span_into_str)))] + pub inner: String, + #[pest_ast(outer())] + pub span: Span<'ast>, } #[derive(Debug, FromPest, PartialEq, Clone)] diff --git a/zokrates_test/src/lib.rs b/zokrates_test/src/lib.rs index 7ddbaf09..0ed36090 100644 --- a/zokrates_test/src/lib.rs +++ b/zokrates_test/src/lib.rs @@ -164,7 +164,7 @@ fn compile_and_run(t: Tests) { .unwrap() }; - let output = interpreter.execute(bin.clone(), &input); + let output = interpreter.execute(bin.clone(), &input, &mut std::io::sink()); use zokrates_abi::Decode; let output: Result = output.map(|witness| Output {