From 8d039c6808bd173f4257bb6eb61c8279d3c301b7 Mon Sep 17 00:00:00 2001
From: Savio <72797635+Savio-Sou@users.noreply.github.com>
Date: Fri, 7 Jun 2024 02:09:58 +0900
Subject: [PATCH 01/57] chore(docs): Update docs homepage (#5198)
# Description
## Problem\*
Description of Noir on the page is outdated and not fully accurate:
- Implies support for SNARK proving systems only
- Defines ZKP as Zero-Knowledge _Programs_
## Summary\*
This PR updates the descriptions accordingly.
## Documentation\*
Check one:
- [x] No documentation needed.
- [ ] Documentation included in this PR.
- [ ] **[For Experimental Features]** Documentation to be submitted in a
separate PR.
# PR Checklist\*
- [ ] I have tested the changes locally.
- [ ] I have formatted the changes with [Prettier](https://prettier.io/)
and/or `cargo fmt` on default settings.
---
docs/docs/index.mdx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/docs/index.mdx b/docs/docs/index.mdx
index 75086ddcdde..a6bd306f91d 100644
--- a/docs/docs/index.mdx
+++ b/docs/docs/index.mdx
@@ -24,9 +24,9 @@ import TabItem from '@theme/TabItem';
-Noir is a Domain-Specific Language for SNARK proving systems developed by [Aztec Labs](https://aztec.network/). It allows you to generate complex Zero-Knowledge Programs (ZKP) by using simple and flexible syntax, requiring no previous knowledge on the underlying mathematics or cryptography.
+Noir is an open-source Domain-Specific Language for safe and seamless construction of privacy-preserving Zero-Knowledge programs, requiring no previous knowledge on the underlying mathematics or cryptography.
-ZK programs are programs that can generate short proofs of a certain statement without revealing some details about it. You can read more about ZKPs [here](https://dev.to/spalladino/a-beginners-intro-to-coding-zero-knowledge-proofs-c56).
+ZK programs are programs that can generate short proofs of statements without revealing all inputs to the statements. You can read more about Zero-Knowledge Proofs [here](https://dev.to/spalladino/a-beginners-intro-to-coding-zero-knowledge-proofs-c56).
## What's new about Noir?
From 42e0eb9145eb375ff42801793843c1333c2ce36c Mon Sep 17 00:00:00 2001
From: Savio <72797635+Savio-Sou@users.noreply.github.com>
Date: Fri, 7 Jun 2024 19:17:47 +0900
Subject: [PATCH 02/57] chore(docs): Supplement Noir Debugger's dependency
versions (#5199)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
# Description
## Problem\*
Dependency versions of Noir / Nargo / vscode-noir for using the Noir
Debugger are currently listed as "0.xx" in the docs.
## Summary\*
This PR updates to docs to specify the actual versions required:
- Noir & Nargo ≥0.28.0
- Noir's VS Code extension ≥0.0.11
## Documentation\*
Check one:
- [ ] No documentation needed.
- [x] Documentation included in this PR.
- [ ] **[For Experimental Features]** Documentation to be submitted in a
separate PR.
# PR Checklist\*
- [ ] I have tested the changes locally.
- [x] I have formatted the changes with [Prettier](https://prettier.io/)
and/or `cargo fmt` on default settings.
---
docs/docs/tooling/debugger.md | 5 ++---
docs/versioned_docs/version-v0.28.0/tooling/debugger.md | 5 ++---
docs/versioned_docs/version-v0.29.0/tooling/debugger.md | 5 ++---
docs/versioned_docs/version-v0.30.0/tooling/debugger.md | 5 ++---
4 files changed, 8 insertions(+), 12 deletions(-)
diff --git a/docs/docs/tooling/debugger.md b/docs/docs/tooling/debugger.md
index 184c436068f..7c158d949d1 100644
--- a/docs/docs/tooling/debugger.md
+++ b/docs/docs/tooling/debugger.md
@@ -14,9 +14,8 @@ There are currently two ways of debugging Noir programs:
In order to use either version of the debugger, you will need to install recent enough versions of Noir, [Nargo](../getting_started/installation) and vscode-noir:
-- Noir 0.xx
-- Nargo 0.xx
-- vscode-noir 0.xx
+- Noir & Nargo ≥0.28.0
+- Noir's VS Code extension ≥0.0.11
:::info
At the moment, the debugger supports debugging binary projects, but not contracts.
diff --git a/docs/versioned_docs/version-v0.28.0/tooling/debugger.md b/docs/versioned_docs/version-v0.28.0/tooling/debugger.md
index 184c436068f..7c158d949d1 100644
--- a/docs/versioned_docs/version-v0.28.0/tooling/debugger.md
+++ b/docs/versioned_docs/version-v0.28.0/tooling/debugger.md
@@ -14,9 +14,8 @@ There are currently two ways of debugging Noir programs:
In order to use either version of the debugger, you will need to install recent enough versions of Noir, [Nargo](../getting_started/installation) and vscode-noir:
-- Noir 0.xx
-- Nargo 0.xx
-- vscode-noir 0.xx
+- Noir & Nargo ≥0.28.0
+- Noir's VS Code extension ≥0.0.11
:::info
At the moment, the debugger supports debugging binary projects, but not contracts.
diff --git a/docs/versioned_docs/version-v0.29.0/tooling/debugger.md b/docs/versioned_docs/version-v0.29.0/tooling/debugger.md
index 184c436068f..7c158d949d1 100644
--- a/docs/versioned_docs/version-v0.29.0/tooling/debugger.md
+++ b/docs/versioned_docs/version-v0.29.0/tooling/debugger.md
@@ -14,9 +14,8 @@ There are currently two ways of debugging Noir programs:
In order to use either version of the debugger, you will need to install recent enough versions of Noir, [Nargo](../getting_started/installation) and vscode-noir:
-- Noir 0.xx
-- Nargo 0.xx
-- vscode-noir 0.xx
+- Noir & Nargo ≥0.28.0
+- Noir's VS Code extension ≥0.0.11
:::info
At the moment, the debugger supports debugging binary projects, but not contracts.
diff --git a/docs/versioned_docs/version-v0.30.0/tooling/debugger.md b/docs/versioned_docs/version-v0.30.0/tooling/debugger.md
index 184c436068f..7c158d949d1 100644
--- a/docs/versioned_docs/version-v0.30.0/tooling/debugger.md
+++ b/docs/versioned_docs/version-v0.30.0/tooling/debugger.md
@@ -14,9 +14,8 @@ There are currently two ways of debugging Noir programs:
In order to use either version of the debugger, you will need to install recent enough versions of Noir, [Nargo](../getting_started/installation) and vscode-noir:
-- Noir 0.xx
-- Nargo 0.xx
-- vscode-noir 0.xx
+- Noir & Nargo ≥0.28.0
+- Noir's VS Code extension ≥0.0.11
:::info
At the moment, the debugger supports debugging binary projects, but not contracts.
From 7f08343dfcafddfcec1b238746a69273ae4f4e2b Mon Sep 17 00:00:00 2001
From: jfecher
Date: Fri, 7 Jun 2024 15:17:12 +0100
Subject: [PATCH 03/57] feat: Implement println in the comptime interpreter
(#5197)
# Description
## Problem\*
Resolves
## Summary\*
## Additional Context
## Documentation\*
Check one:
- [ ] No documentation needed.
- [ ] Documentation included in this PR.
- [x] **[For Experimental Features]** Documentation to be submitted in a
separate PR.
# PR Checklist\*
- [x] I have tested the changes locally.
- [x] I have formatted the changes with [Prettier](https://prettier.io/)
and/or `cargo fmt` on default settings.
---
compiler/noirc_frontend/src/ast/expression.rs | 4 +-
.../src/elaborator/expressions.rs | 2 +-
.../noirc_frontend/src/hir/comptime/errors.rs | 2 +-
.../src/hir/comptime/interpreter.rs | 68 +++++++++++++++++--
.../noirc_frontend/src/hir/comptime/value.rs | 52 +++++++++++++-
.../src/hir/resolution/resolver.rs | 4 +-
compiler/noirc_frontend/src/lexer/token.rs | 11 ++-
.../src/monomorphization/mod.rs | 23 +++----
compiler/noirc_frontend/src/parser/parser.rs | 4 +-
.../comptime_println/Nargo.toml | 7 ++
.../comptime_println/src/main.nr | 7 ++
tooling/nargo_fmt/src/rewrite/expr.rs | 4 +-
12 files changed, 154 insertions(+), 34 deletions(-)
create mode 100644 test_programs/execution_success/comptime_println/Nargo.toml
create mode 100644 test_programs/execution_success/comptime_println/src/main.nr
diff --git a/compiler/noirc_frontend/src/ast/expression.rs b/compiler/noirc_frontend/src/ast/expression.rs
index 749e41d9c1c..50836add8de 100644
--- a/compiler/noirc_frontend/src/ast/expression.rs
+++ b/compiler/noirc_frontend/src/ast/expression.rs
@@ -34,7 +34,7 @@ pub enum ExpressionKind {
Lambda(Box),
Parenthesized(Box),
Quote(BlockExpression),
- Comptime(BlockExpression),
+ Comptime(BlockExpression, Span),
// This variant is only emitted when inlining the result of comptime
// code. It is used to translate function values back into the AST while
@@ -536,7 +536,7 @@ impl Display for ExpressionKind {
Lambda(lambda) => lambda.fmt(f),
Parenthesized(sub_expr) => write!(f, "({sub_expr})"),
Quote(block) => write!(f, "quote {block}"),
- Comptime(block) => write!(f, "comptime {block}"),
+ Comptime(block, _) => write!(f, "comptime {block}"),
Error => write!(f, "Error"),
Resolved(_) => write!(f, "?Resolved"),
}
diff --git a/compiler/noirc_frontend/src/elaborator/expressions.rs b/compiler/noirc_frontend/src/elaborator/expressions.rs
index 5eee7ee6c7c..a922f552c4b 100644
--- a/compiler/noirc_frontend/src/elaborator/expressions.rs
+++ b/compiler/noirc_frontend/src/elaborator/expressions.rs
@@ -59,7 +59,7 @@ impl<'context> Elaborator<'context> {
ExpressionKind::Lambda(lambda) => self.elaborate_lambda(*lambda),
ExpressionKind::Parenthesized(expr) => return self.elaborate_expression(*expr),
ExpressionKind::Quote(quote) => self.elaborate_quote(quote),
- ExpressionKind::Comptime(comptime) => {
+ ExpressionKind::Comptime(comptime, _) => {
return self.elaborate_comptime_block(comptime, expr.span)
}
ExpressionKind::Resolved(id) => return (id, self.interner.id_type(id)),
diff --git a/compiler/noirc_frontend/src/hir/comptime/errors.rs b/compiler/noirc_frontend/src/hir/comptime/errors.rs
index df4bc941f66..05962420f8a 100644
--- a/compiler/noirc_frontend/src/hir/comptime/errors.rs
+++ b/compiler/noirc_frontend/src/hir/comptime/errors.rs
@@ -36,7 +36,7 @@ pub enum InterpreterError {
CannotInlineMacro { value: Value, location: Location },
UnquoteFoundDuringEvaluation { location: Location },
- Unimplemented { item: &'static str, location: Location },
+ Unimplemented { item: String, location: Location },
// Perhaps this should be unreachable! due to type checking also preventing this error?
// Currently it and the Continue variant are the only interpreter errors without a Location field
diff --git a/compiler/noirc_frontend/src/hir/comptime/interpreter.rs b/compiler/noirc_frontend/src/hir/comptime/interpreter.rs
index e1e19ad653c..dd436144969 100644
--- a/compiler/noirc_frontend/src/hir/comptime/interpreter.rs
+++ b/compiler/noirc_frontend/src/hir/comptime/interpreter.rs
@@ -59,11 +59,6 @@ impl<'a> Interpreter<'a> {
let previous_state = self.enter_function();
let meta = self.interner.function_meta(&function);
- if meta.kind != FunctionKind::Normal {
- let item = "Evaluation for builtin functions";
- return Err(InterpreterError::Unimplemented { item, location });
- }
-
if meta.parameters.len() != arguments.len() {
return Err(InterpreterError::ArgumentCountMismatch {
expected: meta.parameters.len(),
@@ -72,6 +67,10 @@ impl<'a> Interpreter<'a> {
});
}
+ if meta.kind != FunctionKind::Normal {
+ return self.call_builtin(function, arguments, location);
+ }
+
let parameters = meta.parameters.0.clone();
for ((parameter, typ, _), (argument, arg_location)) in parameters.iter().zip(arguments) {
self.define_pattern(parameter, typ, argument, arg_location)?;
@@ -84,6 +83,35 @@ impl<'a> Interpreter<'a> {
Ok(result)
}
+ fn call_builtin(
+ &mut self,
+ function: FuncId,
+ arguments: Vec<(Value, Location)>,
+ location: Location,
+ ) -> IResult {
+ let attributes = self.interner.function_attributes(&function);
+ let func_attrs = attributes.function.as_ref()
+ .expect("all builtin functions must contain a function attribute which contains the opcode which it links to");
+
+ if let Some(builtin) = func_attrs.builtin() {
+ let item = format!("Evaluation for builtin functions like {builtin}");
+ Err(InterpreterError::Unimplemented { item, location })
+ } else if let Some(foreign) = func_attrs.foreign() {
+ let item = format!("Evaluation for foreign functions like {foreign}");
+ Err(InterpreterError::Unimplemented { item, location })
+ } else if let Some(oracle) = func_attrs.oracle() {
+ if oracle == "print" {
+ self.print_oracle(arguments)
+ } else {
+ let item = format!("Evaluation for oracle functions like {oracle}");
+ Err(InterpreterError::Unimplemented { item, location })
+ }
+ } else {
+ let name = self.interner.function_name(&function);
+ unreachable!("Non-builtin, lowlevel or oracle builtin fn '{name}'")
+ }
+ }
+
fn call_closure(
&mut self,
closure: HirLambda,
@@ -219,7 +247,8 @@ impl<'a> Interpreter<'a> {
argument: Value,
location: Location,
) -> IResult<()> {
- self.type_check(typ, &argument, location)?;
+ // Temporarily disabled since this fails on generic types
+ // self.type_check(typ, &argument, location)?;
self.current_scope_mut().insert(id, argument);
Ok(())
}
@@ -360,7 +389,11 @@ impl<'a> Interpreter<'a> {
self.evaluate_integer(value, is_negative, id)
}
HirLiteral::Str(string) => Ok(Value::String(Rc::new(string))),
- HirLiteral::FmtStr(_, _) => todo!("Evaluate format strings"),
+ HirLiteral::FmtStr(_, _) => {
+ let item = "format strings in a comptime context".into();
+ let location = self.interner.expr_location(&id);
+ Err(InterpreterError::Unimplemented { item, location })
+ }
HirLiteral::Array(array) => self.evaluate_array(array, id),
HirLiteral::Slice(array) => self.evaluate_slice(array, id),
}
@@ -454,6 +487,14 @@ impl<'a> Interpreter<'a> {
Ok(Value::I64(value))
}
}
+ } else if let Type::TypeVariable(variable, TypeVariableKind::IntegerOrField) = &typ {
+ Ok(Value::Field(value))
+ } else if let Type::TypeVariable(variable, TypeVariableKind::Integer) = &typ {
+ let value: u64 = value
+ .try_to_u64()
+ .ok_or(InterpreterError::IntegerOutOfRangeForType { value, typ, location })?;
+ let value = if is_negative { 0u64.wrapping_sub(value) } else { value };
+ Ok(Value::U64(value))
} else {
Err(InterpreterError::NonIntegerIntegerLiteral { typ, location })
}
@@ -1269,4 +1310,17 @@ impl<'a> Interpreter<'a> {
pub(super) fn evaluate_comptime(&mut self, statement: StmtId) -> IResult {
self.evaluate_statement(statement)
}
+
+ fn print_oracle(&self, arguments: Vec<(Value, Location)>) -> Result {
+ assert_eq!(arguments.len(), 2);
+
+ let print_newline = arguments[0].0 == Value::Bool(true);
+ if print_newline {
+ println!("{}", arguments[1].0);
+ } else {
+ print!("{}", arguments[1].0);
+ }
+
+ Ok(Value::Unit)
+ }
}
diff --git a/compiler/noirc_frontend/src/hir/comptime/value.rs b/compiler/noirc_frontend/src/hir/comptime/value.rs
index 43d461ad043..11bbbc7484d 100644
--- a/compiler/noirc_frontend/src/hir/comptime/value.rs
+++ b/compiler/noirc_frontend/src/hir/comptime/value.rs
@@ -1,4 +1,4 @@
-use std::{borrow::Cow, rc::Rc};
+use std::{borrow::Cow, fmt::Display, rc::Rc};
use acvm::{AcirField, FieldElement};
use im::Vector;
@@ -135,7 +135,7 @@ impl Value {
}
Value::Closure(_lambda, _env, _typ) => {
// TODO: How should a closure's environment be inlined?
- let item = "Returning closures from a comptime fn";
+ let item = "Returning closures from a comptime fn".into();
return Err(InterpreterError::Unimplemented { item, location });
}
Value::Tuple(fields) => {
@@ -235,7 +235,7 @@ impl Value {
}
Value::Closure(_lambda, _env, _typ) => {
// TODO: How should a closure's environment be inlined?
- let item = "Returning closures from a comptime fn";
+ let item = "Returning closures from a comptime fn".into();
return Err(InterpreterError::Unimplemented { item, location });
}
Value::Tuple(fields) => {
@@ -306,3 +306,49 @@ impl Value {
fn unwrap_rc(rc: Rc) -> T {
Rc::try_unwrap(rc).unwrap_or_else(|rc| (*rc).clone())
}
+
+impl Display for Value {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match self {
+ Value::Unit => write!(f, "()"),
+ Value::Bool(value) => {
+ let msg = if *value { "true" } else { "false" };
+ write!(f, "{msg}")
+ }
+ Value::Field(value) => write!(f, "{value}"),
+ Value::I8(value) => write!(f, "{value}"),
+ Value::I16(value) => write!(f, "{value}"),
+ Value::I32(value) => write!(f, "{value}"),
+ Value::I64(value) => write!(f, "{value}"),
+ Value::U8(value) => write!(f, "{value}"),
+ Value::U16(value) => write!(f, "{value}"),
+ Value::U32(value) => write!(f, "{value}"),
+ Value::U64(value) => write!(f, "{value}"),
+ Value::String(value) => write!(f, "{value}"),
+ Value::Function(_, _) => write!(f, "(function)"),
+ Value::Closure(_, _, _) => write!(f, "(closure)"),
+ Value::Tuple(fields) => {
+ let fields = vecmap(fields, ToString::to_string);
+ write!(f, "({})", fields.join(", "))
+ }
+ Value::Struct(fields, typ) => {
+ let typename = match typ.follow_bindings() {
+ Type::Struct(def, _) => def.borrow().name.to_string(),
+ other => other.to_string(),
+ };
+ let fields = vecmap(fields, |(name, value)| format!("{}: {}", name, value));
+ write!(f, "{typename} {{ {} }}", fields.join(", "))
+ }
+ Value::Pointer(value) => write!(f, "&mut {}", value.borrow()),
+ Value::Array(values, _) => {
+ let values = vecmap(values, ToString::to_string);
+ write!(f, "[{}]", values.join(", "))
+ }
+ Value::Slice(values, _) => {
+ let values = vecmap(values, ToString::to_string);
+ write!(f, "&[{}]", values.join(", "))
+ }
+ Value::Code(_) => todo!(),
+ }
+ }
+}
diff --git a/compiler/noirc_frontend/src/hir/resolution/resolver.rs b/compiler/noirc_frontend/src/hir/resolution/resolver.rs
index 4988628db83..01f58ba4c27 100644
--- a/compiler/noirc_frontend/src/hir/resolution/resolver.rs
+++ b/compiler/noirc_frontend/src/hir/resolution/resolver.rs
@@ -1642,7 +1642,9 @@ impl<'a> Resolver<'a> {
// The quoted expression isn't resolved since we don't want errors if variables aren't defined
ExpressionKind::Quote(block) => HirExpression::Quote(block),
- ExpressionKind::Comptime(block) => HirExpression::Comptime(self.resolve_block(block)),
+ ExpressionKind::Comptime(block, _) => {
+ HirExpression::Comptime(self.resolve_block(block))
+ }
ExpressionKind::Resolved(_) => unreachable!(
"ExpressionKind::Resolved should only be emitted by the comptime interpreter"
),
diff --git a/compiler/noirc_frontend/src/lexer/token.rs b/compiler/noirc_frontend/src/lexer/token.rs
index fdda271e79c..950697c2536 100644
--- a/compiler/noirc_frontend/src/lexer/token.rs
+++ b/compiler/noirc_frontend/src/lexer/token.rs
@@ -702,20 +702,27 @@ pub enum FunctionAttribute {
}
impl FunctionAttribute {
- pub fn builtin(self) -> Option {
+ pub fn builtin(&self) -> Option<&String> {
match self {
FunctionAttribute::Builtin(name) => Some(name),
_ => None,
}
}
- pub fn foreign(self) -> Option {
+ pub fn foreign(&self) -> Option<&String> {
match self {
FunctionAttribute::Foreign(name) => Some(name),
_ => None,
}
}
+ pub fn oracle(&self) -> Option<&String> {
+ match self {
+ FunctionAttribute::Oracle(name) => Some(name),
+ _ => None,
+ }
+ }
+
pub fn is_foreign(&self) -> bool {
matches!(self, FunctionAttribute::Foreign(_))
}
diff --git a/compiler/noirc_frontend/src/monomorphization/mod.rs b/compiler/noirc_frontend/src/monomorphization/mod.rs
index a25d6488c83..7ecea5c9eac 100644
--- a/compiler/noirc_frontend/src/monomorphization/mod.rs
+++ b/compiler/noirc_frontend/src/monomorphization/mod.rs
@@ -18,7 +18,6 @@ use crate::{
types,
},
node_interner::{self, DefinitionKind, NodeInterner, StmtId, TraitImplKind, TraitMethodId},
- token::FunctionAttribute,
Type, TypeBinding, TypeBindings, TypeVariable, TypeVariableKind,
};
use acvm::{acir::AcirField, FieldElement};
@@ -216,18 +215,18 @@ impl<'interner> Monomorphizer<'interner> {
let attributes = self.interner.function_attributes(&id);
match self.interner.function_meta(&id).kind {
FunctionKind::LowLevel => {
- let attribute = attributes.function.clone().expect("all low level functions must contain a function attribute which contains the opcode which it links to");
+ let attribute = attributes.function.as_ref().expect("all low level functions must contain a function attribute which contains the opcode which it links to");
let opcode = attribute.foreign().expect(
"ice: function marked as foreign, but attribute kind does not match this",
);
- Definition::LowLevel(opcode)
+ Definition::LowLevel(opcode.to_string())
}
FunctionKind::Builtin => {
- let attribute = attributes.function.clone().expect("all low level functions must contain a function attribute which contains the opcode which it links to");
+ let attribute = attributes.function.as_ref().expect("all builtin functions must contain a function attribute which contains the opcode which it links to");
let opcode = attribute.builtin().expect(
"ice: function marked as builtin, but attribute kind does not match this",
);
- Definition::Builtin(opcode)
+ Definition::Builtin(opcode.to_string())
}
FunctionKind::Normal => {
let id =
@@ -235,15 +234,11 @@ impl<'interner> Monomorphizer<'interner> {
Definition::Function(id)
}
FunctionKind::Oracle => {
- let attr = attributes
- .function
- .clone()
- .expect("Oracle function must have an oracle attribute");
-
- match attr {
- FunctionAttribute::Oracle(name) => Definition::Oracle(name),
- _ => unreachable!("Oracle function must have an oracle attribute"),
- }
+ let attribute = attributes.function.as_ref().expect("all oracle functions must contain a function attribute which contains the opcode which it links to");
+ let opcode = attribute.oracle().expect(
+ "ice: function marked as builtin, but attribute kind does not match this",
+ );
+ Definition::Oracle(opcode.to_string())
}
FunctionKind::Recursive => {
unreachable!("Only main can be specified as recursive, which should already be checked");
diff --git a/compiler/noirc_frontend/src/parser/parser.rs b/compiler/noirc_frontend/src/parser/parser.rs
index 702ea79af9d..cabc788e07d 100644
--- a/compiler/noirc_frontend/src/parser/parser.rs
+++ b/compiler/noirc_frontend/src/parser/parser.rs
@@ -545,7 +545,9 @@ fn comptime_expr<'a, S>(statement: S) -> impl NoirParser + 'a
where
S: NoirParser + 'a,
{
- keyword(Keyword::Comptime).ignore_then(block(statement)).map(ExpressionKind::Comptime)
+ keyword(Keyword::Comptime)
+ .ignore_then(spanned(block(statement)))
+ .map(|(block, span)| ExpressionKind::Comptime(block, span))
}
fn declaration<'a, P>(expr_parser: P) -> impl NoirParser + 'a
diff --git a/test_programs/execution_success/comptime_println/Nargo.toml b/test_programs/execution_success/comptime_println/Nargo.toml
new file mode 100644
index 00000000000..7f8ae3a9cb9
--- /dev/null
+++ b/test_programs/execution_success/comptime_println/Nargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "comptime_println"
+type = "bin"
+authors = [""]
+compiler_version = ">=0.27.0"
+
+[dependencies]
diff --git a/test_programs/execution_success/comptime_println/src/main.nr b/test_programs/execution_success/comptime_println/src/main.nr
new file mode 100644
index 00000000000..f9770066c04
--- /dev/null
+++ b/test_programs/execution_success/comptime_println/src/main.nr
@@ -0,0 +1,7 @@
+fn main() {
+ let x = comptime {
+ println("hello from compile-time!");
+ 1 + 2
+ };
+ println(x);
+}
diff --git a/tooling/nargo_fmt/src/rewrite/expr.rs b/tooling/nargo_fmt/src/rewrite/expr.rs
index 9a704717ade..7ff943aea62 100644
--- a/tooling/nargo_fmt/src/rewrite/expr.rs
+++ b/tooling/nargo_fmt/src/rewrite/expr.rs
@@ -167,8 +167,8 @@ pub(crate) fn rewrite(
}
ExpressionKind::Lambda(_) => visitor.slice(span).to_string(),
ExpressionKind::Quote(block) => format!("quote {}", rewrite_block(visitor, block, span)),
- ExpressionKind::Comptime(block) => {
- format!("comptime {}", rewrite_block(visitor, block, span))
+ ExpressionKind::Comptime(block, block_span) => {
+ format!("comptime {}", rewrite_block(visitor, block, block_span))
}
ExpressionKind::Error => unreachable!(),
ExpressionKind::Resolved(_) => {
From 58c7532da8dd86ee02b20d7e7809f5437f667845 Mon Sep 17 00:00:00 2001
From: guipublic <47281315+guipublic@users.noreply.github.com>
Date: Mon, 10 Jun 2024 12:14:12 +0200
Subject: [PATCH 04/57] fix: error for allocate instructions in acir-gen
(#5200)
# Description
## Problem\*
Resolves #5175
## Summary\*
When we cannot resolve some references to an array, its allocate is not
simplified and we get a panic.
I changed this to an error message saying that we could not resolve all
references from the array.
I believe an error message is better than the panic, however I am not
sure whether having remaining allocates only happens because of this
case.
## Additional Context
## Documentation\*
Check one:
- [ ] No documentation needed.
- [ ] Documentation included in this PR.
- [ ] **[For Experimental Features]** Documentation to be submitted in a
separate PR.
# PR Checklist\*
- [ ] I have tested the changes locally.
- [ ] I have formatted the changes with [Prettier](https://prettier.io/)
and/or `cargo fmt` on default settings.
---
compiler/noirc_evaluator/src/errors.rs | 5 ++++-
compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs | 7 ++++++-
2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/compiler/noirc_evaluator/src/errors.rs b/compiler/noirc_evaluator/src/errors.rs
index 1e922060100..dd63a254a18 100644
--- a/compiler/noirc_evaluator/src/errors.rs
+++ b/compiler/noirc_evaluator/src/errors.rs
@@ -43,6 +43,8 @@ pub enum RuntimeError {
UnconstrainedSliceReturnToConstrained { call_stack: CallStack },
#[error("All `oracle` methods should be wrapped in an unconstrained fn")]
UnconstrainedOracleReturnToConstrained { call_stack: CallStack },
+ #[error("Could not resolve some references to the array. All references must be resolved at compile time")]
+ UnknownReference { call_stack: CallStack },
}
#[derive(Debug, Clone, Serialize, Deserialize)]
@@ -123,7 +125,8 @@ impl RuntimeError {
| RuntimeError::NestedSlice { call_stack, .. }
| RuntimeError::BigIntModulus { call_stack, .. }
| RuntimeError::UnconstrainedSliceReturnToConstrained { call_stack }
- | RuntimeError::UnconstrainedOracleReturnToConstrained { call_stack } => call_stack,
+ | RuntimeError::UnconstrainedOracleReturnToConstrained { call_stack }
+ | RuntimeError::UnknownReference { call_stack } => call_stack,
}
}
}
diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs
index 2aac083d727..40170e58a30 100644
--- a/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs
+++ b/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs
@@ -682,7 +682,9 @@ impl<'a> Context<'a> {
self.handle_array_operation(instruction_id, dfg)?;
}
Instruction::Allocate => {
- unreachable!("Expected all allocate instructions to be removed before acir_gen")
+ return Err(RuntimeError::UnknownReference {
+ call_stack: self.acir_context.get_call_stack().clone(),
+ });
}
Instruction::Store { .. } => {
unreachable!("Expected all store instructions to be removed before acir_gen")
@@ -1307,6 +1309,9 @@ impl<'a> Context<'a> {
}
Ok(AcirValue::Array(values))
}
+ Type::Reference(reference_type) => {
+ self.array_get_value(reference_type.as_ref(), block_id, var_index)
+ }
_ => unreachable!("ICE: Expected an array or numeric but got {ssa_type:?}"),
}
}
From 17c859d58da695d64f6a4e203b3ed40bf98df64d Mon Sep 17 00:00:00 2001
From: ricecodekhmer <151774852+ricecodekhmer@users.noreply.github.com>
Date: Mon, 10 Jun 2024 11:17:36 +0100
Subject: [PATCH 05/57] chore(docs): fix incorrect docs github link in footer
(#5206)
# Description
## Problem\*
This PR solves a broken link in the project documentation that
incorrectly points users to an obsolete GitHub repository URL.
## Summary\*
This change corrects the 'Docs GitHub' hyperlink in the footer of the
documentation to direct users to the new correct repository path.
Before, the link directed users to
[https://github.com/noir-lang/docs](https://github.com/noir-lang/docs),
which has been archived. The updated link now correctly points to
[https://github.com/noir-lang/noir/tree/master/docs](https://github.com/noir-lang/noir/tree/master/docs).
## Documentation\*
Check one:
- [ ] No documentation needed.
- [x] Documentation included in this PR.
- [ ] **[For Experimental Features]** Documentation to be submitted in a
separate PR.
# PR Checklist\*
- [x] I have tested the changes locally.
- [x] I have formatted the changes with [Prettier](https://prettier.io/)
and/or `cargo fmt` on default settings.
---
docs/docusaurus.config.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/docusaurus.config.ts b/docs/docusaurus.config.ts
index 2d5b8941f55..29f612b0109 100644
--- a/docs/docusaurus.config.ts
+++ b/docs/docusaurus.config.ts
@@ -109,7 +109,7 @@ export default {
},
{
label: 'Docs GitHub',
- href: 'https://github.com/noir-lang/docs',
+ href: 'https://github.com/noir-lang/noir/tree/master/docs',
},
],
},
From 14adafc965fa9c833e096ec037e086aae67703ad Mon Sep 17 00:00:00 2001
From: Tom French <15848336+TomAFrench@users.noreply.github.com>
Date: Mon, 10 Jun 2024 11:42:24 +0100
Subject: [PATCH 06/57] feat!: add session id to foreign call RPC requests
(#5205)
# Description
## Problem\*
Resolves
## Summary\*
This PR adds an `id` field to RPC foreign call requests so that the
TriXE is able to maintain separate internal state for different test
functions so that Aztec integration tests can be run in parallel. This
has necessitated some changes to the request format so this is a
breaking change.
The RPC request now looks like
```
'{
"jsonrpc":"2.0",
"method":"resolve_foreign_call",
"params":[{
"session_id":3789997497881369652,
"function": "foo",
"inputs": [
"0000000000000000000000000000000000000000000000000000000000000001",
["0000000000000000000000000000000000000000000000000000000000000001","0000000000000000000000000000000000000000000000000000000000000002"
]]
}]}
```
## Additional Context
## Documentation\*
Check one:
- [] No documentation needed.
- [x] Documentation included in this PR.
- [ ] **[For Experimental Features]** Documentation to be submitted in a
separate PR.
# PR Checklist\*
- [x] I have tested the changes locally.
- [x] I have formatted the changes with [Prettier](https://prettier.io/)
and/or `cargo fmt` on default settings.
---
Cargo.lock | 2 +
Cargo.toml | 1 +
acvm-repo/acvm/Cargo.toml | 3 +-
acvm-repo/acvm/src/pwg/brillig.rs | 3 +-
acvm-repo/brillig/src/foreign_call.rs | 1 +
docs/docs/how_to/how-to-oracles.md | 17 ++--
tooling/acvm_cli/Cargo.toml | 2 +-
tooling/nargo/Cargo.toml | 1 +
tooling/nargo/src/ops/foreign_calls.rs | 109 +++++++++++++++++++------
9 files changed, 101 insertions(+), 38 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
index 61bfdd08c0e..8e40315cdd7 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -50,6 +50,7 @@ dependencies = [
"paste",
"proptest",
"rand 0.8.5",
+ "serde",
"thiserror",
"tracing",
]
@@ -2485,6 +2486,7 @@ dependencies = [
"noirc_errors",
"noirc_frontend",
"noirc_printable_type",
+ "rand 0.8.5",
"rayon",
"serde",
"tempfile",
diff --git a/Cargo.toml b/Cargo.toml
index 182580f8d67..d23089adb56 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -131,6 +131,7 @@ similar-asserts = "1.5.0"
tempfile = "3.6.0"
jsonrpc = { version = "0.16.0", features = ["minreq_http"] }
flate2 = "1.0.24"
+rand = "0.8.5"
im = { version = "15.1", features = ["serde"] }
tracing = "0.1.40"
diff --git a/acvm-repo/acvm/Cargo.toml b/acvm-repo/acvm/Cargo.toml
index 577978939b0..0bd6ab6b7c7 100644
--- a/acvm-repo/acvm/Cargo.toml
+++ b/acvm-repo/acvm/Cargo.toml
@@ -16,6 +16,7 @@ repository.workspace = true
num-bigint.workspace = true
thiserror.workspace = true
tracing.workspace = true
+serde.workspace = true
acir.workspace = true
brillig_vm.workspace = true
@@ -36,7 +37,7 @@ bls12_381 = [
]
[dev-dependencies]
-rand = "0.8.5"
+rand.workspace = true
proptest = "1.2.0"
paste = "1.0.14"
ark-bls12-381 = { version = "^0.4.0", default-features = false, features = ["curve"] }
\ No newline at end of file
diff --git a/acvm-repo/acvm/src/pwg/brillig.rs b/acvm-repo/acvm/src/pwg/brillig.rs
index 7e6c207b69a..3a639df044a 100644
--- a/acvm-repo/acvm/src/pwg/brillig.rs
+++ b/acvm-repo/acvm/src/pwg/brillig.rs
@@ -13,6 +13,7 @@ use acir::{
};
use acvm_blackbox_solver::BlackBoxFunctionSolver;
use brillig_vm::{FailureReason, MemoryValue, VMStatus, VM};
+use serde::{Deserialize, Serialize};
use crate::{pwg::OpcodeNotSolvable, OpcodeResolutionError};
@@ -286,7 +287,7 @@ impl<'b, B: BlackBoxFunctionSolver, F: AcirField> BrilligSolver<'b, F, B> {
/// where the result of the foreign call has not yet been provided.
///
/// The caller must resolve this opcode externally based upon the information in the request.
-#[derive(Debug, PartialEq, Clone)]
+#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
pub struct ForeignCallWaitInfo {
/// An identifier interpreted by the caller process
pub function: String,
diff --git a/acvm-repo/brillig/src/foreign_call.rs b/acvm-repo/brillig/src/foreign_call.rs
index a439d5c3202..9a45a4d2f20 100644
--- a/acvm-repo/brillig/src/foreign_call.rs
+++ b/acvm-repo/brillig/src/foreign_call.rs
@@ -3,6 +3,7 @@ use serde::{Deserialize, Serialize};
/// Single output of a [foreign call][crate::Opcode::ForeignCall].
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone)]
+#[serde(untagged)]
pub enum ForeignCallParam {
Single(F),
Array(Vec),
diff --git a/docs/docs/how_to/how-to-oracles.md b/docs/docs/how_to/how-to-oracles.md
index 2811968c634..62ead1f534f 100644
--- a/docs/docs/how_to/how-to-oracles.md
+++ b/docs/docs/how_to/how-to-oracles.md
@@ -137,24 +137,17 @@ app.listen(5555);
Now, we will add our `getSqrt` method, as expected by the `#[oracle(getSqrt)]` decorator in our Noir code. It maps through the params array and returns their square roots:
```js
-server.addMethod("getSqrt", async (params) => {
- const values = params[0].Array.map((field) => {
+server.addMethod("resolve_function_call", async (params) => {
+ if params.function !== "getSqrt" {
+ throw Error("Unexpected foreign call")
+ };
+ const values = params.inputs[0].Array.map((field) => {
return `${Math.sqrt(parseInt(field, 16))}`;
});
return { values: [{ Array: values }] };
});
```
-:::tip
-
-Brillig expects an object with an array of values. Each value is an object declaring to be `Single` or `Array` and returning a field element *as a string*. For example:
-
-```json
-{ "values": [{ "Array": ["1", "2"] }]}
-{ "values": [{ "Single": "1" }]}
-{ "values": [{ "Single": "1" }, { "Array": ["1", "2"] }]}
-```
-
If you're using Typescript, the following types may be helpful in understanding the expected return value and making sure they're easy to follow:
```js
diff --git a/tooling/acvm_cli/Cargo.toml b/tooling/acvm_cli/Cargo.toml
index 72424405d36..1cfd1f3b270 100644
--- a/tooling/acvm_cli/Cargo.toml
+++ b/tooling/acvm_cli/Cargo.toml
@@ -33,6 +33,6 @@ tracing-subscriber.workspace = true
tracing-appender = "0.2.3"
[dev-dependencies]
-rand = "0.8.5"
+rand.workspace = true
proptest = "1.2.0"
paste = "1.0.14"
diff --git a/tooling/nargo/Cargo.toml b/tooling/nargo/Cargo.toml
index 48047d10ea6..8abec267d20 100644
--- a/tooling/nargo/Cargo.toml
+++ b/tooling/nargo/Cargo.toml
@@ -24,6 +24,7 @@ codespan-reporting.workspace = true
tracing.workspace = true
rayon = "1.8.0"
jsonrpc.workspace = true
+rand.workspace = true
[dev-dependencies]
# TODO: This dependency is used to generate unit tests for `get_all_paths_in_dir`
diff --git a/tooling/nargo/src/ops/foreign_calls.rs b/tooling/nargo/src/ops/foreign_calls.rs
index c6b284beb13..115337c1636 100644
--- a/tooling/nargo/src/ops/foreign_calls.rs
+++ b/tooling/nargo/src/ops/foreign_calls.rs
@@ -5,6 +5,8 @@ use acvm::{
};
use jsonrpc::{arg as build_json_rpc_arg, minreq_http::Builder, Client};
use noirc_printable_type::{decode_string_value, ForeignCallError, PrintableValueDisplay};
+use rand::Rng;
+use serde::{Deserialize, Serialize};
pub trait ForeignCallExecutor {
fn execute(
@@ -96,6 +98,12 @@ impl MockedCall {
#[derive(Debug, Default)]
pub struct DefaultForeignCallExecutor {
+ /// A randomly generated id for this `DefaultForeignCallExecutor`.
+ ///
+ /// This is used so that a single `external_resolver` can distinguish between requests from multiple
+ /// instantiations of `DefaultForeignCallExecutor`.
+ id: u64,
+
/// Mocks have unique ids used to identify them in Noir, allowing to update or remove them.
last_mock_id: usize,
/// The registered mocks
@@ -106,6 +114,20 @@ pub struct DefaultForeignCallExecutor {
external_resolver: Option,
}
+#[derive(Debug, Serialize, Deserialize)]
+struct ResolveForeignCallRequest {
+ /// A session ID which allows the external RPC server to link this foreign call request to other foreign calls
+ /// for the same program execution.
+ ///
+ /// This is intended to allow a single RPC server to maintain state related to multiple program executions being
+ /// performed in parallel.
+ session_id: u64,
+
+ #[serde(flatten)]
+ /// The foreign call which the external RPC server is to provide a response for.
+ function_call: ForeignCallWaitInfo,
+}
+
impl DefaultForeignCallExecutor {
pub fn new(show_output: bool, resolver_url: Option<&str>) -> Self {
let oracle_resolver = resolver_url.map(|resolver_url| {
@@ -123,6 +145,7 @@ impl DefaultForeignCallExecutor {
DefaultForeignCallExecutor {
show_output,
external_resolver: oracle_resolver,
+ id: rand::thread_rng().gen(),
..DefaultForeignCallExecutor::default()
}
}
@@ -275,10 +298,13 @@ impl ForeignCallExecutor for DefaultForeignCallExecutor {
} else if let Some(external_resolver) = &self.external_resolver {
// If the user has registered an external resolver then we forward any remaining oracle calls there.
- let encoded_params: Vec<_> =
- foreign_call.inputs.iter().map(build_json_rpc_arg).collect();
+ let encoded_params = vec![build_json_rpc_arg(ResolveForeignCallRequest {
+ session_id: self.id,
+ function_call: foreign_call.clone(),
+ })];
- let req = external_resolver.build_request(foreign_call_name, &encoded_params);
+ let req =
+ external_resolver.build_request("resolve_foreign_call", &encoded_params);
let response = external_resolver.send_request(req)?;
@@ -312,43 +338,49 @@ mod tests {
use crate::ops::{DefaultForeignCallExecutor, ForeignCallExecutor};
+ use super::ResolveForeignCallRequest;
+
#[allow(unreachable_pub)]
#[rpc]
pub trait OracleResolver {
- #[rpc(name = "echo")]
- fn echo(
- &self,
- param: ForeignCallParam,
- ) -> RpcResult>;
-
- #[rpc(name = "sum")]
- fn sum(
+ #[rpc(name = "resolve_foreign_call")]
+ fn resolve_foreign_call(
&self,
- array: ForeignCallParam,
+ req: ResolveForeignCallRequest,
) -> RpcResult>;
}
struct OracleResolverImpl;
- impl OracleResolver for OracleResolverImpl {
- fn echo(
- &self,
- param: ForeignCallParam,
- ) -> RpcResult> {
- Ok(vec![param].into())
+ impl OracleResolverImpl {
+ fn echo(&self, param: ForeignCallParam) -> ForeignCallResult {
+ vec![param].into()
}
- fn sum(
- &self,
- array: ForeignCallParam,
- ) -> RpcResult> {
+ fn sum(&self, array: ForeignCallParam) -> ForeignCallResult {
let mut res: FieldElement = 0_usize.into();
for value in array.fields() {
res += value;
}
- Ok(res.into())
+ res.into()
+ }
+ }
+
+ impl OracleResolver for OracleResolverImpl {
+ fn resolve_foreign_call(
+ &self,
+ req: ResolveForeignCallRequest,
+ ) -> RpcResult> {
+ let response = match req.function_call.function.as_str() {
+ "sum" => self.sum(req.function_call.inputs[0].clone()),
+ "echo" => self.echo(req.function_call.inputs[0].clone()),
+ "id" => FieldElement::from(req.session_id as u128).into(),
+
+ _ => panic!("unexpected foreign call"),
+ };
+ Ok(response)
}
}
@@ -398,4 +430,35 @@ mod tests {
server.close();
}
+
+ #[test]
+ fn foreign_call_executor_id_is_persistent() {
+ let (server, url) = build_oracle_server();
+
+ let mut executor = DefaultForeignCallExecutor::new(false, Some(&url));
+
+ let foreign_call = ForeignCallWaitInfo { function: "id".to_string(), inputs: Vec::new() };
+
+ let result_1 = executor.execute(&foreign_call).unwrap();
+ let result_2 = executor.execute(&foreign_call).unwrap();
+ assert_eq!(result_1, result_2);
+
+ server.close();
+ }
+
+ #[test]
+ fn oracle_resolver_rpc_can_distinguish_executors() {
+ let (server, url) = build_oracle_server();
+
+ let mut executor_1 = DefaultForeignCallExecutor::new(false, Some(&url));
+ let mut executor_2 = DefaultForeignCallExecutor::new(false, Some(&url));
+
+ let foreign_call = ForeignCallWaitInfo { function: "id".to_string(), inputs: Vec::new() };
+
+ let result_1 = executor_1.execute(&foreign_call).unwrap();
+ let result_2 = executor_2.execute(&foreign_call).unwrap();
+ assert_ne!(result_1, result_2);
+
+ server.close();
+ }
}
From 3ec7ce4b74d37721fe025a97a438e4b4df85c040 Mon Sep 17 00:00:00 2001
From: Tom French <15848336+TomAFrench@users.noreply.github.com>
Date: Mon, 10 Jun 2024 14:34:00 +0100
Subject: [PATCH 07/57] chore: make `nargo` crate and debug info generic
(#5184)
# Description
## Problem\*
Related to #5055
## Summary\*
This PR throws generics into more of the codebase.
## Additional Context
## Documentation\*
Check one:
- [x] No documentation needed.
- [ ] Documentation included in this PR.
- [ ] **[For Experimental Features]** Documentation to be submitted in a
separate PR.
# PR Checklist\*
- [x] I have tested the changes locally.
- [x] I have formatted the changes with [Prettier](https://prettier.io/)
and/or `cargo fmt` on default settings.
---
compiler/noirc_printable_type/src/lib.rs | 58 +++++++++---------
tooling/acvm_cli/src/errors.rs | 3 +-
tooling/debugger/src/context.rs | 6 +-
tooling/debugger/src/foreign_calls.rs | 16 ++---
tooling/debugger/src/lib.rs | 2 +-
tooling/debugger/src/repl.rs | 2 +-
tooling/nargo/src/artifacts/debug_vars.rs | 30 +++++-----
tooling/nargo/src/errors.rs | 22 +++----
tooling/nargo/src/ops/execute.rs | 53 +++++++++--------
tooling/nargo/src/ops/foreign_calls.rs | 71 ++++++++++++-----------
tooling/nargo/src/ops/test.rs | 2 +-
tooling/nargo_cli/src/errors.rs | 4 +-
tooling/noirc_abi/src/lib.rs | 6 +-
13 files changed, 137 insertions(+), 138 deletions(-)
diff --git a/compiler/noirc_printable_type/src/lib.rs b/compiler/noirc_printable_type/src/lib.rs
index d9c9c7f9731..dfecd301b35 100644
--- a/compiler/noirc_printable_type/src/lib.rs
+++ b/compiler/noirc_printable_type/src/lib.rs
@@ -1,6 +1,6 @@
use std::{collections::BTreeMap, str};
-use acvm::{acir::AcirField, brillig_vm::brillig::ForeignCallParam, FieldElement};
+use acvm::{acir::AcirField, brillig_vm::brillig::ForeignCallParam};
use iter_extended::vecmap;
use regex::{Captures, Regex};
use serde::{Deserialize, Serialize};
@@ -51,19 +51,19 @@ pub enum PrintableType {
/// For example, a toml file will parse into TomlTypes
/// and those TomlTypes will be mapped to Value
#[derive(Debug, Clone, Serialize, PartialEq)]
-pub enum PrintableValue {
- Field(FieldElement),
+pub enum PrintableValue {
+ Field(F),
String(String),
- Vec { array_elements: Vec, is_slice: bool },
- Struct(BTreeMap),
+ Vec { array_elements: Vec>, is_slice: bool },
+ Struct(BTreeMap>),
Other,
}
/// In order to display a `PrintableValue` we need a `PrintableType` to accurately
/// convert the value into a human-readable format.
-pub enum PrintableValueDisplay {
- Plain(PrintableValue, PrintableType),
- FmtString(String, Vec<(PrintableValue, PrintableType)>),
+pub enum PrintableValueDisplay {
+ Plain(PrintableValue, PrintableType),
+ FmtString(String, Vec<(PrintableValue, PrintableType)>),
}
#[derive(Debug, Error)]
@@ -81,12 +81,10 @@ pub enum ForeignCallError {
ResolvedAssertMessage(String),
}
-impl TryFrom<&[ForeignCallParam]> for PrintableValueDisplay {
+impl TryFrom<&[ForeignCallParam]> for PrintableValueDisplay {
type Error = ForeignCallError;
- fn try_from(
- foreign_call_inputs: &[ForeignCallParam],
- ) -> Result {
+ fn try_from(foreign_call_inputs: &[ForeignCallParam]) -> Result {
let (is_fmt_str, foreign_call_inputs) =
foreign_call_inputs.split_last().ok_or(ForeignCallError::MissingForeignCallInputs)?;
@@ -98,9 +96,9 @@ impl TryFrom<&[ForeignCallParam]> for PrintableValueDisplay {
}
}
-fn convert_string_inputs(
- foreign_call_inputs: &[ForeignCallParam],
-) -> Result {
+fn convert_string_inputs(
+ foreign_call_inputs: &[ForeignCallParam],
+) -> Result, ForeignCallError> {
// Fetch the PrintableType from the foreign call input
// The remaining input values should hold what is to be printed
let (printable_type_as_values, input_values) =
@@ -115,9 +113,9 @@ fn convert_string_inputs(
Ok(PrintableValueDisplay::Plain(value, printable_type))
}
-fn convert_fmt_string_inputs(
- foreign_call_inputs: &[ForeignCallParam],
-) -> Result {
+fn convert_fmt_string_inputs(
+ foreign_call_inputs: &[ForeignCallParam],
+) -> Result, ForeignCallError> {
let (message, input_and_printable_types) =
foreign_call_inputs.split_first().ok_or(ForeignCallError::MissingForeignCallInputs)?;
@@ -144,8 +142,8 @@ fn convert_fmt_string_inputs(
Ok(PrintableValueDisplay::FmtString(message_as_string, output))
}
-fn fetch_printable_type(
- printable_type: &ForeignCallParam,
+fn fetch_printable_type(
+ printable_type: &ForeignCallParam,
) -> Result {
let printable_type_as_fields = printable_type.fields();
let printable_type_as_string = decode_string_value(&printable_type_as_fields);
@@ -154,7 +152,7 @@ fn fetch_printable_type(
Ok(printable_type)
}
-fn to_string(value: &PrintableValue, typ: &PrintableType) -> Option {
+fn to_string(value: &PrintableValue, typ: &PrintableType) -> Option {
let mut output = String::new();
match (value, typ) {
(PrintableValue::Field(f), PrintableType::Field) => {
@@ -269,7 +267,7 @@ fn replace_all(
Ok(new)
}
-impl std::fmt::Display for PrintableValueDisplay {
+impl std::fmt::Display for PrintableValueDisplay {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Plain(value, typ) => {
@@ -295,7 +293,7 @@ impl std::fmt::Display for PrintableValueDisplay {
/// A singular '0' will be prepended as well if the trimmed string has an odd length.
/// A hex string's length needs to be even to decode into bytes, as two digits correspond to
/// one byte.
-fn format_field_string(field: FieldElement) -> String {
+fn format_field_string(field: F) -> String {
if field.is_zero() {
return "0x00".to_owned();
}
@@ -306,11 +304,11 @@ fn format_field_string(field: FieldElement) -> String {
"0x".to_owned() + &trimmed_field
}
-/// Assumes that `field_iterator` contains enough [FieldElement] in order to decode the [PrintableType]
-pub fn decode_value(
- field_iterator: &mut impl Iterator- ,
+/// Assumes that `field_iterator` contains enough field elements in order to decode the [PrintableType]
+pub fn decode_value(
+ field_iterator: &mut impl Iterator
- ,
typ: &PrintableType,
-) -> PrintableValue {
+) -> PrintableValue {
match typ {
PrintableType::Field
| PrintableType::SignedInteger { .. }
@@ -346,7 +344,7 @@ pub fn decode_value(
is_slice: false,
},
PrintableType::String { length } => {
- let field_elements: Vec = field_iterator.take(*length as usize).collect();
+ let field_elements: Vec = field_iterator.take(*length as usize).collect();
PrintableValue::String(decode_string_value(&field_elements))
}
@@ -372,11 +370,11 @@ pub fn decode_value(
// we decode the reference, but it's not really used for printing
decode_value(field_iterator, typ)
}
- PrintableType::Unit => PrintableValue::Field(FieldElement::zero()),
+ PrintableType::Unit => PrintableValue::Field(F::zero()),
}
}
-pub fn decode_string_value(field_elements: &[FieldElement]) -> String {
+pub fn decode_string_value(field_elements: &[F]) -> String {
// TODO: Replace with `into` when Char is supported
let string_as_slice = vecmap(field_elements, |e| {
let mut field_as_bytes = e.to_be_bytes();
diff --git a/tooling/acvm_cli/src/errors.rs b/tooling/acvm_cli/src/errors.rs
index 8bc79347159..886c1bf80f2 100644
--- a/tooling/acvm_cli/src/errors.rs
+++ b/tooling/acvm_cli/src/errors.rs
@@ -1,3 +1,4 @@
+use acir::FieldElement;
use nargo::NargoError;
use std::path::PathBuf;
use thiserror::Error;
@@ -34,7 +35,7 @@ pub(crate) enum CliError {
/// Error related to circuit execution
#[error(transparent)]
- CircuitExecutionError(#[from] NargoError),
+ CircuitExecutionError(#[from] NargoError),
/// Input Witness Value Error
#[error("Error: failed to parse witness value {0}")]
diff --git a/tooling/debugger/src/context.rs b/tooling/debugger/src/context.rs
index 9dc5c758c6f..5d0916b4863 100644
--- a/tooling/debugger/src/context.rs
+++ b/tooling/debugger/src/context.rs
@@ -23,7 +23,7 @@ pub(super) enum DebugCommandResult {
Done,
Ok,
BreakpointReached(OpcodeLocation),
- Error(NargoError),
+ Error(NargoError),
}
pub(super) struct DebugContext<'a, B: BlackBoxFunctionSolver> {
@@ -482,11 +482,11 @@ impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> {
}
}
- pub(super) fn get_variables(&self) -> Vec {
+ pub(super) fn get_variables(&self) -> Vec> {
return self.foreign_call_executor.get_variables();
}
- pub(super) fn current_stack_frame(&self) -> Option {
+ pub(super) fn current_stack_frame(&self) -> Option> {
return self.foreign_call_executor.current_stack_frame();
}
diff --git a/tooling/debugger/src/foreign_calls.rs b/tooling/debugger/src/foreign_calls.rs
index 6989936ae93..03b1a35dfa5 100644
--- a/tooling/debugger/src/foreign_calls.rs
+++ b/tooling/debugger/src/foreign_calls.rs
@@ -38,14 +38,14 @@ impl DebugForeignCall {
}
}
-pub trait DebugForeignCallExecutor: ForeignCallExecutor {
- fn get_variables(&self) -> Vec;
- fn current_stack_frame(&self) -> Option;
+pub trait DebugForeignCallExecutor: ForeignCallExecutor {
+ fn get_variables(&self) -> Vec>;
+ fn current_stack_frame(&self) -> Option>;
}
pub struct DefaultDebugForeignCallExecutor {
- executor: DefaultForeignCallExecutor,
- pub debug_vars: DebugVars,
+ executor: DefaultForeignCallExecutor,
+ pub debug_vars: DebugVars,
}
impl DefaultDebugForeignCallExecutor {
@@ -73,11 +73,11 @@ impl DefaultDebugForeignCallExecutor {
}
impl DebugForeignCallExecutor for DefaultDebugForeignCallExecutor {
- fn get_variables(&self) -> Vec {
+ fn get_variables(&self) -> Vec> {
self.debug_vars.get_variables()
}
- fn current_stack_frame(&self) -> Option {
+ fn current_stack_frame(&self) -> Option> {
self.debug_vars.current_stack_frame()
}
}
@@ -90,7 +90,7 @@ fn debug_fn_id(value: &FieldElement) -> DebugFnId {
DebugFnId(value.to_u128() as u32)
}
-impl ForeignCallExecutor for DefaultDebugForeignCallExecutor {
+impl ForeignCallExecutor for DefaultDebugForeignCallExecutor {
fn execute(
&mut self,
foreign_call: &ForeignCallWaitInfo,
diff --git a/tooling/debugger/src/lib.rs b/tooling/debugger/src/lib.rs
index d7a1337c82f..9168a6228f0 100644
--- a/tooling/debugger/src/lib.rs
+++ b/tooling/debugger/src/lib.rs
@@ -24,7 +24,7 @@ pub fn debug_circuit>(
debug_artifact: DebugArtifact,
initial_witness: WitnessMap,
unconstrained_functions: &[BrilligBytecode],
-) -> Result