From 81fa94c0d09196c2776c82fad688c413a8d1ce57 Mon Sep 17 00:00:00 2001 From: AztecBot Date: Wed, 30 Oct 2024 08:02:17 +0000 Subject: [PATCH] [1 changes] chore: use array instead of Vec in keccak256 (https://github.com/noir-lang/noir/pull/6395) fix: make keccak256 work with input lengths greater than 136 bytes (https://github.com/noir-lang/noir/pull/6393) feat: support specifying generics on a struct when calling an associated function (https://github.com/noir-lang/noir/pull/6306) fix: Display every bit in integer tokens (https://github.com/noir-lang/noir/pull/6360) feat: better LSP hover for functions (https://github.com/noir-lang/noir/pull/6376) feat: Add capacities to brillig vectors and use them in slice ops (https://github.com/noir-lang/noir/pull/6332) feat: suggest removing `!` from macro call that doesn't return Quoted (https://github.com/noir-lang/noir/pull/6384) fix: (formatter) correctly format quote delimiters (https://github.com/noir-lang/noir/pull/6377) fix: allow globals in format strings (https://github.com/noir-lang/noir/pull/6382) --- .noir-sync-commit | 2 +- noir/noir-repo/Cargo.lock | 37 ++ noir/noir-repo/Cargo.toml | 1 + .../opcodes/black_box_function_call.rs | 12 + .../acvm-repo/acir_field/src/field_element.rs | 71 +- .../compiler/optimizers/merge_expressions.rs | 202 ++++++ .../acvm/src/compiler/optimizers/mod.rs | 2 + .../acvm/src/compiler/transformers/mod.rs | 16 +- .../acvm-repo/acvm/src/pwg/brillig.rs | 36 +- noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs | 48 +- noir/noir-repo/acvm-repo/acvm_js/build.sh | 2 +- .../noir-repo/acvm-repo/brillig_vm/src/lib.rs | 55 +- .../compiler/integration-tests/package.json | 2 +- .../brillig/brillig_gen/brillig_black_box.rs | 17 +- .../src/brillig/brillig_gen/brillig_block.rs | 44 +- .../brillig/brillig_gen/brillig_slice_ops.rs | 152 +++-- .../noirc_evaluator/src/brillig/brillig_ir.rs | 4 +- .../brillig_ir/codegen_control_flow.rs | 35 + .../src/brillig/brillig_ir/codegen_memory.rs | 256 +++++++- .../src/brillig/brillig_ir/entry_point.rs | 2 +- .../src/brillig/brillig_ir/procedures/mod.rs | 16 +- .../procedures/prepare_vector_insert.rs | 71 +- .../procedures/prepare_vector_push.rs | 137 +++- .../brillig_ir/procedures/vector_copy.rs | 4 +- .../{vector_pop.rs => vector_pop_back.rs} | 86 ++- .../brillig_ir/procedures/vector_pop_front.rs | 130 ++++ .../brillig_ir/procedures/vector_remove.rs | 39 +- .../src/ssa/acir_gen/acir_ir/acir_variable.rs | 3 +- .../src/ssa/function_builder/mod.rs | 8 +- .../noirc_evaluator/src/ssa/opt/array_set.rs | 22 +- .../noirc_frontend/src/ast/statement.rs | 1 + .../noirc_frontend/src/ast/visitor.rs | 54 +- .../src/elaborator/expressions.rs | 35 +- .../noirc_frontend/src/elaborator/mod.rs | 117 +++- .../noirc_frontend/src/elaborator/patterns.rs | 121 +++- .../noirc_frontend/src/elaborator/scope.rs | 115 ++-- .../src/elaborator/statements.rs | 3 +- .../noirc_frontend/src/elaborator/traits.rs | 4 + .../noirc_frontend/src/elaborator/types.rs | 32 +- .../src/hir/comptime/interpreter.rs | 4 +- .../src/hir/def_collector/dc_crate.rs | 18 +- .../src/hir/def_collector/dc_mod.rs | 1 + .../src/hir/def_map/module_def.rs | 76 --- .../src/hir/def_map/namespace.rs | 8 - .../src/hir/resolution/errors.rs | 2 +- .../src/hir/resolution/import.rs | 255 ++++++-- .../src/hir/resolution/path_resolver.rs | 6 +- .../src/hir/type_check/errors.rs | 14 +- .../noirc_frontend/src/hir_def/traits.rs | 6 + .../noirc_frontend/src/hir_def/types.rs | 5 + .../noirc_frontend/src/lexer/token.rs | 4 +- .../compiler/noirc_frontend/src/locations.rs | 36 +- .../noirc_frontend/src/node_interner.rs | 27 + .../src/parser/parser/use_tree.rs | 42 +- .../compiler/noirc_frontend/src/tests.rs | 37 +- .../noirc_frontend/src/tests/aliases.rs | 33 + .../noirc_frontend/src/tests/bound_checks.rs | 4 +- .../src/tests/metaprogramming.rs | 71 +- .../noirc_frontend/src/tests/traits.rs | 134 ++++ .../noirc_frontend/src/tests/turbofish.rs | 109 +++- .../docs/docs/noir/concepts/comptime.md | 26 +- noir/noir-repo/docs/docusaurus.config.ts | 31 - .../version-v0.36.0/how_to/_category_.json | 3 +- .../noir/concepts/data_types/_category_.json | 2 +- .../cryptographic_primitives/_category_.json | 3 +- noir/noir-repo/noir_stdlib/src/hash/keccak.nr | 40 +- noir/noir-repo/noir_stdlib/src/hash/mod.nr | 1 + noir/noir-repo/noir_stdlib/src/hash/sha256.nr | 429 ++++++++++-- noir/noir-repo/scripts/bump-bb.sh | 2 +- noir/noir-repo/scripts/install_bb.sh | 2 +- .../arithmetic_generics/src/main.nr | 10 +- .../comptime_closures/src/main.nr | 2 +- .../inner_outer_cl/src/main.nr | 2 +- .../use_callers_scope/src/main.nr | 2 +- .../double_verify_honk_proof/Nargo.toml | 6 - .../double_verify_honk_proof/Prover.toml | 5 - .../double_verify_honk_proof/src/main.nr | 28 - .../Nargo.toml | 6 - .../Prover.toml | 5 - .../src/main.nr | 29 - .../fmtstr_with_global/Nargo.toml | 7 + .../fmtstr_with_global/src/main.nr | 5 + .../higher_order_functions/src/main.nr | 2 +- .../verify_honk_proof/Nargo.toml | 6 - .../verify_honk_proof/Prover.toml | 4 - .../verify_honk_proof/src/main.nr | 21 - noir/noir-repo/tooling/debugger/src/repl.rs | 8 + .../lsp/src/attribute_reference_finder.rs | 23 +- noir/noir-repo/tooling/lsp/src/lib.rs | 2 + noir/noir-repo/tooling/lsp/src/modules.rs | 17 +- .../tooling/lsp/src/requests/code_action.rs | 41 +- .../requests/code_action/import_or_qualify.rs | 92 ++- .../code_action/remove_bang_from_call.rs | 97 +++ .../code_action/remove_unused_import.rs | 3 +- .../lsp/src/requests/code_action/tests.rs | 20 +- .../tooling/lsp/src/requests/completion.rs | 44 +- .../src/requests/completion/auto_import.rs | 55 +- .../requests/completion/completion_items.rs | 8 + .../lsp/src/requests/completion/kinds.rs | 4 +- .../lsp/src/requests/completion/tests.rs | 616 +++++++++++++++--- .../tooling/lsp/src/requests/hover.rs | 179 ++++- .../noir-repo/tooling/lsp/src/requests/mod.rs | 2 +- noir/noir-repo/tooling/lsp/src/tests.rs | 33 + .../tooling/lsp/src/use_segment_positions.rs | 336 ++++++++++ noir/noir-repo/tooling/lsp/src/visibility.rs | 57 +- .../test_programs/workspace/two/src/lib.nr | 30 +- .../tooling/nargo/src/ops/execute.rs | 66 +- noir/noir-repo/tooling/nargo/src/ops/mod.rs | 2 +- noir/noir-repo/tooling/nargo_cli/Cargo.toml | 1 + .../tooling/nargo_cli/tests/stdlib-tests.rs | 20 +- .../noir-repo/tooling/nargo_fmt/src/chunks.rs | 85 ++- .../src/formatter/comments_and_whitespace.rs | 9 +- .../nargo_fmt/src/formatter/expression.rs | 193 +++++- .../tooling/nargo_fmt/src/formatter/module.rs | 28 +- .../nargo_fmt/src/formatter/statement.rs | 6 +- .../nargo_fmt/src/formatter/use_tree.rs | 2 +- .../nargo_fmt/src/formatter/use_tree_merge.rs | 2 +- .../nargo_fmt/tests/expected/contract.nr | 2 +- .../tooling/nargo_fmt/tests/expected/tuple.nr | 24 +- .../noir-repo/tooling/noirc_abi_wasm/build.sh | 2 +- .../test/browser/errors.test.ts | 2 +- .../noirc_abi_wasm/test/node/errors.test.ts | 2 +- noir/noir-repo/tooling/profiler/Cargo.toml | 4 + .../src/cli/execution_flamegraph_cmd.rs | 96 +++ .../profiler/src/cli/gates_flamegraph_cmd.rs | 2 +- .../noir-repo/tooling/profiler/src/cli/mod.rs | 11 +- .../src/cli/opcodes_flamegraph_cmd.rs | 4 +- .../tooling/profiler/src/flamegraph.rs | 87 ++- noir/noir-repo/tooling/profiler/src/fs.rs | 29 +- noir/noir-repo/yarn.lock | 13 +- 130 files changed, 4653 insertions(+), 1271 deletions(-) create mode 100644 noir/noir-repo/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs rename noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/{vector_pop.rs => vector_pop_back.rs} (60%) create mode 100644 noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/vector_pop_front.rs create mode 100644 noir/noir-repo/compiler/noirc_frontend/src/tests/aliases.rs delete mode 100644 noir/noir-repo/test_programs/execution_success/double_verify_honk_proof/Nargo.toml delete mode 100644 noir/noir-repo/test_programs/execution_success/double_verify_honk_proof/Prover.toml delete mode 100644 noir/noir-repo/test_programs/execution_success/double_verify_honk_proof/src/main.nr delete mode 100644 noir/noir-repo/test_programs/execution_success/double_verify_honk_proof_recursive/Nargo.toml delete mode 100644 noir/noir-repo/test_programs/execution_success/double_verify_honk_proof_recursive/Prover.toml delete mode 100644 noir/noir-repo/test_programs/execution_success/double_verify_honk_proof_recursive/src/main.nr create mode 100644 noir/noir-repo/test_programs/execution_success/fmtstr_with_global/Nargo.toml create mode 100644 noir/noir-repo/test_programs/execution_success/fmtstr_with_global/src/main.nr delete mode 100644 noir/noir-repo/test_programs/execution_success/verify_honk_proof/Nargo.toml delete mode 100644 noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml delete mode 100644 noir/noir-repo/test_programs/execution_success/verify_honk_proof/src/main.nr create mode 100644 noir/noir-repo/tooling/lsp/src/requests/code_action/remove_bang_from_call.rs create mode 100644 noir/noir-repo/tooling/lsp/src/tests.rs create mode 100644 noir/noir-repo/tooling/lsp/src/use_segment_positions.rs create mode 100644 noir/noir-repo/tooling/profiler/src/cli/execution_flamegraph_cmd.rs diff --git a/.noir-sync-commit b/.noir-sync-commit index 8bf1f2ff4b0..14513b410b0 100644 --- a/.noir-sync-commit +++ b/.noir-sync-commit @@ -1 +1 @@ -598230d9427cf988fc6da8fe9e1eb2b7c00a2fa6 +075c3d32481314d900cbdea0d277de83444747ab diff --git a/noir/noir-repo/Cargo.lock b/noir/noir-repo/Cargo.lock index 3bfffca46e5..3add28d3939 100644 --- a/noir/noir-repo/Cargo.lock +++ b/noir/noir-repo/Cargo.lock @@ -2587,6 +2587,7 @@ dependencies = [ "termcolor", "termion", "test-binary", + "test-case", "thiserror", "tokio", "tokio-util 0.7.10", @@ -2762,12 +2763,15 @@ name = "noir_profiler" version = "0.36.0" dependencies = [ "acir", + "bn254_blackbox_solver", "clap", "color-eyre", "const_format", "fm", + "fxhash", "im", "inferno", + "nargo", "noirc_abi", "noirc_artifacts", "noirc_driver", @@ -4420,6 +4424,39 @@ dependencies = [ "thiserror", ] +[[package]] +name = "test-case" +version = "3.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb2550dd13afcd286853192af8601920d959b14c401fcece38071d53bf0768a8" +dependencies = [ + "test-case-macros", +] + +[[package]] +name = "test-case-core" +version = "3.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adcb7fd841cd518e279be3d5a3eb0636409487998a4aff22f3de87b81e88384f" +dependencies = [ + "cfg-if 1.0.0", + "proc-macro2", + "quote", + "syn 2.0.64", +] + +[[package]] +name = "test-case-macros" +version = "3.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.64", + "test-case-core", +] + [[package]] name = "textwrap" version = "0.13.4" diff --git a/noir/noir-repo/Cargo.toml b/noir/noir-repo/Cargo.toml index 36b4d4c2ce1..222e7dce859 100644 --- a/noir/noir-repo/Cargo.toml +++ b/noir/noir-repo/Cargo.toml @@ -146,6 +146,7 @@ num-bigint = "0.4" num-traits = "0.2" similar-asserts = "1.5.0" tempfile = "3.6.0" +test-case = "3.3.1" jsonrpc = { version = "0.16.0", features = ["minreq_http"] } flate2 = "1.0.24" color-eyre = "0.6.2" diff --git a/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs b/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs index e06286d179e..fa51caf5155 100644 --- a/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs +++ b/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs @@ -1,3 +1,5 @@ +use std::collections::BTreeSet; + use crate::native_types::Witness; use crate::{AcirField, BlackBoxFunc}; @@ -389,6 +391,16 @@ impl BlackBoxFuncCall { BlackBoxFuncCall::BigIntToLeBytes { outputs, .. } => outputs.to_vec(), } } + + pub fn get_input_witnesses(&self) -> BTreeSet { + let mut result = BTreeSet::new(); + for input in self.get_inputs_vec() { + if let ConstantOrWitnessEnum::Witness(w) = input.input() { + result.insert(w); + } + } + result + } } const ABBREVIATION_LIMIT: usize = 5; diff --git a/noir/noir-repo/acvm-repo/acir_field/src/field_element.rs b/noir/noir-repo/acvm-repo/acir_field/src/field_element.rs index 2323f008dbe..47ceb903111 100644 --- a/noir/noir-repo/acvm-repo/acir_field/src/field_element.rs +++ b/noir/noir-repo/acvm-repo/acir_field/src/field_element.rs @@ -8,7 +8,7 @@ use std::ops::{Add, AddAssign, Div, Mul, Neg, Sub, SubAssign}; use crate::AcirField; // XXX: Switch out for a trait and proper implementations -// This implementation is in-efficient, can definitely remove hex usage and Iterator instances for trivial functionality +// This implementation is inefficient, can definitely remove hex usage and Iterator instances for trivial functionality #[derive(Default, Clone, Copy, Eq, PartialOrd, Ord)] pub struct FieldElement(F); @@ -33,46 +33,6 @@ impl std::fmt::Display for FieldElement { write!(f, "-")?; } - // Number of bits needed to represent the smaller representation - let num_bits = smaller_repr.bits(); - - // Check if the number represents a power of 2 - if smaller_repr.count_ones() == 1 { - let mut bit_index = 0; - for i in 0..num_bits { - if smaller_repr.bit(i) { - bit_index = i; - break; - } - } - return match bit_index { - 0 => write!(f, "1"), - 1 => write!(f, "2"), - 2 => write!(f, "4"), - 3 => write!(f, "8"), - _ => write!(f, "2{}", superscript(bit_index)), - }; - } - - // Check if number is a multiple of a power of 2. - // This is used because when computing the quotient - // we usually have numbers in the form 2^t * q + r - // We focus on 2^64, 2^32, 2^16, 2^8, 2^4 because - // they are common. We could extend this to a more - // general factorization strategy, but we pay in terms of CPU time - let mul_sign = "×"; - for power in [64, 32, 16, 8, 4] { - let power_of_two = BigUint::from(2_u128).pow(power); - if &smaller_repr % &power_of_two == BigUint::zero() { - return write!( - f, - "2{}{}{}", - superscript(power as u64), - mul_sign, - smaller_repr / &power_of_two, - ); - } - } write!(f, "{smaller_repr}") } } @@ -409,35 +369,6 @@ impl SubAssign for FieldElement { } } -// For pretty printing powers -fn superscript(n: u64) -> String { - if n == 0 { - "⁰".to_owned() - } else if n == 1 { - "¹".to_owned() - } else if n == 2 { - "²".to_owned() - } else if n == 3 { - "³".to_owned() - } else if n == 4 { - "⁴".to_owned() - } else if n == 5 { - "⁵".to_owned() - } else if n == 6 { - "⁶".to_owned() - } else if n == 7 { - "⁷".to_owned() - } else if n == 8 { - "⁸".to_owned() - } else if n == 9 { - "⁹".to_owned() - } else if n >= 10 { - superscript(n / 10) + &superscript(n % 10) - } else { - panic!("{}", n.to_string() + " can't be converted to superscript."); - } -} - #[cfg(test)] mod tests { use super::{AcirField, FieldElement}; diff --git a/noir/noir-repo/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs b/noir/noir-repo/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs new file mode 100644 index 00000000000..ddf86f60f77 --- /dev/null +++ b/noir/noir-repo/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs @@ -0,0 +1,202 @@ +use std::collections::{BTreeMap, BTreeSet, HashMap}; + +use acir::{ + circuit::{brillig::BrilligInputs, directives::Directive, opcodes::BlockId, Circuit, Opcode}, + native_types::{Expression, Witness}, + AcirField, +}; + +pub(crate) struct MergeExpressionsOptimizer { + resolved_blocks: HashMap>, +} + +impl MergeExpressionsOptimizer { + pub(crate) fn new() -> Self { + MergeExpressionsOptimizer { resolved_blocks: HashMap::new() } + } + /// This pass analyzes the circuit and identifies intermediate variables that are + /// only used in two gates. It then merges the gate that produces the + /// intermediate variable into the second one that uses it + /// Note: This pass is only relevant for backends that can handle unlimited width + pub(crate) fn eliminate_intermediate_variable( + &mut self, + circuit: &Circuit, + acir_opcode_positions: Vec, + ) -> (Vec>, Vec) { + // Keep track, for each witness, of the gates that use it + let circuit_inputs = circuit.circuit_arguments(); + self.resolved_blocks = HashMap::new(); + let mut used_witness: BTreeMap> = BTreeMap::new(); + for (i, opcode) in circuit.opcodes.iter().enumerate() { + let witnesses = self.witness_inputs(opcode); + if let Opcode::MemoryInit { block_id, .. } = opcode { + self.resolved_blocks.insert(*block_id, witnesses.clone()); + } + for w in witnesses { + // We do not simplify circuit inputs + if !circuit_inputs.contains(&w) { + used_witness.entry(w).or_default().insert(i); + } + } + } + + let mut modified_gates: HashMap> = HashMap::new(); + let mut new_circuit = Vec::new(); + let mut new_acir_opcode_positions = Vec::new(); + // For each opcode, try to get a target opcode to merge with + for (i, opcode) in circuit.opcodes.iter().enumerate() { + if !matches!(opcode, Opcode::AssertZero(_)) { + new_circuit.push(opcode.clone()); + new_acir_opcode_positions.push(acir_opcode_positions[i]); + continue; + } + let opcode = modified_gates.get(&i).unwrap_or(opcode).clone(); + let mut to_keep = true; + let input_witnesses = self.witness_inputs(&opcode); + for w in input_witnesses.clone() { + let empty_gates = BTreeSet::new(); + let gates_using_w = used_witness.get(&w).unwrap_or(&empty_gates); + // We only consider witness which are used in exactly two arithmetic gates + if gates_using_w.len() == 2 { + let gates_using_w: Vec<_> = gates_using_w.iter().collect(); + let mut b = *gates_using_w[1]; + if b == i { + b = *gates_using_w[0]; + } else { + // sanity check + assert!(i == *gates_using_w[0]); + } + let second_gate = modified_gates.get(&b).unwrap_or(&circuit.opcodes[b]).clone(); + if let (Opcode::AssertZero(expr_define), Opcode::AssertZero(expr_use)) = + (opcode.clone(), second_gate) + { + if let Some(expr) = Self::merge(&expr_use, &expr_define, w) { + // sanity check + assert!(i < b); + modified_gates.insert(b, Opcode::AssertZero(expr)); + to_keep = false; + // Update the 'used_witness' map to account for the merge. + for w2 in Self::expr_wit(&expr_define) { + if !circuit_inputs.contains(&w2) { + let mut v = used_witness[&w2].clone(); + v.insert(b); + v.remove(&i); + used_witness.insert(w2, v); + } + } + // We need to stop here and continue with the next opcode + // because the merge invalidate the current opcode + break; + } + } + } + } + + if to_keep { + if modified_gates.contains_key(&i) { + new_circuit.push(modified_gates[&i].clone()); + } else { + new_circuit.push(opcode.clone()); + } + new_acir_opcode_positions.push(acir_opcode_positions[i]); + } + } + (new_circuit, new_acir_opcode_positions) + } + + fn expr_wit(expr: &Expression) -> BTreeSet { + let mut result = BTreeSet::new(); + result.extend(expr.mul_terms.iter().flat_map(|i| vec![i.1, i.2])); + result.extend(expr.linear_combinations.iter().map(|i| i.1)); + result + } + + fn brillig_input_wit(&self, input: &BrilligInputs) -> BTreeSet { + let mut result = BTreeSet::new(); + match input { + BrilligInputs::Single(expr) => { + result.extend(Self::expr_wit(expr)); + } + BrilligInputs::Array(exprs) => { + for expr in exprs { + result.extend(Self::expr_wit(expr)); + } + } + BrilligInputs::MemoryArray(block_id) => { + let witnesses = self.resolved_blocks.get(block_id).expect("Unknown block id"); + result.extend(witnesses); + } + } + result + } + + // Returns the input witnesses used by the opcode + fn witness_inputs(&self, opcode: &Opcode) -> BTreeSet { + let mut witnesses = BTreeSet::new(); + match opcode { + Opcode::AssertZero(expr) => Self::expr_wit(expr), + Opcode::BlackBoxFuncCall(bb_func) => bb_func.get_input_witnesses(), + Opcode::Directive(Directive::ToLeRadix { a, .. }) => Self::expr_wit(a), + Opcode::MemoryOp { block_id: _, op, predicate } => { + //index et value, et predicate + let mut witnesses = BTreeSet::new(); + witnesses.extend(Self::expr_wit(&op.index)); + witnesses.extend(Self::expr_wit(&op.value)); + if let Some(p) = predicate { + witnesses.extend(Self::expr_wit(p)); + } + witnesses + } + + Opcode::MemoryInit { block_id: _, init, block_type: _ } => { + init.iter().cloned().collect() + } + Opcode::BrilligCall { inputs, .. } => { + for i in inputs { + witnesses.extend(self.brillig_input_wit(i)); + } + witnesses + } + Opcode::Call { id: _, inputs, outputs: _, predicate } => { + for i in inputs { + witnesses.insert(*i); + } + if let Some(p) = predicate { + witnesses.extend(Self::expr_wit(p)); + } + witnesses + } + } + } + + // Merge 'expr' into 'target' via Gaussian elimination on 'w' + // Returns None if the expressions cannot be merged + fn merge( + target: &Expression, + expr: &Expression, + w: Witness, + ) -> Option> { + // Check that the witness is not part of multiplication terms + for m in &target.mul_terms { + if m.1 == w || m.2 == w { + return None; + } + } + for m in &expr.mul_terms { + if m.1 == w || m.2 == w { + return None; + } + } + + for k in &target.linear_combinations { + if k.1 == w { + for i in &expr.linear_combinations { + if i.1 == w { + return Some(target.add_mul(-(k.0 / i.0), expr)); + } + } + } + } + None + } +} diff --git a/noir/noir-repo/acvm-repo/acvm/src/compiler/optimizers/mod.rs b/noir/noir-repo/acvm-repo/acvm/src/compiler/optimizers/mod.rs index e20ad97a108..1947a80dc35 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/compiler/optimizers/mod.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/compiler/optimizers/mod.rs @@ -5,10 +5,12 @@ use acir::{ // mod constant_backpropagation; mod general; +mod merge_expressions; mod redundant_range; mod unused_memory; pub(crate) use general::GeneralOptimizer; +pub(crate) use merge_expressions::MergeExpressionsOptimizer; pub(crate) use redundant_range::RangeOptimizer; use tracing::info; diff --git a/noir/noir-repo/acvm-repo/acvm/src/compiler/transformers/mod.rs b/noir/noir-repo/acvm-repo/acvm/src/compiler/transformers/mod.rs index 4e29681cbed..b11d054a57b 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/compiler/transformers/mod.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/compiler/transformers/mod.rs @@ -10,7 +10,9 @@ mod csat; pub(crate) use csat::CSatTransformer; pub use csat::MIN_EXPRESSION_WIDTH; -use super::{transform_assert_messages, AcirTransformationMap}; +use super::{ + optimizers::MergeExpressionsOptimizer, transform_assert_messages, AcirTransformationMap, +}; /// Applies [`ProofSystemCompiler`][crate::ProofSystemCompiler] specific optimizations to a [`Circuit`]. pub fn transform( @@ -166,6 +168,16 @@ pub(super) fn transform_internal( // The transformer does not add new public inputs ..acir }; - + let mut merge_optimizer = MergeExpressionsOptimizer::new(); + let (opcodes, new_acir_opcode_positions) = + merge_optimizer.eliminate_intermediate_variable(&acir, new_acir_opcode_positions); + // n.b. we do not update current_witness_index after the eliminate_intermediate_variable pass, the real index could be less. + let acir = Circuit { + current_witness_index, + expression_width, + opcodes, + // The optimizer does not add new public inputs + ..acir + }; (acir, new_acir_opcode_positions) } diff --git a/noir/noir-repo/acvm-repo/acvm/src/pwg/brillig.rs b/noir/noir-repo/acvm-repo/acvm/src/pwg/brillig.rs index 5ec3224dbaa..dffa45dbd7a 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/pwg/brillig.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/pwg/brillig.rs @@ -12,7 +12,7 @@ use acir::{ AcirField, }; use acvm_blackbox_solver::BlackBoxFunctionSolver; -use brillig_vm::{FailureReason, MemoryValue, VMStatus, VM}; +use brillig_vm::{BrilligProfilingSamples, FailureReason, MemoryValue, VMStatus, VM}; use serde::{Deserialize, Serialize}; use crate::{pwg::OpcodeNotSolvable, OpcodeResolutionError}; @@ -58,6 +58,7 @@ impl<'b, B: BlackBoxFunctionSolver, F: AcirField> BrilligSolver<'b, F, B> { /// Constructs a solver for a Brillig block given the bytecode and initial /// witness. + #[allow(clippy::too_many_arguments)] pub(crate) fn new_call( initial_witness: &WitnessMap, memory: &HashMap>, @@ -66,9 +67,16 @@ impl<'b, B: BlackBoxFunctionSolver, F: AcirField> BrilligSolver<'b, F, B> { bb_solver: &'b B, acir_index: usize, brillig_function_id: BrilligFunctionId, + profiling_active: bool, ) -> Result> { - let vm = - Self::setup_brillig_vm(initial_witness, memory, inputs, brillig_bytecode, bb_solver)?; + let vm = Self::setup_brillig_vm( + initial_witness, + memory, + inputs, + brillig_bytecode, + bb_solver, + profiling_active, + )?; Ok(Self { vm, acir_index, function_id: brillig_function_id }) } @@ -78,6 +86,7 @@ impl<'b, B: BlackBoxFunctionSolver, F: AcirField> BrilligSolver<'b, F, B> { inputs: &[BrilligInputs], brillig_bytecode: &'b [BrilligOpcode], bb_solver: &'b B, + profiling_active: bool, ) -> Result, OpcodeResolutionError> { // Set input values let mut calldata: Vec = Vec::new(); @@ -125,7 +134,7 @@ impl<'b, B: BlackBoxFunctionSolver, F: AcirField> BrilligSolver<'b, F, B> { // Instantiate a Brillig VM given the solved calldata // along with the Brillig bytecode. - let vm = VM::new(calldata, brillig_bytecode, vec![], bb_solver); + let vm = VM::new(calldata, brillig_bytecode, vec![], bb_solver, profiling_active); Ok(vm) } @@ -203,6 +212,25 @@ impl<'b, B: BlackBoxFunctionSolver, F: AcirField> BrilligSolver<'b, F, B> { self, witness: &mut WitnessMap, outputs: &[BrilligOutputs], + ) -> Result<(), OpcodeResolutionError> { + assert!(!self.vm.is_profiling_active(), "Expected VM profiling to not be active"); + self.finalize_inner(witness, outputs) + } + + pub(crate) fn finalize_with_profiling( + mut self, + witness: &mut WitnessMap, + outputs: &[BrilligOutputs], + ) -> Result> { + assert!(self.vm.is_profiling_active(), "Expected VM profiling to be active"); + self.finalize_inner(witness, outputs)?; + Ok(self.vm.take_profiling_samples()) + } + + fn finalize_inner( + &self, + witness: &mut WitnessMap, + outputs: &[BrilligOutputs], ) -> Result<(), OpcodeResolutionError> { // Finish the Brillig execution by writing the outputs to the witness map let vm_status = self.vm.get_status(); diff --git a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs index c73893ceea6..fa3498da613 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs @@ -168,6 +168,14 @@ impl From for OpcodeResolutionError { } } +pub type ProfilingSamples = Vec; + +#[derive(Default)] +pub struct ProfilingSample { + pub call_stack: Vec, + pub brillig_function_id: Option, +} + pub struct ACVM<'a, F, B: BlackBoxFunctionSolver> { status: ACVMStatus, @@ -198,6 +206,10 @@ pub struct ACVM<'a, F, B: BlackBoxFunctionSolver> { unconstrained_functions: &'a [BrilligBytecode], assertion_payloads: &'a [(OpcodeLocation, AssertionPayload)], + + profiling_active: bool, + + profiling_samples: ProfilingSamples, } impl<'a, F: AcirField, B: BlackBoxFunctionSolver> ACVM<'a, F, B> { @@ -222,9 +234,16 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> ACVM<'a, F, B> { acir_call_results: Vec::default(), unconstrained_functions, assertion_payloads, + profiling_active: false, + profiling_samples: Vec::new(), } } + // Enable profiling + pub fn with_profiler(&mut self, profiling_active: bool) { + self.profiling_active = profiling_active; + } + /// Returns a reference to the current state of the ACVM's [`WitnessMap`]. /// /// Once execution has completed, the witness map can be extracted using [`ACVM::finalize`] @@ -246,6 +265,10 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> ACVM<'a, F, B> { self.instruction_pointer } + pub fn take_profiling_samples(&mut self) -> ProfilingSamples { + std::mem::take(&mut self.profiling_samples) + } + /// Finalize the ACVM execution, returning the resulting [`WitnessMap`]. pub fn finalize(self) -> WitnessMap { if self.status != ACVMStatus::Solved { @@ -503,6 +526,7 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> ACVM<'a, F, B> { self.backend, self.instruction_pointer, *id, + self.profiling_active, )?, }; @@ -519,7 +543,28 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> ACVM<'a, F, B> { } BrilligSolverStatus::Finished => { // Write execution outputs - solver.finalize(&mut self.witness_map, outputs)?; + if self.profiling_active { + let profiling_info = + solver.finalize_with_profiling(&mut self.witness_map, outputs)?; + profiling_info.into_iter().for_each(|sample| { + let mapped = + sample.call_stack.into_iter().map(|loc| OpcodeLocation::Brillig { + acir_index: self.instruction_pointer, + brillig_index: loc, + }); + self.profiling_samples.push(ProfilingSample { + call_stack: std::iter::once(OpcodeLocation::Acir( + self.instruction_pointer, + )) + .chain(mapped) + .collect(), + brillig_function_id: Some(*id), + }); + }); + } else { + solver.finalize(&mut self.witness_map, outputs)?; + } + Ok(None) } } @@ -575,6 +620,7 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> ACVM<'a, F, B> { self.backend, self.instruction_pointer, *id, + self.profiling_active, ); match solver { Ok(solver) => StepResult::IntoBrillig(solver), diff --git a/noir/noir-repo/acvm-repo/acvm_js/build.sh b/noir/noir-repo/acvm-repo/acvm_js/build.sh index c07d2d8a4c1..16fb26e55db 100755 --- a/noir/noir-repo/acvm-repo/acvm_js/build.sh +++ b/noir/noir-repo/acvm-repo/acvm_js/build.sh @@ -25,7 +25,7 @@ function run_if_available { require_command jq require_command cargo require_command wasm-bindgen -#require_command wasm-opt +require_command wasm-opt self_path=$(dirname "$(readlink -f "$0")") pname=$(cargo read-manifest | jq -r '.name') diff --git a/noir/noir-repo/acvm-repo/brillig_vm/src/lib.rs b/noir/noir-repo/acvm-repo/brillig_vm/src/lib.rs index 1e5ad84eb8f..4d5ce4203f9 100644 --- a/noir/noir-repo/acvm-repo/brillig_vm/src/lib.rs +++ b/noir/noir-repo/acvm-repo/brillig_vm/src/lib.rs @@ -63,6 +63,15 @@ pub enum VMStatus { }, } +// A sample for each opcode that was executed. +pub type BrilligProfilingSamples = Vec; + +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct BrilligProfilingSample { + // The call stack when processing a given opcode. + pub call_stack: Vec, +} + #[derive(Debug, PartialEq, Eq, Clone)] /// VM encapsulates the state of the Brillig VM during execution. pub struct VM<'a, F, B: BlackBoxFunctionSolver> { @@ -88,6 +97,10 @@ pub struct VM<'a, F, B: BlackBoxFunctionSolver> { black_box_solver: &'a B, // The solver for big integers bigint_solver: BrilligBigintSolver, + // Flag that determines whether we want to profile VM. + profiling_active: bool, + // Samples for profiling the VM execution. + profiling_samples: BrilligProfilingSamples, } impl<'a, F: AcirField, B: BlackBoxFunctionSolver> VM<'a, F, B> { @@ -97,6 +110,7 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> VM<'a, F, B> { bytecode: &'a [Opcode], foreign_call_results: Vec>, black_box_solver: &'a B, + profiling_active: bool, ) -> Self { Self { calldata, @@ -109,9 +123,19 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> VM<'a, F, B> { call_stack: Vec::new(), black_box_solver, bigint_solver: Default::default(), + profiling_active, + profiling_samples: Vec::with_capacity(bytecode.len()), } } + pub fn is_profiling_active(&self) -> bool { + self.profiling_active + } + + pub fn take_profiling_samples(&mut self) -> BrilligProfilingSamples { + std::mem::take(&mut self.profiling_samples) + } + /// Updates the current status of the VM. /// Returns the given status. fn status(&mut self, status: VMStatus) -> VMStatus { @@ -196,6 +220,15 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> VM<'a, F, B> { /// Process a single opcode and modify the program counter. pub fn process_opcode(&mut self) -> VMStatus { + if self.profiling_active { + let call_stack: Vec = self.get_call_stack(); + self.profiling_samples.push(BrilligProfilingSample { call_stack }); + } + + self.process_opcode_internal() + } + + fn process_opcode_internal(&mut self) -> VMStatus { let opcode = &self.bytecode[self.program_counter]; match opcode { Opcode::BinaryFieldOp { op, lhs, rhs, destination: result } => { @@ -813,7 +846,7 @@ mod tests { }]; // Start VM - let mut vm = VM::new(calldata, &opcodes, vec![], &StubbedBlackBoxSolver); + let mut vm = VM::new(calldata, &opcodes, vec![], &StubbedBlackBoxSolver, false); let status = vm.process_opcode(); assert_eq!(status, VMStatus::Finished { return_data_offset: 0, return_data_size: 0 }); @@ -863,7 +896,7 @@ mod tests { Opcode::JumpIf { condition: destination, location: 6 }, ]; - let mut vm = VM::new(calldata, &opcodes, vec![], &StubbedBlackBoxSolver); + let mut vm = VM::new(calldata, &opcodes, vec![], &StubbedBlackBoxSolver, false); let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); @@ -921,7 +954,7 @@ mod tests { }, ]; - let mut vm = VM::new(calldata, &opcodes, vec![], &StubbedBlackBoxSolver); + let mut vm = VM::new(calldata, &opcodes, vec![], &StubbedBlackBoxSolver, false); let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); @@ -982,7 +1015,7 @@ mod tests { }, Opcode::Stop { return_data_offset: 1, return_data_size: 1 }, ]; - let mut vm = VM::new(calldata, opcodes, vec![], &StubbedBlackBoxSolver); + let mut vm = VM::new(calldata, opcodes, vec![], &StubbedBlackBoxSolver, false); let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); @@ -1033,7 +1066,7 @@ mod tests { }, Opcode::Stop { return_data_offset: 1, return_data_size: 1 }, ]; - let mut vm = VM::new(calldata, opcodes, vec![], &StubbedBlackBoxSolver); + let mut vm = VM::new(calldata, opcodes, vec![], &StubbedBlackBoxSolver, false); let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); @@ -1079,7 +1112,7 @@ mod tests { }, Opcode::Mov { destination: MemoryAddress::direct(2), source: MemoryAddress::direct(0) }, ]; - let mut vm = VM::new(calldata, opcodes, vec![], &StubbedBlackBoxSolver); + let mut vm = VM::new(calldata, opcodes, vec![], &StubbedBlackBoxSolver, false); let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); @@ -1144,7 +1177,7 @@ mod tests { condition: MemoryAddress::direct(1), }, ]; - let mut vm = VM::new(calldata, opcodes, vec![], &StubbedBlackBoxSolver); + let mut vm = VM::new(calldata, opcodes, vec![], &StubbedBlackBoxSolver, false); let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); @@ -1240,7 +1273,7 @@ mod tests { .chain(cast_opcodes) .chain([equal_opcode, not_equal_opcode, less_than_opcode, less_than_equal_opcode]) .collect(); - let mut vm = VM::new(calldata, &opcodes, vec![], &StubbedBlackBoxSolver); + let mut vm = VM::new(calldata, &opcodes, vec![], &StubbedBlackBoxSolver, false); // Calldata copy let status = vm.process_opcode(); @@ -1368,7 +1401,7 @@ mod tests { value: FieldElement::from(27_usize), }, ]; - let mut vm = VM::new(vec![], opcodes, vec![], &StubbedBlackBoxSolver); + let mut vm = VM::new(vec![], opcodes, vec![], &StubbedBlackBoxSolver, false); let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); @@ -1592,7 +1625,7 @@ mod tests { calldata: Vec, opcodes: &[Opcode], ) -> VM<'_, F, StubbedBlackBoxSolver> { - let mut vm = VM::new(calldata, opcodes, vec![], &StubbedBlackBoxSolver); + let mut vm = VM::new(calldata, opcodes, vec![], &StubbedBlackBoxSolver, false); brillig_execute(&mut vm); assert_eq!(vm.call_stack, vec![]); vm @@ -2271,7 +2304,7 @@ mod tests { }, ]; - let mut vm = VM::new(calldata, &opcodes, vec![], &StubbedBlackBoxSolver); + let mut vm = VM::new(calldata, &opcodes, vec![], &StubbedBlackBoxSolver, false); vm.process_opcode(); vm.process_opcode(); diff --git a/noir/noir-repo/compiler/integration-tests/package.json b/noir/noir-repo/compiler/integration-tests/package.json index e33179f31e7..62ae699fc4e 100644 --- a/noir/noir-repo/compiler/integration-tests/package.json +++ b/noir/noir-repo/compiler/integration-tests/package.json @@ -13,7 +13,7 @@ "lint": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ./.eslintignore --max-warnings 0" }, "dependencies": { - "@aztec/bb.js": "portal:../../../../barretenberg/ts", + "@aztec/bb.js": "0.60.0", "@noir-lang/noir_js": "workspace:*", "@noir-lang/noir_wasm": "workspace:*", "@nomicfoundation/hardhat-chai-matchers": "^2.0.0", diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs index 55f89dcb30f..3685c9540f3 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs @@ -8,7 +8,7 @@ use acvm::{ use crate::brillig::brillig_ir::{ brillig_variable::BrilligVariable, debug_show::DebugToString, registers::RegisterAllocator, - BrilligBinaryOp, BrilligContext, + BrilligContext, }; /// Transforms SSA's black box function calls into the corresponding brillig instructions @@ -395,19 +395,8 @@ pub(crate) fn convert_black_box_call BrilligBlock<'block> { match output_register { // Returned vectors need to emit some bytecode to format the result as a BrilligVector ValueOrArray::HeapVector(heap_vector) => { - // Update the stack pointer so that we do not overwrite - // dynamic memory returned from other external calls - // Single values and allocation of fixed sized arrays has already been handled - // inside of `allocate_external_call_result` - let total_size = self.brillig_context.allocate_register(); - self.brillig_context.codegen_usize_op( - heap_vector.size, - total_size, - BrilligBinaryOp::Add, - 2, // RC and Length + self.brillig_context.initialize_externally_returned_vector( + output_variable.extract_vector(), + *heap_vector, ); - - self.brillig_context - .increase_free_memory_pointer_instruction(total_size); - let brillig_vector = output_variable.extract_vector(); - let size_pointer = self.brillig_context.allocate_register(); - - self.brillig_context.codegen_usize_op( - brillig_vector.pointer, - size_pointer, - BrilligBinaryOp::Add, - 1_usize, // Slices are [RC, Size, ...items] - ); - self.brillig_context - .store_instruction(size_pointer, heap_vector.size); - self.brillig_context.deallocate_register(size_pointer); - self.brillig_context.deallocate_register(total_size); - // Update the dynamic slice length maintained in SSA if let ValueOrArray::MemoryAddress(len_index) = output_values[i - 1] { @@ -515,8 +491,11 @@ impl<'block> BrilligBlock<'block> { element_size, ); - self.brillig_context - .codegen_initialize_vector(destination_vector, source_size_register); + self.brillig_context.codegen_initialize_vector( + destination_vector, + source_size_register, + None, + ); // Items let vector_items_pointer = @@ -1551,7 +1530,7 @@ impl<'block> BrilligBlock<'block> { let size = self .brillig_context .make_usize_constant_instruction(array.len().into()); - self.brillig_context.codegen_initialize_vector(vector, size); + self.brillig_context.codegen_initialize_vector(vector, size, None); self.brillig_context.deallocate_single_addr(size); } _ => unreachable!( @@ -1797,11 +1776,6 @@ impl<'block> BrilligBlock<'block> { // The stack pointer will then be updated by the caller of this method // once the external call is resolved and the array size is known self.brillig_context.load_free_memory_pointer_instruction(vector.pointer); - self.brillig_context.indirect_const_instruction( - vector.pointer, - BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, - 1_usize.into(), - ); variable } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs index 76e35395dd6..26c7151bf07 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs @@ -79,17 +79,15 @@ impl<'block> BrilligBlock<'block> { source_vector: BrilligVector, removed_items: &[BrilligVariable], ) { - let read_pointer = self.brillig_context.allocate_register(); - self.brillig_context.call_vector_pop_procedure( + let read_pointer = self.brillig_context.codegen_make_vector_items_pointer(source_vector); + self.read_variables(read_pointer, removed_items); + self.brillig_context.deallocate_register(read_pointer); + + self.brillig_context.call_vector_pop_front_procedure( source_vector, target_vector, - read_pointer, removed_items.len(), - false, ); - - self.read_variables(read_pointer, removed_items); - self.brillig_context.deallocate_register(read_pointer); } pub(crate) fn slice_pop_back_operation( @@ -99,12 +97,11 @@ impl<'block> BrilligBlock<'block> { removed_items: &[BrilligVariable], ) { let read_pointer = self.brillig_context.allocate_register(); - self.brillig_context.call_vector_pop_procedure( + self.brillig_context.call_vector_pop_back_procedure( source_vector, target_vector, read_pointer, removed_items.len(), - true, ); self.read_variables(read_pointer, removed_items); @@ -213,7 +210,7 @@ mod tests { push_back: bool, array: Vec, item_to_push: FieldElement, - mut expected_return: Vec, + expected_return: Vec, ) { let arguments = vec![ BrilligParameter::Slice( @@ -223,11 +220,15 @@ mod tests { BrilligParameter::SingleAddr(BRILLIG_MEMORY_ADDRESSING_BIT_SIZE), ]; let result_length = array.len() + 1; + assert_eq!(result_length, expected_return.len()); + let result_length_with_metadata = result_length + 2; // Leading length and capacity + + // Entry points don't support returning slices, so we implicitly cast the vector to an array + // With the metadata at the start. let returns = vec![BrilligParameter::Array( vec![BrilligParameter::SingleAddr(BRILLIG_MEMORY_ADDRESSING_BIT_SIZE)], - result_length + 1, // Leading length since the we return a vector + result_length_with_metadata, )]; - expected_return.insert(0, FieldElement::from(result_length)); let (_, mut function_context, mut context) = create_test_environment(); @@ -262,14 +263,17 @@ mod tests { let bytecode = create_entry_point_bytecode(context, arguments, returns).byte_code; let (vm, return_data_offset, return_data_size) = create_and_run_vm(array.into_iter().chain(vec![item_to_push]).collect(), &bytecode); - assert_eq!(return_data_size, expected_return.len()); - assert_eq!( - vm.get_memory()[return_data_offset..(return_data_offset + expected_return.len())] - .iter() - .map(|mem_val| mem_val.to_field()) - .collect::>(), - expected_return - ); + assert_eq!(return_data_size, result_length_with_metadata); + let mut returned_vector: Vec = vm.get_memory() + [return_data_offset..(return_data_offset + result_length_with_metadata)] + .iter() + .map(|mem_val| mem_val.to_field()) + .collect(); + let returned_size = returned_vector.remove(0); + assert_eq!(returned_size, result_length.into()); + let _returned_capacity = returned_vector.remove(0); + + assert_eq!(returned_vector, expected_return); } test_case_push( @@ -321,7 +325,7 @@ mod tests { fn test_case_pop( pop_back: bool, array: Vec, - mut expected_return_array: Vec, + expected_return_array: Vec, expected_return_item: FieldElement, ) { let arguments = vec![BrilligParameter::Slice( @@ -329,15 +333,18 @@ mod tests { array.len(), )]; let result_length = array.len() - 1; + assert_eq!(result_length, expected_return_array.len()); + let result_length_with_metadata = result_length + 2; // Leading length and capacity + // Entry points don't support returning slices, so we implicitly cast the vector to an array + // With the metadata at the start. let returns = vec![ + BrilligParameter::SingleAddr(BRILLIG_MEMORY_ADDRESSING_BIT_SIZE), BrilligParameter::Array( vec![BrilligParameter::SingleAddr(BRILLIG_MEMORY_ADDRESSING_BIT_SIZE)], - result_length + 1, + result_length_with_metadata, ), - BrilligParameter::SingleAddr(BRILLIG_MEMORY_ADDRESSING_BIT_SIZE), ]; - expected_return_array.insert(0, FieldElement::from(result_length)); let (_, mut function_context, mut context) = create_test_environment(); @@ -367,22 +374,28 @@ mod tests { ); } - context.codegen_return(&[target_vector.pointer, removed_item.address]); + context.codegen_return(&[removed_item.address, target_vector.pointer]); let bytecode = create_entry_point_bytecode(context, arguments, returns).byte_code; - let expected_return: Vec<_> = - expected_return_array.into_iter().chain(vec![expected_return_item]).collect(); + let (vm, return_data_offset, return_data_size) = create_and_run_vm(array.clone(), &bytecode); - assert_eq!(return_data_size, expected_return.len()); - - assert_eq!( - vm.get_memory()[return_data_offset..(return_data_offset + expected_return.len())] - .iter() - .map(|mem_val| mem_val.to_field()) - .collect::>(), - expected_return - ); + // vector + removed item + assert_eq!(return_data_size, result_length_with_metadata + 1); + + let mut return_data: Vec = vm.get_memory() + [return_data_offset..(return_data_offset + return_data_size)] + .iter() + .map(|mem_val| mem_val.to_field()) + .collect(); + let returned_item = return_data.remove(0); + assert_eq!(returned_item, expected_return_item); + + let returned_size = return_data.remove(0); + assert_eq!(returned_size, result_length.into()); + let _returned_capacity = return_data.remove(0); + + assert_eq!(return_data, expected_return_array); } test_case_pop( @@ -414,7 +427,7 @@ mod tests { array: Vec, item: FieldElement, index: FieldElement, - mut expected_return: Vec, + expected_return: Vec, ) { let arguments = vec![ BrilligParameter::Slice( @@ -425,11 +438,15 @@ mod tests { BrilligParameter::SingleAddr(BRILLIG_MEMORY_ADDRESSING_BIT_SIZE), ]; let result_length = array.len() + 1; + assert_eq!(result_length, expected_return.len()); + let result_length_with_metadata = result_length + 2; // Leading length and capacity + + // Entry points don't support returning slices, so we implicitly cast the vector to an array + // With the metadata at the start. let returns = vec![BrilligParameter::Array( vec![BrilligParameter::SingleAddr(BRILLIG_MEMORY_ADDRESSING_BIT_SIZE)], - result_length + 1, + result_length_with_metadata, )]; - expected_return.insert(0, FieldElement::from(result_length)); let (_, mut function_context, mut context) = create_test_environment(); @@ -461,15 +478,18 @@ mod tests { let bytecode = create_entry_point_bytecode(context, arguments, returns).byte_code; let (vm, return_data_offset, return_data_size) = create_and_run_vm(calldata, &bytecode); - assert_eq!(return_data_size, expected_return.len()); - - assert_eq!( - vm.get_memory()[return_data_offset..(return_data_offset + expected_return.len())] - .iter() - .map(|mem_val| mem_val.to_field()) - .collect::>(), - expected_return - ); + assert_eq!(return_data_size, result_length_with_metadata); + + let mut returned_vector: Vec = vm.get_memory() + [return_data_offset..(return_data_offset + result_length_with_metadata)] + .iter() + .map(|mem_val| mem_val.to_field()) + .collect(); + let returned_size = returned_vector.remove(0); + assert_eq!(returned_size, result_length.into()); + let _returned_capacity = returned_vector.remove(0); + + assert_eq!(returned_vector, expected_return); } test_case_insert( @@ -546,7 +566,7 @@ mod tests { fn test_case_remove( array: Vec, index: FieldElement, - mut expected_array: Vec, + expected_array: Vec, expected_removed_item: FieldElement, ) { let arguments = vec![ @@ -557,15 +577,16 @@ mod tests { BrilligParameter::SingleAddr(BRILLIG_MEMORY_ADDRESSING_BIT_SIZE), ]; let result_length = array.len() - 1; + assert_eq!(result_length, expected_array.len()); + let result_length_with_metadata = result_length + 2; // Leading length and capacity let returns = vec![ + BrilligParameter::SingleAddr(BRILLIG_MEMORY_ADDRESSING_BIT_SIZE), BrilligParameter::Array( vec![BrilligParameter::SingleAddr(BRILLIG_MEMORY_ADDRESSING_BIT_SIZE)], - result_length + 1, + result_length_with_metadata, ), - BrilligParameter::SingleAddr(BRILLIG_MEMORY_ADDRESSING_BIT_SIZE), ]; - expected_array.insert(0, FieldElement::from(result_length)); let (_, mut function_context, mut context) = create_test_environment(); @@ -592,24 +613,29 @@ mod tests { &[BrilligVariable::SingleAddr(removed_item)], ); - context.codegen_return(&[target_vector.pointer, removed_item.address]); + context.codegen_return(&[removed_item.address, target_vector.pointer]); let calldata: Vec<_> = array.into_iter().chain(vec![index]).collect(); let bytecode = create_entry_point_bytecode(context, arguments, returns).byte_code; let (vm, return_data_offset, return_data_size) = create_and_run_vm(calldata, &bytecode); - let expected_return: Vec<_> = - expected_array.into_iter().chain(vec![expected_removed_item]).collect(); - assert_eq!(return_data_size, expected_return.len()); + // vector + removed item + assert_eq!(return_data_size, result_length_with_metadata + 1); - assert_eq!( - vm.get_memory()[return_data_offset..(return_data_offset + expected_return.len())] - .iter() - .map(|mem_val| mem_val.to_field()) - .collect::>(), - expected_return - ); + let mut return_data: Vec = vm.get_memory() + [return_data_offset..(return_data_offset + return_data_size)] + .iter() + .map(|mem_val| mem_val.to_field()) + .collect(); + let returned_item = return_data.remove(0); + assert_eq!(returned_item, expected_removed_item); + + let returned_size = return_data.remove(0); + assert_eq!(returned_size, result_length.into()); + let _returned_capacity = return_data.remove(0); + + assert_eq!(return_data, expected_array); } test_case_remove( diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir.rs index 4964ff27f60..416f0300508 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir.rs @@ -233,7 +233,8 @@ pub(crate) mod tests { calldata: Vec, bytecode: &[BrilligOpcode], ) -> (VM<'_, FieldElement, DummyBlackBoxSolver>, usize, usize) { - let mut vm = VM::new(calldata, bytecode, vec![], &DummyBlackBoxSolver); + let profiling_active = false; + let mut vm = VM::new(calldata, bytecode, vec![], &DummyBlackBoxSolver, profiling_active); let status = vm.process_opcodes(); if let VMStatus::Finished { return_data_offset, return_data_size } = status { @@ -301,6 +302,7 @@ pub(crate) mod tests { &bytecode, vec![ForeignCallResult { values: vec![ForeignCallParam::Array(number_sequence)] }], &DummyBlackBoxSolver, + false, ); let status = vm.process_opcodes(); assert_eq!(status, VMStatus::Finished { return_data_offset: 0, return_data_size: 0 }); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_control_flow.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_control_flow.rs index c305d8c78f3..b74154c16be 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_control_flow.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_control_flow.rs @@ -12,6 +12,41 @@ use super::{ }; impl BrilligContext { + pub(crate) fn codegen_generic_iteration( + &mut self, + make_iterator: impl FnOnce(&mut BrilligContext) -> T, + update_iterator: impl FnOnce(&mut BrilligContext, &T), + make_finish_condition: impl FnOnce(&mut BrilligContext, &T) -> SingleAddrVariable, + on_iteration: impl FnOnce(&mut BrilligContext, &T), + clean_iterator: impl FnOnce(&mut BrilligContext, T), + ) { + let iterator = make_iterator(self); + + let (loop_section, loop_label) = self.reserve_next_section_label(); + self.enter_section(loop_section); + + // Loop body + let should_end = make_finish_condition(self, &iterator); + + let (exit_loop_section, exit_loop_label) = self.reserve_next_section_label(); + + self.jump_if_instruction(should_end.address, exit_loop_label); + + // Call the on iteration function + on_iteration(self, &iterator); + + // Update iterator + update_iterator(self, &iterator); + self.jump_instruction(loop_label); + + // Exit the loop + self.enter_section(exit_loop_section); + + // Deallocate our temporary registers + self.deallocate_single_addr(should_end); + clean_iterator(self, iterator); + } + /// This codegen will issue a loop for (let iterator_register = loop_start; i < loop_bound; i += step) /// The body of the loop should be issued by the caller in the on_iteration closure. pub(crate) fn codegen_for_loop( diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_memory.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_memory.rs index 0199d9537a6..a34034bb550 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_memory.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_memory.rs @@ -93,16 +93,125 @@ impl BrilligContext< ); } else { let value_register = self.allocate_register(); + let end_source_pointer = self.allocate_register(); + self.memory_op_instruction( + source_pointer, + num_elements_variable.address, + end_source_pointer, + BrilligBinaryOp::Add, + ); - self.codegen_loop(num_elements_variable.address, |ctx, iterator| { - ctx.codegen_load_with_offset(source_pointer, iterator, value_register); - ctx.codegen_store_with_offset(destination_pointer, iterator, value_register); - }); - + self.codegen_generic_iteration( + |brillig_context| { + let source_iterator = brillig_context.allocate_register(); + let target_iterator = brillig_context.allocate_register(); + + brillig_context.mov_instruction(source_iterator, source_pointer); + brillig_context.mov_instruction(target_iterator, destination_pointer); + + (source_iterator, target_iterator) + }, + |brillig_context, &(source_iterator, target_iterator)| { + brillig_context.codegen_usize_op_in_place( + source_iterator, + BrilligBinaryOp::Add, + 1, + ); + brillig_context.codegen_usize_op_in_place( + target_iterator, + BrilligBinaryOp::Add, + 1, + ); + }, + |brillig_context, &(source_iterator, _)| { + // We have finished when the source/target pointer is less than the source/target start + let finish_condition = + SingleAddrVariable::new(brillig_context.allocate_register(), 1); + brillig_context.memory_op_instruction( + source_iterator, + end_source_pointer, + finish_condition.address, + BrilligBinaryOp::Equals, + ); + finish_condition + }, + |brillig_context, &(source_iterator, target_iterator)| { + brillig_context.load_instruction(value_register, source_iterator); + brillig_context.store_instruction(target_iterator, value_register); + }, + |brillig_context, (source_iterator, target_iterator)| { + brillig_context.deallocate_register(source_iterator); + brillig_context.deallocate_register(target_iterator); + }, + ); self.deallocate_register(value_register); + self.deallocate_register(end_source_pointer); } } + /// Copies num_elements_variable from the source pointer to the target pointer, starting from the end + pub(crate) fn codegen_mem_copy_from_the_end( + &mut self, + source_start: MemoryAddress, + target_start: MemoryAddress, + num_elements_variable: SingleAddrVariable, + ) { + self.codegen_generic_iteration( + |brillig_context| { + // Create the pointer to the last item for both source and target + let num_items_minus_one = brillig_context.allocate_register(); + brillig_context.codegen_usize_op( + num_elements_variable.address, + num_items_minus_one, + BrilligBinaryOp::Sub, + 1, + ); + let target_pointer = brillig_context.allocate_register(); + brillig_context.memory_op_instruction( + target_start, + num_items_minus_one, + target_pointer, + BrilligBinaryOp::Add, + ); + let source_pointer = brillig_context.allocate_register(); + brillig_context.memory_op_instruction( + source_start, + num_items_minus_one, + source_pointer, + BrilligBinaryOp::Add, + ); + brillig_context.deallocate_register(num_items_minus_one); + (source_pointer, target_pointer) + }, + |brillig_context, &(source_pointer, target_pointer)| { + brillig_context.codegen_usize_op_in_place(source_pointer, BrilligBinaryOp::Sub, 1); + brillig_context.codegen_usize_op_in_place(target_pointer, BrilligBinaryOp::Sub, 1); + }, + |brillig_context, &(source_pointer, _)| { + // We have finished when the source/target pointer is less than the source/target start + let finish_condition = + SingleAddrVariable::new(brillig_context.allocate_register(), 1); + brillig_context.memory_op_instruction( + source_pointer, + source_start, + finish_condition.address, + BrilligBinaryOp::LessThan, + ); + finish_condition + }, + |brillig_context, &(source_pointer, target_pointer)| { + let value_register = brillig_context.allocate_register(); + brillig_context.load_instruction(value_register, source_pointer); + brillig_context.store_instruction(target_pointer, value_register); + brillig_context.deallocate_register(value_register); + }, + |brillig_context, (source_pointer, target_pointer)| { + brillig_context.deallocate_register(source_pointer); + brillig_context.deallocate_register(target_pointer); + }, + ); + } + /// This instruction will reverse the order of the `size` elements pointed by `pointer`. pub(crate) fn codegen_array_reverse( &mut self, @@ -170,7 +279,7 @@ impl BrilligContext< self.codegen_usize_op(vector.pointer, current_pointer, BrilligBinaryOp::Add, 1); self.load_instruction(heap_vector.size, current_pointer); // Now prepare the pointer to the items - self.codegen_usize_op(current_pointer, heap_vector.pointer, BrilligBinaryOp::Add, 1); + self.codegen_usize_op(current_pointer, heap_vector.pointer, BrilligBinaryOp::Add, 2); self.deallocate_register(current_pointer); heap_vector @@ -201,16 +310,73 @@ impl BrilligContext< result } + pub(crate) fn codegen_update_vector_length( + &mut self, + vector: BrilligVector, + new_length: SingleAddrVariable, + ) { + let write_pointer = self.allocate_register(); + self.codegen_usize_op(vector.pointer, write_pointer, BrilligBinaryOp::Add, 1); + self.store_instruction(write_pointer, new_length.address); + self.deallocate_register(write_pointer); + } + + /// Returns a variable holding the capacity of a given vector + pub(crate) fn codegen_make_vector_capacity( + &mut self, + vector: BrilligVector, + ) -> SingleAddrVariable { + let result = SingleAddrVariable::new_usize(self.allocate_register()); + self.codegen_usize_op(vector.pointer, result.address, BrilligBinaryOp::Add, 2); + self.load_instruction(result.address, result.address); + result + } + + /// Writes a pointer to the items of a given vector + pub(crate) fn codegen_vector_items_pointer( + &mut self, + vector: BrilligVector, + result: MemoryAddress, + ) { + self.codegen_usize_op(vector.pointer, result, BrilligBinaryOp::Add, 3); + } + /// Returns a pointer to the items of a given vector pub(crate) fn codegen_make_vector_items_pointer( &mut self, vector: BrilligVector, ) -> MemoryAddress { let result = self.allocate_register(); - self.codegen_usize_op(vector.pointer, result, BrilligBinaryOp::Add, 2); + self.codegen_vector_items_pointer(vector, result); result } + /// Reads the metadata of a vector and stores it in the given variables + pub(crate) fn codegen_read_vector_metadata( + &mut self, + vector: BrilligVector, + rc: SingleAddrVariable, + size: SingleAddrVariable, + capacity: SingleAddrVariable, + items_pointer: SingleAddrVariable, + ) { + assert!(rc.bit_size == BRILLIG_MEMORY_ADDRESSING_BIT_SIZE); + assert!(size.bit_size == BRILLIG_MEMORY_ADDRESSING_BIT_SIZE); + assert!(capacity.bit_size == BRILLIG_MEMORY_ADDRESSING_BIT_SIZE); + assert!(items_pointer.bit_size == BRILLIG_MEMORY_ADDRESSING_BIT_SIZE); + + self.load_instruction(rc.address, vector.pointer); + + let read_pointer = self.allocate_register(); + self.codegen_usize_op(vector.pointer, read_pointer, BrilligBinaryOp::Add, 1); + self.load_instruction(size.address, read_pointer); + self.codegen_usize_op_in_place(read_pointer, BrilligBinaryOp::Add, 1); + self.load_instruction(capacity.address, read_pointer); + self.codegen_usize_op(read_pointer, items_pointer.address, BrilligBinaryOp::Add, 1); + + self.deallocate_register(read_pointer); + } + /// Returns a variable holding the length of a given array pub(crate) fn codegen_make_array_length(&mut self, array: BrilligArray) -> SingleAddrVariable { let result = SingleAddrVariable::new_usize(self.allocate_register()); @@ -262,28 +428,88 @@ impl BrilligContext< ); } - /// Initializes a vector, allocating memory to store its representation and initializing the reference counter and size. + pub(crate) fn codegen_initialize_vector_metadata( + &mut self, + vector: BrilligVector, + size: SingleAddrVariable, + capacity: Option, + ) { + // Write RC + self.indirect_const_instruction( + vector.pointer, + BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, + 1_usize.into(), + ); + + // Write size + let write_pointer = self.allocate_register(); + self.codegen_usize_op(vector.pointer, write_pointer, BrilligBinaryOp::Add, 1); + self.store_instruction(write_pointer, size.address); + + // Write capacity + self.codegen_usize_op_in_place(write_pointer, BrilligBinaryOp::Add, 1); + self.store_instruction(write_pointer, capacity.unwrap_or(size).address); + + self.deallocate_register(write_pointer); + } + + /// Initializes a vector, allocating memory to store its representation and initializing the reference counter, size and capacity pub(crate) fn codegen_initialize_vector( &mut self, vector: BrilligVector, size: SingleAddrVariable, + capacity: Option, // Defaults to size if None ) { let allocation_size = self.allocate_register(); - self.codegen_usize_op(size.address, allocation_size, BrilligBinaryOp::Add, 2); + // Allocation size = capacity + 3 (rc, size, capacity) + self.codegen_usize_op( + capacity.unwrap_or(size).address, + allocation_size, + BrilligBinaryOp::Add, + 3, + ); self.codegen_allocate_mem(vector.pointer, allocation_size); self.deallocate_register(allocation_size); - // Write RC + self.codegen_initialize_vector_metadata(vector, size, capacity); + } + + /// We don't know the length of a vector returned externally before the call + /// so we pass the free memory pointer and then use this function to allocate + /// after the fact when we know the length. + pub(crate) fn initialize_externally_returned_vector( + &mut self, + vector: BrilligVector, + resulting_heap_vector: HeapVector, + ) { + let total_size = self.allocate_register(); + self.codegen_usize_op( + resulting_heap_vector.size, + total_size, + BrilligBinaryOp::Add, + 3, // Rc, length and capacity + ); + + self.increase_free_memory_pointer_instruction(total_size); + let write_pointer = self.allocate_register(); + + // Vectors are [RC, Size, Capacity, ...items] + // Initialize RC self.indirect_const_instruction( vector.pointer, BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, 1_usize.into(), ); - // Write size - let len_write_pointer = self.allocate_register(); - self.codegen_usize_op(vector.pointer, len_write_pointer, BrilligBinaryOp::Add, 1); - self.store_instruction(len_write_pointer, size.address); - self.deallocate_register(len_write_pointer); + // Initialize size + self.codegen_usize_op(vector.pointer, write_pointer, BrilligBinaryOp::Add, 1_usize); + self.store_instruction(write_pointer, resulting_heap_vector.size); + + // Initialize capacity + self.codegen_usize_op_in_place(write_pointer, BrilligBinaryOp::Add, 1_usize); + self.store_instruction(write_pointer, resulting_heap_vector.size); + + self.deallocate_register(write_pointer); + self.deallocate_register(total_size); } } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs index 75d91716c23..b78dcb09d9a 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs @@ -196,7 +196,7 @@ impl BrilligContext { let deflattened_items_pointer = if is_vector { let vector = BrilligVector { pointer: deflattened_array_pointer }; - self.codegen_initialize_vector(vector, deflattened_size_variable); + self.codegen_initialize_vector(vector, deflattened_size_variable, None); self.codegen_make_vector_items_pointer(vector) } else { diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/mod.rs index 0ee6fe49435..1c3d1f4d0ad 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/mod.rs @@ -5,7 +5,8 @@ mod mem_copy; mod prepare_vector_insert; mod prepare_vector_push; mod vector_copy; -mod vector_pop; +mod vector_pop_back; +mod vector_pop_front; mod vector_remove; use array_copy::compile_array_copy_procedure; @@ -15,7 +16,8 @@ use mem_copy::compile_mem_copy_procedure; use prepare_vector_insert::compile_prepare_vector_insert_procedure; use prepare_vector_push::compile_prepare_vector_push_procedure; use vector_copy::compile_vector_copy_procedure; -use vector_pop::compile_vector_pop_procedure; +use vector_pop_back::compile_vector_pop_back_procedure; +use vector_pop_front::compile_vector_pop_front_procedure; use vector_remove::compile_vector_remove_procedure; use crate::brillig::brillig_ir::AcirField; @@ -36,7 +38,8 @@ pub(crate) enum ProcedureId { VectorCopy, MemCopy, PrepareVectorPush(bool), - VectorPop(bool), + VectorPopFront, + VectorPopBack, PrepareVectorInsert, VectorRemove, CheckMaxStackDepth, @@ -56,8 +59,11 @@ pub(crate) fn compile_procedure( ProcedureId::PrepareVectorPush(push_back) => { compile_prepare_vector_push_procedure(&mut brillig_context, push_back); } - ProcedureId::VectorPop(pop_back) => { - compile_vector_pop_procedure(&mut brillig_context, pop_back); + ProcedureId::VectorPopFront => { + compile_vector_pop_front_procedure(&mut brillig_context); + } + ProcedureId::VectorPopBack => { + compile_vector_pop_back_procedure(&mut brillig_context); } ProcedureId::PrepareVectorInsert => { compile_prepare_vector_insert_procedure(&mut brillig_context); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/prepare_vector_insert.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/prepare_vector_insert.rs index 8dbbf80782c..1c1a738509c 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/prepare_vector_insert.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/prepare_vector_insert.rs @@ -2,7 +2,7 @@ use std::vec; use acvm::{acir::brillig::MemoryAddress, AcirField}; -use super::ProcedureId; +use super::{prepare_vector_push::reallocate_vector_for_insertion, ProcedureId}; use crate::brillig::brillig_ir::{ brillig_variable::{BrilligVector, SingleAddrVariable}, debug_show::DebugToString, @@ -58,9 +58,19 @@ pub(super) fn compile_prepare_vector_insert_procedure( + brillig_context: &mut BrilligContext, + source_vector: BrilligVector, + source_rc: SingleAddrVariable, + source_capacity: SingleAddrVariable, + target_vector: BrilligVector, + target_size: SingleAddrVariable, +) { + let does_capacity_fit = SingleAddrVariable::new(brillig_context.allocate_register(), 1); + brillig_context.memory_op_instruction( + target_size.address, + source_capacity.address, + does_capacity_fit.address, + BrilligBinaryOp::LessThanEquals, + ); + + let is_rc_one = SingleAddrVariable::new(brillig_context.allocate_register(), 1); + brillig_context.codegen_usize_op( + source_rc.address, + is_rc_one.address, + BrilligBinaryOp::Equals, + 1, + ); + + // Reallocate target vector for insertion + brillig_context.codegen_branch( + does_capacity_fit.address, + |brillig_context, does_capacity_fit| { + if does_capacity_fit { + brillig_context.codegen_branch(is_rc_one.address, |brillig_context, is_rc_one| { + if is_rc_one { + // We can insert in place, so we can just move the source pointer to the destination pointer and update the length + brillig_context + .mov_instruction(target_vector.pointer, source_vector.pointer); + brillig_context.codegen_update_vector_length(target_vector, target_size); + } else { + brillig_context.codegen_initialize_vector( + target_vector, + target_size, + Some(source_capacity), + ); + } + }); + } else { + let double_size = + SingleAddrVariable::new_usize(brillig_context.allocate_register()); + brillig_context.codegen_usize_op( + target_size.address, + double_size.address, + BrilligBinaryOp::Mul, + 2_usize, + ); + brillig_context.codegen_initialize_vector( + target_vector, + target_size, + Some(double_size), + ); + brillig_context.deallocate_single_addr(double_size); + } + }, + ); + + brillig_context.deallocate_single_addr(is_rc_one); + brillig_context.deallocate_single_addr(does_capacity_fit); +} diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/vector_copy.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/vector_copy.rs index 7695e840c0b..6d2f9c4afb4 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/vector_copy.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/vector_copy.rs @@ -53,8 +53,8 @@ pub(super) fn compile_vector_copy_procedure( let result_vector = BrilligVector { pointer: new_vector_pointer_return }; // Allocate the memory for the new vec - let allocation_size = ctx.codegen_make_vector_length(source_vector); - ctx.codegen_usize_op_in_place(allocation_size.address, BrilligBinaryOp::Add, 2_usize); + let allocation_size = ctx.codegen_make_vector_capacity(source_vector); + ctx.codegen_usize_op_in_place(allocation_size.address, BrilligBinaryOp::Add, 3_usize); // Capacity plus 3 (rc, len, cap) ctx.codegen_allocate_mem(result_vector.pointer, allocation_size.address); ctx.codegen_mem_copy(source_vector.pointer, result_vector.pointer, allocation_size); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/vector_pop.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/vector_pop_back.rs similarity index 60% rename from noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/vector_pop.rs rename to noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/vector_pop_back.rs index 8fcfebb2360..bfc9d512852 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/vector_pop.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/vector_pop_back.rs @@ -11,14 +11,13 @@ use crate::brillig::brillig_ir::{ }; impl BrilligContext { - /// Pops items from the vector, returning the new vector and the pointer to the popped items in read_pointer. - pub(crate) fn call_vector_pop_procedure( + /// Pops items from the back of a vector, returning the new vector and the pointer to the popped items in read_pointer. + pub(crate) fn call_vector_pop_back_procedure( &mut self, source_vector: BrilligVector, destination_vector: BrilligVector, read_pointer: MemoryAddress, item_pop_count: usize, - back: bool, ) { let source_vector_pointer_arg = MemoryAddress::direct(ScratchSpace::start()); let item_pop_count_arg = MemoryAddress::direct(ScratchSpace::start() + 1); @@ -28,16 +27,15 @@ impl BrilligContext< self.mov_instruction(source_vector_pointer_arg, source_vector.pointer); self.usize_const_instruction(item_pop_count_arg, item_pop_count.into()); - self.add_procedure_call_instruction(ProcedureId::VectorPop(back)); + self.add_procedure_call_instruction(ProcedureId::VectorPopBack); self.mov_instruction(destination_vector.pointer, new_vector_pointer_return); self.mov_instruction(read_pointer, read_pointer_return); } } -pub(super) fn compile_vector_pop_procedure( +pub(super) fn compile_vector_pop_back_procedure( brillig_context: &mut BrilligContext, - pop_back: bool, ) { let source_vector_pointer_arg = MemoryAddress::direct(ScratchSpace::start()); let item_pop_count_arg = MemoryAddress::direct(ScratchSpace::start() + 1); @@ -65,49 +63,47 @@ pub(super) fn compile_vector_pop_procedure( BrilligBinaryOp::Sub, ); - brillig_context.codegen_initialize_vector(target_vector, target_size); + let rc = brillig_context.allocate_register(); + brillig_context.load_instruction(rc, source_vector.pointer); + let is_rc_one = brillig_context.allocate_register(); + brillig_context.codegen_usize_op(rc, is_rc_one, BrilligBinaryOp::Equals, 1_usize); - // Now we offset the source pointer by removed_items.len() let source_vector_items_pointer = brillig_context.codegen_make_vector_items_pointer(source_vector); - let target_vector_items_pointer = - brillig_context.codegen_make_vector_items_pointer(target_vector); - - if pop_back { - // Now we copy the source vector starting at index 0 into the target vector - brillig_context.codegen_mem_copy( - source_vector_items_pointer, - target_vector_items_pointer, - target_size, - ); - brillig_context.memory_op_instruction( - source_vector_items_pointer, - target_size.address, - read_pointer_return, - BrilligBinaryOp::Add, - ); - } else { - let source_copy_pointer = brillig_context.allocate_register(); - brillig_context.memory_op_instruction( - source_vector_items_pointer, - item_pop_count_arg, - source_copy_pointer, - BrilligBinaryOp::Add, - ); - - // Now we copy the source vector starting at index removed_items.len() into the target vector - brillig_context.codegen_mem_copy( - source_copy_pointer, - target_vector_items_pointer, - target_size, - ); - brillig_context.mov_instruction(read_pointer_return, source_vector_items_pointer); - - brillig_context.deallocate_register(source_copy_pointer); - } + + brillig_context.codegen_branch(is_rc_one, |brillig_context, is_rc_one| { + if is_rc_one { + // We can reuse the source vector updating its length + brillig_context.mov_instruction(target_vector.pointer, source_vector.pointer); + brillig_context.codegen_update_vector_length(target_vector, target_size); + } else { + // We need to clone the source vector + brillig_context.codegen_initialize_vector(target_vector, target_size, None); + + let target_vector_items_pointer = + brillig_context.codegen_make_vector_items_pointer(target_vector); + + // Now we copy the source vector starting at index 0 into the target vector but with the reduced length + brillig_context.codegen_mem_copy( + source_vector_items_pointer, + target_vector_items_pointer, + target_size, + ); + brillig_context.deallocate_register(target_vector_items_pointer); + } + }); + + brillig_context.memory_op_instruction( + source_vector_items_pointer, + target_size.address, + read_pointer_return, + BrilligBinaryOp::Add, + ); + + brillig_context.deallocate_register(rc); + brillig_context.deallocate_register(is_rc_one); + brillig_context.deallocate_register(source_vector_items_pointer); brillig_context.deallocate_single_addr(source_size); brillig_context.deallocate_single_addr(target_size); - brillig_context.deallocate_register(source_vector_items_pointer); - brillig_context.deallocate_register(target_vector_items_pointer); } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/vector_pop_front.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/vector_pop_front.rs new file mode 100644 index 00000000000..49123ca2f50 --- /dev/null +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/vector_pop_front.rs @@ -0,0 +1,130 @@ +use std::vec; + +use acvm::{acir::brillig::MemoryAddress, AcirField}; + +use super::ProcedureId; +use crate::brillig::brillig_ir::{ + brillig_variable::{BrilligVector, SingleAddrVariable}, + debug_show::DebugToString, + registers::{RegisterAllocator, ScratchSpace}, + BrilligBinaryOp, BrilligContext, +}; + +impl BrilligContext { + /// Pops items from the front of a vector, returning the new vector + pub(crate) fn call_vector_pop_front_procedure( + &mut self, + source_vector: BrilligVector, + destination_vector: BrilligVector, + item_pop_count: usize, + ) { + let source_vector_pointer_arg = MemoryAddress::direct(ScratchSpace::start()); + let item_pop_count_arg = MemoryAddress::direct(ScratchSpace::start() + 1); + let new_vector_pointer_return = MemoryAddress::direct(ScratchSpace::start() + 2); + + self.mov_instruction(source_vector_pointer_arg, source_vector.pointer); + self.usize_const_instruction(item_pop_count_arg, item_pop_count.into()); + + self.add_procedure_call_instruction(ProcedureId::VectorPopFront); + + self.mov_instruction(destination_vector.pointer, new_vector_pointer_return); + } +} + +pub(super) fn compile_vector_pop_front_procedure( + brillig_context: &mut BrilligContext, +) { + let source_vector_pointer_arg = MemoryAddress::direct(ScratchSpace::start()); + let item_pop_count_arg = MemoryAddress::direct(ScratchSpace::start() + 1); + let new_vector_pointer_return = MemoryAddress::direct(ScratchSpace::start() + 2); + + brillig_context.set_allocated_registers(vec![ + source_vector_pointer_arg, + item_pop_count_arg, + new_vector_pointer_return, + ]); + + let source_vector = BrilligVector { pointer: source_vector_pointer_arg }; + let target_vector = BrilligVector { pointer: new_vector_pointer_return }; + + let source_rc = SingleAddrVariable::new_usize(brillig_context.allocate_register()); + let source_size = SingleAddrVariable::new_usize(brillig_context.allocate_register()); + let source_capacity = SingleAddrVariable::new_usize(brillig_context.allocate_register()); + let source_items_pointer = SingleAddrVariable::new_usize(brillig_context.allocate_register()); + brillig_context.codegen_read_vector_metadata( + source_vector, + source_rc, + source_size, + source_capacity, + source_items_pointer, + ); + + // target_size = source_size - item_pop_count + let target_size = SingleAddrVariable::new_usize(brillig_context.allocate_register()); + brillig_context.memory_op_instruction( + source_size.address, + item_pop_count_arg, + target_size.address, + BrilligBinaryOp::Sub, + ); + + let is_rc_one = brillig_context.allocate_register(); + brillig_context.codegen_usize_op( + source_rc.address, + is_rc_one, + BrilligBinaryOp::Equals, + 1_usize, + ); + + brillig_context.codegen_branch(is_rc_one, |brillig_context, is_rc_one| { + if is_rc_one { + // We reuse the source vector, moving the metadata to the right (decreasing capacity) + brillig_context.memory_op_instruction( + source_vector.pointer, + item_pop_count_arg, + target_vector.pointer, + BrilligBinaryOp::Add, + ); + brillig_context.memory_op_instruction( + source_capacity.address, + item_pop_count_arg, + source_capacity.address, + BrilligBinaryOp::Sub, + ); + brillig_context.codegen_initialize_vector_metadata( + target_vector, + target_size, + Some(source_capacity), + ); + } else { + brillig_context.codegen_initialize_vector(target_vector, target_size, None); + + let target_vector_items_pointer = + brillig_context.codegen_make_vector_items_pointer(target_vector); + + let source_copy_pointer = brillig_context.allocate_register(); + brillig_context.memory_op_instruction( + source_items_pointer.address, + item_pop_count_arg, + source_copy_pointer, + BrilligBinaryOp::Add, + ); + // Now we copy the source vector starting at index removed_items.len() into the target vector + brillig_context.codegen_mem_copy( + source_copy_pointer, + target_vector_items_pointer, + target_size, + ); + + brillig_context.deallocate_register(source_copy_pointer); + brillig_context.deallocate_register(target_vector_items_pointer); + } + }); + + brillig_context.deallocate_register(is_rc_one); + brillig_context.deallocate_single_addr(target_size); + brillig_context.deallocate_single_addr(source_rc); + brillig_context.deallocate_single_addr(source_size); + brillig_context.deallocate_single_addr(source_capacity); + brillig_context.deallocate_single_addr(source_items_pointer); +} diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/vector_remove.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/vector_remove.rs index b7b54f970fa..7abc43286ee 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/vector_remove.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/vector_remove.rs @@ -53,7 +53,7 @@ pub(super) fn compile_vector_remove_procedure( let target_vector = BrilligVector { pointer: new_vector_pointer_return }; let index = SingleAddrVariable::new_usize(index_arg); - // First we need to allocate the target vector decrementing the size by removed_items.len() + // Reallocate if necessary let source_size = brillig_context.codegen_make_vector_length(source_vector); let target_size = SingleAddrVariable::new_usize(brillig_context.allocate_register()); @@ -64,19 +64,36 @@ pub(super) fn compile_vector_remove_procedure( BrilligBinaryOp::Sub, ); - brillig_context.codegen_initialize_vector(target_vector, target_size); + let rc = brillig_context.allocate_register(); + brillig_context.load_instruction(rc, source_vector.pointer); + let is_rc_one = brillig_context.allocate_register(); + brillig_context.codegen_usize_op(rc, is_rc_one, BrilligBinaryOp::Equals, 1_usize); - // Copy the elements to the left of the index let source_vector_items_pointer = brillig_context.codegen_make_vector_items_pointer(source_vector); - let target_vector_items_pointer = - brillig_context.codegen_make_vector_items_pointer(target_vector); - brillig_context.codegen_mem_copy( - source_vector_items_pointer, - target_vector_items_pointer, - index, - ); + let target_vector_items_pointer = brillig_context.allocate_register(); + + brillig_context.codegen_branch(is_rc_one, |brillig_context, is_rc_one| { + if is_rc_one { + brillig_context.mov_instruction(target_vector.pointer, source_vector.pointer); + brillig_context.codegen_update_vector_length(target_vector, target_size); + brillig_context + .codegen_vector_items_pointer(target_vector, target_vector_items_pointer); + } else { + brillig_context.codegen_initialize_vector(target_vector, target_size, None); + + // Copy the elements to the left of the index + brillig_context + .codegen_vector_items_pointer(target_vector, target_vector_items_pointer); + + brillig_context.codegen_mem_copy( + source_vector_items_pointer, + target_vector_items_pointer, + index, + ); + } + }); // Compute the source pointer after the removed items let source_pointer_after_index = brillig_context.allocate_register(); @@ -124,6 +141,8 @@ pub(super) fn compile_vector_remove_procedure( SingleAddrVariable::new_usize(item_count), ); + brillig_context.deallocate_register(rc); + brillig_context.deallocate_register(is_rc_one); brillig_context.deallocate_register(source_pointer_after_index); brillig_context.deallocate_register(target_pointer_at_index); brillig_context.deallocate_register(item_count); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index db08b906185..811b728a9d5 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -2195,7 +2195,8 @@ fn execute_brillig( // We pass a stubbed solver here as a concrete solver implies a field choice which conflicts with this function // being generic. let solver = acvm::blackbox_solver::StubbedBlackBoxSolver; - let mut vm = VM::new(calldata, code, Vec::new(), &solver); + let profiling_active = false; + let mut vm = VM::new(calldata, code, Vec::new(), &solver, profiling_active); // Run the Brillig VM on these inputs, bytecode, etc! let vm_status = vm.process_opcodes(); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs index f810b65d105..aebb47ccf8e 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs @@ -442,13 +442,7 @@ impl FunctionBuilder { match self.type_of_value(value) { Type::Numeric(_) => (), Type::Function => (), - Type::Reference(element) => { - if element.contains_an_array() { - let reference = value; - let value = self.insert_load(reference, element.as_ref().clone()); - self.update_array_reference_count(value, increment); - } - } + Type::Reference(_) => (), Type::Array(..) | Type::Slice(..) => { // If there are nested arrays or slices, we wait until ArrayGet // is issued to increment the count of that array. diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/array_set.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/array_set.rs index 6ae13bc085a..7035345436e 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/array_set.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/array_set.rs @@ -53,7 +53,9 @@ struct Context<'f> { is_brillig_runtime: bool, array_to_last_use: HashMap, instructions_that_can_be_made_mutable: HashSet, - arrays_from_load: HashSet, + // Mapping of an array that comes from a load and whether the address + // it was loaded from is a reference parameter. + arrays_from_load: HashMap, inner_nested_arrays: HashMap, } @@ -64,7 +66,7 @@ impl<'f> Context<'f> { is_brillig_runtime, array_to_last_use: HashMap::default(), instructions_that_can_be_made_mutable: HashSet::default(), - arrays_from_load: HashSet::default(), + arrays_from_load: HashMap::default(), inner_nested_arrays: HashMap::default(), } } @@ -113,9 +115,13 @@ impl<'f> Context<'f> { array_in_terminator = true; } }); - if (!self.arrays_from_load.contains(&array) || is_return_block) - && !array_in_terminator - { + if let Some(is_from_param) = self.arrays_from_load.get(&array) { + // If the array was loaded from a reference parameter, we cannot + // safely mark that array mutable as it may be shared by another value. + if !is_from_param && is_return_block { + self.instructions_that_can_be_made_mutable.insert(*instruction_id); + } + } else if !array_in_terminator { self.instructions_that_can_be_made_mutable.insert(*instruction_id); } } @@ -133,10 +139,12 @@ impl<'f> Context<'f> { } } } - Instruction::Load { .. } => { + Instruction::Load { address } => { let result = self.dfg.instruction_results(*instruction_id)[0]; if matches!(self.dfg.type_of_value(result), Array { .. } | Slice { .. }) { - self.arrays_from_load.insert(result); + let is_reference_param = + self.dfg.block_parameters(block_id).contains(address); + self.arrays_from_load.insert(result, is_reference_param); } } _ => (), diff --git a/noir/noir-repo/compiler/noirc_frontend/src/ast/statement.rs b/noir/noir-repo/compiler/noirc_frontend/src/ast/statement.rs index 038a7b76bac..a25b87b7395 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/ast/statement.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/ast/statement.rs @@ -327,6 +327,7 @@ pub enum PathKind { pub struct UseTree { pub prefix: Path, pub kind: UseTreeKind, + pub span: Span, } impl Display for UseTree { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/ast/visitor.rs b/noir/noir-repo/compiler/noirc_frontend/src/ast/visitor.rs index 632c5656137..16ee0fc4c02 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/ast/visitor.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/ast/visitor.rs @@ -22,8 +22,8 @@ use crate::{ use super::{ ForBounds, FunctionReturnType, GenericTypeArgs, IntegerBitSize, ItemVisibility, Pattern, - Signedness, TraitImplItemKind, TypePath, UnresolvedGenerics, UnresolvedTraitConstraint, - UnresolvedType, UnresolvedTypeData, UnresolvedTypeExpression, + Signedness, TraitBound, TraitImplItemKind, TypePath, UnresolvedGenerics, + UnresolvedTraitConstraint, UnresolvedType, UnresolvedTypeData, UnresolvedTypeExpression, }; #[derive(Debug, Copy, Clone, PartialEq, Eq)] @@ -438,6 +438,14 @@ pub trait Visitor { true } + fn visit_trait_bound(&mut self, _: &TraitBound) -> bool { + true + } + + fn visit_unresolved_trait_constraint(&mut self, _: &UnresolvedTraitConstraint) -> bool { + true + } + fn visit_pattern(&mut self, _: &Pattern) -> bool { true } @@ -555,6 +563,12 @@ impl NoirFunction { param.typ.accept(visitor); } + self.def.return_type.accept(visitor); + + for constraint in &self.def.where_clause { + constraint.accept(visitor); + } + self.def.body.accept(None, visitor); } } @@ -645,6 +659,14 @@ impl NoirTrait { attribute.accept(AttributeTarget::Trait, visitor); } + for bound in &self.bounds { + bound.accept(visitor); + } + + for constraint in &self.where_clause { + constraint.accept(visitor); + } + for item in &self.items { item.item.accept(visitor); } @@ -686,7 +708,7 @@ impl TraitItem { return_type.accept(visitor); for unresolved_trait_constraint in where_clause { - unresolved_trait_constraint.typ.accept(visitor); + unresolved_trait_constraint.accept(visitor); } if let Some(body) = body { @@ -1346,6 +1368,32 @@ impl FunctionReturnType { } } +impl TraitBound { + pub fn accept(&self, visitor: &mut impl Visitor) { + if visitor.visit_trait_bound(self) { + self.accept_children(visitor); + } + } + + pub fn accept_children(&self, visitor: &mut impl Visitor) { + self.trait_path.accept(visitor); + self.trait_generics.accept(visitor); + } +} + +impl UnresolvedTraitConstraint { + pub fn accept(&self, visitor: &mut impl Visitor) { + if visitor.visit_unresolved_trait_constraint(self) { + self.accept_children(visitor); + } + } + + pub fn accept_children(&self, visitor: &mut impl Visitor) { + self.typ.accept(visitor); + self.trait_bound.accept(visitor); + } +} + impl Pattern { pub fn accept(&self, visitor: &mut impl Visitor) { if visitor.visit_pattern(self) { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/expressions.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/expressions.rs index 31a518ca97f..6dfd295db6f 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/expressions.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/expressions.rs @@ -8,7 +8,7 @@ use crate::{ ast::{ ArrayLiteral, BlockExpression, CallExpression, CastExpression, ConstructorExpression, Expression, ExpressionKind, Ident, IfExpression, IndexExpression, InfixExpression, - ItemVisibility, Lambda, Literal, MemberAccessExpression, MethodCallExpression, + ItemVisibility, Lambda, Literal, MemberAccessExpression, MethodCallExpression, Path, PrefixExpression, StatementKind, UnaryOp, UnresolvedTypeData, UnresolvedTypeExpression, }, hir::{ @@ -21,7 +21,7 @@ use crate::{ hir_def::{ expr::{ HirArrayLiteral, HirBinaryOp, HirBlockExpression, HirCallExpression, HirCastExpression, - HirConstructorExpression, HirExpression, HirIfExpression, HirIndexExpression, + HirConstructorExpression, HirExpression, HirIdent, HirIfExpression, HirIndexExpression, HirInfixExpression, HirLambda, HirLiteral, HirMemberAccess, HirMethodCallExpression, HirPrefixExpression, }, @@ -247,27 +247,35 @@ impl<'context> Elaborator<'context> { let scope_tree = self.scopes.current_scope_tree(); let variable = scope_tree.find(ident_name); - if let Some((old_value, _)) = variable { + + let hir_ident = if let Some((old_value, _)) = variable { old_value.num_times_used += 1; - let ident = HirExpression::Ident(old_value.ident.clone(), None); - let expr_id = self.interner.push_expr(ident); - self.interner.push_expr_location(expr_id, call_expr_span, self.file); - let ident = old_value.ident.clone(); - let typ = self.type_check_variable(ident, expr_id, None); - self.interner.push_expr_type(expr_id, typ.clone()); - capture_types.push(typ); - fmt_str_idents.push(expr_id); + old_value.ident.clone() + } else if let Ok((definition_id, _)) = + self.lookup_global(Path::from_single(ident_name.to_string(), call_expr_span)) + { + HirIdent::non_trait_method(definition_id, Location::new(call_expr_span, self.file)) } else if ident_name.parse::().is_ok() { self.push_err(ResolverError::NumericConstantInFormatString { name: ident_name.to_owned(), span: call_expr_span, }); + continue; } else { self.push_err(ResolverError::VariableNotDeclared { name: ident_name.to_owned(), span: call_expr_span, }); - } + continue; + }; + + let hir_expr = HirExpression::Ident(hir_ident.clone(), None); + let expr_id = self.interner.push_expr(hir_expr); + self.interner.push_expr_location(expr_id, call_expr_span, self.file); + let typ = self.type_check_variable(hir_ident, expr_id, None); + self.interner.push_expr_type(expr_id, typ.clone()); + capture_types.push(typ); + fmt_str_idents.push(expr_id); } let len = Type::Constant(str.len().into(), Kind::u32()); @@ -528,9 +536,6 @@ impl<'context> Elaborator<'context> { last_segment.generics = Some(generics.ordered_args); } - let exclude_last_segment = true; - self.check_unsupported_turbofish_usage(&path, exclude_last_segment); - let last_segment = path.last_segment(); let is_self_type = last_segment.ident.is_self_type_name(); diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/mod.rs index 641e2d1d57e..2a723286d8b 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/mod.rs @@ -4,7 +4,8 @@ use std::{ }; use crate::{ - ast::ItemVisibility, hir_def::traits::ResolvedTraitBound, StructField, StructType, TypeBindings, + ast::ItemVisibility, hir::resolution::import::PathResolutionItem, + hir_def::traits::ResolvedTraitBound, StructField, StructType, TypeBindings, }; use crate::{ ast::{ @@ -20,7 +21,7 @@ use crate::{ }, def_collector::{dc_crate::CollectedItems, errors::DefCollectorErrorKind}, def_map::{DefMaps, ModuleData}, - def_map::{LocalModuleId, ModuleDefId, ModuleId, MAIN_FUNCTION}, + def_map::{LocalModuleId, ModuleId, MAIN_FUNCTION}, resolution::errors::ResolverError, resolution::import::PathResolution, scope::ScopeForest as GenericScopeForest, @@ -667,11 +668,11 @@ impl<'context> Elaborator<'context> { pub fn resolve_module_by_path(&mut self, path: Path) -> Option { match self.resolve_path(path.clone()) { - Ok(PathResolution { module_def_id: ModuleDefId::ModuleId(module_id), error }) => { - if error.is_some() { - None - } else { + Ok(PathResolution { item: PathResolutionItem::Module(module_id), errors }) => { + if errors.is_empty() { Some(module_id) + } else { + None } } _ => None, @@ -680,8 +681,8 @@ impl<'context> Elaborator<'context> { fn resolve_trait_by_path(&mut self, path: Path) -> Option { let error = match self.resolve_path(path.clone()) { - Ok(PathResolution { module_def_id: ModuleDefId::TraitId(trait_id), error }) => { - if let Some(error) = error { + Ok(PathResolution { item: PathResolutionItem::Trait(trait_id), errors }) => { + for error in errors { self.push_err(error); } return Some(trait_id); @@ -1041,11 +1042,14 @@ impl<'context> Elaborator<'context> { self.file = trait_impl.file_id; self.local_module = trait_impl.module_id; - self.check_parent_traits_are_implemented(&trait_impl); - - self.generics = trait_impl.resolved_generics; + self.generics = trait_impl.resolved_generics.clone(); self.current_trait_impl = trait_impl.impl_id; + self.add_trait_impl_assumed_trait_implementations(trait_impl.impl_id); + self.check_trait_impl_where_clause_matches_trait_where_clause(&trait_impl); + self.check_parent_traits_are_implemented(&trait_impl); + self.remove_trait_impl_assumed_trait_implementations(trait_impl.impl_id); + for (module, function, _) in &trait_impl.methods.functions { self.local_module = *module; let errors = check_trait_impl_method_matches_declaration(self.interner, *function); @@ -1059,6 +1063,95 @@ impl<'context> Elaborator<'context> { self.generics.clear(); } + fn add_trait_impl_assumed_trait_implementations(&mut self, impl_id: Option) { + if let Some(impl_id) = impl_id { + if let Some(trait_implementation) = self.interner.try_get_trait_implementation(impl_id) + { + for trait_constrain in &trait_implementation.borrow().where_clause { + let trait_bound = &trait_constrain.trait_bound; + self.interner.add_assumed_trait_implementation( + trait_constrain.typ.clone(), + trait_bound.trait_id, + trait_bound.trait_generics.clone(), + ); + } + } + } + } + + fn remove_trait_impl_assumed_trait_implementations(&mut self, impl_id: Option) { + if let Some(impl_id) = impl_id { + if let Some(trait_implementation) = self.interner.try_get_trait_implementation(impl_id) + { + for trait_constrain in &trait_implementation.borrow().where_clause { + self.interner.remove_assumed_trait_implementations_for_trait( + trait_constrain.trait_bound.trait_id, + ); + } + } + } + } + + fn check_trait_impl_where_clause_matches_trait_where_clause( + &mut self, + trait_impl: &UnresolvedTraitImpl, + ) { + let Some(trait_id) = trait_impl.trait_id else { + return; + }; + + let Some(the_trait) = self.interner.try_get_trait(trait_id) else { + return; + }; + + if the_trait.where_clause.is_empty() { + return; + } + + let impl_trait = the_trait.name.to_string(); + let the_trait_file = the_trait.location.file; + + let mut bindings = TypeBindings::new(); + bind_ordered_generics( + &the_trait.generics, + &trait_impl.resolved_trait_generics, + &mut bindings, + ); + + // Check that each of the trait's where clause constraints is satisfied + for trait_constraint in the_trait.where_clause.clone() { + let Some(trait_constraint_trait) = + self.interner.try_get_trait(trait_constraint.trait_bound.trait_id) + else { + continue; + }; + + let trait_constraint_type = trait_constraint.typ.substitute(&bindings); + let trait_bound = &trait_constraint.trait_bound; + + if self + .interner + .try_lookup_trait_implementation( + &trait_constraint_type, + trait_bound.trait_id, + &trait_bound.trait_generics.ordered, + &trait_bound.trait_generics.named, + ) + .is_err() + { + let missing_trait = + format!("{}{}", trait_constraint_trait.name, trait_bound.trait_generics); + self.push_err(ResolverError::TraitNotImplemented { + impl_trait: impl_trait.clone(), + missing_trait, + type_missing_trait: trait_constraint_type.to_string(), + span: trait_impl.object_type.span, + missing_trait_location: Location::new(trait_bound.span, the_trait_file), + }); + } + } + } + fn check_parent_traits_are_implemented(&mut self, trait_impl: &UnresolvedTraitImpl) { let Some(trait_id) = trait_impl.trait_id else { return; @@ -1182,7 +1275,7 @@ impl<'context> Elaborator<'context> { trait_id, trait_generics, file: trait_impl.file_id, - where_clause: where_clause.clone(), + where_clause, methods, }); diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/patterns.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/patterns.rs index d55011f98a1..b45f455633b 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/patterns.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/patterns.rs @@ -9,7 +9,7 @@ use crate::{ }, hir::{ def_collector::dc_crate::CompilationError, - resolution::errors::ResolverError, + resolution::{errors::ResolverError, import::PathResolutionItem}, type_check::{Source, TypeCheckError}, }, hir_def::{ @@ -178,9 +178,6 @@ impl<'context> Elaborator<'context> { mutable: Option, new_definitions: &mut Vec, ) -> HirPattern { - let exclude_last_segment = true; - self.check_unsupported_turbofish_usage(&name, exclude_last_segment); - let last_segment = name.last_segment(); let name_span = last_segment.ident.span(); let is_self_type = last_segment.ident.is_self_type_name(); @@ -195,7 +192,7 @@ impl<'context> Elaborator<'context> { }; let (struct_type, generics) = match self.lookup_type_or_error(name) { - Some(Type::Struct(struct_type, generics)) => (struct_type, generics), + Some(Type::Struct(struct_type, struct_generics)) => (struct_type, struct_generics), None => return error_identifier(self), Some(typ) => { let typ = typ.to_string(); @@ -468,54 +465,102 @@ impl<'context> Elaborator<'context> { } pub(super) fn elaborate_variable(&mut self, variable: Path) -> (ExprId, Type) { - let exclude_last_segment = true; - self.check_unsupported_turbofish_usage(&variable, exclude_last_segment); - let unresolved_turbofish = variable.segments.last().unwrap().generics.clone(); let span = variable.span; - let expr = self.resolve_variable(variable); + let (expr, item) = self.resolve_variable(variable); let definition_id = expr.id; + let type_generics = item.map(|item| self.resolve_item_turbofish(item)).unwrap_or_default(); + let definition_kind = self.interner.try_definition(definition_id).map(|definition| definition.kind.clone()); + let mut bindings = TypeBindings::new(); + // Resolve any generics if we the variable we have resolved is a function // and if the turbofish operator was used. - let generics = definition_kind.and_then(|definition_kind| match &definition_kind { - DefinitionKind::Function(function) => { - self.resolve_function_turbofish_generics(function, unresolved_turbofish, span) + let generics = if let Some(DefinitionKind::Function(func_id)) = &definition_kind { + self.resolve_function_turbofish_generics(func_id, unresolved_turbofish, span) + } else { + None + }; + + // If this is a function call on a type that has generics, we need to bind those generic types. + if !type_generics.is_empty() { + if let Some(DefinitionKind::Function(func_id)) = &definition_kind { + // `all_generics` will always have the enclosing type generics first, so we need to bind those + let func_generics = &self.interner.function_meta(func_id).all_generics; + for (type_generic, func_generic) in type_generics.into_iter().zip(func_generics) { + let type_var = &func_generic.type_var; + bindings + .insert(type_var.id(), (type_var.clone(), type_var.kind(), type_generic)); + } } - _ => None, - }); + } let id = self.interner.push_expr(HirExpression::Ident(expr.clone(), generics.clone())); self.interner.push_expr_location(id, span, self.file); - let typ = self.type_check_variable(expr, id, generics); + let typ = self.type_check_variable_with_bindings(expr, id, generics, bindings); self.interner.push_expr_type(id, typ.clone()); (id, typ) } - fn resolve_variable(&mut self, path: Path) -> HirIdent { + /// Solve any generics that are part of the path before the function, for example: + /// + /// foo::Bar::::baz + /// ^^^^^ + /// solve these + fn resolve_item_turbofish(&mut self, item: PathResolutionItem) -> Vec { + match item { + PathResolutionItem::StructFunction(struct_id, Some(generics), _func_id) => { + let struct_type = self.interner.get_struct(struct_id); + let struct_type = struct_type.borrow(); + let struct_generics = struct_type.instantiate(self.interner); + self.resolve_struct_turbofish_generics( + &struct_type, + struct_generics, + Some(generics.generics), + generics.span, + ) + } + PathResolutionItem::TypeAliasFunction(_type_alias_id, Some(generics), _func_id) => { + // TODO: https://github.com/noir-lang/noir/issues/6311 + self.push_err(TypeCheckError::UnsupportedTurbofishUsage { span: generics.span }); + Vec::new() + } + PathResolutionItem::TraitFunction(_trait_id, Some(generics), _func_id) => { + // TODO: https://github.com/noir-lang/noir/issues/6310 + self.push_err(TypeCheckError::UnsupportedTurbofishUsage { span: generics.span }); + Vec::new() + } + _ => Vec::new(), + } + } + + fn resolve_variable(&mut self, path: Path) -> (HirIdent, Option) { if let Some(trait_path_resolution) = self.resolve_trait_generic_path(&path) { - if let Some(error) = trait_path_resolution.error { + for error in trait_path_resolution.errors { self.push_err(error); } - HirIdent { - location: Location::new(path.span, self.file), - id: self.interner.trait_method_id(trait_path_resolution.method.method_id), - impl_kind: ImplKind::TraitMethod(trait_path_resolution.method), - } + ( + HirIdent { + location: Location::new(path.span, self.file), + id: self.interner.trait_method_id(trait_path_resolution.method.method_id), + impl_kind: ImplKind::TraitMethod(trait_path_resolution.method), + }, + None, + ) } else { // If the Path is being used as an Expression, then it is referring to a global from a separate module // Otherwise, then it is referring to an Identifier // This lookup allows support of such statements: let x = foo::bar::SOME_GLOBAL + 10; // If the expression is a singular indent, we search the resolver's current scope as normal. let span = path.span(); - let (hir_ident, var_scope_index) = self.get_ident_from_path(path); + let ((hir_ident, var_scope_index), item) = self.get_ident_from_path(path); if hir_ident.id != DefinitionId::dummy_id() { match self.interner.definition(hir_ident.id).kind { @@ -557,7 +602,7 @@ impl<'context> Elaborator<'context> { } } - hir_ident + (hir_ident, item) } } @@ -567,8 +612,17 @@ impl<'context> Elaborator<'context> { expr_id: ExprId, generics: Option>, ) -> Type { - let mut bindings = TypeBindings::new(); + let bindings = TypeBindings::new(); + self.type_check_variable_with_bindings(ident, expr_id, generics, bindings) + } + pub(super) fn type_check_variable_with_bindings( + &mut self, + ident: HirIdent, + expr_id: ExprId, + generics: Option>, + mut bindings: TypeBindings, + ) -> Type { // Add type bindings from any constraints that were used. // We need to do this first since otherwise instantiating the type below // will replace each trait generic with a fresh type variable, rather than @@ -668,24 +722,31 @@ impl<'context> Elaborator<'context> { } } - pub fn get_ident_from_path(&mut self, path: Path) -> (HirIdent, usize) { + pub fn get_ident_from_path( + &mut self, + path: Path, + ) -> ((HirIdent, usize), Option) { let location = Location::new(path.last_ident().span(), self.file); let error = match path.as_ident().map(|ident| self.use_variable(ident)) { - Some(Ok(found)) => return found, + Some(Ok(found)) => return (found, None), // Try to look it up as a global, but still issue the first error if we fail Some(Err(error)) => match self.lookup_global(path) { - Ok(id) => return (HirIdent::non_trait_method(id, location), 0), + Ok((id, item)) => { + return ((HirIdent::non_trait_method(id, location), 0), Some(item)) + } Err(_) => error, }, None => match self.lookup_global(path) { - Ok(id) => return (HirIdent::non_trait_method(id, location), 0), + Ok((id, item)) => { + return ((HirIdent::non_trait_method(id, location), 0), Some(item)) + } Err(error) => error, }, }; self.push_err(error); let id = DefinitionId::dummy_id(); - (HirIdent::non_trait_method(id, location), 0) + ((HirIdent::non_trait_method(id, location), 0), None) } pub(super) fn elaborate_type_path(&mut self, path: TypePath) -> (ExprId, Type) { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/scope.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/scope.rs index b83a1494ab9..8e033c914be 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/scope.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/scope.rs @@ -2,14 +2,11 @@ use noirc_errors::{Location, Spanned}; use crate::ast::{Ident, Path, PathKind, ERROR_IDENT}; use crate::hir::def_map::{LocalModuleId, ModuleId}; -use crate::hir::resolution::import::{PathResolution, PathResolutionResult}; +use crate::hir::resolution::import::{PathResolution, PathResolutionItem, PathResolutionResult}; use crate::hir::resolution::path_resolver::{PathResolver, StandardPathResolver}; use crate::hir::scope::{Scope as GenericScope, ScopeTree as GenericScopeTree}; use crate::{ - hir::{ - def_map::{ModuleDefId, TryFromModuleDefId}, - resolution::errors::ResolverError, - }, + hir::resolution::errors::ResolverError, hir_def::{ expr::{HirCapturedVar, HirIdent}, traits::Trait, @@ -26,16 +23,6 @@ type Scope = GenericScope; type ScopeTree = GenericScopeTree; impl<'context> Elaborator<'context> { - pub(super) fn lookup(&mut self, path: Path) -> Result { - let span = path.span(); - let id = self.resolve_path_or_error(path)?; - T::try_from(id).ok_or_else(|| ResolverError::Expected { - expected: T::description(), - got: id.as_str().to_owned(), - span, - }) - } - pub fn module_id(&self) -> ModuleId { assert_ne!(self.local_module, LocalModuleId::dummy_id(), "local_module is unset"); ModuleId { krate: self.crate_id, local_id: self.local_module } @@ -53,14 +40,14 @@ impl<'context> Elaborator<'context> { pub(super) fn resolve_path_or_error( &mut self, path: Path, - ) -> Result { + ) -> Result { let path_resolution = self.resolve_path(path)?; - if let Some(error) = path_resolution.error { + for error in path_resolution.errors { self.push_err(error); } - Ok(path_resolution.module_def_id) + Ok(path_resolution.item) } pub(super) fn resolve_path(&mut self, path: Path) -> PathResolutionResult { @@ -72,8 +59,8 @@ impl<'context> Elaborator<'context> { let struct_type = struct_type.borrow(); if path.segments.len() == 1 { return Ok(PathResolution { - module_def_id: ModuleDefId::TypeId(struct_type.id), - error: None, + item: PathResolutionItem::Struct(struct_type.id), + errors: Vec::new(), }); } @@ -132,8 +119,8 @@ impl<'context> Elaborator<'context> { Err(err) => return Err(err), }; - self.interner.add_module_def_id_reference( - path_resolution.module_def_id, + self.interner.add_path_resolution_kind_reference( + path_resolution.item.clone(), location, is_self_type_name, ); @@ -183,21 +170,24 @@ impl<'context> Elaborator<'context> { } } - pub(super) fn lookup_global(&mut self, path: Path) -> Result { + pub(super) fn lookup_global( + &mut self, + path: Path, + ) -> Result<(DefinitionId, PathResolutionItem), ResolverError> { let span = path.span(); - let id = self.resolve_path_or_error(path)?; + let item = self.resolve_path_or_error(path)?; - if let Some(function) = TryFromModuleDefId::try_from(id) { - return Ok(self.interner.function_definition_id(function)); + if let Some(function) = item.function_id() { + return Ok((self.interner.function_definition_id(function), item)); } - if let Some(global) = TryFromModuleDefId::try_from(id) { + if let PathResolutionItem::Global(global) = item { let global = self.interner.get_global(global); - return Ok(global.definition_id); + return Ok((global.definition_id, item)); } - let expected = "global variable".into(); - let got = "local variable".into(); + let expected = "global variable"; + let got = "local variable"; Err(ResolverError::Expected { span, expected, got }) } @@ -239,10 +229,22 @@ impl<'context> Elaborator<'context> { /// Lookup a given trait by name/path. pub fn lookup_trait_or_error(&mut self, path: Path) -> Option<&mut Trait> { - match self.lookup(path) { - Ok(trait_id) => Some(self.get_trait_mut(trait_id)), - Err(error) => { - self.push_err(error); + let span = path.span(); + match self.resolve_path_or_error(path) { + Ok(item) => { + if let PathResolutionItem::Trait(trait_id) = item { + Some(self.get_trait_mut(trait_id)) + } else { + self.push_err(ResolverError::Expected { + expected: "trait", + got: item.description(), + span, + }); + None + } + } + Err(err) => { + self.push_err(err); None } } @@ -250,10 +252,22 @@ impl<'context> Elaborator<'context> { /// Lookup a given struct type by name. pub fn lookup_struct_or_error(&mut self, path: Path) -> Option> { - match self.lookup(path) { - Ok(struct_id) => Some(self.get_struct(struct_id)), - Err(error) => { - self.push_err(error); + let span = path.span(); + match self.resolve_path_or_error(path) { + Ok(item) => { + if let PathResolutionItem::Struct(struct_id) = item { + Some(self.get_struct(struct_id)) + } else { + self.push_err(ResolverError::Expected { + expected: "type", + got: item.description(), + span, + }); + None + } + } + Err(err) => { + self.push_err(err); None } } @@ -269,12 +283,26 @@ impl<'context> Elaborator<'context> { } } - match self.lookup(path) { - Ok(struct_id) => { + let span = path.span; + match self.resolve_path_or_error(path) { + Ok(PathResolutionItem::Struct(struct_id)) => { let struct_type = self.get_struct(struct_id); let generics = struct_type.borrow().instantiate(self.interner); Some(Type::Struct(struct_type, generics)) } + Ok(PathResolutionItem::TypeAlias(alias_id)) => { + let alias = self.interner.get_type_alias(alias_id); + let alias = alias.borrow(); + Some(alias.instantiate(self.interner)) + } + Ok(other) => { + self.push_err(ResolverError::Expected { + expected: "type", + got: other.description(), + span, + }); + None + } Err(error) => { self.push_err(error); None @@ -283,6 +311,11 @@ impl<'context> Elaborator<'context> { } pub fn lookup_type_alias(&mut self, path: Path) -> Option> { - self.lookup(path).ok().map(|id| self.interner.get_type_alias(id)) + match self.resolve_path_or_error(path) { + Ok(PathResolutionItem::TypeAlias(type_alias_id)) => { + Some(self.interner.get_type_alias(type_alias_id)) + } + _ => None, + } } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/statements.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/statements.rs index 238160e5aa4..757def16a93 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/statements.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/statements.rs @@ -293,7 +293,8 @@ impl<'context> Elaborator<'context> { let mut mutable = true; let span = ident.span(); let path = Path::from_single(ident.0.contents, span); - let (ident, scope_index) = self.get_ident_from_path(path); + let ((ident, scope_index), _) = self.get_ident_from_path(path); + self.resolve_local_variable(ident.clone(), scope_index); let typ = if ident.id == DefinitionId::dummy_id() { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/traits.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/traits.rs index e877682972c..ae278616e03 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/traits.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/traits.rs @@ -32,6 +32,9 @@ impl<'context> Elaborator<'context> { &resolved_generics, ); + let where_clause = + this.resolve_trait_constraints(&unresolved_trait.trait_def.where_clause); + // Each associated type in this trait is also an implicit generic for associated_type in &this.interner.get_trait(*trait_id).associated_types { this.generics.push(associated_type.clone()); @@ -48,6 +51,7 @@ impl<'context> Elaborator<'context> { this.interner.update_trait(*trait_id, |trait_def| { trait_def.set_methods(methods); trait_def.set_trait_bounds(resolved_trait_bounds); + trait_def.set_where_clause(where_clause); }); }); diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/types.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/types.rs index 8ffbd15bdab..2879204d3ee 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/types.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/types.rs @@ -14,8 +14,10 @@ use crate::{ hir::{ comptime::{Interpreter, Value}, def_collector::dc_crate::CompilationError, - def_map::ModuleDefId, - resolution::{errors::ResolverError, import::PathResolutionError}, + resolution::{ + errors::ResolverError, + import::{PathResolutionError, PathResolutionItem}, + }, type_check::{ generics::{Generic, TraitGenerics}, NoMatchingImplFoundError, Source, TypeCheckError, @@ -46,7 +48,7 @@ pub const WILDCARD_TYPE: &str = "_"; pub(super) struct TraitPathResolution { pub(super) method: TraitMethod, - pub(super) error: Option, + pub(super) errors: Vec, } impl<'context> Elaborator<'context> { @@ -404,7 +406,7 @@ impl<'context> Elaborator<'context> { // If we cannot find a local generic of the same name, try to look up a global match self.resolve_path_or_error(path.clone()) { - Ok(ModuleDefId::GlobalId(id)) => { + Ok(PathResolutionItem::Global(id)) => { if let Some(current_item) = self.current_item { self.interner.add_global_dependency(current_item, id); } @@ -551,7 +553,7 @@ impl<'context> Elaborator<'context> { let constraint = the_trait.as_constraint(path.span); return Some(TraitPathResolution { method: TraitMethod { method_id: method, constraint, assumed: true }, - error: None, + errors: Vec::new(), }); } } @@ -564,15 +566,14 @@ impl<'context> Elaborator<'context> { // E.g. `t.method()` with `where T: Foo` in scope will return `(Foo::method, T, vec![Bar])` fn resolve_trait_static_method(&mut self, path: &Path) -> Option { let path_resolution = self.resolve_path(path.clone()).ok()?; - let ModuleDefId::FunctionId(func_id) = path_resolution.module_def_id else { return None }; - + let func_id = path_resolution.item.function_id()?; let meta = self.interner.function_meta(&func_id); let the_trait = self.interner.get_trait(meta.trait_id?); let method = the_trait.find_method(path.last_name())?; let constraint = the_trait.as_constraint(path.span); Some(TraitPathResolution { method: TraitMethod { method_id: method, constraint, assumed: false }, - error: path_resolution.error, + errors: path_resolution.errors, }) } @@ -600,7 +601,7 @@ impl<'context> Elaborator<'context> { if let Some(method) = the_trait.find_method(path.last_name()) { return Some(TraitPathResolution { method: TraitMethod { method_id: method, constraint, assumed: true }, - error: None, + errors: Vec::new(), }); } } @@ -1826,19 +1827,6 @@ impl<'context> Elaborator<'context> { context.trait_constraints.push((constraint, expr_id)); } - pub fn check_unsupported_turbofish_usage(&mut self, path: &Path, exclude_last_segment: bool) { - for (index, segment) in path.segments.iter().enumerate() { - if exclude_last_segment && index == path.segments.len() - 1 { - continue; - } - - if segment.generics.is_some() { - let span = segment.turbofish_span(); - self.push_err(TypeCheckError::UnsupportedTurbofishUsage { span }); - } - } - } - pub fn bind_generics_from_trait_constraint( &self, constraint: &TraitConstraint, diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter.rs index ffb759e74a2..7205242ead9 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter.rs @@ -554,8 +554,8 @@ impl<'local, 'interner> Interpreter<'local, 'interner> { match &definition.kind { DefinitionKind::Function(function_id) => { let typ = self.elaborator.interner.id_type(id).follow_bindings(); - let bindings = - Rc::new(self.elaborator.interner.get_instantiation_bindings(id).clone()); + let bindings = self.elaborator.interner.try_get_instantiation_bindings(id); + let bindings = Rc::new(bindings.map_or(TypeBindings::default(), Clone::clone)); Ok(Value::Function(*function_id, typ, bindings)) } DefinitionKind::Local(_) => self.lookup(&ident), diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs index 16fd43ba2a2..20c162fbd3a 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs @@ -303,7 +303,12 @@ impl DefCollector { def_map.extern_prelude.insert(dep.as_name(), module_id); let location = dep_def_map[dep_def_root].location; - let attributes = ModuleAttributes { name: dep.as_name(), location, parent: None }; + let attributes = ModuleAttributes { + name: dep.as_name(), + location, + parent: None, + visibility: ItemVisibility::Public, + }; context.def_interner.add_module_attributes(module_id, attributes); } @@ -380,9 +385,8 @@ impl DefCollector { let current_def_map = context.def_maps.get_mut(&crate_id).unwrap(); let file_id = current_def_map.file_id(module_id); - let has_path_resolution_error = resolved_import.error.is_some(); - - if let Some(error) = resolved_import.error { + let has_path_resolution_error = !resolved_import.errors.is_empty(); + for error in resolved_import.errors { errors.push(( DefCollectorErrorKind::PathResolutionError(error).into(), file_id, @@ -552,7 +556,7 @@ fn inject_prelude( span: Span::default(), }; - if let Ok(PathResolution { module_def_id, error }) = path_resolver::resolve_path( + if let Ok(PathResolution { item, errors }) = path_resolver::resolve_path( &context.def_maps, ModuleId { krate: crate_id, local_id: crate_root }, None, @@ -560,8 +564,8 @@ fn inject_prelude( &mut context.def_interner.usage_tracker, &mut None, ) { - assert!(error.is_none(), "Tried to add private item to prelude"); - let module_id = module_def_id.as_module().expect("std::prelude should be a module"); + assert!(errors.is_empty(), "Tried to add private item to prelude"); + let module_id = item.module_id().expect("std::prelude should be a module"); let prelude = context.module(module_id).scope().names(); for path in prelude { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs index b9ce8f361f7..825a8414fe0 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs @@ -885,6 +885,7 @@ fn push_child_module( name: mod_name.0.contents.clone(), location: mod_location, parent: Some(parent), + visibility, }, ); diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/module_def.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/module_def.rs index a487bda81b3..a751eacd2dd 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/module_def.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/module_def.rs @@ -99,79 +99,3 @@ impl From for ModuleDefId { ModuleDefId::TraitId(trait_id) } } - -pub trait TryFromModuleDefId: Sized { - fn try_from(id: ModuleDefId) -> Option; - fn dummy_id() -> Self; - fn description() -> String; -} - -impl TryFromModuleDefId for FuncId { - fn try_from(id: ModuleDefId) -> Option { - id.as_function() - } - - fn dummy_id() -> Self { - FuncId::dummy_id() - } - - fn description() -> String { - "function".to_string() - } -} - -impl TryFromModuleDefId for StructId { - fn try_from(id: ModuleDefId) -> Option { - id.as_type() - } - - fn dummy_id() -> Self { - StructId::dummy_id() - } - - fn description() -> String { - "type".to_string() - } -} - -impl TryFromModuleDefId for TypeAliasId { - fn try_from(id: ModuleDefId) -> Option { - id.as_type_alias() - } - - fn dummy_id() -> Self { - TypeAliasId::dummy_id() - } - - fn description() -> String { - "type alias".to_string() - } -} - -impl TryFromModuleDefId for TraitId { - fn try_from(id: ModuleDefId) -> Option { - id.as_trait() - } - - fn dummy_id() -> Self { - TraitId::dummy_id() - } - - fn description() -> String { - "trait".to_string() - } -} - -impl TryFromModuleDefId for GlobalId { - fn try_from(id: ModuleDefId) -> Option { - id.as_global() - } - - fn dummy_id() -> Self { - GlobalId::dummy_id() - } - - fn description() -> String { - "global".to_string() - } -} diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/namespace.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/namespace.rs index 6fac6d2b991..a600d98dd8b 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/namespace.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/namespace.rs @@ -13,14 +13,6 @@ impl PerNs { PerNs { types: Some((t, ItemVisibility::Public, false)), values: None } } - pub fn take_types(self) -> Option { - self.types.map(|it| it.0) - } - - pub fn take_values(self) -> Option { - self.values.map(|it| it.0) - } - pub fn iter_defs(self) -> impl Iterator { self.types.map(|it| it.0).into_iter().chain(self.values.map(|it| it.0)) } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/errors.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/errors.rs index 3c4022b58bb..e1e60daff60 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/errors.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/errors.rs @@ -38,7 +38,7 @@ pub enum ResolverError { #[error("could not resolve path")] PathResolutionError(#[from] PathResolutionError), #[error("Expected")] - Expected { span: Span, expected: String, got: String }, + Expected { span: Span, expected: &'static str, got: &'static str }, #[error("Duplicate field in constructor")] DuplicateField { field: Ident }, #[error("No such field in struct")] diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/import.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/import.rs index 93039b1ea7f..58a3a841801 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/import.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/import.rs @@ -3,12 +3,13 @@ use thiserror::Error; use crate::graph::CrateId; use crate::hir::def_collector::dc_crate::CompilationError; -use crate::node_interner::ReferenceId; + +use crate::node_interner::{FuncId, GlobalId, ReferenceId, StructId, TraitId, TypeAliasId}; use crate::usage_tracker::UsageTracker; use std::collections::BTreeMap; -use crate::ast::{Ident, ItemVisibility, Path, PathKind, PathSegment}; +use crate::ast::{Ident, ItemVisibility, Path, PathKind, PathSegment, UnresolvedType}; use crate::hir::def_map::{CrateDefMap, LocalModuleId, ModuleDefId, ModuleId, PerNs}; use super::errors::ResolverError; @@ -26,16 +27,80 @@ pub struct ImportDirective { struct NamespaceResolution { module_id: ModuleId, + item: PathResolutionItem, namespace: PerNs, - error: Option, + errors: Vec, } type NamespaceResolutionResult = Result; +#[derive(Debug)] pub struct PathResolution { - pub module_def_id: ModuleDefId, + pub item: PathResolutionItem, + pub errors: Vec, +} - pub error: Option, +/// All possible items that result from resolving a Path. +/// Note that this item doesn't include the last turbofish in a Path, +/// only intermediate ones, if any. +#[derive(Debug, Clone)] +pub enum PathResolutionItem { + Module(ModuleId), + Struct(StructId), + TypeAlias(TypeAliasId), + Trait(TraitId), + Global(GlobalId), + ModuleFunction(FuncId), + StructFunction(StructId, Option, FuncId), + TypeAliasFunction(TypeAliasId, Option, FuncId), + TraitFunction(TraitId, Option, FuncId), +} + +impl PathResolutionItem { + pub fn function_id(&self) -> Option { + match self { + PathResolutionItem::ModuleFunction(func_id) + | PathResolutionItem::StructFunction(_, _, func_id) + | PathResolutionItem::TypeAliasFunction(_, _, func_id) + | PathResolutionItem::TraitFunction(_, _, func_id) => Some(*func_id), + _ => None, + } + } + + pub fn module_id(&self) -> Option { + match self { + Self::Module(module_id) => Some(*module_id), + _ => None, + } + } + + pub fn description(&self) -> &'static str { + match self { + PathResolutionItem::Module(..) => "module", + PathResolutionItem::Struct(..) => "type", + PathResolutionItem::TypeAlias(..) => "type alias", + PathResolutionItem::Trait(..) => "trait", + PathResolutionItem::Global(..) => "global", + PathResolutionItem::ModuleFunction(..) + | PathResolutionItem::StructFunction(..) + | PathResolutionItem::TypeAliasFunction(..) + | PathResolutionItem::TraitFunction(..) => "function", + } + } +} + +#[derive(Debug, Clone)] +pub struct Turbofish { + pub generics: Vec, + pub span: Span, +} + +/// Any item that can appear before the last segment in a path. +#[derive(Debug)] +enum IntermediatePathResolutionItem { + Module(ModuleId), + Struct(StructId, Option), + Trait(TraitId, Option), } pub(crate) type PathResolutionResult = Result; @@ -48,6 +113,8 @@ pub enum PathResolutionError { Private(Ident), #[error("There is no super module")] NoSuper(Span), + #[error("turbofish (`::<_>`) not allowed on {item}")] + TurbofishNotAllowedOnItem { item: String, span: Span }, } #[derive(Debug)] @@ -56,10 +123,12 @@ pub struct ResolvedImport { pub name: Ident, // The symbol which we have resolved to pub resolved_namespace: PerNs, + // The item which we have resolved to + pub item: PathResolutionItem, // The module which we must add the resolved namespace to pub module_scope: LocalModuleId, pub is_prelude: bool, - pub error: Option, + pub errors: Vec, } impl From for CompilationError { @@ -83,6 +152,9 @@ impl<'a> From<&'a PathResolutionError> for CustomDiagnostic { PathResolutionError::NoSuper(span) => { CustomDiagnostic::simple_error(error.to_string(), String::new(), *span) } + PathResolutionError::TurbofishNotAllowedOnItem { item: _, span } => { + CustomDiagnostic::simple_error(error.to_string(), String::new(), *span) + } } } } @@ -95,15 +167,19 @@ pub fn resolve_import( path_references: &mut Option<&mut Vec>, ) -> Result { let module_scope = import_directive.module_id; - let NamespaceResolution { module_id: resolved_module, namespace: resolved_namespace, error } = - resolve_path_to_ns( - import_directive, - crate_id, - crate_id, - def_maps, - usage_tracker, - path_references, - )?; + let NamespaceResolution { + module_id: resolved_module, + item, + namespace: resolved_namespace, + mut errors, + } = resolve_path_to_ns( + import_directive, + crate_id, + crate_id, + def_maps, + usage_tracker, + path_references, + )?; let name = resolve_path_name(import_directive); @@ -113,28 +189,25 @@ pub fn resolve_import( .map(|(_, visibility, _)| visibility) .expect("Found empty namespace"); - let error = error.or_else(|| { - if import_directive.self_type_module_id == Some(resolved_module) - || can_reference_module_id( - def_maps, - crate_id, - import_directive.module_id, - resolved_module, - visibility, - ) - { - None - } else { - Some(PathResolutionError::Private(name.clone())) - } - }); + if !(import_directive.self_type_module_id == Some(resolved_module) + || can_reference_module_id( + def_maps, + crate_id, + import_directive.module_id, + resolved_module, + visibility, + )) + { + errors.push(PathResolutionError::Private(name.clone())); + } Ok(ResolvedImport { name, resolved_namespace, + item, module_scope, is_prelude: import_directive.is_prelude, - error, + errors, }) } @@ -275,13 +348,16 @@ fn resolve_name_in_module( let mut current_mod_id = ModuleId { krate, local_id: starting_mod }; let mut current_mod = &def_map.modules[current_mod_id.local_id.0]; + let mut intermediate_item = IntermediatePathResolutionItem::Module(current_mod_id); + // There is a possibility that the import path is empty // In that case, early return if import_path.is_empty() { return Ok(NamespaceResolution { module_id: current_mod_id, + item: PathResolutionItem::Module(current_mod_id), namespace: PerNs::types(current_mod_id.into()), - error: None, + errors: Vec::new(), }); } @@ -293,25 +369,34 @@ fn resolve_name_in_module( usage_tracker.mark_as_referenced(current_mod_id, first_segment); - let mut warning: Option = None; + let mut errors = Vec::new(); for (index, (last_segment, current_segment)) in import_path.iter().zip(import_path.iter().skip(1)).enumerate() { - let last_segment = &last_segment.ident; - let current_segment = ¤t_segment.ident; + let last_ident = &last_segment.ident; + let current_ident = ¤t_segment.ident; + let last_segment_generics = &last_segment.generics; let (typ, visibility) = match current_ns.types { - None => return Err(PathResolutionError::Unresolved(last_segment.clone())), + None => return Err(PathResolutionError::Unresolved(last_ident.clone())), Some((typ, visibility, _)) => (typ, visibility), }; // In the type namespace, only Mod can be used in a path. - current_mod_id = match typ { + (current_mod_id, intermediate_item) = match typ { ModuleDefId::ModuleId(id) => { if let Some(path_references) = path_references { path_references.push(ReferenceId::Module(id)); } - id + + if last_segment_generics.is_some() { + errors.push(PathResolutionError::TurbofishNotAllowedOnItem { + item: format!("module `{last_ident}`"), + span: last_segment.turbofish_span(), + }); + } + + (id, IntermediatePathResolutionItem::Module(id)) } ModuleDefId::FunctionId(_) => panic!("functions cannot be in the type namespace"), // TODO: If impls are ever implemented, types can be used in a path @@ -319,51 +404,75 @@ fn resolve_name_in_module( if let Some(path_references) = path_references { path_references.push(ReferenceId::Struct(id)); } - id.module_id() + + ( + id.module_id(), + IntermediatePathResolutionItem::Struct( + id, + last_segment_generics.as_ref().map(|generics| Turbofish { + generics: generics.clone(), + span: last_segment.turbofish_span(), + }), + ), + ) } ModuleDefId::TypeAliasId(_) => panic!("type aliases cannot be used in type namespace"), ModuleDefId::TraitId(id) => { if let Some(path_references) = path_references { path_references.push(ReferenceId::Trait(id)); } - id.0 + + ( + id.0, + IntermediatePathResolutionItem::Trait( + id, + last_segment_generics.as_ref().map(|generics| Turbofish { + generics: generics.clone(), + span: last_segment.turbofish_span(), + }), + ), + ) } ModuleDefId::GlobalId(_) => panic!("globals cannot be in the type namespace"), }; - warning = warning.or_else(|| { - // If the path is plain or crate, the first segment will always refer to - // something that's visible from the current module. - if (plain_or_crate && index == 0) - || can_reference_module_id( - def_maps, - importing_crate, - starting_mod, - current_mod_id, - visibility, - ) - { - None - } else { - Some(PathResolutionError::Private(last_segment.clone())) - } - }); + // If the path is plain or crate, the first segment will always refer to + // something that's visible from the current module. + if !((plain_or_crate && index == 0) + || can_reference_module_id( + def_maps, + importing_crate, + starting_mod, + current_mod_id, + visibility, + )) + { + errors.push(PathResolutionError::Private(last_ident.clone())); + } current_mod = &def_maps[¤t_mod_id.krate].modules[current_mod_id.local_id.0]; // Check if namespace - let found_ns = current_mod.find_name(current_segment); + let found_ns = current_mod.find_name(current_ident); if found_ns.is_none() { - return Err(PathResolutionError::Unresolved(current_segment.clone())); + return Err(PathResolutionError::Unresolved(current_ident.clone())); } - usage_tracker.mark_as_referenced(current_mod_id, current_segment); + usage_tracker.mark_as_referenced(current_mod_id, current_ident); current_ns = found_ns; } - Ok(NamespaceResolution { module_id: current_mod_id, namespace: current_ns, error: warning }) + let module_def_id = + current_ns.values.or(current_ns.types).map(|(id, _, _)| id).expect("Found empty namespace"); + + let item = merge_intermediate_path_resolution_item_with_module_def_id( + intermediate_item, + module_def_id, + ); + + Ok(NamespaceResolution { module_id: current_mod_id, item, namespace: current_ns, errors }) } fn resolve_path_name(import_directive: &ImportDirective) -> Ident { @@ -425,3 +534,27 @@ fn resolve_external_dep( path_references, ) } + +fn merge_intermediate_path_resolution_item_with_module_def_id( + intermediate_item: IntermediatePathResolutionItem, + module_def_id: ModuleDefId, +) -> PathResolutionItem { + match module_def_id { + ModuleDefId::ModuleId(module_id) => PathResolutionItem::Module(module_id), + ModuleDefId::TypeId(struct_id) => PathResolutionItem::Struct(struct_id), + ModuleDefId::TypeAliasId(type_alias_id) => PathResolutionItem::TypeAlias(type_alias_id), + ModuleDefId::TraitId(trait_id) => PathResolutionItem::Trait(trait_id), + ModuleDefId::GlobalId(global_id) => PathResolutionItem::Global(global_id), + ModuleDefId::FunctionId(func_id) => match intermediate_item { + IntermediatePathResolutionItem::Module(_) => { + PathResolutionItem::ModuleFunction(func_id) + } + IntermediatePathResolutionItem::Struct(struct_id, generics) => { + PathResolutionItem::StructFunction(struct_id, generics, func_id) + } + IntermediatePathResolutionItem::Trait(trait_id, generics) => { + PathResolutionItem::TraitFunction(trait_id, generics, func_id) + } + }, + } +} diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/path_resolver.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/path_resolver.rs index 562366fae77..705820e9101 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/path_resolver.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/path_resolver.rs @@ -88,9 +88,5 @@ pub fn resolve_path( let resolved_import = resolve_import(module_id.krate, &import, def_maps, usage_tracker, path_references)?; - let namespace = resolved_import.resolved_namespace; - let id = - namespace.values.or(namespace.types).map(|(id, _, _)| id).expect("Found empty namespace"); - - Ok(PathResolution { module_def_id: id, error: resolved_import.error }) + Ok(PathResolution { item: resolved_import.item, errors: resolved_import.errors }) } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs index 99de6bca434..3b4ab148ef7 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs @@ -434,11 +434,15 @@ impl<'a> From<&'a TypeCheckError> for Diagnostic { let msg = format!("Expected {expected_count} generic{expected_plural} from this function, but {actual_count} {actual_plural} provided"); Diagnostic::simple_error(msg, "".into(), *span) }, - TypeCheckError::MacroReturningNonExpr { typ, span } => Diagnostic::simple_error( - format!("Expected macro call to return a `Quoted` but found a(n) `{typ}`"), - "Macro calls must return quoted values, otherwise there is no code to insert".into(), - *span, - ), + TypeCheckError::MacroReturningNonExpr { typ, span } => { + let mut error = Diagnostic::simple_error( + format!("Expected macro call to return a `Quoted` but found a(n) `{typ}`"), + "Macro calls must return quoted values, otherwise there is no code to insert.".into(), + *span, + ); + error.add_secondary("Hint: remove the `!` from the end of the function name.".to_string(), *span); + error + }, TypeCheckError::UnsupportedTurbofishUsage { span } => { let msg = "turbofish (`::<_>`) usage at this position isn't supported yet"; Diagnostic::simple_error(msg.to_string(), "".to_string(), *span) diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/traits.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/traits.rs index 534805c2dad..6fd3c4f7a24 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/traits.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/traits.rs @@ -75,6 +75,8 @@ pub struct Trait { /// The resolved trait bounds (for example in `trait Foo: Bar + Baz`, this would be `Bar + Baz`) pub trait_bounds: Vec, + + pub where_clause: Vec, } #[derive(Debug)] @@ -154,6 +156,10 @@ impl Trait { self.trait_bounds = trait_bounds; } + pub fn set_where_clause(&mut self, where_clause: Vec) { + self.where_clause = where_clause; + } + pub fn find_method(&self, name: &str) -> Option { for (idx, method) in self.methods.iter().enumerate() { if &method.name == name { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/types.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/types.rs index fa2a455c06d..77030b0e048 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/types.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/types.rs @@ -590,6 +590,11 @@ impl TypeAlias { self.typ.substitute(&substitutions) } + + pub fn instantiate(&self, interner: &NodeInterner) -> Type { + let args = vecmap(&self.generics, |_| interner.next_type_variable()); + self.get_type(&args) + } } /// A shared, mutable reference to some T. diff --git a/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs b/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs index 8f05832d26d..daf59445982 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs @@ -1,4 +1,4 @@ -use acvm::{acir::AcirField, FieldElement}; +use acvm::FieldElement; use noirc_errors::{Position, Span, Spanned}; use std::fmt; @@ -367,7 +367,7 @@ impl fmt::Display for Token { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Token::Ident(ref s) => write!(f, "{s}"), - Token::Int(n) => write!(f, "{}", n.to_u128()), + Token::Int(n) => write!(f, "{}", n), Token::Bool(b) => write!(f, "{b}"), Token::Str(ref b) => write!(f, "{b:?}"), Token::FmtStr(ref b) => write!(f, "f{b:?}"), diff --git a/noir/noir-repo/compiler/noirc_frontend/src/locations.rs b/noir/noir-repo/compiler/noirc_frontend/src/locations.rs index 48660142d0a..4dd699251a6 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/locations.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/locations.rs @@ -5,7 +5,10 @@ use rustc_hash::FxHashMap as HashMap; use crate::{ ast::{FunctionDefinition, ItemVisibility}, - hir::def_map::{ModuleDefId, ModuleId}, + hir::{ + def_map::{ModuleDefId, ModuleId}, + resolution::import::PathResolutionItem, + }, node_interner::{ DefinitionId, FuncId, GlobalId, NodeInterner, ReferenceId, StructId, TraitId, TypeAliasId, }, @@ -99,6 +102,37 @@ impl NodeInterner { }; } + pub(crate) fn add_path_resolution_kind_reference( + &mut self, + kind: PathResolutionItem, + location: Location, + is_self_type: bool, + ) { + match kind { + PathResolutionItem::Module(module_id) => { + self.add_module_reference(module_id, location); + } + PathResolutionItem::Struct(struct_id) => { + self.add_struct_reference(struct_id, location, is_self_type); + } + PathResolutionItem::TypeAlias(type_alias_id) => { + self.add_alias_reference(type_alias_id, location); + } + PathResolutionItem::Trait(trait_id) => { + self.add_trait_reference(trait_id, location, is_self_type); + } + PathResolutionItem::Global(global_id) => { + self.add_global_reference(global_id, location); + } + PathResolutionItem::ModuleFunction(func_id) + | PathResolutionItem::StructFunction(_, _, func_id) + | PathResolutionItem::TypeAliasFunction(_, _, func_id) + | PathResolutionItem::TraitFunction(_, _, func_id) => { + self.add_function_reference(func_id, location); + } + } + } + pub(crate) fn add_module_reference(&mut self, id: ModuleId, location: Location) { self.add_reference(ReferenceId::Module(id), location, false); } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs b/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs index ca7e0c6aa59..68510f2ffbd 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs @@ -56,6 +56,7 @@ pub struct ModuleAttributes { pub name: String, pub location: Location, pub parent: Option, + pub visibility: ItemVisibility, } type StructAttributes = Vec; @@ -735,6 +736,7 @@ impl NodeInterner { method_ids: unresolved_trait.method_ids.clone(), associated_types, trait_bounds: Vec::new(), + where_clause: Vec::new(), }; self.traits.insert(type_id, new_trait); @@ -1874,8 +1876,33 @@ impl NodeInterner { /// Removes all TraitImplKind::Assumed from the list of known impls for the given trait pub fn remove_assumed_trait_implementations_for_trait(&mut self, trait_id: TraitId) { + self.remove_assumed_trait_implementations_for_trait_and_parents(trait_id, trait_id); + } + + fn remove_assumed_trait_implementations_for_trait_and_parents( + &mut self, + trait_id: TraitId, + starting_trait_id: TraitId, + ) { let entries = self.trait_implementation_map.entry(trait_id).or_default(); entries.retain(|(_, kind)| matches!(kind, TraitImplKind::Normal(_))); + + // Also remove assumed implementations for the parent traits, if any + if let Some(trait_bounds) = + self.try_get_trait(trait_id).map(|the_trait| the_trait.trait_bounds.clone()) + { + for parent_trait_bound in trait_bounds { + // Avoid looping forever in case there are cycles + if parent_trait_bound.trait_id == starting_trait_id { + continue; + } + + self.remove_assumed_trait_implementations_for_trait_and_parents( + parent_trait_bound.trait_id, + starting_trait_id, + ); + } + } } /// Tags the given identifier with the selected trait_impl so that monomorphization diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/use_tree.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/use_tree.rs index bc95c04d46b..08834383f99 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/use_tree.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/use_tree.rs @@ -53,13 +53,17 @@ impl<'a> Parser<'a> { Self::parse_use_tree_in_list, ); - UseTree { prefix, kind: UseTreeKind::List(use_trees) } + UseTree { + prefix, + kind: UseTreeKind::List(use_trees), + span: self.span_since(start_span), + } } else { self.expected_token(Token::LeftBrace); - self.parse_path_use_tree_end(prefix, nested) + self.parse_path_use_tree_end(prefix, nested, start_span) } } else { - self.parse_path_use_tree_end(prefix, nested) + self.parse_path_use_tree_end(prefix, nested, start_span) } } @@ -71,6 +75,7 @@ impl<'a> Parser<'a> { return Some(UseTree { prefix: Path { segments: Vec::new(), kind: PathKind::Plain, span: start_span }, kind: UseTreeKind::Path(Ident::new("self".to_string(), start_span), None), + span: start_span, }); } @@ -89,25 +94,46 @@ impl<'a> Parser<'a> { } } - pub(super) fn parse_path_use_tree_end(&mut self, mut prefix: Path, nested: bool) -> UseTree { + pub(super) fn parse_path_use_tree_end( + &mut self, + mut prefix: Path, + nested: bool, + start_span: Span, + ) -> UseTree { if prefix.segments.is_empty() { if nested { self.expected_identifier(); } else { self.expected_label(ParsingRuleLabel::UseSegment); } - UseTree { prefix, kind: UseTreeKind::Path(Ident::default(), None) } + UseTree { + prefix, + kind: UseTreeKind::Path(Ident::default(), None), + span: self.span_since(start_span), + } } else { let ident = prefix.segments.pop().unwrap().ident; if self.eat_keyword(Keyword::As) { if let Some(alias) = self.eat_ident() { - UseTree { prefix, kind: UseTreeKind::Path(ident, Some(alias)) } + UseTree { + prefix, + kind: UseTreeKind::Path(ident, Some(alias)), + span: self.span_since(start_span), + } } else { self.expected_identifier(); - UseTree { prefix, kind: UseTreeKind::Path(ident, None) } + UseTree { + prefix, + kind: UseTreeKind::Path(ident, None), + span: self.span_since(start_span), + } } } else { - UseTree { prefix, kind: UseTreeKind::Path(ident, None) } + UseTree { + prefix, + kind: UseTreeKind::Path(ident, None), + span: self.span_since(start_span), + } } } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/tests.rs b/noir/noir-repo/compiler/noirc_frontend/src/tests.rs index ce4ad4d1bb9..5ce3ec6686c 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/tests.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/tests.rs @@ -1,7 +1,9 @@ #![cfg(test)] +mod aliases; mod bound_checks; mod imports; +mod metaprogramming; mod name_shadowing; mod references; mod traits; @@ -615,8 +617,8 @@ fn check_trait_impl_for_non_type() { for (err, _file_id) in errors { match &err { CompilationError::ResolverError(ResolverError::Expected { expected, got, .. }) => { - assert_eq!(expected, "type"); - assert_eq!(got, "function"); + assert_eq!(*expected, "type"); + assert_eq!(*got, "function"); } _ => { panic!("No other errors are expected! Found = {:?}", err); @@ -2969,9 +2971,7 @@ fn uses_self_type_in_trait_where_clause() { } } - struct Bar { - - } + struct Bar {} impl Foo for Bar { @@ -2983,12 +2983,17 @@ fn uses_self_type_in_trait_where_clause() { "#; let errors = get_program_errors(src); - assert_eq!(errors.len(), 1); + assert_eq!(errors.len(), 2); + + let CompilationError::ResolverError(ResolverError::TraitNotImplemented { .. }) = &errors[0].0 + else { + panic!("Expected a trait not implemented error, got {:?}", errors[0].0); + }; let CompilationError::TypeError(TypeCheckError::UnresolvedMethodCall { method_name, .. }) = - &errors[0].0 + &errors[1].0 else { - panic!("Expected an unresolved method call error, got {:?}", errors[0].0); + panic!("Expected an unresolved method call error, got {:?}", errors[1].0); }; assert_eq!(method_name, "trait_func"); @@ -3541,3 +3546,19 @@ fn uses_self_in_import() { "#; assert_no_errors(src); } + +#[test] +fn alias_in_let_pattern() { + let src = r#" + struct Foo { x: T } + + type Bar = Foo; + + fn main() { + let Bar { x } = Foo { x: [0] }; + // This is just to show the compiler knows this is an array. + let _: [Field; 1] = x; + } + "#; + assert_no_errors(src); +} diff --git a/noir/noir-repo/compiler/noirc_frontend/src/tests/aliases.rs b/noir/noir-repo/compiler/noirc_frontend/src/tests/aliases.rs new file mode 100644 index 00000000000..5239abcb366 --- /dev/null +++ b/noir/noir-repo/compiler/noirc_frontend/src/tests/aliases.rs @@ -0,0 +1,33 @@ +use super::assert_no_errors; + +#[test] +fn allows_usage_of_type_alias_as_argument_type() { + let src = r#" + type Foo = Field; + + fn accepts_a_foo(x: Foo) { + assert_eq(x, 42); + } + + fn main() { + accepts_a_foo(42); + } + "#; + assert_no_errors(src); +} + +#[test] +fn allows_usage_of_type_alias_as_return_type() { + let src = r#" + type Foo = Field; + + fn returns_a_foo() -> Foo { + 42 + } + + fn main() { + let _ = returns_a_foo(); + } + "#; + assert_no_errors(src); +} diff --git a/noir/noir-repo/compiler/noirc_frontend/src/tests/bound_checks.rs b/noir/noir-repo/compiler/noirc_frontend/src/tests/bound_checks.rs index 271f9d7a1a7..05669bda411 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/tests/bound_checks.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/tests/bound_checks.rs @@ -14,7 +14,7 @@ fn overflowing_u8() { if let CompilationError::TypeError(error) = &errors[0].0 { assert_eq!( error.to_string(), - "The value `2⁸` cannot fit into `u8` which has range `0..=255`" + "The value `256` cannot fit into `u8` which has range `0..=255`" ); } else { panic!("Expected OverflowingAssignment error, got {:?}", errors[0].0); @@ -52,7 +52,7 @@ fn overflowing_i8() { if let CompilationError::TypeError(error) = &errors[0].0 { assert_eq!( error.to_string(), - "The value `2⁷` cannot fit into `i8` which has range `-128..=127`" + "The value `128` cannot fit into `i8` which has range `-128..=127`" ); } else { panic!("Expected OverflowingAssignment error, got {:?}", errors[0].0); diff --git a/noir/noir-repo/compiler/noirc_frontend/src/tests/metaprogramming.rs b/noir/noir-repo/compiler/noirc_frontend/src/tests/metaprogramming.rs index ec52310b3d6..82c40203244 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/tests/metaprogramming.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/tests/metaprogramming.rs @@ -1,6 +1,18 @@ -use crate::hir::def_collector::dc_crate::CompilationError; +use noirc_errors::Spanned; -use super::get_program_errors; +use crate::{ + ast::Ident, + hir::{ + def_collector::{ + dc_crate::CompilationError, + errors::{DefCollectorErrorKind, DuplicateType}, + }, + resolution::errors::ResolverError, + type_check::TypeCheckError, + }, +}; + +use super::{assert_no_errors, get_program_errors}; // Regression for #5388 #[test] @@ -74,3 +86,58 @@ fn unquoted_integer_as_integer_token() { assert_no_errors(src); } + +#[test] +fn allows_references_to_structs_generated_by_macros() { + let src = r#" + comptime fn make_new_struct(_s: StructDefinition) -> Quoted { + quote { struct Bar {} } + } + + #[make_new_struct] + struct Foo {} + + fn main() { + let _ = Foo {}; + let _ = Bar {}; + } + "#; + + assert_no_errors(src); +} + +#[test] +fn errors_if_macros_inject_functions_with_name_collisions() { + let src = r#" + comptime fn make_colliding_functions(_s: StructDefinition) -> Quoted { + quote { + fn foo() {} + } + } + + #[make_colliding_functions] + struct Foo {} + + #[make_colliding_functions] + struct Bar {} + + fn main() { + let _ = Foo {}; + let _ = Bar {}; + foo(); + } + "#; + + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); + assert!(matches!( + &errors[0].0, + CompilationError::DefinitionError( + DefCollectorErrorKind::Duplicate { + typ: DuplicateType::Function, + first_def: Ident(Spanned { contents, .. }), + .. + }, + ) if contents == "foo" + )); +} diff --git a/noir/noir-repo/compiler/noirc_frontend/src/tests/traits.rs b/noir/noir-repo/compiler/noirc_frontend/src/tests/traits.rs index ee84cc0e890..dd6430a94cc 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/tests/traits.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/tests/traits.rs @@ -148,3 +148,137 @@ fn trait_inheritance_missing_parent_implementation() { assert_eq!(typ, "Struct"); assert_eq!(impl_trait, "Bar"); } + +#[test] +fn errors_on_unknown_type_in_trait_where_clause() { + let src = r#" + pub trait Foo where T: Unknown {} + + fn main() { + } + "#; + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); +} + +#[test] +fn does_not_error_if_impl_trait_constraint_is_satisfied_for_concrete_type() { + let src = r#" + pub trait Greeter { + fn greet(self); + } + + pub trait Foo + where + T: Greeter, + { + fn greet(object: U) + where + U: Greeter, + { + object.greet(); + } + } + + pub struct SomeGreeter; + impl Greeter for SomeGreeter { + fn greet(self) {} + } + + pub struct Bar; + + impl Foo for Bar {} + + fn main() {} + "#; + assert_no_errors(src); +} + +#[test] +fn does_not_error_if_impl_trait_constraint_is_satisfied_for_type_variable() { + let src = r#" + pub trait Greeter { + fn greet(self); + } + + pub trait Foo where T: Greeter { + fn greet(object: T) { + object.greet(); + } + } + + pub struct Bar; + + impl Foo for Bar where T: Greeter { + } + + fn main() { + } + "#; + assert_no_errors(src); +} +#[test] +fn errors_if_impl_trait_constraint_is_not_satisfied() { + let src = r#" + pub trait Greeter { + fn greet(self); + } + + pub trait Foo + where + T: Greeter, + { + fn greet(object: U) + where + U: Greeter, + { + object.greet(); + } + } + + pub struct SomeGreeter; + + pub struct Bar; + + impl Foo for Bar {} + + fn main() {} + "#; + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); + + let CompilationError::ResolverError(ResolverError::TraitNotImplemented { + impl_trait, + missing_trait: the_trait, + type_missing_trait: typ, + .. + }) = &errors[0].0 + else { + panic!("Expected a TraitNotImplemented error, got {:?}", &errors[0].0); + }; + + assert_eq!(the_trait, "Greeter"); + assert_eq!(typ, "SomeGreeter"); + assert_eq!(impl_trait, "Foo"); +} + +#[test] +fn removes_assumed_parent_traits_after_function_ends() { + let src = r#" + trait Foo {} + trait Bar: Foo {} + + pub fn foo() + where + T: Bar, + {} + + pub fn bar() + where + T: Foo, + {} + + fn main() {} + "#; + assert_no_errors(src); +} diff --git a/noir/noir-repo/compiler/noirc_frontend/src/tests/turbofish.rs b/noir/noir-repo/compiler/noirc_frontend/src/tests/turbofish.rs index 71e63e878e8..3ded243a280 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/tests/turbofish.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/tests/turbofish.rs @@ -1,4 +1,8 @@ -use crate::hir::{def_collector::dc_crate::CompilationError, type_check::TypeCheckError}; +use crate::hir::{ + def_collector::dc_crate::CompilationError, + resolution::{errors::ResolverError, import::PathResolutionError}, + type_check::TypeCheckError, +}; use super::{assert_no_errors, get_program_errors}; @@ -100,32 +104,6 @@ fn turbofish_in_constructor() { assert_eq!(expr_typ, "Field"); } -#[test] -fn turbofish_in_middle_of_variable_unsupported_yet() { - let src = r#" - struct Foo { - x: T - } - - impl Foo { - pub fn new(x: T) -> Self { - Foo { x } - } - } - - fn main() { - let _ = Foo::::new(1); - } - "#; - let errors = get_program_errors(src); - assert_eq!(errors.len(), 1); - - assert!(matches!( - errors[0].0, - CompilationError::TypeError(TypeCheckError::UnsupportedTurbofishUsage { .. }), - )); -} - #[test] fn turbofish_in_struct_pattern() { let src = r#" @@ -214,3 +192,80 @@ fn numeric_turbofish() { "#; assert_no_errors(src); } + +#[test] +fn errors_if_turbofish_after_module() { + let src = r#" + mod moo { + pub fn foo() {} + } + + fn main() { + moo::::foo(); + } + "#; + + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); + + let CompilationError::ResolverError(ResolverError::PathResolutionError( + PathResolutionError::TurbofishNotAllowedOnItem { item, .. }, + )) = &errors[0].0 + else { + panic!("Expected a turbofish not allowed on item error, got {:?}", errors[0].0); + }; + assert_eq!(item, "module `moo`"); +} + +#[test] +fn turbofish_in_type_before_call_does_not_error() { + let src = r#" + struct Foo { + x: T + } + + impl Foo { + fn new(x: T) -> Self { + Foo { x } + } + } + + fn main() { + let _ = Foo::::new(1); + } + "#; + assert_no_errors(src); +} + +#[test] +fn turbofish_in_type_before_call_errors() { + let src = r#" + struct Foo { + x: T + } + + impl Foo { + fn new(x: T) -> Self { + Foo { x } + } + } + + fn main() { + let _ = Foo::::new(true); + } + "#; + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); + + let CompilationError::TypeError(TypeCheckError::TypeMismatch { + expected_typ, + expr_typ, + expr_span: _, + }) = &errors[0].0 + else { + panic!("Expected a type mismatch error, got {:?}", errors[0].0); + }; + + assert_eq!(expected_typ, "i32"); + assert_eq!(expr_typ, "bool"); +} diff --git a/noir/noir-repo/docs/docs/noir/concepts/comptime.md b/noir/noir-repo/docs/docs/noir/concepts/comptime.md index cea3a896c17..37457d47b46 100644 --- a/noir/noir-repo/docs/docs/noir/concepts/comptime.md +++ b/noir/noir-repo/docs/docs/noir/concepts/comptime.md @@ -5,7 +5,7 @@ keywords: [Noir, comptime, compile-time, metaprogramming, macros, quote, unquote sidebar_position: 15 --- -# Overview +## Overview Metaprogramming in Noir is comprised of three parts: 1. `comptime` code @@ -21,7 +21,7 @@ for greater analysis and modification of programs. --- -# Comptime +## Comptime `comptime` is a new keyword in Noir which marks an item as executing or existing at compile-time. It can be used in several ways: @@ -32,11 +32,11 @@ for greater analysis and modification of programs. - `comptime let` to define a variable whose value is evaluated at compile-time. - `comptime for` to run a for loop at compile-time. Syntax sugar for `comptime { for .. }`. -## Scoping +### Scoping Note that while in a `comptime` context, any runtime variables _local to the current function_ are never visible. -## Evaluating +### Evaluating Evaluation rules of `comptime` follows the normal unconstrained evaluation rules for other Noir code. There are a few things to note though: @@ -62,7 +62,7 @@ For example, using globals to generate unique ids should be fine but relying on function itself was called at compile-time previously, it will already be resolved and cannot be modified. To prevent accidentally calling functions you wish to modify at compile-time, it may be helpful to sort your `comptime` annotation functions into a different crate along with any dependencies they require. -## Lowering +### Lowering When a `comptime` value is used in runtime code it must be lowered into a runtime value. This means replacing the expression with the literal that it evaluated to. For example, the code: @@ -102,7 +102,7 @@ comptime fn get_type() -> Type { ... } --- -# (Quasi) Quote +## (Quasi) Quote Macros in Noir are `comptime` functions which return code as a value which is inserted into the call site when it is lowered there. A code value in this case is of type `Quoted` and can be created by a `quote { ... }` expression. @@ -121,7 +121,7 @@ Calling such a function at compile-time without `!` will just return the `Quoted For those familiar with quoting from other languages (primarily lisps), Noir's `quote` is actually a _quasiquote_. This means we can escape the quoting by using the unquote operator to splice values in the middle of quoted code. -# Unquote +## Unquote The unquote operator `$` is usable within a `quote` expression. It takes a variable as an argument, evaluates the variable, and splices the resulting value into the quoted token stream at that point. For example, @@ -160,7 +160,7 @@ comptime { --- -# Annotations +## Annotations Annotations provide a way to run a `comptime` function on an item in the program. When you use an annotation, the function with the same name will be called with that item as an argument: @@ -188,7 +188,7 @@ For example, this is the mechanism used to insert additional trait implementatio #include_code derive-field-count-example noir_stdlib/src/meta/mod.nr rust -## Calling annotations with additional arguments +### Calling annotations with additional arguments Arguments may optionally be given to annotations. When this is done, these additional arguments are passed to the annotation function after the item argument. @@ -201,13 +201,13 @@ We can also take any number of arguments by adding the `varargs` annotation: --- -# Comptime API +## Comptime API Although `comptime`, `quote`, and unquoting provide a flexible base for writing macros, Noir's true metaprogramming ability comes from being able to interact with the compiler through a compile-time API. This API can be accessed through built-in functions in `std::meta` as well as on methods of several `comptime` types. -The following is an incomplete list of some `comptime` types along with some useful methods on them. +The following is an incomplete list of some `comptime` types along with some useful methods on them. You can see more in the standard library [Metaprogramming section](../standard_library/meta). - `Quoted`: A token stream - `Type`: The type of a Noir type @@ -238,7 +238,7 @@ The following is an incomplete list of some `comptime` types along with some use There are many more functions available by exploring the `std::meta` module and its submodules. Using these methods is the key to writing powerful metaprogramming libraries. -## `#[use_callers_scope]` +### `#[use_callers_scope]` Since certain functions such as `Quoted::as_type`, `Expression::as_type`, or `Quoted::as_trait_constraint` will attempt to resolve their contents in a particular scope - it can be useful to change the scope they resolve in. By default @@ -251,7 +251,7 @@ your attribute function and a helper function it calls use it, then they can bot --- -# Example: Derive +## Example: Derive Using all of the above, we can write a `derive` macro that behaves similarly to Rust's but is not built into the language. From the user's perspective it will look like this: diff --git a/noir/noir-repo/docs/docusaurus.config.ts b/noir/noir-repo/docs/docusaurus.config.ts index c7af7e494d1..c53d11e3373 100644 --- a/noir/noir-repo/docs/docusaurus.config.ts +++ b/noir/noir-repo/docs/docusaurus.config.ts @@ -181,37 +181,6 @@ export default { membersWithOwnFile: ['Interface', 'Class', 'TypeAlias', 'Function'], }, ], - [ - 'docusaurus-plugin-typedoc', - { - id: 'noir_js_backend_barretenberg', - entryPoints: ['../tooling/noir_js_backend_barretenberg/src/index.ts'], - tsconfig: '../tooling/noir_js_backend_barretenberg/tsconfig.json', - entryPointStrategy: 'resolve', - out: 'processed-docs/reference/NoirJS/backend_barretenberg', - plugin: ['typedoc-plugin-markdown'], - name: 'backend_barretenberg', - disableSources: true, - excludePrivate: true, - skipErrorChecking: true, - sidebar: { - filteredIds: ['reference/NoirJS/backend_barretenberg/index'], - }, - readme: 'none', - hidePageHeader: true, - hideBreadcrumbs: true, - hideInPageTOC: true, - useCodeBlocks: true, - typeDeclarationFormat: 'table', - propertiesFormat: 'table', - parametersFormat: 'table', - enumMembersFormat: 'table', - indexFormat: 'table', - outputFileStrategy: 'members', - memberPageTitle: '{name}', - membersWithOwnFile: ['Interface', 'Class', 'TypeAlias'], - }, - ], [ 'docusaurus-plugin-typedoc', { diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.36.0/how_to/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.36.0/how_to/_category_.json index 360a8ad77f0..0b4f367ce53 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.36.0/how_to/_category_.json +++ b/noir/noir-repo/docs/versioned_docs/version-v0.36.0/how_to/_category_.json @@ -1,6 +1,5 @@ { - "label": "Modules, Packages and Crates", - "position": 2, + "position": 1, "collapsible": true, "collapsed": true } diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.36.0/noir/concepts/data_types/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.36.0/noir/concepts/data_types/_category_.json index 5b6a20a609a..5d694210bbf 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.36.0/noir/concepts/data_types/_category_.json +++ b/noir/noir-repo/docs/versioned_docs/version-v0.36.0/noir/concepts/data_types/_category_.json @@ -1,5 +1,5 @@ { - "position": 4, + "position": 0, "collapsible": true, "collapsed": true } diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.36.0/noir/standard_library/cryptographic_primitives/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.36.0/noir/standard_library/cryptographic_primitives/_category_.json index 7da08f8a8c5..5d694210bbf 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.36.0/noir/standard_library/cryptographic_primitives/_category_.json +++ b/noir/noir-repo/docs/versioned_docs/version-v0.36.0/noir/standard_library/cryptographic_primitives/_category_.json @@ -1,6 +1,5 @@ { - "label": "Concepts", "position": 0, "collapsible": true, "collapsed": true -} \ No newline at end of file +} diff --git a/noir/noir-repo/noir_stdlib/src/hash/keccak.nr b/noir/noir-repo/noir_stdlib/src/hash/keccak.nr index 50fbab8a416..93b366d1ec1 100644 --- a/noir/noir-repo/noir_stdlib/src/hash/keccak.nr +++ b/noir/noir-repo/noir_stdlib/src/hash/keccak.nr @@ -1,4 +1,3 @@ -use crate::collections::vec::Vec; use crate::runtime::is_unconstrained; global BLOCK_SIZE_IN_BYTES: u32 = 136; //(1600 - BITS * 2) / WORD_SIZE; @@ -12,7 +11,10 @@ fn keccakf1600(input: [u64; 25]) -> [u64; 25] {} #[no_predicates] pub(crate) fn keccak256(input: [u8; N], message_size: u32) -> [u8; 32] { assert(N >= message_size); - let mut block_bytes = [0; BLOCK_SIZE_IN_BYTES]; + + // Copy input to block bytes. For that we'll need at least input bytes (N) + // but we want it to be padded to a multiple of BLOCK_SIZE_IN_BYTES. + let mut block_bytes = [0; ((N / BLOCK_SIZE_IN_BYTES) + 1) * BLOCK_SIZE_IN_BYTES]; if is_unconstrained() { for i in 0..message_size { block_bytes[i] = input[i]; @@ -28,7 +30,6 @@ pub(crate) fn keccak256(input: [u8; N], message_size: u32) -> [u8; 3 //1. format_input_lanes let max_blocks = (N + BLOCK_SIZE_IN_BYTES) / BLOCK_SIZE_IN_BYTES; //maximum number of bytes to hash - let max_blocks_length = (BLOCK_SIZE_IN_BYTES * max_blocks); let real_max_blocks = (message_size + BLOCK_SIZE_IN_BYTES) / BLOCK_SIZE_IN_BYTES; let real_blocks_bytes = real_max_blocks * BLOCK_SIZE_IN_BYTES; @@ -36,9 +37,9 @@ pub(crate) fn keccak256(input: [u8; N], message_size: u32) -> [u8; 3 block_bytes[real_blocks_bytes - 1] = 0x80; // populate a vector of 64-bit limbs from our byte array - let num_limbs = max_blocks_length / WORD_SIZE; - let mut sliced_buffer = Vec::new(); - for i in 0..num_limbs { + let mut sliced_buffer = + [0; (((N / BLOCK_SIZE_IN_BYTES) + 1) * BLOCK_SIZE_IN_BYTES) / WORD_SIZE]; + for i in 0..sliced_buffer.len() { let limb_start = WORD_SIZE * i; let mut sliced = 0; @@ -48,7 +49,7 @@ pub(crate) fn keccak256(input: [u8; N], message_size: u32) -> [u8; 3 v *= 256; } - sliced_buffer.push(sliced as u64); + sliced_buffer[i] = sliced as u64; } //2. sponge_absorb @@ -59,11 +60,11 @@ pub(crate) fn keccak256(input: [u8; N], message_size: u32) -> [u8; 3 for i in 0..real_max_blocks { if (i == 0) { for j in 0..LIMBS_PER_BLOCK { - state[j] = sliced_buffer.get(j); + state[j] = sliced_buffer[j]; } } else { for j in 0..LIMBS_PER_BLOCK { - state[j] = state[j] ^ sliced_buffer.get(i * LIMBS_PER_BLOCK + j); + state[j] = state[j] ^ sliced_buffer[i * LIMBS_PER_BLOCK + j]; } } state = keccakf1600(state); @@ -73,13 +74,13 @@ pub(crate) fn keccak256(input: [u8; N], message_size: u32) -> [u8; 3 // We peel out the first block as to avoid a conditional inside of the loop. // Otherwise, a dynamic predicate can cause a blowup in a constrained runtime. for j in 0..LIMBS_PER_BLOCK { - state[j] = sliced_buffer.get(j); + state[j] = sliced_buffer[j]; } state = keccakf1600(state); for i in 1..max_blocks { if i < real_max_blocks { for j in 0..LIMBS_PER_BLOCK { - state[j] = state[j] ^ sliced_buffer.get(i * LIMBS_PER_BLOCK + j); + state[j] = state[j] ^ sliced_buffer[i * LIMBS_PER_BLOCK + j]; } state = keccakf1600(state); } @@ -114,8 +115,7 @@ mod tests { #[test] fn hash_hello_world() { - // "hello world" - let input = [72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 33]; + let input = "Hello world!".as_bytes(); let result = [ 0xec, 0xd0, 0xe1, 0x8, 0xa9, 0x8e, 0x19, 0x2a, 0xf1, 0xd2, 0xc2, 0x50, 0x55, 0xf4, 0xe3, 0xbe, 0xd7, 0x84, 0xb5, 0xc8, 0x77, 0x20, 0x4e, 0x73, 0x21, 0x9a, 0x52, 0x3, 0x25, 0x1f, @@ -137,4 +137,18 @@ mod tests { ]; assert_eq(keccak256(input, 13), result); } + + #[test] + fn hash_longer_than_136_bytes() { + let input = "123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789" + .as_bytes(); + assert(input.len() > 136); + + let result = [ + 0x1d, 0xca, 0xeb, 0xdf, 0xd9, 0xd6, 0x24, 0x67, 0x1c, 0x18, 0x16, 0xda, 0xd, 0x8a, 0xeb, + 0xa8, 0x75, 0x71, 0x2c, 0xc, 0x89, 0xe0, 0x25, 0x2, 0xe8, 0xb6, 0x5e, 0x16, 0x5, 0x55, + 0xe4, 0x40, + ]; + assert_eq(keccak256(input, input.len()), result); + } } diff --git a/noir/noir-repo/noir_stdlib/src/hash/mod.nr b/noir/noir-repo/noir_stdlib/src/hash/mod.nr index 15112757312..c5e6da9d76f 100644 --- a/noir/noir-repo/noir_stdlib/src/hash/mod.nr +++ b/noir/noir-repo/noir_stdlib/src/hash/mod.nr @@ -75,6 +75,7 @@ pub fn pedersen_hash_with_separator(input: [Field; N], separator: u3 } #[field(bn254)] +#[inline_always] pub fn derive_generators( domain_separator_bytes: [u8; M], starting_index: u32, diff --git a/noir/noir-repo/noir_stdlib/src/hash/sha256.nr b/noir/noir-repo/noir_stdlib/src/hash/sha256.nr index b5d2624d3e7..d3ab1b7f1b8 100644 --- a/noir/noir-repo/noir_stdlib/src/hash/sha256.nr +++ b/noir/noir-repo/noir_stdlib/src/hash/sha256.nr @@ -12,6 +12,20 @@ global MSG_SIZE_PTR = 56; // Size of the message block when packed as 4-byte integer array. global INT_BLOCK_SIZE = 16; +// A `u32` integer consists of 4 bytes. +global INT_SIZE = 4; + +// Index of the integer in the `INT_BLOCK` where the length is written. +global INT_SIZE_PTR = MSG_SIZE_PTR / INT_SIZE; + +// Magic numbers for bit shifting. +// Works with actual bit shifting as well as the compiler turns them into * and / +// but circuit execution appears to be 10% faster this way. +global TWO_POW_8 = 256; +global TWO_POW_16 = TWO_POW_8 * 256; +global TWO_POW_24 = TWO_POW_16 * 256; +global TWO_POW_32 = TWO_POW_24 as u64 * 256; + // Index of a byte in a 64 byte block; ie. 0..=63 type BLOCK_BYTE_PTR = u32; @@ -19,8 +33,8 @@ type BLOCK_BYTE_PTR = u32; type INT_BLOCK = [u32; INT_BLOCK_SIZE]; // A message block is a slice of the original message of a fixed size, -// potentially padded with zeroes. -type MSG_BLOCK = [u8; BLOCK_SIZE]; +// potentially padded with zeros, with neighbouring 4 bytes packed into integers. +type MSG_BLOCK = INT_BLOCK; // The hash is 32 bytes. type HASH = [u8; 32]; @@ -50,16 +64,19 @@ pub fn digest(msg: [u8; N]) -> HASH { pub fn sha256_var(msg: [u8; N], message_size: u64) -> HASH { let message_size = message_size as u32; let num_blocks = N / BLOCK_SIZE; - let mut msg_block: MSG_BLOCK = [0; BLOCK_SIZE]; + let mut msg_block: MSG_BLOCK = [0; INT_BLOCK_SIZE]; + // Intermediate hash, starting with the canonical initial value let mut h: STATE = [ 1779033703, 3144134277, 1013904242, 2773480762, 1359893119, 2600822924, 528734635, 1541459225, - ]; // Intermediate hash, starting with the canonical initial value - let mut msg_byte_ptr = 0; // Pointer into msg_block + ]; + // Pointer into msg_block on a 64 byte scale + let mut msg_byte_ptr = 0; for i in 0..num_blocks { let msg_start = BLOCK_SIZE * i; let (new_msg_block, new_msg_byte_ptr) = unsafe { build_msg_block(msg, message_size, msg_start) }; + if msg_start < message_size { msg_block = new_msg_block; } @@ -77,7 +94,7 @@ pub fn sha256_var(msg: [u8; N], message_size: u64) -> HASH { // If the block is filled, compress it. // An un-filled block is handled after this loop. if (msg_start < message_size) & (msg_byte_ptr == BLOCK_SIZE) { - h = sha256_compression(msg_u8_to_u32(msg_block), h); + h = sha256_compression(msg_block, h); } } @@ -114,49 +131,39 @@ pub fn sha256_var(msg: [u8; N], message_size: u64) -> HASH { // Pad the rest such that we have a [u32; 2] block at the end representing the length // of the message, and a block of 1 0 ... 0 following the message (i.e. [1 << 7, 0, ..., 0]). // Here we rely on the fact that everything beyond the available input is set to 0. - msg_block[msg_byte_ptr] = 1 << 7; - let last_block = msg_block; + msg_block = update_block_item( + msg_block, + msg_byte_ptr, + |msg_item| set_item_byte_then_zeros(msg_item, msg_byte_ptr, 1 << 7), + ); msg_byte_ptr = msg_byte_ptr + 1; + let last_block = msg_block; // If we don't have room to write the size, compress the block and reset it. if msg_byte_ptr > MSG_SIZE_PTR { - h = sha256_compression(msg_u8_to_u32(msg_block), h); + h = sha256_compression(msg_block, h); // `attach_len_to_msg_block` will zero out everything after the `msg_byte_ptr`. msg_byte_ptr = 0; } msg_block = unsafe { attach_len_to_msg_block(msg_block, msg_byte_ptr, message_size) }; - if !crate::runtime::is_unconstrained() { + if !is_unconstrained() { verify_msg_len(msg_block, last_block, msg_byte_ptr, message_size); } hash_final_block(msg_block, h) } -// Convert 64-byte array to array of 16 u32s -fn msg_u8_to_u32(msg: MSG_BLOCK) -> INT_BLOCK { - let mut msg32: INT_BLOCK = [0; INT_BLOCK_SIZE]; - - for i in 0..INT_BLOCK_SIZE { - let mut msg_field: Field = 0; - for j in 0..4 { - msg_field = msg_field * 256 + msg[64 - 4 * (i + 1) + j] as Field; - } - msg32[15 - i] = msg_field as u32; - } - - msg32 -} - // Take `BLOCK_SIZE` number of bytes from `msg` starting at `msg_start`. -// Returns the block and the length that has been copied rather than padded with zeroes. +// Returns the block and the length that has been copied rather than padded with zeros. unconstrained fn build_msg_block( msg: [u8; N], message_size: u32, msg_start: u32, ) -> (MSG_BLOCK, BLOCK_BYTE_PTR) { - let mut msg_block: MSG_BLOCK = [0; BLOCK_SIZE]; + let mut msg_block: MSG_BLOCK = [0; INT_BLOCK_SIZE]; + // We insert `BLOCK_SIZE` bytes (or up to the end of the message) let block_input = if msg_start + BLOCK_SIZE > message_size { if message_size < msg_start { @@ -169,29 +176,73 @@ unconstrained fn build_msg_block( } else { BLOCK_SIZE }; - for k in 0..block_input { - msg_block[k] = msg[msg_start + k]; + + // Figure out the number of items in the int array that we have to pack. + // e.g. if the input is [0,1,2,3,4,5] then we need to pack it as 2 items: [0123, 4500] + let mut int_input = block_input / INT_SIZE; + if block_input % INT_SIZE != 0 { + int_input = int_input + 1; + }; + + for i in 0..int_input { + let mut msg_item: u32 = 0; + // Always construct the integer as 4 bytes, even if it means going beyond the input. + for j in 0..INT_SIZE { + let k = i * INT_SIZE + j; + let msg_byte = if k < block_input { + msg[msg_start + k] + } else { + 0 + }; + msg_item = lshift8(msg_item, 1) + msg_byte as u32; + } + msg_block[i] = msg_item; } + + // Returning the index as if it was a 64 byte array. + // We have to project it down to 16 items and bit shifting to get a byte back if we need it. (msg_block, block_input) } // Verify the block we are compressing was appropriately constructed by `build_msg_block` // and matches the input data. Returns the index of the first unset item. +// If `message_size` is less than `msg_start` then this is called with the old non-empty block; +// in that case we can skip verification, ie. no need to check that everything is zero. fn verify_msg_block( msg: [u8; N], message_size: u32, msg_block: MSG_BLOCK, msg_start: u32, ) -> BLOCK_BYTE_PTR { - let mut msg_byte_ptr: u32 = 0; // Message byte pointer + let mut msg_byte_ptr = 0; let mut msg_end = msg_start + BLOCK_SIZE; if msg_end > N { msg_end = N; } + // We might have to go beyond the input to pad the fields. + if msg_end % INT_SIZE != 0 { + msg_end = msg_end + INT_SIZE - msg_end % INT_SIZE; + } - for k in msg_start..msg_end { - if k < message_size { - assert_eq(msg_block[msg_byte_ptr], msg[k]); + // Reconstructed packed item. + let mut msg_item: u32 = 0; + + // Inclusive at the end so that we can compare the last item. + let mut i: u32 = 0; + for k in msg_start..=msg_end { + if k % INT_SIZE == 0 { + // If we consumed some input we can compare against the block. + if (msg_start < message_size) & (k > msg_start) { + assert_eq(msg_block[i], msg_item as u32); + i = i + 1; + msg_item = 0; + } + } + // Shift the accumulator + msg_item = lshift8(msg_item, 1); + // If we have input to consume, add it at the rightmost position. + if k < message_size & k < msg_end { + msg_item = msg_item + msg[k] as u32; msg_byte_ptr = msg_byte_ptr + 1; } } @@ -199,69 +250,261 @@ fn verify_msg_block( msg_byte_ptr } -// Verify the block we are compressing was appropriately padded with zeroes by `build_msg_block`. +// Verify the block we are compressing was appropriately padded with zeros by `build_msg_block`. // This is only relevant for the last, potentially partially filled block. fn verify_msg_block_padding(msg_block: MSG_BLOCK, msg_byte_ptr: BLOCK_BYTE_PTR) { + // Check all the way to the end of the block. + verify_msg_block_zeros(msg_block, msg_byte_ptr, INT_BLOCK_SIZE); +} + +// Verify that a region of ints in the message block are (partially) zeroed, +// up to an (exclusive) maximum which can either be the end of the block +// or just where the size is to be written. +fn verify_msg_block_zeros( + msg_block: MSG_BLOCK, + mut msg_byte_ptr: BLOCK_BYTE_PTR, + max_int_byte_ptr: u32, +) { // This variable is used to get around the compiler under-constrained check giving a warning. // We want to check against a constant zero, but if it does not come from the circuit inputs // or return values the compiler check will issue a warning. let zero = msg_block[0] - msg_block[0]; - for i in 0..BLOCK_SIZE { - if i >= msg_byte_ptr { + // First integer which is supposed to be (partially) zero. + let mut int_byte_ptr = msg_byte_ptr / INT_SIZE; + + // Check partial zeros. + let modulo = msg_byte_ptr % INT_SIZE; + if modulo != 0 { + let zeros = INT_SIZE - modulo; + let mask = if zeros == 3 { + TWO_POW_24 + } else if zeros == 2 { + TWO_POW_16 + } else { + TWO_POW_8 + }; + assert_eq(msg_block[int_byte_ptr] % mask, zero); + int_byte_ptr = int_byte_ptr + 1; + } + + // Check the rest of the items. + for i in 0..max_int_byte_ptr { + if i >= int_byte_ptr { assert_eq(msg_block[i], zero); } } } +// Verify that up to the byte pointer the two blocks are equal. +// At the byte pointer the new block can be partially zeroed. +fn verify_msg_block_equals_last( + msg_block: MSG_BLOCK, + last_block: MSG_BLOCK, + mut msg_byte_ptr: BLOCK_BYTE_PTR, +) { + // msg_byte_ptr is the position at which they are no longer have to be the same. + // First integer which is supposed to be (partially) zero contains that pointer. + let mut int_byte_ptr = msg_byte_ptr / INT_SIZE; + + // Check partial zeros. + let modulo = msg_byte_ptr % INT_SIZE; + if modulo != 0 { + // Reconstruct the partially zero item from the last block. + let last_field = last_block[int_byte_ptr]; + let mut msg_item: u32 = 0; + // Reset to where they are still equal. + msg_byte_ptr = msg_byte_ptr - modulo; + for i in 0..INT_SIZE { + msg_item = lshift8(msg_item, 1); + if i < modulo { + msg_item = msg_item + get_item_byte(last_field, msg_byte_ptr) as u32; + msg_byte_ptr = msg_byte_ptr + 1; + } + } + assert_eq(msg_block[int_byte_ptr], msg_item); + } + + for i in 0..INT_SIZE_PTR { + if i < int_byte_ptr { + assert_eq(msg_block[i], last_block[i]); + } + } +} + +// Apply a function on the block item which the pointer indicates. +fn update_block_item( + mut msg_block: MSG_BLOCK, + msg_byte_ptr: BLOCK_BYTE_PTR, + f: fn[Env](u32) -> u32, +) -> MSG_BLOCK { + let i = msg_byte_ptr / INT_SIZE; + msg_block[i] = f(msg_block[i]); + msg_block +} + +// Set the rightmost `zeros` number of bytes to 0. +fn set_item_zeros(item: u32, zeros: u8) -> u32 { + lshift8(rshift8(item, zeros), zeros) +} + +// Replace one byte in the item with a value, and set everything after it to zero. +fn set_item_byte_then_zeros(msg_item: u32, msg_byte_ptr: BLOCK_BYTE_PTR, msg_byte: u8) -> u32 { + let zeros = INT_SIZE - msg_byte_ptr % INT_SIZE; + let zeroed_item = set_item_zeros(msg_item, zeros as u8); + let new_item = byte_into_item(msg_byte, msg_byte_ptr); + zeroed_item + new_item +} + +// Get a byte of a message item according to its overall position in the `BLOCK_SIZE` space. +fn get_item_byte(mut msg_item: u32, msg_byte_ptr: BLOCK_BYTE_PTR) -> u8 { + // How many times do we have to shift to the right to get to the position we want? + let max_shifts = INT_SIZE - 1; + let shifts = max_shifts - msg_byte_ptr % INT_SIZE; + msg_item = rshift8(msg_item, shifts as u8); + // At this point the byte we want is in the rightmost position. + msg_item as u8 +} + +// Project a byte into a position in a field based on the overall block pointer. +// For example putting 1 into pointer 5 would be 100, because overall we would +// have [____, 0100] with indexes [0123,4567]. +fn byte_into_item(msg_byte: u8, msg_byte_ptr: BLOCK_BYTE_PTR) -> u32 { + let mut msg_item = msg_byte as u32; + // How many times do we have to shift to the left to get to the position we want? + let max_shifts = INT_SIZE - 1; + let shifts = max_shifts - msg_byte_ptr % INT_SIZE; + lshift8(msg_item, shifts as u8) +} + +// Construct a field out of 4 bytes. +fn make_item(b0: u8, b1: u8, b2: u8, b3: u8) -> u32 { + let mut item = b0 as u32; + item = lshift8(item, 1) + b1 as u32; + item = lshift8(item, 1) + b2 as u32; + item = lshift8(item, 1) + b3 as u32; + item +} + +// Shift by 8 bits to the left between 0 and 4 times. +// Checks `is_unconstrained()` to just use a bitshift if we're running in an unconstrained context, +// otherwise multiplies by 256. +fn lshift8(item: u32, shifts: u8) -> u32 { + if is_unconstrained() { + if item == 0 { + 0 + } else { + // Brillig wouldn't shift 0<<4 without overflow. + item << (8 * shifts) + } + } else { + // We can do a for loop up to INT_SIZE or an if-else. + if shifts == 0 { + item + } else if shifts == 1 { + item * TWO_POW_8 + } else if shifts == 2 { + item * TWO_POW_16 + } else if shifts == 3 { + item * TWO_POW_24 + } else { + // Doesn't make sense, but it's most likely called on 0 anyway. + 0 + } + } +} + +// Shift by 8 bits to the right between 0 and 4 times. +// Checks `is_unconstrained()` to just use a bitshift if we're running in an unconstrained context, +// otherwise divides by 256. +fn rshift8(item: u32, shifts: u8) -> u32 { + if is_unconstrained() { + item >> (8 * shifts) + } else { + // Division wouldn't work on `Field`. + if shifts == 0 { + item + } else if shifts == 1 { + item / TWO_POW_8 + } else if shifts == 2 { + item / TWO_POW_16 + } else if shifts == 3 { + item / TWO_POW_24 + } else { + 0 + } + } +} + // Zero out all bytes between the end of the message and where the length is appended, // then write the length into the last 8 bytes of the block. unconstrained fn attach_len_to_msg_block( mut msg_block: MSG_BLOCK, - msg_byte_ptr: BLOCK_BYTE_PTR, + mut msg_byte_ptr: BLOCK_BYTE_PTR, message_size: u32, ) -> MSG_BLOCK { // We assume that `msg_byte_ptr` is less than 57 because if not then it is reset to zero before calling this function. - // In any case, fill blocks up with zeros until the last 64 (i.e. until msg_byte_ptr = 56). - for i in msg_byte_ptr..MSG_SIZE_PTR { + // In any case, fill blocks up with zeros until the last 64 bits (i.e. until msg_byte_ptr = 56). + // There can be one item which has to be partially zeroed. + let modulo = msg_byte_ptr % INT_SIZE; + if modulo != 0 { + // Index of the block in which we find the item we need to partially zero. + let i = msg_byte_ptr / INT_SIZE; + let zeros = INT_SIZE - modulo; + msg_block[i] = set_item_zeros(msg_block[i], zeros as u8); + msg_byte_ptr = msg_byte_ptr + zeros; + } + + // The rest can be zeroed without bit shifting anything. + for i in (msg_byte_ptr / INT_SIZE)..INT_SIZE_PTR { msg_block[i] = 0; } + // Set the last two 4 byte ints as the first/second half of the 8 bytes of the length. let len = 8 * message_size; let len_bytes: [u8; 8] = (len as Field).to_be_bytes(); - for i in 0..8 { - msg_block[MSG_SIZE_PTR + i] = len_bytes[i]; + for i in 0..=1 { + let shift = i * 4; + msg_block[INT_SIZE_PTR + i] = make_item( + len_bytes[shift], + len_bytes[shift + 1], + len_bytes[shift + 2], + len_bytes[shift + 3], + ); } msg_block } -// Verify that the message length was correctly written by `attach_len_to_msg_block`. +// Verify that the message length was correctly written by `attach_len_to_msg_block`, +// and that everything between the byte pointer and the size pointer was zeroed, +// and that everything before the byte pointer was untouched. fn verify_msg_len( msg_block: MSG_BLOCK, last_block: MSG_BLOCK, msg_byte_ptr: BLOCK_BYTE_PTR, message_size: u32, ) { - for i in 0..MSG_SIZE_PTR { - let predicate = (i < msg_byte_ptr) as u8; - let expected_byte = predicate * last_block[i]; - assert_eq(msg_block[i], expected_byte); - } + // Check zeros up to the size pointer. + verify_msg_block_zeros(msg_block, msg_byte_ptr, INT_SIZE_PTR); + + // Check that up to the pointer we match the last block. + verify_msg_block_equals_last(msg_block, last_block, msg_byte_ptr); // We verify the message length was inserted correctly by reversing the byte decomposition. - let len = 8 * message_size; - let mut reconstructed_len: Field = 0; - for i in MSG_SIZE_PTR..BLOCK_SIZE { - reconstructed_len = 256 * reconstructed_len + msg_block[i] as Field; + let mut reconstructed_len: u64 = 0; + for i in INT_SIZE_PTR..INT_BLOCK_SIZE { + reconstructed_len = reconstructed_len * TWO_POW_32; + reconstructed_len = reconstructed_len + msg_block[i] as u64; } - assert_eq(reconstructed_len, len as Field); + let len = 8 * message_size as u64; + assert_eq(reconstructed_len, len); } // Perform the final compression, then transform the `STATE` into `HASH`. fn hash_final_block(msg_block: MSG_BLOCK, mut state: STATE) -> HASH { let mut out_h: HASH = [0; 32]; // Digest as sequence of bytes // Hash final padded block - state = sha256_compression(msg_u8_to_u32(msg_block), state); + state = sha256_compression(msg_block, state); // Return final hash as byte array for j in 0..8 { @@ -275,6 +518,11 @@ fn hash_final_block(msg_block: MSG_BLOCK, mut state: STATE) -> HASH { } mod tests { + use super::{ + attach_len_to_msg_block, build_msg_block, byte_into_item, get_item_byte, make_item, + set_item_byte_then_zeros, set_item_zeros, + }; + use super::INT_BLOCK; use super::sha256_var; #[test] @@ -510,4 +758,79 @@ mod tests { assert_eq(var_length_hash_575, fixed_length_hash); assert_eq(var_length_hash_576, fixed_length_hash); } + + #[test] + fn test_get_item_byte() { + let fld = make_item(10, 20, 30, 40); + assert_eq(fld, 0x0a141e28); + assert_eq(get_item_byte(fld, 0), 10); + assert_eq(get_item_byte(fld, 4), 10); + assert_eq(get_item_byte(fld, 6), 30); + } + + #[test] + fn test_byte_into_item() { + let fld = make_item(0, 20, 0, 0); + assert_eq(byte_into_item(20, 1), fld); + assert_eq(byte_into_item(20, 5), fld); + } + + #[test] + fn test_set_item_zeros() { + let fld0 = make_item(10, 20, 30, 40); + let fld1 = make_item(10, 0, 0, 0); + assert_eq(set_item_zeros(fld0, 3), fld1); + assert_eq(set_item_zeros(fld0, 4), 0); + assert_eq(set_item_zeros(0, 4), 0); + } + + #[test] + fn test_set_item_byte_then_zeros() { + let fld0 = make_item(10, 20, 30, 40); + let fld1 = make_item(10, 50, 0, 0); + assert_eq(set_item_byte_then_zeros(fld0, 1, 50), fld1); + } + + #[test] + fn test_build_msg_block_start_0() { + let input = [ + 102, 114, 111, 109, 58, 114, 117, 110, 110, 105, 101, 114, 46, 108, 101, 97, 103, 117, + 101, 115, 46, 48, + ]; + assert_eq(input.len(), 22); + let (msg_block, msg_byte_ptr) = unsafe { build_msg_block(input, input.len(), 0) }; + assert_eq(msg_byte_ptr, input.len()); + assert_eq(msg_block[0], make_item(input[0], input[1], input[2], input[3])); + assert_eq(msg_block[1], make_item(input[4], input[5], input[6], input[7])); + assert_eq(msg_block[5], make_item(input[20], input[21], 0, 0)); + assert_eq(msg_block[6], 0); + } + + #[test] + fn test_build_msg_block_start_1() { + let input = [ + 102, 114, 111, 109, 58, 114, 117, 110, 110, 105, 101, 114, 46, 108, 101, 97, 103, 117, + 101, 115, 46, 48, 106, 64, 105, 99, 108, 111, 117, 100, 46, 99, 111, 109, 13, 10, 99, + 111, 110, 116, 101, 110, 116, 45, 116, 121, 112, 101, 58, 116, 101, 120, 116, 47, 112, + 108, 97, 105, 110, 59, 32, 99, 104, 97, 114, 115, 101, 116, + ]; + assert_eq(input.len(), 68); + let (msg_block, msg_byte_ptr) = unsafe { build_msg_block(input, input.len(), 64) }; + assert_eq(msg_byte_ptr, 4); + assert_eq(msg_block[0], make_item(input[64], input[65], input[66], input[67])); + assert_eq(msg_block[1], 0); + } + + #[test] + fn test_attach_len_to_msg_block() { + let input: INT_BLOCK = [ + 2152555847, 1397309779, 1936618851, 1262052426, 1936876331, 1985297723, 543702374, + 1919905082, 1131376244, 1701737517, 1417244773, 978151789, 1697470053, 1920166255, + 1849316213, 1651139939, + ]; + let msg_block = unsafe { attach_len_to_msg_block(input, 1, 448) }; + assert_eq(msg_block[0], ((1 << 7) as u32) * 256 * 256 * 256); + assert_eq(msg_block[1], 0); + assert_eq(msg_block[15], 3584); + } } diff --git a/noir/noir-repo/scripts/bump-bb.sh b/noir/noir-repo/scripts/bump-bb.sh index fb1a2b1d31e..661a8eb9d43 100755 --- a/noir/noir-repo/scripts/bump-bb.sh +++ b/noir/noir-repo/scripts/bump-bb.sh @@ -5,7 +5,7 @@ BB_VERSION=$1 sed -i.bak "s/^VERSION=.*/VERSION=\"$BB_VERSION\"/" ./scripts/install_bb.sh && rm ./scripts/install_bb.sh.bak tmp=$(mktemp) -INTEGRATION_TESTS_PACKAGE_JSON=./compiler/integration_tests/package.json +INTEGRATION_TESTS_PACKAGE_JSON=./compiler/integration-tests/package.json jq --arg v $BB_VERSION '.dependencies."@aztec/bb.js" = $v' $INTEGRATION_TESTS_PACKAGE_JSON > $tmp && mv $tmp $INTEGRATION_TESTS_PACKAGE_JSON YARN_ENABLE_IMMUTABLE_INSTALLS=false yarn install diff --git a/noir/noir-repo/scripts/install_bb.sh b/noir/noir-repo/scripts/install_bb.sh index 596f0a54ba4..64baf78c182 100755 --- a/noir/noir-repo/scripts/install_bb.sh +++ b/noir/noir-repo/scripts/install_bb.sh @@ -1,6 +1,6 @@ #!/bin/bash -VERSION="0.58.0" +VERSION="0.60.0" BBUP_PATH=~/.bb/bbup diff --git a/noir/noir-repo/test_programs/compile_success_empty/arithmetic_generics/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/arithmetic_generics/src/main.nr index f599d2879ee..ae50748c8e7 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/arithmetic_generics/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_empty/arithmetic_generics/src/main.nr @@ -77,25 +77,25 @@ fn equiv_trans( x: Equiv, y: Equiv, ) -> Equiv, Equiv), V, (Equiv, Equiv)> { - Equiv { to_: |z| { y.to(x.to(z)) }, fro_: |z| { x.fro(y.fro(z)) } } + Equiv { to_: |z| y.to(x.to(z)), fro_: |z| x.fro(y.fro(z)) } } fn mul_one_r() -> Equiv, (), W, ()> { - Equiv { to_: |_x| { W {} }, fro_: |_x| { W {} } } + Equiv { to_: |_x| W {}, fro_: |_x| W {} } } fn add_equiv_r( _: Equiv, EN, W, EM>, ) -> Equiv, (), W, ()> { - Equiv { to_: |_x| { W {} }, fro_: |_x| { W {} } } + Equiv { to_: |_x| W {}, fro_: |_x| W {} } } fn mul_comm() -> Equiv, (), W, ()> { - Equiv { to_: |_x| { W {} }, fro_: |_x| { W {} } } + Equiv { to_: |_x| W {}, fro_: |_x| W {} } } fn mul_add() -> Equiv, (), W, ()> { - Equiv { to_: |_x| { W {} }, fro_: |_x| { W {} } } + Equiv { to_: |_x| W {}, fro_: |_x| W {} } } // (N + 1) * N == N * N + N diff --git a/noir/noir-repo/test_programs/compile_success_empty/comptime_closures/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/comptime_closures/src/main.nr index 132c6df6c91..e8a0366a304 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/comptime_closures/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_empty/comptime_closures/src/main.nr @@ -6,7 +6,7 @@ fn main() { fn closure_test(mut x: Field) { let one = 1; - let add1 = |z| { (|| { *z += one; })() }; + let add1 = |z| (|| { *z += one; })(); let two = 2; let add2 = |z| { *z = *z + two; }; diff --git a/noir/noir-repo/test_programs/compile_success_empty/inner_outer_cl/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/inner_outer_cl/src/main.nr index 57890cd6b67..17cbabec48e 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/inner_outer_cl/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_empty/inner_outer_cl/src/main.nr @@ -2,7 +2,7 @@ fn main() { let z1 = 0; let z2 = 1; let cl_outer = |x| { - let cl_inner = |y| { x + y + z2 }; + let cl_inner = |y| x + y + z2; cl_inner(1) + z1 }; let result = cl_outer(1); diff --git a/noir/noir-repo/test_programs/compile_success_empty/use_callers_scope/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/use_callers_scope/src/main.nr index bc93bc5187e..26429997f0e 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/use_callers_scope/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_empty/use_callers_scope/src/main.nr @@ -19,7 +19,7 @@ mod bar { // Ensure closures can still access Bar even // though `map` separates them from `fn_attr`. - let _ = &[1, 2, 3].map(|_| { quote { Bar }.as_type() }); + let _ = &[1, 2, 3].map(|_| quote { Bar }.as_type()); } // use_callers_scope should also work nested diff --git a/noir/noir-repo/test_programs/execution_success/double_verify_honk_proof/Nargo.toml b/noir/noir-repo/test_programs/execution_success/double_verify_honk_proof/Nargo.toml deleted file mode 100644 index 5f819990c72..00000000000 --- a/noir/noir-repo/test_programs/execution_success/double_verify_honk_proof/Nargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "double_verify_honk_proof" -type = "bin" -authors = [""] - -[dependencies] diff --git a/noir/noir-repo/test_programs/execution_success/double_verify_honk_proof/Prover.toml b/noir/noir-repo/test_programs/execution_success/double_verify_honk_proof/Prover.toml deleted file mode 100644 index f8e7ba41a18..00000000000 --- a/noir/noir-repo/test_programs/execution_success/double_verify_honk_proof/Prover.toml +++ /dev/null @@ -1,5 +0,0 @@ -key_hash = "0x0000000000000000000000000000000000000000000000000000000000000000" -proof = ["0x0000000000000000000000000000000000000000000000000000000000000040", "0x0000000000000000000000000000000000000000000000000000000000000011", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000042ab5d6d1986846cf", "0x00000000000000000000000000000000000000000000000b75c020998797da78", "0x0000000000000000000000000000000000000000000000005a107acb64952eca", "0x000000000000000000000000000000000000000000000000000031e97a575e9d", "0x00000000000000000000000000000000000000000000000b5666547acf8bd5a4", "0x00000000000000000000000000000000000000000000000c410db10a01750aeb", "0x00000000000000000000000000000000000000000000000d722669117f9758a4", "0x000000000000000000000000000000000000000000000000000178cbf4206471", "0x000000000000000000000000000000000000000000000000e91b8a11e7842c38", "0x000000000000000000000000000000000000000000000007fd51009034b3357f", "0x000000000000000000000000000000000000000000000009889939f81e9c7402", "0x0000000000000000000000000000000000000000000000000000f94656a2ca48", "0x000000000000000000000000000000000000000000000006fb128b46c1ddb67f", "0x0000000000000000000000000000000000000000000000093fe27776f50224bd", "0x000000000000000000000000000000000000000000000004a0c80c0da527a081", "0x0000000000000000000000000000000000000000000000000001b52c2020d746", "0x0000000000000000000000000000005a9bae947e1e91af9e4033d8d6aa6ed632", "0x000000000000000000000000000000000025e485e013446d4ac7981c88ba6ecc", "0x000000000000000000000000000000ff1e0496e30ab24a63b32b2d1120b76e62", "0x00000000000000000000000000000000001afe0a8a685d7cd85d1010e55d9d7c", "0x000000000000000000000000000000b0804efd6573805f991458295f510a2004", "0x00000000000000000000000000000000000c81a178016e2fe18605022d5a8b0e", "0x000000000000000000000000000000eba51e76eb1cfff60a53a0092a3c3dea47", "0x000000000000000000000000000000000022e7466247b533282f5936ac4e6c15", "0x00000000000000000000000000000071b1d76edf770edff98f00ff4deec264cd", "0x00000000000000000000000000000000001e48128e68794d8861fcbb2986a383", "0x000000000000000000000000000000d3a2af4915ae6d86b097adc377fafda2d4", "0x000000000000000000000000000000000006359de9ca452dab3a4f1f8d9c9d98", "0x0000000000000000000000000000006cf7dd96d7636fda5953191b1ad776d491", "0x00000000000000000000000000000000001633d881a08d136e834cb13a28fcc6", "0x00000000000000000000000000000001254956cff6908b069fca0e6cf1c47eb1", "0x000000000000000000000000000000000006f4d4dd3890e997e75e75886bf8f7", "0x0000000000000000000000000000006cf7dd96d7636fda5953191b1ad776d491", "0x00000000000000000000000000000000001633d881a08d136e834cb13a28fcc6", "0x00000000000000000000000000000001254956cff6908b069fca0e6cf1c47eb1", "0x000000000000000000000000000000000006f4d4dd3890e997e75e75886bf8f7", "0x000000000000000000000000000000f968b227a358a305607f3efc933823d288", "0x00000000000000000000000000000000000eaf8adb390375a76d95e918b65e08", "0x000000000000000000000000000000bb34b4b447aae56f5e24f81c3acd6d547f", "0x00000000000000000000000000000000002175d012746260ebcfe339a91a81e1", "0x00000000000000000000000000000052eebbd1f6f7554e837f60c44000ed14b6", "0x00000000000000000000000000000000001c1c045a3ec94b8801f2272cc0b3f4", "0x0000000000000000000000000000004d2ef74134578f6b431a9df071ffca4292", "0x0000000000000000000000000000000000291326ade7aa6f0dfc8900eab5580b", "0x0000000000000000000000000000002433eec6418a6dba820c9527e2581fc8bc", "0x00000000000000000000000000000000000e88b7daad19af2ac2f9bdf9e50ee2", "0x000000000000000000000000000000dcfce2c427155cc3e4d035735d3dd5ece8", "0x00000000000000000000000000000000002d7d473cac1a15d0fee8b22c1a7b3e", "0x1a4249b90be4602c8ff40c7c276160ee41b2a0f8a238ce7706e9face2db03d48", "0x162204b9d54d3ffd285c393a5a1ff76ee681474fd780a21a3cf7fac5c24fc2b9", "0x30279eb953d8ee79b2155c69c04e6443c5de6bf7e02886256dd7b3cd3c9502a4", "0x0d32c1bd21baf43e72d5d82d461ef54833807ff81a877adc822f27a6db88d754", "0x0fe15e055c0803d5ebe6dd77689b70cfd82138f008810ce24535c992daaff27d", "0x1fba82c012671212ce2fc13fd09bf8fba4f7d5875ab8d37495d1ccfcff287331", "0x090738a5842fa4d2699b3726aa0dd97cb59569b4be2c6825335ec4969f859dc2", "0x0c6cb72dabbc28abcf4a50c203534e066c29f48c24ca64d672092f263df3f9d7", "0x0f27fbea0d9145f815c288b50fe7e8c10b8185d325b5264624fd57102855d05d", "0x2a815cd3fd1c43c72ee0130465250ff771d1e7be2347e4ada331b83265a03450", "0x148b4ecf2ad7ed17409417086867ee27bc1b0906dbc9cbb3714c285071e2db70", "0x08e700a42b1d6d36ee65f8ebedf47d3a44463ff9fa579dce13b7492e20142c3a", "0x2e23c69521d572ff2152c50f8c9a9191535f4cf37f95f1e0428692e78842b642", "0x14519e0354365923fb41400c19866135b45e975d56a0980260bc99f0390b1d5f", "0x04caded1f05738f736cb5bcf08d785e395e58eb7738523a20638aa16bc51593e", "0x28787eaccd38383215ea21ec02895c32d979f68ca155f534a2e2d377bff6698b", "0x20a1b81fa96c58cf11c5762c5ceb731efdcb081fca2d34d5c463d2cf40e6da18", "0x11789a06fe3bf53833741d180f068d29534d5bb58a5c64b8119542e62b189fb4", "0x23d00fcd032ace719ffcbc513bfa177a55b04377d76455c2788d999d05d011e2", "0x01f0e81b57b4a73cc118e51ede18f8724debf25c2d109db6ef45280f99f1a3fa", "0x156d1c9b61749810de728f259c2c1c1fd4dbff97101426e26087ca461c93307c", "0x1c5d619ac3a478cfd06d5eebfd879960bb321236be173813f5e78d1366d32c69", "0x250cfae4e1dfc551406f1f3d10b649a637dcb7bcb0f6f697994cf96afd35d0c1", "0x242b999f58cf5f53c874d1092bd38725aa9ea076f5bc8f176efa9ea23393874b", "0x2e15748255c4a5e0e9fe38047341b692a967257de27a85a3a38681bc9f1602ea", "0x01ef83886ea7017253699cb6371988eb8e21b4f7023d7479ece4907fe6d4a6fd", "0x08db2dbc271e375b9312f695c59c48f313235b3432cad50921c8d9ad6dd7ad7a", "0x199309f2c2cd45c15a4abb0e6554a1615ff5a6e9488a8d900bbf835fc8f664ef", "0x074be7a3d88e31ab1b59c9208c012bcfb1f85f351c709e68134996891db52b57", "0x301b1011354d2ebf46134fc4d6d734bb6ed8542d719f38f5e09a376a580cad7f", "0x12968f3eccaa27e44f14d5aaac6ecb70c00d040e07536292e685d7cab03fc563", "0x2110a023c8c22fd2ed70270a2d0a265b92a32ce2217ffe1be9a5d7d5c25f512f", "0x1e8cf4c60c53900f0430d5b44de5804fe8b38299bc803beeb4216e1a289cf624", "0x12301cb908ccb28a2616e29b831ec7105b5d3ebf45ff5fe91d50a9dd53a50b52", "0x0f1029ed107d84ff2d6d4a416cbd01da3f3d7bf5b2209ce93ba424f4b85616fc", "0x1b431d016611b8abd684afd9e92331c3325967b1116bfa91d4f44e2f8e2c9fc2", "0x281e335a0fd117064c8ace3f01e02b134a19e9b9220571ebfaaaa0e3a12d34db", "0x22559c106f77e2ae95677d5e38e288343e3b7168371aec7d3aaab9ef8150af70", "0x13f113b1d9b590149cf08c3f6e90589cda5c7b98528866b891256cb9d5d814e7", "0x10252ef388e4c80246962e98b9e976fab2cd25e1e6f1e3fd2a7d4786c5218a97", "0x16b890723dfdebd9912a9207255f95cb800222165b6fae97ec46e461f23e83f3", "0x25caf77c7d2e8e069341ec90f3c8f6d64319cfd2d77cab0625cf0377285ba11c", "0x016c84288b0bc3c50eebbe250cdd5a4ee50b2c65a24ac64d0c930cbdecb95141", "0x20a537c045b069d47dc6315f45b391f60681222381e5059ec7c8b17bf677d911", "0x2594c0edfcd4064d215a3d797bc8e3b2f401c61f3961ae96ccbec8f8fd29e81f", "0x1c831d7047483ca00ed59bdb84c47ffb8bbebbae92aa164c7b35fcffbb8a35d3", "0x2ea7f60de52b8cd6b0bd06f861fc1f2c5ed1d1fbfa53caccdb836400a03df434", "0x275c6c8bd115f7d2ce196439e2330fad305c6745bab0bf1ce3f2fa32dadc3c43", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x2b3f4e210619347288731e7f0eea1ae60dd8696fe87319044864d099a03a9536", "0x0fecd3d2aebedeb8be2b0b7e3a74de9ec8bd2cb72851541463729e0715aef48b", "0x10bee385ad0c2cd3ff88ef4d630840749e4367f9add4a300fc4f545a7778e92c", "0x1fe792730eeafbd22c4eb80e86e2b40108b1e55b2a08db786289eea5745b9e3b", "0x04d411679da432816b213cd5580dda1fd6c2f258684c036be19b5b26baca583c", "0x159f17b655d2b8a803e0cfb564918628be52d3baa950ca1b127854491624f8f4", "0x225340463867d9252a1269013536e2e1dd219aa18eadef13c324b63d44679334", "0x1885e231554e02abb40ed54b72ebf09b883d0298a6bc06fc645a30365f370ef2", "0x233344517f25170972b8ba35d01f2df2e073d322993abce7df26796126e93498", "0x08990e8faa13b18b4433ec417c5cc596885e11ffd372d5f612c08cc79a5d5c80", "0x1e960a0c892b755c28e21dcbed816c1b182d7da43bae07f8ee622bd4485f79e7", "0x27b58e2ee290a179d349ace82752528b2ff946d60c092b99ef42f53c25d0c99f", "0x2a5cf8a3193107d982edd253002c7a52ab876b445dde8307ab78fbdca022d93c", "0x2b1ab4d5277f8c82750c1c7bd043889b71465ec64a9afc1bfa37d06b1ebd0725", "0x2a0dbf5c4373a58a83d5f2a031ea0615bf12800e33b70c3191a7cbb15966ced8", "0x1f272bb4a19d14a0abdfebc9fc83125e10623b9aef730f8d25f2bf5bead38ea9", "0x2c2339cf0ae7aff56091a568c1e2c3f01f52d8ed13400737fd31eaabcaffb9bd", "0x21f5fefe6b5fa0b5da71089befb74a1a39e52b4f830cb330c3c284e154614dfd", "0x1e6f6ba4b2444586b380dc4e2b3fad111ff1f4754420a846f53ea0789ebfb0ad", "0x1193d170b0b2dd0c4a04331a4b4aa3f12920f182ec3ab547837e30f1116ca584", "0x00000000000000000000000000000025704a15c9e2ce8a69558e7bbcdcbc7784", "0x2e5d36112770fb6c985681cafe40a8c99ad13f702309e7969801dd0ed080e727", "0x0eefc2585f591bb457183134e19ad643966272234d645514bf7868d6dd8ae2cb", "0x300803e4e2339ad39b9c31f228949bbeaf9c74b7101e7be1930b088126247eaa", "0x2bb562a50ed944b438b83b01f200101a34faef7f296a75c84c731755ebddbc1a", "0x1288e0b9c742af39cbcac21357c1b29511b0bbdd3d0e3cf5e14b2eef68a28ab3", "0x20f089131cc96d86ff1cfb67fa3f51670f4bad30158751b2587354bbec76cdf9", "0x1a26c6d3e633f9bf8434cf755b5f1217dad0d455071a97a7bcf85b824f5cf07a", "0x0d7e9b8a51fccf910ec25bdbd13e70b34bd6ea6f4d629fa744f9cdf5f2beb1cf", "0x0b40f28ce428e64df9cf5a024133fc420f39decf5f6af020cc3211ab298d4631", "0x0ca4f189dde7a55fe829f46681232904f6670249a22e0deb47222bd309523a8a", "0x2c544f2e31143783977645edb2a6bdb39b875053963bfa1a5b3ae9de204a7ebe", "0x00aae4454eb48fb18ff60db6b9d015abea2e770a2f7d86d121522b834c791ba5", "0x07d74e351fd4cccf4e18475d25211efa8a359066fc693a5c8505ddb507e4b74b", "0x07d74e351fd4cccf4e18475d25211efa8a359066fc693a5c8505ddb507e4b74b", "0x2d9e5bff47207d82533e2445959941181cc890c5779bc7f24d6e8a7b9e425b5c", "0x0aea3c0c317c441a5775a9849108d7a6889b39128235f717b09b184aa08e4eb7", "0x1ca5bc6fb37c55a562f4991901c39902f42d14db71284116df74cb4e7d55e493", "0x220fed26d64cd69f40e6d145a423e4a3c8cd0dce747e7d51647441270ad4d774", "0x15be574c9358889257aa2a30ff7b5fcc31a57da7032296e2c1201c49a44bbdb6", "0x2de539925525bedd3b7f43a9c6bf0f713151a17f79ac7ff4a9cd27b15ffe892a", "0x083086693dbf465211741e2cbff70ff38eb08383faf22d397eb2742c8ad7396a", "0x1fdfa258a890598816e807c50058d7a1462edd5ff196a2eae0f862e454b49aa1", "0x10c434c6daaa8226fa8e3e302123dfdc4455cf68063df518949df5a65a945213", "0x0000000000000000000000000000006472a7874de2c454a4591ed7784df1c104", "0x000000000000000000000000000000000008c46ac53d2c4ad0c26a5d6c790082", "0x0000000000000000000000000000005e422f9cfb8725800de60dfe0a8d4104c0", "0x000000000000000000000000000000000000f10fd4e4de81a0c00073ec91c274", "0x000000000000000000000000000000b20813090eca76bc6aa4a699b1ec8d5d6d", "0x0000000000000000000000000000000000292cc9f8a744eb00e0903c29ce87a7", "0x000000000000000000000000000000350a368b415fbb99fa90a26a42b1a3affd", "0x0000000000000000000000000000000000280eb9275cb05a3435f464d1dc369d", "0x000000000000000000000000000000280df6505e20c7725fe6d29439f96ee05d", "0x000000000000000000000000000000000017ef5033a08535451e2747827aa94b", "0x0000000000000000000000000000002f9ba89ae91b4e4a4ff8ccbd0526faad2f", "0x00000000000000000000000000000000001c2013561dafcc02cb03220bdf23c4", "0x000000000000000000000000000000aac102c400f9e5da0321ded4510994434b", "0x00000000000000000000000000000000001ec8ab9cc834b492fde124962f04a1", "0x0000000000000000000000000000000673dbd698da8b8cce450d2a083aba9987", "0x00000000000000000000000000000000000a49e55bb040249cb41c63cea901cd", "0x000000000000000000000000000000133d92af8d76ee0c74a12081ee7b2ef8c4", "0x0000000000000000000000000000000000240f552d1c6cbb007650e4b142e0a5", "0x000000000000000000000000000000e29c6e7d982ec08d51c79d6261c28d742d", "0x000000000000000000000000000000000021baeec04d9be419c923626034e7b3", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x1e940a528b42d8230e7d4dff76262a80986c0d00b2c02a9bc0559e36212d1547", "0x1ceccf21ac39f70d76ad6f7fe0dcb33b6af04555a0b1959e4714d65925e4e253", "0x096139d757046cdbdb7ee89a95f112f70882a43a46c2f739d9be115dda013420", "0x2f9c8ac67c7825b08eff0e7f7656a671f4c64e5601f2efab35b1b795801eec04", "0x2077e648e1704851cdffd7e6e56311634a7b741bab77ca34d9dff12a6a2bfe99", "0x115d48c4a97aeb3c447a060f9e0d675b0dc7f4a05a3f5776e2f279f3a165d7dc", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x000000000000000000000000000000fd38c45c3ec5b841482a80e3a56ce82555", "0x00000000000000000000000000000000000ad70b03f092f60af3e0ce1bb29d2c", "0x0000000000000000000000000000007a184d5342c90c634c0b1a050f0b97c9fb", "0x0000000000000000000000000000000000271f42abcb3bc1f0332e4b3ca85e1d", "0x0000000000000000000000000000008256322bbe2c1b8cd9d84e5ff6123477f2", "0x000000000000000000000000000000000025cab962761681dd9547f4c78814df", "0x0000000000000000000000000000008c4234510e5825c02b9ac427bcbf8e279a", "0x000000000000000000000000000000000013a14e0d7fc073c44643af38cc5396"] -public_inputs = ["0x0000000000000000000000000000000000000000000000000000000000000003"] -verification_key = ["0x0000000000000000000000000000000000000000000000000000000000000040", "0x0000000000000000000000000000000000000000000000000000000000000011", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000003", "0x0000000000000000000000000000000000000000000000000000000000000004", "0x0000000000000000000000000000000000000000000000000000000000000005", "0x0000000000000000000000000000000000000000000000000000000000000006", "0x0000000000000000000000000000000000000000000000000000000000000007", "0x0000000000000000000000000000000000000000000000000000000000000008", "0x0000000000000000000000000000000000000000000000000000000000000009", "0x000000000000000000000000000000000000000000000000000000000000000a", "0x000000000000000000000000000000000000000000000000000000000000000b", "0x000000000000000000000000000000000000000000000000000000000000000c", "0x000000000000000000000000000000000000000000000000000000000000000d", "0x000000000000000000000000000000000000000000000000000000000000000e", "0x000000000000000000000000000000000000000000000000000000000000000f", "0x0000000000000000000000000000000000000000000000000000000000000010", "0x00000000000000000000000000000060e430ad1c23bfcf3514323aae3f206e84", "0x00000000000000000000000000000000001b5c3ff4c2458d8f481b1c068f27ae", "0x000000000000000000000000000000bb510ab2112def34980e4fc6998ad9dd16", "0x00000000000000000000000000000000000576e7c105b43e061e13cb877fefe1", "0x000000000000000000000000000000ced074785d11857b065d8199e6669a601c", "0x00000000000000000000000000000000000053b48a4098c1c0ae268f273952f7", "0x000000000000000000000000000000d1d4b26e941db8168cee8f6de548ae0fd8", "0x00000000000000000000000000000000001a9adf5a6dadc3d948bb61dfd63f4c", "0x0000000000000000000000000000009ce1faac6f8de6ebb18f1db17372c82ad5", "0x00000000000000000000000000000000002002681bb417184b2df070a16a3858", "0x000000000000000000000000000000161baa651a8092e0e84725594de5aba511", "0x00000000000000000000000000000000000be0064399c2a1efff9eb0cdcb2223", "0x0000000000000000000000000000008673be6fd1bdbe980a29d8c1ded54381e7", "0x000000000000000000000000000000000008a5158a7d9648cf1d234524c9fa0c", "0x0000000000000000000000000000002b4fce6e4b1c72062b296d49bca2aa4130", "0x00000000000000000000000000000000002e45a9eff4b6769e55fb710cded44f", "0x00000000000000000000000000000072b85bf733758b76bcf97333efb85a23e3", "0x000000000000000000000000000000000017da0ea508994fc82862715e4b5592", "0x00000000000000000000000000000094fa74695cf058dba8ff35aec95456c6c3", "0x0000000000000000000000000000000000211acddb851061c24b8f159e832bd1", "0x000000000000000000000000000000303b5e5c531384b9a792e11702ad3bcab0", "0x00000000000000000000000000000000000d336dff51a60b8833d5d7f6d4314c", "0x0000000000000000000000000000009f825dde88092070747180d581c342444a", "0x0000000000000000000000000000000000237fbd6511a03cca8cac01b555fe01", "0x0000000000000000000000000000007c313205159495df6d8de292079a4844ff", "0x000000000000000000000000000000000018facdfc468530dd45e8f7a1d38ce9", "0x0000000000000000000000000000000d1ce33446fc3dc4ab40ca38d92dac74e1", "0x00000000000000000000000000000000000852d8e3e0e8f4435af3e94222688b", "0x0000000000000000000000000000006c04ee19ec1dfec87ed47d6d04aa158de2", "0x000000000000000000000000000000000013240f97a584b45184c8ec31319b5f", "0x000000000000000000000000000000cefb5d240b07ceb4be26ea429b6dc9d9e0", "0x00000000000000000000000000000000002dad22022121d689f57fb38ca21349", "0x000000000000000000000000000000c9f189f2a91aeb664ce376d8b157ba98f8", "0x00000000000000000000000000000000002531a51ad54f124d58094b219818d2", "0x000000000000000000000000000000ef1e6db71809307f677677e62b4163f556", "0x0000000000000000000000000000000000272da4396fb2a7ee0638b9140e523d", "0x0000000000000000000000000000002e54c0244a7732c87bc4712a76dd8c83fb", "0x000000000000000000000000000000000007db77b3e04b7eba9643da57cbbe4d", "0x000000000000000000000000000000e0dfe1ddd7f74ae0d636c910c3e85830d8", "0x00000000000000000000000000000000000466fa9b57ec4664abd1505b490862", "0x0000000000000000000000000000009ee55ae8a32fe5384c79907067cc27192e", "0x00000000000000000000000000000000000799d0e465cec07ecb5238c854e830", "0x0000000000000000000000000000001d5910ad361e76e1c241247a823733c39f", "0x00000000000000000000000000000000002b03f2ccf7507564da2e6678bef8fe", "0x000000000000000000000000000000ee40d90bea71fba7a412dd61fcf34e8ceb", "0x0000000000000000000000000000000000140b0936c323fd2471155617b6af56", "0x0000000000000000000000000000002b90071823185c5ff8e440fd3d73b6fefc", "0x00000000000000000000000000000000002b6c10790a5f6631c87d652e059df4", "0x00000000000000000000000000000029a17181c7934fc3fdbd352eac5cb521b9", "0x00000000000000000000000000000000001f497cbf5284ff29a2d336e5991999", "0x000000000000000000000000000000072bd9c0c6beda1fdee6d4ff0432ba9e1b", "0x000000000000000000000000000000000013ea38a0bd2aa751a490a724fac818", "0x000000000000000000000000000000c599f63dcd3edd49f08ae5c3141c1e3493", "0x00000000000000000000000000000000002bdb36be0bea09950dd32a8ccf6fbc", "0x00000000000000000000000000000047f27f29724e7f19eba0340256a0bd4b7d", "0x00000000000000000000000000000000001c1c5ccf87a962129ca785f8f35120", "0x000000000000000000000000000000c5c71efdae00679bbe4a95096e012b1817", "0x000000000000000000000000000000000017a365de041e317817d0135f2b48e0", "0x0000000000000000000000000000008ae711ac402f7848d719c93a89ba8d39f1", "0x00000000000000000000000000000000002b6fb40ed8a1935226f4f9786a0499", "0x0000000000000000000000000000002f03a71501d83de1da5715a4e9462d6198", "0x00000000000000000000000000000000001644064443b8546f48eae693af47b8", "0x00000000000000000000000000000083763ab1b6e8fe269b2fe4c7b9c448c08d", "0x000000000000000000000000000000000021d7cc18c59676a8eeb47c0111c251", "0x000000000000000000000000000000b5f937153073e03ea7d51a996e0ebc2e6b", "0x000000000000000000000000000000000011ddd0e26457373eb06e0493177672", "0x000000000000000000000000000000c5f6eb9f6fc8fa99811a4a88c74a6d018b", "0x000000000000000000000000000000000025bcd07a0732c123567834f5109558", "0x000000000000000000000000000000aeb08a0b1a4442189448b4e97490568146", "0x000000000000000000000000000000000002a1744e4771705536a88f07e0f90f", "0x000000000000000000000000000000b938568293bd0724b0ea76c2ec34c4a829", "0x0000000000000000000000000000000000053296e8f3b9ad3af877dfa9c7c2a7", "0x000000000000000000000000000000f0ca1db6323996eba26bdc86dafef9d10b", "0x00000000000000000000000000000000001441a46c58af03d5645d52721d956a", "0x0000000000000000000000000000008bbf8f884013c66c28ba09c2fbd573b656", "0x0000000000000000000000000000000000206c391ca06fac27d1908e94570243", "0x0000000000000000000000000000002d4f5aaed88ba4f79612d53b804ca8f194", "0x00000000000000000000000000000000001674011c96392df08970fa6b7b4cb8", "0x0000000000000000000000000000009f88297c1729d76c4d9306853598c91325", "0x0000000000000000000000000000000000256f51adfcacc3c1e340be4d32d3e9", "0x0000000000000000000000000000000ab9955eec0d74eb799afed2a802b24d75", "0x00000000000000000000000000000000001fcbe43ea105b30d36ed0b21b03411", "0x000000000000000000000000000000d66b1d5433f1aa5305cd1edce7c22de466", "0x00000000000000000000000000000000002331546a256b8a3b751956806680d4", "0x000000000000000000000000000000e97954ad6cd6f45fb15c91434121db4304", "0x00000000000000000000000000000000002e20a97e09d50f227ced47e7a98250", "0x0000000000000000000000000000001ebbc27eb9ebededefba79522eb58ae89b", "0x0000000000000000000000000000000000090efa4974e566e81d1177b85a30be", "0x0000000000000000000000000000005eafa070b9c9632404052642e3bc14f9fd", "0x00000000000000000000000000000000001489068864102daca6a6b8bc4d448b", "0x0000000000000000000000000000009ebc91aaaac036a6477cadbe54e8556dfd", "0x00000000000000000000000000000000000ef6d835e2ed3343b95c82c8c54037", "0x00000000000000000000000000000033b28b529dff46e93af4e7422530478e4a", "0x000000000000000000000000000000000020a86c2f8591bf190bcddcc03c42fb", "0x000000000000000000000000000000a9679d0acc088f7dc27bf6d866bcd2dda2", "0x00000000000000000000000000000000002fb9d0d2d4099402bed74f738f64cc", "0x00000000000000000000000000000023b09f876a29a061582848a8b9a5870c12", "0x00000000000000000000000000000000001d5bb906f03f0d49e9c4791bc43af9", "0x00000000000000000000000000000017aac9854ea240d8ec97bf760c4d4ba870", "0x00000000000000000000000000000000000b227a556c414ada0dc75bb303e30e", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000009b624fa65d1a24b7f14a8f25f3789622af", "0x000000000000000000000000000000000013d47bff8c630e847b70e2732fd3f0", "0x00000000000000000000000000000061d21663e93132f32921075f4c936a84df", "0x00000000000000000000000000000000001a74ca4e118fb480b9b999902989a3"] -proof_b = ["0x0000000000000000000000000000000000000000000000000000000000000040", "0x0000000000000000000000000000000000000000000000000000000000000011", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000042ab5d6d1986846cf", "0x00000000000000000000000000000000000000000000000b75c020998797da78", "0x0000000000000000000000000000000000000000000000005a107acb64952eca", "0x000000000000000000000000000000000000000000000000000031e97a575e9d", "0x00000000000000000000000000000000000000000000000b5666547acf8bd5a4", "0x00000000000000000000000000000000000000000000000c410db10a01750aeb", "0x00000000000000000000000000000000000000000000000d722669117f9758a4", "0x000000000000000000000000000000000000000000000000000178cbf4206471", "0x000000000000000000000000000000000000000000000000e91b8a11e7842c38", "0x000000000000000000000000000000000000000000000007fd51009034b3357f", "0x000000000000000000000000000000000000000000000009889939f81e9c7402", "0x0000000000000000000000000000000000000000000000000000f94656a2ca48", "0x000000000000000000000000000000000000000000000006fb128b46c1ddb67f", "0x0000000000000000000000000000000000000000000000093fe27776f50224bd", "0x000000000000000000000000000000000000000000000004a0c80c0da527a081", "0x0000000000000000000000000000000000000000000000000001b52c2020d746", "0x0000000000000000000000000000005a9bae947e1e91af9e4033d8d6aa6ed632", "0x000000000000000000000000000000000025e485e013446d4ac7981c88ba6ecc", "0x000000000000000000000000000000ff1e0496e30ab24a63b32b2d1120b76e62", "0x00000000000000000000000000000000001afe0a8a685d7cd85d1010e55d9d7c", "0x000000000000000000000000000000b0804efd6573805f991458295f510a2004", "0x00000000000000000000000000000000000c81a178016e2fe18605022d5a8b0e", "0x000000000000000000000000000000eba51e76eb1cfff60a53a0092a3c3dea47", "0x000000000000000000000000000000000022e7466247b533282f5936ac4e6c15", "0x00000000000000000000000000000071b1d76edf770edff98f00ff4deec264cd", "0x00000000000000000000000000000000001e48128e68794d8861fcbb2986a383", "0x000000000000000000000000000000d3a2af4915ae6d86b097adc377fafda2d4", "0x000000000000000000000000000000000006359de9ca452dab3a4f1f8d9c9d98", "0x0000000000000000000000000000006cf7dd96d7636fda5953191b1ad776d491", "0x00000000000000000000000000000000001633d881a08d136e834cb13a28fcc6", "0x00000000000000000000000000000001254956cff6908b069fca0e6cf1c47eb1", "0x000000000000000000000000000000000006f4d4dd3890e997e75e75886bf8f7", "0x0000000000000000000000000000006cf7dd96d7636fda5953191b1ad776d491", "0x00000000000000000000000000000000001633d881a08d136e834cb13a28fcc6", "0x00000000000000000000000000000001254956cff6908b069fca0e6cf1c47eb1", "0x000000000000000000000000000000000006f4d4dd3890e997e75e75886bf8f7", "0x000000000000000000000000000000f968b227a358a305607f3efc933823d288", "0x00000000000000000000000000000000000eaf8adb390375a76d95e918b65e08", "0x000000000000000000000000000000bb34b4b447aae56f5e24f81c3acd6d547f", "0x00000000000000000000000000000000002175d012746260ebcfe339a91a81e1", "0x00000000000000000000000000000052eebbd1f6f7554e837f60c44000ed14b6", "0x00000000000000000000000000000000001c1c045a3ec94b8801f2272cc0b3f4", "0x0000000000000000000000000000004d2ef74134578f6b431a9df071ffca4292", "0x0000000000000000000000000000000000291326ade7aa6f0dfc8900eab5580b", "0x0000000000000000000000000000002433eec6418a6dba820c9527e2581fc8bc", "0x00000000000000000000000000000000000e88b7daad19af2ac2f9bdf9e50ee2", "0x000000000000000000000000000000dcfce2c427155cc3e4d035735d3dd5ece8", "0x00000000000000000000000000000000002d7d473cac1a15d0fee8b22c1a7b3e", "0x1a4249b90be4602c8ff40c7c276160ee41b2a0f8a238ce7706e9face2db03d48", "0x162204b9d54d3ffd285c393a5a1ff76ee681474fd780a21a3cf7fac5c24fc2b9", "0x30279eb953d8ee79b2155c69c04e6443c5de6bf7e02886256dd7b3cd3c9502a4", "0x0d32c1bd21baf43e72d5d82d461ef54833807ff81a877adc822f27a6db88d754", "0x0fe15e055c0803d5ebe6dd77689b70cfd82138f008810ce24535c992daaff27d", "0x1fba82c012671212ce2fc13fd09bf8fba4f7d5875ab8d37495d1ccfcff287331", "0x090738a5842fa4d2699b3726aa0dd97cb59569b4be2c6825335ec4969f859dc2", "0x0c6cb72dabbc28abcf4a50c203534e066c29f48c24ca64d672092f263df3f9d7", "0x0f27fbea0d9145f815c288b50fe7e8c10b8185d325b5264624fd57102855d05d", "0x2a815cd3fd1c43c72ee0130465250ff771d1e7be2347e4ada331b83265a03450", "0x148b4ecf2ad7ed17409417086867ee27bc1b0906dbc9cbb3714c285071e2db70", "0x08e700a42b1d6d36ee65f8ebedf47d3a44463ff9fa579dce13b7492e20142c3a", "0x2e23c69521d572ff2152c50f8c9a9191535f4cf37f95f1e0428692e78842b642", "0x14519e0354365923fb41400c19866135b45e975d56a0980260bc99f0390b1d5f", "0x04caded1f05738f736cb5bcf08d785e395e58eb7738523a20638aa16bc51593e", "0x28787eaccd38383215ea21ec02895c32d979f68ca155f534a2e2d377bff6698b", "0x20a1b81fa96c58cf11c5762c5ceb731efdcb081fca2d34d5c463d2cf40e6da18", "0x11789a06fe3bf53833741d180f068d29534d5bb58a5c64b8119542e62b189fb4", "0x23d00fcd032ace719ffcbc513bfa177a55b04377d76455c2788d999d05d011e2", "0x01f0e81b57b4a73cc118e51ede18f8724debf25c2d109db6ef45280f99f1a3fa", "0x156d1c9b61749810de728f259c2c1c1fd4dbff97101426e26087ca461c93307c", "0x1c5d619ac3a478cfd06d5eebfd879960bb321236be173813f5e78d1366d32c69", "0x250cfae4e1dfc551406f1f3d10b649a637dcb7bcb0f6f697994cf96afd35d0c1", "0x242b999f58cf5f53c874d1092bd38725aa9ea076f5bc8f176efa9ea23393874b", "0x2e15748255c4a5e0e9fe38047341b692a967257de27a85a3a38681bc9f1602ea", "0x01ef83886ea7017253699cb6371988eb8e21b4f7023d7479ece4907fe6d4a6fd", "0x08db2dbc271e375b9312f695c59c48f313235b3432cad50921c8d9ad6dd7ad7a", "0x199309f2c2cd45c15a4abb0e6554a1615ff5a6e9488a8d900bbf835fc8f664ef", "0x074be7a3d88e31ab1b59c9208c012bcfb1f85f351c709e68134996891db52b57", "0x301b1011354d2ebf46134fc4d6d734bb6ed8542d719f38f5e09a376a580cad7f", "0x12968f3eccaa27e44f14d5aaac6ecb70c00d040e07536292e685d7cab03fc563", "0x2110a023c8c22fd2ed70270a2d0a265b92a32ce2217ffe1be9a5d7d5c25f512f", "0x1e8cf4c60c53900f0430d5b44de5804fe8b38299bc803beeb4216e1a289cf624", "0x12301cb908ccb28a2616e29b831ec7105b5d3ebf45ff5fe91d50a9dd53a50b52", "0x0f1029ed107d84ff2d6d4a416cbd01da3f3d7bf5b2209ce93ba424f4b85616fc", "0x1b431d016611b8abd684afd9e92331c3325967b1116bfa91d4f44e2f8e2c9fc2", "0x281e335a0fd117064c8ace3f01e02b134a19e9b9220571ebfaaaa0e3a12d34db", "0x22559c106f77e2ae95677d5e38e288343e3b7168371aec7d3aaab9ef8150af70", "0x13f113b1d9b590149cf08c3f6e90589cda5c7b98528866b891256cb9d5d814e7", "0x10252ef388e4c80246962e98b9e976fab2cd25e1e6f1e3fd2a7d4786c5218a97", "0x16b890723dfdebd9912a9207255f95cb800222165b6fae97ec46e461f23e83f3", "0x25caf77c7d2e8e069341ec90f3c8f6d64319cfd2d77cab0625cf0377285ba11c", "0x016c84288b0bc3c50eebbe250cdd5a4ee50b2c65a24ac64d0c930cbdecb95141", "0x20a537c045b069d47dc6315f45b391f60681222381e5059ec7c8b17bf677d911", "0x2594c0edfcd4064d215a3d797bc8e3b2f401c61f3961ae96ccbec8f8fd29e81f", "0x1c831d7047483ca00ed59bdb84c47ffb8bbebbae92aa164c7b35fcffbb8a35d3", "0x2ea7f60de52b8cd6b0bd06f861fc1f2c5ed1d1fbfa53caccdb836400a03df434", "0x275c6c8bd115f7d2ce196439e2330fad305c6745bab0bf1ce3f2fa32dadc3c43", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x2b3f4e210619347288731e7f0eea1ae60dd8696fe87319044864d099a03a9536", "0x0fecd3d2aebedeb8be2b0b7e3a74de9ec8bd2cb72851541463729e0715aef48b", "0x10bee385ad0c2cd3ff88ef4d630840749e4367f9add4a300fc4f545a7778e92c", "0x1fe792730eeafbd22c4eb80e86e2b40108b1e55b2a08db786289eea5745b9e3b", "0x04d411679da432816b213cd5580dda1fd6c2f258684c036be19b5b26baca583c", "0x159f17b655d2b8a803e0cfb564918628be52d3baa950ca1b127854491624f8f4", "0x225340463867d9252a1269013536e2e1dd219aa18eadef13c324b63d44679334", "0x1885e231554e02abb40ed54b72ebf09b883d0298a6bc06fc645a30365f370ef2", "0x233344517f25170972b8ba35d01f2df2e073d322993abce7df26796126e93498", "0x08990e8faa13b18b4433ec417c5cc596885e11ffd372d5f612c08cc79a5d5c80", "0x1e960a0c892b755c28e21dcbed816c1b182d7da43bae07f8ee622bd4485f79e7", "0x27b58e2ee290a179d349ace82752528b2ff946d60c092b99ef42f53c25d0c99f", "0x2a5cf8a3193107d982edd253002c7a52ab876b445dde8307ab78fbdca022d93c", "0x2b1ab4d5277f8c82750c1c7bd043889b71465ec64a9afc1bfa37d06b1ebd0725", "0x2a0dbf5c4373a58a83d5f2a031ea0615bf12800e33b70c3191a7cbb15966ced8", "0x1f272bb4a19d14a0abdfebc9fc83125e10623b9aef730f8d25f2bf5bead38ea9", "0x2c2339cf0ae7aff56091a568c1e2c3f01f52d8ed13400737fd31eaabcaffb9bd", "0x21f5fefe6b5fa0b5da71089befb74a1a39e52b4f830cb330c3c284e154614dfd", "0x1e6f6ba4b2444586b380dc4e2b3fad111ff1f4754420a846f53ea0789ebfb0ad", "0x1193d170b0b2dd0c4a04331a4b4aa3f12920f182ec3ab547837e30f1116ca584", "0x00000000000000000000000000000025704a15c9e2ce8a69558e7bbcdcbc7784", "0x2e5d36112770fb6c985681cafe40a8c99ad13f702309e7969801dd0ed080e727", "0x0eefc2585f591bb457183134e19ad643966272234d645514bf7868d6dd8ae2cb", "0x300803e4e2339ad39b9c31f228949bbeaf9c74b7101e7be1930b088126247eaa", "0x2bb562a50ed944b438b83b01f200101a34faef7f296a75c84c731755ebddbc1a", "0x1288e0b9c742af39cbcac21357c1b29511b0bbdd3d0e3cf5e14b2eef68a28ab3", "0x20f089131cc96d86ff1cfb67fa3f51670f4bad30158751b2587354bbec76cdf9", "0x1a26c6d3e633f9bf8434cf755b5f1217dad0d455071a97a7bcf85b824f5cf07a", "0x0d7e9b8a51fccf910ec25bdbd13e70b34bd6ea6f4d629fa744f9cdf5f2beb1cf", "0x0b40f28ce428e64df9cf5a024133fc420f39decf5f6af020cc3211ab298d4631", "0x0ca4f189dde7a55fe829f46681232904f6670249a22e0deb47222bd309523a8a", "0x2c544f2e31143783977645edb2a6bdb39b875053963bfa1a5b3ae9de204a7ebe", "0x00aae4454eb48fb18ff60db6b9d015abea2e770a2f7d86d121522b834c791ba5", "0x07d74e351fd4cccf4e18475d25211efa8a359066fc693a5c8505ddb507e4b74b", "0x07d74e351fd4cccf4e18475d25211efa8a359066fc693a5c8505ddb507e4b74b", "0x2d9e5bff47207d82533e2445959941181cc890c5779bc7f24d6e8a7b9e425b5c", "0x0aea3c0c317c441a5775a9849108d7a6889b39128235f717b09b184aa08e4eb7", "0x1ca5bc6fb37c55a562f4991901c39902f42d14db71284116df74cb4e7d55e493", "0x220fed26d64cd69f40e6d145a423e4a3c8cd0dce747e7d51647441270ad4d774", "0x15be574c9358889257aa2a30ff7b5fcc31a57da7032296e2c1201c49a44bbdb6", "0x2de539925525bedd3b7f43a9c6bf0f713151a17f79ac7ff4a9cd27b15ffe892a", "0x083086693dbf465211741e2cbff70ff38eb08383faf22d397eb2742c8ad7396a", "0x1fdfa258a890598816e807c50058d7a1462edd5ff196a2eae0f862e454b49aa1", "0x10c434c6daaa8226fa8e3e302123dfdc4455cf68063df518949df5a65a945213", "0x0000000000000000000000000000006472a7874de2c454a4591ed7784df1c104", "0x000000000000000000000000000000000008c46ac53d2c4ad0c26a5d6c790082", "0x0000000000000000000000000000005e422f9cfb8725800de60dfe0a8d4104c0", "0x000000000000000000000000000000000000f10fd4e4de81a0c00073ec91c274", "0x000000000000000000000000000000b20813090eca76bc6aa4a699b1ec8d5d6d", "0x0000000000000000000000000000000000292cc9f8a744eb00e0903c29ce87a7", "0x000000000000000000000000000000350a368b415fbb99fa90a26a42b1a3affd", "0x0000000000000000000000000000000000280eb9275cb05a3435f464d1dc369d", "0x000000000000000000000000000000280df6505e20c7725fe6d29439f96ee05d", "0x000000000000000000000000000000000017ef5033a08535451e2747827aa94b", "0x0000000000000000000000000000002f9ba89ae91b4e4a4ff8ccbd0526faad2f", "0x00000000000000000000000000000000001c2013561dafcc02cb03220bdf23c4", "0x000000000000000000000000000000aac102c400f9e5da0321ded4510994434b", "0x00000000000000000000000000000000001ec8ab9cc834b492fde124962f04a1", "0x0000000000000000000000000000000673dbd698da8b8cce450d2a083aba9987", "0x00000000000000000000000000000000000a49e55bb040249cb41c63cea901cd", "0x000000000000000000000000000000133d92af8d76ee0c74a12081ee7b2ef8c4", "0x0000000000000000000000000000000000240f552d1c6cbb007650e4b142e0a5", "0x000000000000000000000000000000e29c6e7d982ec08d51c79d6261c28d742d", "0x000000000000000000000000000000000021baeec04d9be419c923626034e7b3", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x1e940a528b42d8230e7d4dff76262a80986c0d00b2c02a9bc0559e36212d1547", "0x1ceccf21ac39f70d76ad6f7fe0dcb33b6af04555a0b1959e4714d65925e4e253", "0x096139d757046cdbdb7ee89a95f112f70882a43a46c2f739d9be115dda013420", "0x2f9c8ac67c7825b08eff0e7f7656a671f4c64e5601f2efab35b1b795801eec04", "0x2077e648e1704851cdffd7e6e56311634a7b741bab77ca34d9dff12a6a2bfe99", "0x115d48c4a97aeb3c447a060f9e0d675b0dc7f4a05a3f5776e2f279f3a165d7dc", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x000000000000000000000000000000fd38c45c3ec5b841482a80e3a56ce82555", "0x00000000000000000000000000000000000ad70b03f092f60af3e0ce1bb29d2c", "0x0000000000000000000000000000007a184d5342c90c634c0b1a050f0b97c9fb", "0x0000000000000000000000000000000000271f42abcb3bc1f0332e4b3ca85e1d", "0x0000000000000000000000000000008256322bbe2c1b8cd9d84e5ff6123477f2", "0x000000000000000000000000000000000025cab962761681dd9547f4c78814df", "0x0000000000000000000000000000008c4234510e5825c02b9ac427bcbf8e279a", "0x000000000000000000000000000000000013a14e0d7fc073c44643af38cc5396"] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/double_verify_honk_proof/src/main.nr b/noir/noir-repo/test_programs/execution_success/double_verify_honk_proof/src/main.nr deleted file mode 100644 index aecaa931d43..00000000000 --- a/noir/noir-repo/test_programs/execution_success/double_verify_honk_proof/src/main.nr +++ /dev/null @@ -1,28 +0,0 @@ -// This circuit aggregates two Honk proof from `assert_statement_recursive`. -global SIZE_OF_PROOF_IF_LOGN_IS_28: u32 = 463; -global HONK_IDENTIFIER: u32 = 1; -fn main( - verification_key: [Field; 128], - // This is the proof without public inputs attached. - // This means: the size of this does not change with the number of public inputs. - proof: [Field; SIZE_OF_PROOF_IF_LOGN_IS_28], - public_inputs: pub [Field; 1], - key_hash: Field, - // The second proof, currently set to be identical - proof_b: [Field; SIZE_OF_PROOF_IF_LOGN_IS_28], -) { - std::verify_proof_with_type( - verification_key, - proof, - public_inputs, - key_hash, - HONK_IDENTIFIER, - ); - std::verify_proof_with_type( - verification_key, - proof_b, - public_inputs, - key_hash, - HONK_IDENTIFIER, - ); -} diff --git a/noir/noir-repo/test_programs/execution_success/double_verify_honk_proof_recursive/Nargo.toml b/noir/noir-repo/test_programs/execution_success/double_verify_honk_proof_recursive/Nargo.toml deleted file mode 100644 index 618ba8a87b7..00000000000 --- a/noir/noir-repo/test_programs/execution_success/double_verify_honk_proof_recursive/Nargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "double_verify_honk_proof_recursive" -type = "bin" -authors = [""] - -[dependencies] diff --git a/noir/noir-repo/test_programs/execution_success/double_verify_honk_proof_recursive/Prover.toml b/noir/noir-repo/test_programs/execution_success/double_verify_honk_proof_recursive/Prover.toml deleted file mode 100644 index f8e7ba41a18..00000000000 --- a/noir/noir-repo/test_programs/execution_success/double_verify_honk_proof_recursive/Prover.toml +++ /dev/null @@ -1,5 +0,0 @@ -key_hash = "0x0000000000000000000000000000000000000000000000000000000000000000" -proof = ["0x0000000000000000000000000000000000000000000000000000000000000040", "0x0000000000000000000000000000000000000000000000000000000000000011", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000042ab5d6d1986846cf", "0x00000000000000000000000000000000000000000000000b75c020998797da78", "0x0000000000000000000000000000000000000000000000005a107acb64952eca", "0x000000000000000000000000000000000000000000000000000031e97a575e9d", "0x00000000000000000000000000000000000000000000000b5666547acf8bd5a4", "0x00000000000000000000000000000000000000000000000c410db10a01750aeb", "0x00000000000000000000000000000000000000000000000d722669117f9758a4", "0x000000000000000000000000000000000000000000000000000178cbf4206471", "0x000000000000000000000000000000000000000000000000e91b8a11e7842c38", "0x000000000000000000000000000000000000000000000007fd51009034b3357f", "0x000000000000000000000000000000000000000000000009889939f81e9c7402", "0x0000000000000000000000000000000000000000000000000000f94656a2ca48", "0x000000000000000000000000000000000000000000000006fb128b46c1ddb67f", "0x0000000000000000000000000000000000000000000000093fe27776f50224bd", "0x000000000000000000000000000000000000000000000004a0c80c0da527a081", "0x0000000000000000000000000000000000000000000000000001b52c2020d746", "0x0000000000000000000000000000005a9bae947e1e91af9e4033d8d6aa6ed632", "0x000000000000000000000000000000000025e485e013446d4ac7981c88ba6ecc", "0x000000000000000000000000000000ff1e0496e30ab24a63b32b2d1120b76e62", "0x00000000000000000000000000000000001afe0a8a685d7cd85d1010e55d9d7c", "0x000000000000000000000000000000b0804efd6573805f991458295f510a2004", "0x00000000000000000000000000000000000c81a178016e2fe18605022d5a8b0e", "0x000000000000000000000000000000eba51e76eb1cfff60a53a0092a3c3dea47", "0x000000000000000000000000000000000022e7466247b533282f5936ac4e6c15", "0x00000000000000000000000000000071b1d76edf770edff98f00ff4deec264cd", "0x00000000000000000000000000000000001e48128e68794d8861fcbb2986a383", "0x000000000000000000000000000000d3a2af4915ae6d86b097adc377fafda2d4", "0x000000000000000000000000000000000006359de9ca452dab3a4f1f8d9c9d98", "0x0000000000000000000000000000006cf7dd96d7636fda5953191b1ad776d491", "0x00000000000000000000000000000000001633d881a08d136e834cb13a28fcc6", "0x00000000000000000000000000000001254956cff6908b069fca0e6cf1c47eb1", "0x000000000000000000000000000000000006f4d4dd3890e997e75e75886bf8f7", "0x0000000000000000000000000000006cf7dd96d7636fda5953191b1ad776d491", "0x00000000000000000000000000000000001633d881a08d136e834cb13a28fcc6", "0x00000000000000000000000000000001254956cff6908b069fca0e6cf1c47eb1", "0x000000000000000000000000000000000006f4d4dd3890e997e75e75886bf8f7", "0x000000000000000000000000000000f968b227a358a305607f3efc933823d288", "0x00000000000000000000000000000000000eaf8adb390375a76d95e918b65e08", "0x000000000000000000000000000000bb34b4b447aae56f5e24f81c3acd6d547f", "0x00000000000000000000000000000000002175d012746260ebcfe339a91a81e1", "0x00000000000000000000000000000052eebbd1f6f7554e837f60c44000ed14b6", "0x00000000000000000000000000000000001c1c045a3ec94b8801f2272cc0b3f4", "0x0000000000000000000000000000004d2ef74134578f6b431a9df071ffca4292", "0x0000000000000000000000000000000000291326ade7aa6f0dfc8900eab5580b", "0x0000000000000000000000000000002433eec6418a6dba820c9527e2581fc8bc", "0x00000000000000000000000000000000000e88b7daad19af2ac2f9bdf9e50ee2", "0x000000000000000000000000000000dcfce2c427155cc3e4d035735d3dd5ece8", "0x00000000000000000000000000000000002d7d473cac1a15d0fee8b22c1a7b3e", "0x1a4249b90be4602c8ff40c7c276160ee41b2a0f8a238ce7706e9face2db03d48", "0x162204b9d54d3ffd285c393a5a1ff76ee681474fd780a21a3cf7fac5c24fc2b9", "0x30279eb953d8ee79b2155c69c04e6443c5de6bf7e02886256dd7b3cd3c9502a4", "0x0d32c1bd21baf43e72d5d82d461ef54833807ff81a877adc822f27a6db88d754", "0x0fe15e055c0803d5ebe6dd77689b70cfd82138f008810ce24535c992daaff27d", "0x1fba82c012671212ce2fc13fd09bf8fba4f7d5875ab8d37495d1ccfcff287331", "0x090738a5842fa4d2699b3726aa0dd97cb59569b4be2c6825335ec4969f859dc2", "0x0c6cb72dabbc28abcf4a50c203534e066c29f48c24ca64d672092f263df3f9d7", "0x0f27fbea0d9145f815c288b50fe7e8c10b8185d325b5264624fd57102855d05d", "0x2a815cd3fd1c43c72ee0130465250ff771d1e7be2347e4ada331b83265a03450", "0x148b4ecf2ad7ed17409417086867ee27bc1b0906dbc9cbb3714c285071e2db70", "0x08e700a42b1d6d36ee65f8ebedf47d3a44463ff9fa579dce13b7492e20142c3a", "0x2e23c69521d572ff2152c50f8c9a9191535f4cf37f95f1e0428692e78842b642", "0x14519e0354365923fb41400c19866135b45e975d56a0980260bc99f0390b1d5f", "0x04caded1f05738f736cb5bcf08d785e395e58eb7738523a20638aa16bc51593e", "0x28787eaccd38383215ea21ec02895c32d979f68ca155f534a2e2d377bff6698b", "0x20a1b81fa96c58cf11c5762c5ceb731efdcb081fca2d34d5c463d2cf40e6da18", "0x11789a06fe3bf53833741d180f068d29534d5bb58a5c64b8119542e62b189fb4", "0x23d00fcd032ace719ffcbc513bfa177a55b04377d76455c2788d999d05d011e2", "0x01f0e81b57b4a73cc118e51ede18f8724debf25c2d109db6ef45280f99f1a3fa", "0x156d1c9b61749810de728f259c2c1c1fd4dbff97101426e26087ca461c93307c", "0x1c5d619ac3a478cfd06d5eebfd879960bb321236be173813f5e78d1366d32c69", "0x250cfae4e1dfc551406f1f3d10b649a637dcb7bcb0f6f697994cf96afd35d0c1", "0x242b999f58cf5f53c874d1092bd38725aa9ea076f5bc8f176efa9ea23393874b", "0x2e15748255c4a5e0e9fe38047341b692a967257de27a85a3a38681bc9f1602ea", "0x01ef83886ea7017253699cb6371988eb8e21b4f7023d7479ece4907fe6d4a6fd", "0x08db2dbc271e375b9312f695c59c48f313235b3432cad50921c8d9ad6dd7ad7a", "0x199309f2c2cd45c15a4abb0e6554a1615ff5a6e9488a8d900bbf835fc8f664ef", "0x074be7a3d88e31ab1b59c9208c012bcfb1f85f351c709e68134996891db52b57", "0x301b1011354d2ebf46134fc4d6d734bb6ed8542d719f38f5e09a376a580cad7f", "0x12968f3eccaa27e44f14d5aaac6ecb70c00d040e07536292e685d7cab03fc563", "0x2110a023c8c22fd2ed70270a2d0a265b92a32ce2217ffe1be9a5d7d5c25f512f", "0x1e8cf4c60c53900f0430d5b44de5804fe8b38299bc803beeb4216e1a289cf624", "0x12301cb908ccb28a2616e29b831ec7105b5d3ebf45ff5fe91d50a9dd53a50b52", "0x0f1029ed107d84ff2d6d4a416cbd01da3f3d7bf5b2209ce93ba424f4b85616fc", "0x1b431d016611b8abd684afd9e92331c3325967b1116bfa91d4f44e2f8e2c9fc2", "0x281e335a0fd117064c8ace3f01e02b134a19e9b9220571ebfaaaa0e3a12d34db", "0x22559c106f77e2ae95677d5e38e288343e3b7168371aec7d3aaab9ef8150af70", "0x13f113b1d9b590149cf08c3f6e90589cda5c7b98528866b891256cb9d5d814e7", "0x10252ef388e4c80246962e98b9e976fab2cd25e1e6f1e3fd2a7d4786c5218a97", "0x16b890723dfdebd9912a9207255f95cb800222165b6fae97ec46e461f23e83f3", "0x25caf77c7d2e8e069341ec90f3c8f6d64319cfd2d77cab0625cf0377285ba11c", "0x016c84288b0bc3c50eebbe250cdd5a4ee50b2c65a24ac64d0c930cbdecb95141", "0x20a537c045b069d47dc6315f45b391f60681222381e5059ec7c8b17bf677d911", "0x2594c0edfcd4064d215a3d797bc8e3b2f401c61f3961ae96ccbec8f8fd29e81f", "0x1c831d7047483ca00ed59bdb84c47ffb8bbebbae92aa164c7b35fcffbb8a35d3", "0x2ea7f60de52b8cd6b0bd06f861fc1f2c5ed1d1fbfa53caccdb836400a03df434", "0x275c6c8bd115f7d2ce196439e2330fad305c6745bab0bf1ce3f2fa32dadc3c43", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x2b3f4e210619347288731e7f0eea1ae60dd8696fe87319044864d099a03a9536", "0x0fecd3d2aebedeb8be2b0b7e3a74de9ec8bd2cb72851541463729e0715aef48b", "0x10bee385ad0c2cd3ff88ef4d630840749e4367f9add4a300fc4f545a7778e92c", "0x1fe792730eeafbd22c4eb80e86e2b40108b1e55b2a08db786289eea5745b9e3b", "0x04d411679da432816b213cd5580dda1fd6c2f258684c036be19b5b26baca583c", "0x159f17b655d2b8a803e0cfb564918628be52d3baa950ca1b127854491624f8f4", "0x225340463867d9252a1269013536e2e1dd219aa18eadef13c324b63d44679334", "0x1885e231554e02abb40ed54b72ebf09b883d0298a6bc06fc645a30365f370ef2", "0x233344517f25170972b8ba35d01f2df2e073d322993abce7df26796126e93498", "0x08990e8faa13b18b4433ec417c5cc596885e11ffd372d5f612c08cc79a5d5c80", "0x1e960a0c892b755c28e21dcbed816c1b182d7da43bae07f8ee622bd4485f79e7", "0x27b58e2ee290a179d349ace82752528b2ff946d60c092b99ef42f53c25d0c99f", "0x2a5cf8a3193107d982edd253002c7a52ab876b445dde8307ab78fbdca022d93c", "0x2b1ab4d5277f8c82750c1c7bd043889b71465ec64a9afc1bfa37d06b1ebd0725", "0x2a0dbf5c4373a58a83d5f2a031ea0615bf12800e33b70c3191a7cbb15966ced8", "0x1f272bb4a19d14a0abdfebc9fc83125e10623b9aef730f8d25f2bf5bead38ea9", "0x2c2339cf0ae7aff56091a568c1e2c3f01f52d8ed13400737fd31eaabcaffb9bd", "0x21f5fefe6b5fa0b5da71089befb74a1a39e52b4f830cb330c3c284e154614dfd", "0x1e6f6ba4b2444586b380dc4e2b3fad111ff1f4754420a846f53ea0789ebfb0ad", "0x1193d170b0b2dd0c4a04331a4b4aa3f12920f182ec3ab547837e30f1116ca584", "0x00000000000000000000000000000025704a15c9e2ce8a69558e7bbcdcbc7784", "0x2e5d36112770fb6c985681cafe40a8c99ad13f702309e7969801dd0ed080e727", "0x0eefc2585f591bb457183134e19ad643966272234d645514bf7868d6dd8ae2cb", "0x300803e4e2339ad39b9c31f228949bbeaf9c74b7101e7be1930b088126247eaa", "0x2bb562a50ed944b438b83b01f200101a34faef7f296a75c84c731755ebddbc1a", "0x1288e0b9c742af39cbcac21357c1b29511b0bbdd3d0e3cf5e14b2eef68a28ab3", "0x20f089131cc96d86ff1cfb67fa3f51670f4bad30158751b2587354bbec76cdf9", "0x1a26c6d3e633f9bf8434cf755b5f1217dad0d455071a97a7bcf85b824f5cf07a", "0x0d7e9b8a51fccf910ec25bdbd13e70b34bd6ea6f4d629fa744f9cdf5f2beb1cf", "0x0b40f28ce428e64df9cf5a024133fc420f39decf5f6af020cc3211ab298d4631", "0x0ca4f189dde7a55fe829f46681232904f6670249a22e0deb47222bd309523a8a", "0x2c544f2e31143783977645edb2a6bdb39b875053963bfa1a5b3ae9de204a7ebe", "0x00aae4454eb48fb18ff60db6b9d015abea2e770a2f7d86d121522b834c791ba5", "0x07d74e351fd4cccf4e18475d25211efa8a359066fc693a5c8505ddb507e4b74b", "0x07d74e351fd4cccf4e18475d25211efa8a359066fc693a5c8505ddb507e4b74b", "0x2d9e5bff47207d82533e2445959941181cc890c5779bc7f24d6e8a7b9e425b5c", "0x0aea3c0c317c441a5775a9849108d7a6889b39128235f717b09b184aa08e4eb7", "0x1ca5bc6fb37c55a562f4991901c39902f42d14db71284116df74cb4e7d55e493", "0x220fed26d64cd69f40e6d145a423e4a3c8cd0dce747e7d51647441270ad4d774", "0x15be574c9358889257aa2a30ff7b5fcc31a57da7032296e2c1201c49a44bbdb6", "0x2de539925525bedd3b7f43a9c6bf0f713151a17f79ac7ff4a9cd27b15ffe892a", "0x083086693dbf465211741e2cbff70ff38eb08383faf22d397eb2742c8ad7396a", "0x1fdfa258a890598816e807c50058d7a1462edd5ff196a2eae0f862e454b49aa1", "0x10c434c6daaa8226fa8e3e302123dfdc4455cf68063df518949df5a65a945213", "0x0000000000000000000000000000006472a7874de2c454a4591ed7784df1c104", "0x000000000000000000000000000000000008c46ac53d2c4ad0c26a5d6c790082", "0x0000000000000000000000000000005e422f9cfb8725800de60dfe0a8d4104c0", "0x000000000000000000000000000000000000f10fd4e4de81a0c00073ec91c274", "0x000000000000000000000000000000b20813090eca76bc6aa4a699b1ec8d5d6d", "0x0000000000000000000000000000000000292cc9f8a744eb00e0903c29ce87a7", "0x000000000000000000000000000000350a368b415fbb99fa90a26a42b1a3affd", "0x0000000000000000000000000000000000280eb9275cb05a3435f464d1dc369d", "0x000000000000000000000000000000280df6505e20c7725fe6d29439f96ee05d", "0x000000000000000000000000000000000017ef5033a08535451e2747827aa94b", "0x0000000000000000000000000000002f9ba89ae91b4e4a4ff8ccbd0526faad2f", "0x00000000000000000000000000000000001c2013561dafcc02cb03220bdf23c4", "0x000000000000000000000000000000aac102c400f9e5da0321ded4510994434b", "0x00000000000000000000000000000000001ec8ab9cc834b492fde124962f04a1", "0x0000000000000000000000000000000673dbd698da8b8cce450d2a083aba9987", "0x00000000000000000000000000000000000a49e55bb040249cb41c63cea901cd", "0x000000000000000000000000000000133d92af8d76ee0c74a12081ee7b2ef8c4", "0x0000000000000000000000000000000000240f552d1c6cbb007650e4b142e0a5", "0x000000000000000000000000000000e29c6e7d982ec08d51c79d6261c28d742d", "0x000000000000000000000000000000000021baeec04d9be419c923626034e7b3", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x1e940a528b42d8230e7d4dff76262a80986c0d00b2c02a9bc0559e36212d1547", "0x1ceccf21ac39f70d76ad6f7fe0dcb33b6af04555a0b1959e4714d65925e4e253", "0x096139d757046cdbdb7ee89a95f112f70882a43a46c2f739d9be115dda013420", "0x2f9c8ac67c7825b08eff0e7f7656a671f4c64e5601f2efab35b1b795801eec04", "0x2077e648e1704851cdffd7e6e56311634a7b741bab77ca34d9dff12a6a2bfe99", "0x115d48c4a97aeb3c447a060f9e0d675b0dc7f4a05a3f5776e2f279f3a165d7dc", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x000000000000000000000000000000fd38c45c3ec5b841482a80e3a56ce82555", "0x00000000000000000000000000000000000ad70b03f092f60af3e0ce1bb29d2c", "0x0000000000000000000000000000007a184d5342c90c634c0b1a050f0b97c9fb", "0x0000000000000000000000000000000000271f42abcb3bc1f0332e4b3ca85e1d", "0x0000000000000000000000000000008256322bbe2c1b8cd9d84e5ff6123477f2", "0x000000000000000000000000000000000025cab962761681dd9547f4c78814df", "0x0000000000000000000000000000008c4234510e5825c02b9ac427bcbf8e279a", "0x000000000000000000000000000000000013a14e0d7fc073c44643af38cc5396"] -public_inputs = ["0x0000000000000000000000000000000000000000000000000000000000000003"] -verification_key = ["0x0000000000000000000000000000000000000000000000000000000000000040", "0x0000000000000000000000000000000000000000000000000000000000000011", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000003", "0x0000000000000000000000000000000000000000000000000000000000000004", "0x0000000000000000000000000000000000000000000000000000000000000005", "0x0000000000000000000000000000000000000000000000000000000000000006", "0x0000000000000000000000000000000000000000000000000000000000000007", "0x0000000000000000000000000000000000000000000000000000000000000008", "0x0000000000000000000000000000000000000000000000000000000000000009", "0x000000000000000000000000000000000000000000000000000000000000000a", "0x000000000000000000000000000000000000000000000000000000000000000b", "0x000000000000000000000000000000000000000000000000000000000000000c", "0x000000000000000000000000000000000000000000000000000000000000000d", "0x000000000000000000000000000000000000000000000000000000000000000e", "0x000000000000000000000000000000000000000000000000000000000000000f", "0x0000000000000000000000000000000000000000000000000000000000000010", "0x00000000000000000000000000000060e430ad1c23bfcf3514323aae3f206e84", "0x00000000000000000000000000000000001b5c3ff4c2458d8f481b1c068f27ae", "0x000000000000000000000000000000bb510ab2112def34980e4fc6998ad9dd16", "0x00000000000000000000000000000000000576e7c105b43e061e13cb877fefe1", "0x000000000000000000000000000000ced074785d11857b065d8199e6669a601c", "0x00000000000000000000000000000000000053b48a4098c1c0ae268f273952f7", "0x000000000000000000000000000000d1d4b26e941db8168cee8f6de548ae0fd8", "0x00000000000000000000000000000000001a9adf5a6dadc3d948bb61dfd63f4c", "0x0000000000000000000000000000009ce1faac6f8de6ebb18f1db17372c82ad5", "0x00000000000000000000000000000000002002681bb417184b2df070a16a3858", "0x000000000000000000000000000000161baa651a8092e0e84725594de5aba511", "0x00000000000000000000000000000000000be0064399c2a1efff9eb0cdcb2223", "0x0000000000000000000000000000008673be6fd1bdbe980a29d8c1ded54381e7", "0x000000000000000000000000000000000008a5158a7d9648cf1d234524c9fa0c", "0x0000000000000000000000000000002b4fce6e4b1c72062b296d49bca2aa4130", "0x00000000000000000000000000000000002e45a9eff4b6769e55fb710cded44f", "0x00000000000000000000000000000072b85bf733758b76bcf97333efb85a23e3", "0x000000000000000000000000000000000017da0ea508994fc82862715e4b5592", "0x00000000000000000000000000000094fa74695cf058dba8ff35aec95456c6c3", "0x0000000000000000000000000000000000211acddb851061c24b8f159e832bd1", "0x000000000000000000000000000000303b5e5c531384b9a792e11702ad3bcab0", "0x00000000000000000000000000000000000d336dff51a60b8833d5d7f6d4314c", "0x0000000000000000000000000000009f825dde88092070747180d581c342444a", "0x0000000000000000000000000000000000237fbd6511a03cca8cac01b555fe01", "0x0000000000000000000000000000007c313205159495df6d8de292079a4844ff", "0x000000000000000000000000000000000018facdfc468530dd45e8f7a1d38ce9", "0x0000000000000000000000000000000d1ce33446fc3dc4ab40ca38d92dac74e1", "0x00000000000000000000000000000000000852d8e3e0e8f4435af3e94222688b", "0x0000000000000000000000000000006c04ee19ec1dfec87ed47d6d04aa158de2", "0x000000000000000000000000000000000013240f97a584b45184c8ec31319b5f", "0x000000000000000000000000000000cefb5d240b07ceb4be26ea429b6dc9d9e0", "0x00000000000000000000000000000000002dad22022121d689f57fb38ca21349", "0x000000000000000000000000000000c9f189f2a91aeb664ce376d8b157ba98f8", "0x00000000000000000000000000000000002531a51ad54f124d58094b219818d2", "0x000000000000000000000000000000ef1e6db71809307f677677e62b4163f556", "0x0000000000000000000000000000000000272da4396fb2a7ee0638b9140e523d", "0x0000000000000000000000000000002e54c0244a7732c87bc4712a76dd8c83fb", "0x000000000000000000000000000000000007db77b3e04b7eba9643da57cbbe4d", "0x000000000000000000000000000000e0dfe1ddd7f74ae0d636c910c3e85830d8", "0x00000000000000000000000000000000000466fa9b57ec4664abd1505b490862", "0x0000000000000000000000000000009ee55ae8a32fe5384c79907067cc27192e", "0x00000000000000000000000000000000000799d0e465cec07ecb5238c854e830", "0x0000000000000000000000000000001d5910ad361e76e1c241247a823733c39f", "0x00000000000000000000000000000000002b03f2ccf7507564da2e6678bef8fe", "0x000000000000000000000000000000ee40d90bea71fba7a412dd61fcf34e8ceb", "0x0000000000000000000000000000000000140b0936c323fd2471155617b6af56", "0x0000000000000000000000000000002b90071823185c5ff8e440fd3d73b6fefc", "0x00000000000000000000000000000000002b6c10790a5f6631c87d652e059df4", "0x00000000000000000000000000000029a17181c7934fc3fdbd352eac5cb521b9", "0x00000000000000000000000000000000001f497cbf5284ff29a2d336e5991999", "0x000000000000000000000000000000072bd9c0c6beda1fdee6d4ff0432ba9e1b", "0x000000000000000000000000000000000013ea38a0bd2aa751a490a724fac818", "0x000000000000000000000000000000c599f63dcd3edd49f08ae5c3141c1e3493", "0x00000000000000000000000000000000002bdb36be0bea09950dd32a8ccf6fbc", "0x00000000000000000000000000000047f27f29724e7f19eba0340256a0bd4b7d", "0x00000000000000000000000000000000001c1c5ccf87a962129ca785f8f35120", "0x000000000000000000000000000000c5c71efdae00679bbe4a95096e012b1817", "0x000000000000000000000000000000000017a365de041e317817d0135f2b48e0", "0x0000000000000000000000000000008ae711ac402f7848d719c93a89ba8d39f1", "0x00000000000000000000000000000000002b6fb40ed8a1935226f4f9786a0499", "0x0000000000000000000000000000002f03a71501d83de1da5715a4e9462d6198", "0x00000000000000000000000000000000001644064443b8546f48eae693af47b8", "0x00000000000000000000000000000083763ab1b6e8fe269b2fe4c7b9c448c08d", "0x000000000000000000000000000000000021d7cc18c59676a8eeb47c0111c251", "0x000000000000000000000000000000b5f937153073e03ea7d51a996e0ebc2e6b", "0x000000000000000000000000000000000011ddd0e26457373eb06e0493177672", "0x000000000000000000000000000000c5f6eb9f6fc8fa99811a4a88c74a6d018b", "0x000000000000000000000000000000000025bcd07a0732c123567834f5109558", "0x000000000000000000000000000000aeb08a0b1a4442189448b4e97490568146", "0x000000000000000000000000000000000002a1744e4771705536a88f07e0f90f", "0x000000000000000000000000000000b938568293bd0724b0ea76c2ec34c4a829", "0x0000000000000000000000000000000000053296e8f3b9ad3af877dfa9c7c2a7", "0x000000000000000000000000000000f0ca1db6323996eba26bdc86dafef9d10b", "0x00000000000000000000000000000000001441a46c58af03d5645d52721d956a", "0x0000000000000000000000000000008bbf8f884013c66c28ba09c2fbd573b656", "0x0000000000000000000000000000000000206c391ca06fac27d1908e94570243", "0x0000000000000000000000000000002d4f5aaed88ba4f79612d53b804ca8f194", "0x00000000000000000000000000000000001674011c96392df08970fa6b7b4cb8", "0x0000000000000000000000000000009f88297c1729d76c4d9306853598c91325", "0x0000000000000000000000000000000000256f51adfcacc3c1e340be4d32d3e9", "0x0000000000000000000000000000000ab9955eec0d74eb799afed2a802b24d75", "0x00000000000000000000000000000000001fcbe43ea105b30d36ed0b21b03411", "0x000000000000000000000000000000d66b1d5433f1aa5305cd1edce7c22de466", "0x00000000000000000000000000000000002331546a256b8a3b751956806680d4", "0x000000000000000000000000000000e97954ad6cd6f45fb15c91434121db4304", "0x00000000000000000000000000000000002e20a97e09d50f227ced47e7a98250", "0x0000000000000000000000000000001ebbc27eb9ebededefba79522eb58ae89b", "0x0000000000000000000000000000000000090efa4974e566e81d1177b85a30be", "0x0000000000000000000000000000005eafa070b9c9632404052642e3bc14f9fd", "0x00000000000000000000000000000000001489068864102daca6a6b8bc4d448b", "0x0000000000000000000000000000009ebc91aaaac036a6477cadbe54e8556dfd", "0x00000000000000000000000000000000000ef6d835e2ed3343b95c82c8c54037", "0x00000000000000000000000000000033b28b529dff46e93af4e7422530478e4a", "0x000000000000000000000000000000000020a86c2f8591bf190bcddcc03c42fb", "0x000000000000000000000000000000a9679d0acc088f7dc27bf6d866bcd2dda2", "0x00000000000000000000000000000000002fb9d0d2d4099402bed74f738f64cc", "0x00000000000000000000000000000023b09f876a29a061582848a8b9a5870c12", "0x00000000000000000000000000000000001d5bb906f03f0d49e9c4791bc43af9", "0x00000000000000000000000000000017aac9854ea240d8ec97bf760c4d4ba870", "0x00000000000000000000000000000000000b227a556c414ada0dc75bb303e30e", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000009b624fa65d1a24b7f14a8f25f3789622af", "0x000000000000000000000000000000000013d47bff8c630e847b70e2732fd3f0", "0x00000000000000000000000000000061d21663e93132f32921075f4c936a84df", "0x00000000000000000000000000000000001a74ca4e118fb480b9b999902989a3"] -proof_b = ["0x0000000000000000000000000000000000000000000000000000000000000040", "0x0000000000000000000000000000000000000000000000000000000000000011", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000042ab5d6d1986846cf", "0x00000000000000000000000000000000000000000000000b75c020998797da78", "0x0000000000000000000000000000000000000000000000005a107acb64952eca", "0x000000000000000000000000000000000000000000000000000031e97a575e9d", "0x00000000000000000000000000000000000000000000000b5666547acf8bd5a4", "0x00000000000000000000000000000000000000000000000c410db10a01750aeb", "0x00000000000000000000000000000000000000000000000d722669117f9758a4", "0x000000000000000000000000000000000000000000000000000178cbf4206471", "0x000000000000000000000000000000000000000000000000e91b8a11e7842c38", "0x000000000000000000000000000000000000000000000007fd51009034b3357f", "0x000000000000000000000000000000000000000000000009889939f81e9c7402", "0x0000000000000000000000000000000000000000000000000000f94656a2ca48", "0x000000000000000000000000000000000000000000000006fb128b46c1ddb67f", "0x0000000000000000000000000000000000000000000000093fe27776f50224bd", "0x000000000000000000000000000000000000000000000004a0c80c0da527a081", "0x0000000000000000000000000000000000000000000000000001b52c2020d746", "0x0000000000000000000000000000005a9bae947e1e91af9e4033d8d6aa6ed632", "0x000000000000000000000000000000000025e485e013446d4ac7981c88ba6ecc", "0x000000000000000000000000000000ff1e0496e30ab24a63b32b2d1120b76e62", "0x00000000000000000000000000000000001afe0a8a685d7cd85d1010e55d9d7c", "0x000000000000000000000000000000b0804efd6573805f991458295f510a2004", "0x00000000000000000000000000000000000c81a178016e2fe18605022d5a8b0e", "0x000000000000000000000000000000eba51e76eb1cfff60a53a0092a3c3dea47", "0x000000000000000000000000000000000022e7466247b533282f5936ac4e6c15", "0x00000000000000000000000000000071b1d76edf770edff98f00ff4deec264cd", "0x00000000000000000000000000000000001e48128e68794d8861fcbb2986a383", "0x000000000000000000000000000000d3a2af4915ae6d86b097adc377fafda2d4", "0x000000000000000000000000000000000006359de9ca452dab3a4f1f8d9c9d98", "0x0000000000000000000000000000006cf7dd96d7636fda5953191b1ad776d491", "0x00000000000000000000000000000000001633d881a08d136e834cb13a28fcc6", "0x00000000000000000000000000000001254956cff6908b069fca0e6cf1c47eb1", "0x000000000000000000000000000000000006f4d4dd3890e997e75e75886bf8f7", "0x0000000000000000000000000000006cf7dd96d7636fda5953191b1ad776d491", "0x00000000000000000000000000000000001633d881a08d136e834cb13a28fcc6", "0x00000000000000000000000000000001254956cff6908b069fca0e6cf1c47eb1", "0x000000000000000000000000000000000006f4d4dd3890e997e75e75886bf8f7", "0x000000000000000000000000000000f968b227a358a305607f3efc933823d288", "0x00000000000000000000000000000000000eaf8adb390375a76d95e918b65e08", "0x000000000000000000000000000000bb34b4b447aae56f5e24f81c3acd6d547f", "0x00000000000000000000000000000000002175d012746260ebcfe339a91a81e1", "0x00000000000000000000000000000052eebbd1f6f7554e837f60c44000ed14b6", "0x00000000000000000000000000000000001c1c045a3ec94b8801f2272cc0b3f4", "0x0000000000000000000000000000004d2ef74134578f6b431a9df071ffca4292", "0x0000000000000000000000000000000000291326ade7aa6f0dfc8900eab5580b", "0x0000000000000000000000000000002433eec6418a6dba820c9527e2581fc8bc", "0x00000000000000000000000000000000000e88b7daad19af2ac2f9bdf9e50ee2", "0x000000000000000000000000000000dcfce2c427155cc3e4d035735d3dd5ece8", "0x00000000000000000000000000000000002d7d473cac1a15d0fee8b22c1a7b3e", "0x1a4249b90be4602c8ff40c7c276160ee41b2a0f8a238ce7706e9face2db03d48", "0x162204b9d54d3ffd285c393a5a1ff76ee681474fd780a21a3cf7fac5c24fc2b9", "0x30279eb953d8ee79b2155c69c04e6443c5de6bf7e02886256dd7b3cd3c9502a4", "0x0d32c1bd21baf43e72d5d82d461ef54833807ff81a877adc822f27a6db88d754", "0x0fe15e055c0803d5ebe6dd77689b70cfd82138f008810ce24535c992daaff27d", "0x1fba82c012671212ce2fc13fd09bf8fba4f7d5875ab8d37495d1ccfcff287331", "0x090738a5842fa4d2699b3726aa0dd97cb59569b4be2c6825335ec4969f859dc2", "0x0c6cb72dabbc28abcf4a50c203534e066c29f48c24ca64d672092f263df3f9d7", "0x0f27fbea0d9145f815c288b50fe7e8c10b8185d325b5264624fd57102855d05d", "0x2a815cd3fd1c43c72ee0130465250ff771d1e7be2347e4ada331b83265a03450", "0x148b4ecf2ad7ed17409417086867ee27bc1b0906dbc9cbb3714c285071e2db70", "0x08e700a42b1d6d36ee65f8ebedf47d3a44463ff9fa579dce13b7492e20142c3a", "0x2e23c69521d572ff2152c50f8c9a9191535f4cf37f95f1e0428692e78842b642", "0x14519e0354365923fb41400c19866135b45e975d56a0980260bc99f0390b1d5f", "0x04caded1f05738f736cb5bcf08d785e395e58eb7738523a20638aa16bc51593e", "0x28787eaccd38383215ea21ec02895c32d979f68ca155f534a2e2d377bff6698b", "0x20a1b81fa96c58cf11c5762c5ceb731efdcb081fca2d34d5c463d2cf40e6da18", "0x11789a06fe3bf53833741d180f068d29534d5bb58a5c64b8119542e62b189fb4", "0x23d00fcd032ace719ffcbc513bfa177a55b04377d76455c2788d999d05d011e2", "0x01f0e81b57b4a73cc118e51ede18f8724debf25c2d109db6ef45280f99f1a3fa", "0x156d1c9b61749810de728f259c2c1c1fd4dbff97101426e26087ca461c93307c", "0x1c5d619ac3a478cfd06d5eebfd879960bb321236be173813f5e78d1366d32c69", "0x250cfae4e1dfc551406f1f3d10b649a637dcb7bcb0f6f697994cf96afd35d0c1", "0x242b999f58cf5f53c874d1092bd38725aa9ea076f5bc8f176efa9ea23393874b", "0x2e15748255c4a5e0e9fe38047341b692a967257de27a85a3a38681bc9f1602ea", "0x01ef83886ea7017253699cb6371988eb8e21b4f7023d7479ece4907fe6d4a6fd", "0x08db2dbc271e375b9312f695c59c48f313235b3432cad50921c8d9ad6dd7ad7a", "0x199309f2c2cd45c15a4abb0e6554a1615ff5a6e9488a8d900bbf835fc8f664ef", "0x074be7a3d88e31ab1b59c9208c012bcfb1f85f351c709e68134996891db52b57", "0x301b1011354d2ebf46134fc4d6d734bb6ed8542d719f38f5e09a376a580cad7f", "0x12968f3eccaa27e44f14d5aaac6ecb70c00d040e07536292e685d7cab03fc563", "0x2110a023c8c22fd2ed70270a2d0a265b92a32ce2217ffe1be9a5d7d5c25f512f", "0x1e8cf4c60c53900f0430d5b44de5804fe8b38299bc803beeb4216e1a289cf624", "0x12301cb908ccb28a2616e29b831ec7105b5d3ebf45ff5fe91d50a9dd53a50b52", "0x0f1029ed107d84ff2d6d4a416cbd01da3f3d7bf5b2209ce93ba424f4b85616fc", "0x1b431d016611b8abd684afd9e92331c3325967b1116bfa91d4f44e2f8e2c9fc2", "0x281e335a0fd117064c8ace3f01e02b134a19e9b9220571ebfaaaa0e3a12d34db", "0x22559c106f77e2ae95677d5e38e288343e3b7168371aec7d3aaab9ef8150af70", "0x13f113b1d9b590149cf08c3f6e90589cda5c7b98528866b891256cb9d5d814e7", "0x10252ef388e4c80246962e98b9e976fab2cd25e1e6f1e3fd2a7d4786c5218a97", "0x16b890723dfdebd9912a9207255f95cb800222165b6fae97ec46e461f23e83f3", "0x25caf77c7d2e8e069341ec90f3c8f6d64319cfd2d77cab0625cf0377285ba11c", "0x016c84288b0bc3c50eebbe250cdd5a4ee50b2c65a24ac64d0c930cbdecb95141", "0x20a537c045b069d47dc6315f45b391f60681222381e5059ec7c8b17bf677d911", "0x2594c0edfcd4064d215a3d797bc8e3b2f401c61f3961ae96ccbec8f8fd29e81f", "0x1c831d7047483ca00ed59bdb84c47ffb8bbebbae92aa164c7b35fcffbb8a35d3", "0x2ea7f60de52b8cd6b0bd06f861fc1f2c5ed1d1fbfa53caccdb836400a03df434", "0x275c6c8bd115f7d2ce196439e2330fad305c6745bab0bf1ce3f2fa32dadc3c43", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x2b3f4e210619347288731e7f0eea1ae60dd8696fe87319044864d099a03a9536", "0x0fecd3d2aebedeb8be2b0b7e3a74de9ec8bd2cb72851541463729e0715aef48b", "0x10bee385ad0c2cd3ff88ef4d630840749e4367f9add4a300fc4f545a7778e92c", "0x1fe792730eeafbd22c4eb80e86e2b40108b1e55b2a08db786289eea5745b9e3b", "0x04d411679da432816b213cd5580dda1fd6c2f258684c036be19b5b26baca583c", "0x159f17b655d2b8a803e0cfb564918628be52d3baa950ca1b127854491624f8f4", "0x225340463867d9252a1269013536e2e1dd219aa18eadef13c324b63d44679334", "0x1885e231554e02abb40ed54b72ebf09b883d0298a6bc06fc645a30365f370ef2", "0x233344517f25170972b8ba35d01f2df2e073d322993abce7df26796126e93498", "0x08990e8faa13b18b4433ec417c5cc596885e11ffd372d5f612c08cc79a5d5c80", "0x1e960a0c892b755c28e21dcbed816c1b182d7da43bae07f8ee622bd4485f79e7", "0x27b58e2ee290a179d349ace82752528b2ff946d60c092b99ef42f53c25d0c99f", "0x2a5cf8a3193107d982edd253002c7a52ab876b445dde8307ab78fbdca022d93c", "0x2b1ab4d5277f8c82750c1c7bd043889b71465ec64a9afc1bfa37d06b1ebd0725", "0x2a0dbf5c4373a58a83d5f2a031ea0615bf12800e33b70c3191a7cbb15966ced8", "0x1f272bb4a19d14a0abdfebc9fc83125e10623b9aef730f8d25f2bf5bead38ea9", "0x2c2339cf0ae7aff56091a568c1e2c3f01f52d8ed13400737fd31eaabcaffb9bd", "0x21f5fefe6b5fa0b5da71089befb74a1a39e52b4f830cb330c3c284e154614dfd", "0x1e6f6ba4b2444586b380dc4e2b3fad111ff1f4754420a846f53ea0789ebfb0ad", "0x1193d170b0b2dd0c4a04331a4b4aa3f12920f182ec3ab547837e30f1116ca584", "0x00000000000000000000000000000025704a15c9e2ce8a69558e7bbcdcbc7784", "0x2e5d36112770fb6c985681cafe40a8c99ad13f702309e7969801dd0ed080e727", "0x0eefc2585f591bb457183134e19ad643966272234d645514bf7868d6dd8ae2cb", "0x300803e4e2339ad39b9c31f228949bbeaf9c74b7101e7be1930b088126247eaa", "0x2bb562a50ed944b438b83b01f200101a34faef7f296a75c84c731755ebddbc1a", "0x1288e0b9c742af39cbcac21357c1b29511b0bbdd3d0e3cf5e14b2eef68a28ab3", "0x20f089131cc96d86ff1cfb67fa3f51670f4bad30158751b2587354bbec76cdf9", "0x1a26c6d3e633f9bf8434cf755b5f1217dad0d455071a97a7bcf85b824f5cf07a", "0x0d7e9b8a51fccf910ec25bdbd13e70b34bd6ea6f4d629fa744f9cdf5f2beb1cf", "0x0b40f28ce428e64df9cf5a024133fc420f39decf5f6af020cc3211ab298d4631", "0x0ca4f189dde7a55fe829f46681232904f6670249a22e0deb47222bd309523a8a", "0x2c544f2e31143783977645edb2a6bdb39b875053963bfa1a5b3ae9de204a7ebe", "0x00aae4454eb48fb18ff60db6b9d015abea2e770a2f7d86d121522b834c791ba5", "0x07d74e351fd4cccf4e18475d25211efa8a359066fc693a5c8505ddb507e4b74b", "0x07d74e351fd4cccf4e18475d25211efa8a359066fc693a5c8505ddb507e4b74b", "0x2d9e5bff47207d82533e2445959941181cc890c5779bc7f24d6e8a7b9e425b5c", "0x0aea3c0c317c441a5775a9849108d7a6889b39128235f717b09b184aa08e4eb7", "0x1ca5bc6fb37c55a562f4991901c39902f42d14db71284116df74cb4e7d55e493", "0x220fed26d64cd69f40e6d145a423e4a3c8cd0dce747e7d51647441270ad4d774", "0x15be574c9358889257aa2a30ff7b5fcc31a57da7032296e2c1201c49a44bbdb6", "0x2de539925525bedd3b7f43a9c6bf0f713151a17f79ac7ff4a9cd27b15ffe892a", "0x083086693dbf465211741e2cbff70ff38eb08383faf22d397eb2742c8ad7396a", "0x1fdfa258a890598816e807c50058d7a1462edd5ff196a2eae0f862e454b49aa1", "0x10c434c6daaa8226fa8e3e302123dfdc4455cf68063df518949df5a65a945213", "0x0000000000000000000000000000006472a7874de2c454a4591ed7784df1c104", "0x000000000000000000000000000000000008c46ac53d2c4ad0c26a5d6c790082", "0x0000000000000000000000000000005e422f9cfb8725800de60dfe0a8d4104c0", "0x000000000000000000000000000000000000f10fd4e4de81a0c00073ec91c274", "0x000000000000000000000000000000b20813090eca76bc6aa4a699b1ec8d5d6d", "0x0000000000000000000000000000000000292cc9f8a744eb00e0903c29ce87a7", "0x000000000000000000000000000000350a368b415fbb99fa90a26a42b1a3affd", "0x0000000000000000000000000000000000280eb9275cb05a3435f464d1dc369d", "0x000000000000000000000000000000280df6505e20c7725fe6d29439f96ee05d", "0x000000000000000000000000000000000017ef5033a08535451e2747827aa94b", "0x0000000000000000000000000000002f9ba89ae91b4e4a4ff8ccbd0526faad2f", "0x00000000000000000000000000000000001c2013561dafcc02cb03220bdf23c4", "0x000000000000000000000000000000aac102c400f9e5da0321ded4510994434b", "0x00000000000000000000000000000000001ec8ab9cc834b492fde124962f04a1", "0x0000000000000000000000000000000673dbd698da8b8cce450d2a083aba9987", "0x00000000000000000000000000000000000a49e55bb040249cb41c63cea901cd", "0x000000000000000000000000000000133d92af8d76ee0c74a12081ee7b2ef8c4", "0x0000000000000000000000000000000000240f552d1c6cbb007650e4b142e0a5", "0x000000000000000000000000000000e29c6e7d982ec08d51c79d6261c28d742d", "0x000000000000000000000000000000000021baeec04d9be419c923626034e7b3", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x1e940a528b42d8230e7d4dff76262a80986c0d00b2c02a9bc0559e36212d1547", "0x1ceccf21ac39f70d76ad6f7fe0dcb33b6af04555a0b1959e4714d65925e4e253", "0x096139d757046cdbdb7ee89a95f112f70882a43a46c2f739d9be115dda013420", "0x2f9c8ac67c7825b08eff0e7f7656a671f4c64e5601f2efab35b1b795801eec04", "0x2077e648e1704851cdffd7e6e56311634a7b741bab77ca34d9dff12a6a2bfe99", "0x115d48c4a97aeb3c447a060f9e0d675b0dc7f4a05a3f5776e2f279f3a165d7dc", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x000000000000000000000000000000fd38c45c3ec5b841482a80e3a56ce82555", "0x00000000000000000000000000000000000ad70b03f092f60af3e0ce1bb29d2c", "0x0000000000000000000000000000007a184d5342c90c634c0b1a050f0b97c9fb", "0x0000000000000000000000000000000000271f42abcb3bc1f0332e4b3ca85e1d", "0x0000000000000000000000000000008256322bbe2c1b8cd9d84e5ff6123477f2", "0x000000000000000000000000000000000025cab962761681dd9547f4c78814df", "0x0000000000000000000000000000008c4234510e5825c02b9ac427bcbf8e279a", "0x000000000000000000000000000000000013a14e0d7fc073c44643af38cc5396"] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/double_verify_honk_proof_recursive/src/main.nr b/noir/noir-repo/test_programs/execution_success/double_verify_honk_proof_recursive/src/main.nr deleted file mode 100644 index 63902824da1..00000000000 --- a/noir/noir-repo/test_programs/execution_success/double_verify_honk_proof_recursive/src/main.nr +++ /dev/null @@ -1,29 +0,0 @@ -// This circuit aggregates two Honk proofs from `assert_statement_recursive`. -global SIZE_OF_PROOF_IF_LOGN_IS_28: u32 = 463; -global HONK_IDENTIFIER: u32 = 1; -#[recursive] -fn main( - verification_key: [Field; 128], - // This is the proof without public inputs attached. - // This means: the size of this does not change with the number of public inputs. - proof: [Field; SIZE_OF_PROOF_IF_LOGN_IS_28], - public_inputs: pub [Field; 1], - key_hash: Field, - // The second proof, currently set to be identical to the first proof - proof_b: [Field; SIZE_OF_PROOF_IF_LOGN_IS_28], -) { - std::verify_proof_with_type( - verification_key, - proof, - public_inputs, - key_hash, - HONK_IDENTIFIER, - ); - std::verify_proof_with_type( - verification_key, - proof_b, - public_inputs, - key_hash, - HONK_IDENTIFIER, - ); -} diff --git a/noir/noir-repo/test_programs/execution_success/fmtstr_with_global/Nargo.toml b/noir/noir-repo/test_programs/execution_success/fmtstr_with_global/Nargo.toml new file mode 100644 index 00000000000..889683f7410 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/fmtstr_with_global/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "fmtstr_with_global" +type = "bin" +authors = [""] +compiler_version = ">=0.32.0" + +[dependencies] diff --git a/noir/noir-repo/test_programs/execution_success/fmtstr_with_global/src/main.nr b/noir/noir-repo/test_programs/execution_success/fmtstr_with_global/src/main.nr new file mode 100644 index 00000000000..8b9c9635015 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/fmtstr_with_global/src/main.nr @@ -0,0 +1,5 @@ +global FOO = 1; + +fn main() { + println(f"foo = {FOO}"); +} diff --git a/noir/noir-repo/test_programs/execution_success/higher_order_functions/src/main.nr b/noir/noir-repo/test_programs/execution_success/higher_order_functions/src/main.nr index 6d094946f6c..1f9598f8591 100644 --- a/noir/noir-repo/test_programs/execution_success/higher_order_functions/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/higher_order_functions/src/main.nr @@ -5,7 +5,7 @@ fn main(w: Field) -> pub Field { assert(twice(|x| x * 2, 5) == 20); assert((|x, y| x + y + 1)(2, 3) == 6); // nested lambdas - assert((|a, b| { a + (|c| c + 2)(b) })(0, 1) == 3); + assert((|a, b| a + (|c| c + 2)(b))(0, 1) == 3); // Closures: let a = 42; let g = || a; diff --git a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Nargo.toml b/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Nargo.toml deleted file mode 100644 index 8fce1bf44b6..00000000000 --- a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Nargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "verify_honk_proof" -type = "bin" -authors = [""] - -[dependencies] diff --git a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml b/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml deleted file mode 100644 index 45a84c26eb8..00000000000 --- a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml +++ /dev/null @@ -1,4 +0,0 @@ -key_hash = "0x0000000000000000000000000000000000000000000000000000000000000000" -proof = ["0x0000000000000000000000000000000000000000000000000000000000000040", "0x0000000000000000000000000000000000000000000000000000000000000011", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000042ab5d6d1986846cf", "0x00000000000000000000000000000000000000000000000b75c020998797da78", "0x0000000000000000000000000000000000000000000000005a107acb64952eca", "0x000000000000000000000000000000000000000000000000000031e97a575e9d", "0x00000000000000000000000000000000000000000000000b5666547acf8bd5a4", "0x00000000000000000000000000000000000000000000000c410db10a01750aeb", "0x00000000000000000000000000000000000000000000000d722669117f9758a4", "0x000000000000000000000000000000000000000000000000000178cbf4206471", "0x000000000000000000000000000000000000000000000000e91b8a11e7842c38", "0x000000000000000000000000000000000000000000000007fd51009034b3357f", "0x000000000000000000000000000000000000000000000009889939f81e9c7402", "0x0000000000000000000000000000000000000000000000000000f94656a2ca48", "0x000000000000000000000000000000000000000000000006fb128b46c1ddb67f", "0x0000000000000000000000000000000000000000000000093fe27776f50224bd", "0x000000000000000000000000000000000000000000000004a0c80c0da527a081", "0x0000000000000000000000000000000000000000000000000001b52c2020d746", "0x0000000000000000000000000000005a9bae947e1e91af9e4033d8d6aa6ed632", "0x000000000000000000000000000000000025e485e013446d4ac7981c88ba6ecc", "0x000000000000000000000000000000ff1e0496e30ab24a63b32b2d1120b76e62", "0x00000000000000000000000000000000001afe0a8a685d7cd85d1010e55d9d7c", "0x000000000000000000000000000000b0804efd6573805f991458295f510a2004", "0x00000000000000000000000000000000000c81a178016e2fe18605022d5a8b0e", "0x000000000000000000000000000000eba51e76eb1cfff60a53a0092a3c3dea47", "0x000000000000000000000000000000000022e7466247b533282f5936ac4e6c15", "0x00000000000000000000000000000071b1d76edf770edff98f00ff4deec264cd", "0x00000000000000000000000000000000001e48128e68794d8861fcbb2986a383", "0x000000000000000000000000000000d3a2af4915ae6d86b097adc377fafda2d4", "0x000000000000000000000000000000000006359de9ca452dab3a4f1f8d9c9d98", "0x0000000000000000000000000000006cf7dd96d7636fda5953191b1ad776d491", "0x00000000000000000000000000000000001633d881a08d136e834cb13a28fcc6", "0x00000000000000000000000000000001254956cff6908b069fca0e6cf1c47eb1", "0x000000000000000000000000000000000006f4d4dd3890e997e75e75886bf8f7", "0x0000000000000000000000000000006cf7dd96d7636fda5953191b1ad776d491", "0x00000000000000000000000000000000001633d881a08d136e834cb13a28fcc6", "0x00000000000000000000000000000001254956cff6908b069fca0e6cf1c47eb1", "0x000000000000000000000000000000000006f4d4dd3890e997e75e75886bf8f7", "0x000000000000000000000000000000f968b227a358a305607f3efc933823d288", "0x00000000000000000000000000000000000eaf8adb390375a76d95e918b65e08", "0x000000000000000000000000000000bb34b4b447aae56f5e24f81c3acd6d547f", "0x00000000000000000000000000000000002175d012746260ebcfe339a91a81e1", "0x00000000000000000000000000000052eebbd1f6f7554e837f60c44000ed14b6", "0x00000000000000000000000000000000001c1c045a3ec94b8801f2272cc0b3f4", "0x0000000000000000000000000000004d2ef74134578f6b431a9df071ffca4292", "0x0000000000000000000000000000000000291326ade7aa6f0dfc8900eab5580b", "0x0000000000000000000000000000002433eec6418a6dba820c9527e2581fc8bc", "0x00000000000000000000000000000000000e88b7daad19af2ac2f9bdf9e50ee2", "0x000000000000000000000000000000dcfce2c427155cc3e4d035735d3dd5ece8", "0x00000000000000000000000000000000002d7d473cac1a15d0fee8b22c1a7b3e", "0x1a4249b90be4602c8ff40c7c276160ee41b2a0f8a238ce7706e9face2db03d48", "0x162204b9d54d3ffd285c393a5a1ff76ee681474fd780a21a3cf7fac5c24fc2b9", "0x30279eb953d8ee79b2155c69c04e6443c5de6bf7e02886256dd7b3cd3c9502a4", "0x0d32c1bd21baf43e72d5d82d461ef54833807ff81a877adc822f27a6db88d754", "0x0fe15e055c0803d5ebe6dd77689b70cfd82138f008810ce24535c992daaff27d", "0x1fba82c012671212ce2fc13fd09bf8fba4f7d5875ab8d37495d1ccfcff287331", "0x090738a5842fa4d2699b3726aa0dd97cb59569b4be2c6825335ec4969f859dc2", "0x0c6cb72dabbc28abcf4a50c203534e066c29f48c24ca64d672092f263df3f9d7", "0x0f27fbea0d9145f815c288b50fe7e8c10b8185d325b5264624fd57102855d05d", "0x2a815cd3fd1c43c72ee0130465250ff771d1e7be2347e4ada331b83265a03450", "0x148b4ecf2ad7ed17409417086867ee27bc1b0906dbc9cbb3714c285071e2db70", "0x08e700a42b1d6d36ee65f8ebedf47d3a44463ff9fa579dce13b7492e20142c3a", "0x2e23c69521d572ff2152c50f8c9a9191535f4cf37f95f1e0428692e78842b642", "0x14519e0354365923fb41400c19866135b45e975d56a0980260bc99f0390b1d5f", "0x04caded1f05738f736cb5bcf08d785e395e58eb7738523a20638aa16bc51593e", "0x28787eaccd38383215ea21ec02895c32d979f68ca155f534a2e2d377bff6698b", "0x20a1b81fa96c58cf11c5762c5ceb731efdcb081fca2d34d5c463d2cf40e6da18", "0x11789a06fe3bf53833741d180f068d29534d5bb58a5c64b8119542e62b189fb4", "0x23d00fcd032ace719ffcbc513bfa177a55b04377d76455c2788d999d05d011e2", "0x01f0e81b57b4a73cc118e51ede18f8724debf25c2d109db6ef45280f99f1a3fa", "0x156d1c9b61749810de728f259c2c1c1fd4dbff97101426e26087ca461c93307c", "0x1c5d619ac3a478cfd06d5eebfd879960bb321236be173813f5e78d1366d32c69", "0x250cfae4e1dfc551406f1f3d10b649a637dcb7bcb0f6f697994cf96afd35d0c1", "0x242b999f58cf5f53c874d1092bd38725aa9ea076f5bc8f176efa9ea23393874b", "0x2e15748255c4a5e0e9fe38047341b692a967257de27a85a3a38681bc9f1602ea", "0x01ef83886ea7017253699cb6371988eb8e21b4f7023d7479ece4907fe6d4a6fd", "0x08db2dbc271e375b9312f695c59c48f313235b3432cad50921c8d9ad6dd7ad7a", "0x199309f2c2cd45c15a4abb0e6554a1615ff5a6e9488a8d900bbf835fc8f664ef", "0x074be7a3d88e31ab1b59c9208c012bcfb1f85f351c709e68134996891db52b57", "0x301b1011354d2ebf46134fc4d6d734bb6ed8542d719f38f5e09a376a580cad7f", "0x12968f3eccaa27e44f14d5aaac6ecb70c00d040e07536292e685d7cab03fc563", "0x2110a023c8c22fd2ed70270a2d0a265b92a32ce2217ffe1be9a5d7d5c25f512f", "0x1e8cf4c60c53900f0430d5b44de5804fe8b38299bc803beeb4216e1a289cf624", "0x12301cb908ccb28a2616e29b831ec7105b5d3ebf45ff5fe91d50a9dd53a50b52", "0x0f1029ed107d84ff2d6d4a416cbd01da3f3d7bf5b2209ce93ba424f4b85616fc", "0x1b431d016611b8abd684afd9e92331c3325967b1116bfa91d4f44e2f8e2c9fc2", "0x281e335a0fd117064c8ace3f01e02b134a19e9b9220571ebfaaaa0e3a12d34db", "0x22559c106f77e2ae95677d5e38e288343e3b7168371aec7d3aaab9ef8150af70", "0x13f113b1d9b590149cf08c3f6e90589cda5c7b98528866b891256cb9d5d814e7", "0x10252ef388e4c80246962e98b9e976fab2cd25e1e6f1e3fd2a7d4786c5218a97", "0x16b890723dfdebd9912a9207255f95cb800222165b6fae97ec46e461f23e83f3", "0x25caf77c7d2e8e069341ec90f3c8f6d64319cfd2d77cab0625cf0377285ba11c", "0x016c84288b0bc3c50eebbe250cdd5a4ee50b2c65a24ac64d0c930cbdecb95141", "0x20a537c045b069d47dc6315f45b391f60681222381e5059ec7c8b17bf677d911", "0x2594c0edfcd4064d215a3d797bc8e3b2f401c61f3961ae96ccbec8f8fd29e81f", "0x1c831d7047483ca00ed59bdb84c47ffb8bbebbae92aa164c7b35fcffbb8a35d3", "0x2ea7f60de52b8cd6b0bd06f861fc1f2c5ed1d1fbfa53caccdb836400a03df434", "0x275c6c8bd115f7d2ce196439e2330fad305c6745bab0bf1ce3f2fa32dadc3c43", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x2b3f4e210619347288731e7f0eea1ae60dd8696fe87319044864d099a03a9536", "0x0fecd3d2aebedeb8be2b0b7e3a74de9ec8bd2cb72851541463729e0715aef48b", "0x10bee385ad0c2cd3ff88ef4d630840749e4367f9add4a300fc4f545a7778e92c", "0x1fe792730eeafbd22c4eb80e86e2b40108b1e55b2a08db786289eea5745b9e3b", "0x04d411679da432816b213cd5580dda1fd6c2f258684c036be19b5b26baca583c", "0x159f17b655d2b8a803e0cfb564918628be52d3baa950ca1b127854491624f8f4", "0x225340463867d9252a1269013536e2e1dd219aa18eadef13c324b63d44679334", "0x1885e231554e02abb40ed54b72ebf09b883d0298a6bc06fc645a30365f370ef2", "0x233344517f25170972b8ba35d01f2df2e073d322993abce7df26796126e93498", "0x08990e8faa13b18b4433ec417c5cc596885e11ffd372d5f612c08cc79a5d5c80", "0x1e960a0c892b755c28e21dcbed816c1b182d7da43bae07f8ee622bd4485f79e7", "0x27b58e2ee290a179d349ace82752528b2ff946d60c092b99ef42f53c25d0c99f", "0x2a5cf8a3193107d982edd253002c7a52ab876b445dde8307ab78fbdca022d93c", "0x2b1ab4d5277f8c82750c1c7bd043889b71465ec64a9afc1bfa37d06b1ebd0725", "0x2a0dbf5c4373a58a83d5f2a031ea0615bf12800e33b70c3191a7cbb15966ced8", "0x1f272bb4a19d14a0abdfebc9fc83125e10623b9aef730f8d25f2bf5bead38ea9", "0x2c2339cf0ae7aff56091a568c1e2c3f01f52d8ed13400737fd31eaabcaffb9bd", "0x21f5fefe6b5fa0b5da71089befb74a1a39e52b4f830cb330c3c284e154614dfd", "0x1e6f6ba4b2444586b380dc4e2b3fad111ff1f4754420a846f53ea0789ebfb0ad", "0x1193d170b0b2dd0c4a04331a4b4aa3f12920f182ec3ab547837e30f1116ca584", "0x00000000000000000000000000000025704a15c9e2ce8a69558e7bbcdcbc7784", "0x2e5d36112770fb6c985681cafe40a8c99ad13f702309e7969801dd0ed080e727", "0x0eefc2585f591bb457183134e19ad643966272234d645514bf7868d6dd8ae2cb", "0x300803e4e2339ad39b9c31f228949bbeaf9c74b7101e7be1930b088126247eaa", "0x2bb562a50ed944b438b83b01f200101a34faef7f296a75c84c731755ebddbc1a", "0x1288e0b9c742af39cbcac21357c1b29511b0bbdd3d0e3cf5e14b2eef68a28ab3", "0x20f089131cc96d86ff1cfb67fa3f51670f4bad30158751b2587354bbec76cdf9", "0x1a26c6d3e633f9bf8434cf755b5f1217dad0d455071a97a7bcf85b824f5cf07a", "0x0d7e9b8a51fccf910ec25bdbd13e70b34bd6ea6f4d629fa744f9cdf5f2beb1cf", "0x0b40f28ce428e64df9cf5a024133fc420f39decf5f6af020cc3211ab298d4631", "0x0ca4f189dde7a55fe829f46681232904f6670249a22e0deb47222bd309523a8a", "0x2c544f2e31143783977645edb2a6bdb39b875053963bfa1a5b3ae9de204a7ebe", "0x00aae4454eb48fb18ff60db6b9d015abea2e770a2f7d86d121522b834c791ba5", "0x07d74e351fd4cccf4e18475d25211efa8a359066fc693a5c8505ddb507e4b74b", "0x07d74e351fd4cccf4e18475d25211efa8a359066fc693a5c8505ddb507e4b74b", "0x2d9e5bff47207d82533e2445959941181cc890c5779bc7f24d6e8a7b9e425b5c", "0x0aea3c0c317c441a5775a9849108d7a6889b39128235f717b09b184aa08e4eb7", "0x1ca5bc6fb37c55a562f4991901c39902f42d14db71284116df74cb4e7d55e493", "0x220fed26d64cd69f40e6d145a423e4a3c8cd0dce747e7d51647441270ad4d774", "0x15be574c9358889257aa2a30ff7b5fcc31a57da7032296e2c1201c49a44bbdb6", "0x2de539925525bedd3b7f43a9c6bf0f713151a17f79ac7ff4a9cd27b15ffe892a", "0x083086693dbf465211741e2cbff70ff38eb08383faf22d397eb2742c8ad7396a", "0x1fdfa258a890598816e807c50058d7a1462edd5ff196a2eae0f862e454b49aa1", "0x10c434c6daaa8226fa8e3e302123dfdc4455cf68063df518949df5a65a945213", "0x0000000000000000000000000000006472a7874de2c454a4591ed7784df1c104", "0x000000000000000000000000000000000008c46ac53d2c4ad0c26a5d6c790082", "0x0000000000000000000000000000005e422f9cfb8725800de60dfe0a8d4104c0", "0x000000000000000000000000000000000000f10fd4e4de81a0c00073ec91c274", "0x000000000000000000000000000000b20813090eca76bc6aa4a699b1ec8d5d6d", "0x0000000000000000000000000000000000292cc9f8a744eb00e0903c29ce87a7", "0x000000000000000000000000000000350a368b415fbb99fa90a26a42b1a3affd", "0x0000000000000000000000000000000000280eb9275cb05a3435f464d1dc369d", "0x000000000000000000000000000000280df6505e20c7725fe6d29439f96ee05d", "0x000000000000000000000000000000000017ef5033a08535451e2747827aa94b", "0x0000000000000000000000000000002f9ba89ae91b4e4a4ff8ccbd0526faad2f", "0x00000000000000000000000000000000001c2013561dafcc02cb03220bdf23c4", "0x000000000000000000000000000000aac102c400f9e5da0321ded4510994434b", "0x00000000000000000000000000000000001ec8ab9cc834b492fde124962f04a1", "0x0000000000000000000000000000000673dbd698da8b8cce450d2a083aba9987", "0x00000000000000000000000000000000000a49e55bb040249cb41c63cea901cd", "0x000000000000000000000000000000133d92af8d76ee0c74a12081ee7b2ef8c4", "0x0000000000000000000000000000000000240f552d1c6cbb007650e4b142e0a5", "0x000000000000000000000000000000e29c6e7d982ec08d51c79d6261c28d742d", "0x000000000000000000000000000000000021baeec04d9be419c923626034e7b3", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x1e940a528b42d8230e7d4dff76262a80986c0d00b2c02a9bc0559e36212d1547", "0x1ceccf21ac39f70d76ad6f7fe0dcb33b6af04555a0b1959e4714d65925e4e253", "0x096139d757046cdbdb7ee89a95f112f70882a43a46c2f739d9be115dda013420", "0x2f9c8ac67c7825b08eff0e7f7656a671f4c64e5601f2efab35b1b795801eec04", "0x2077e648e1704851cdffd7e6e56311634a7b741bab77ca34d9dff12a6a2bfe99", "0x115d48c4a97aeb3c447a060f9e0d675b0dc7f4a05a3f5776e2f279f3a165d7dc", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x000000000000000000000000000000fd38c45c3ec5b841482a80e3a56ce82555", "0x00000000000000000000000000000000000ad70b03f092f60af3e0ce1bb29d2c", "0x0000000000000000000000000000007a184d5342c90c634c0b1a050f0b97c9fb", "0x0000000000000000000000000000000000271f42abcb3bc1f0332e4b3ca85e1d", "0x0000000000000000000000000000008256322bbe2c1b8cd9d84e5ff6123477f2", "0x000000000000000000000000000000000025cab962761681dd9547f4c78814df", "0x0000000000000000000000000000008c4234510e5825c02b9ac427bcbf8e279a", "0x000000000000000000000000000000000013a14e0d7fc073c44643af38cc5396"] -public_inputs = ["0x0000000000000000000000000000000000000000000000000000000000000003"] -verification_key = ["0x0000000000000000000000000000000000000000000000000000000000000040", "0x0000000000000000000000000000000000000000000000000000000000000011", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000003", "0x0000000000000000000000000000000000000000000000000000000000000004", "0x0000000000000000000000000000000000000000000000000000000000000005", "0x0000000000000000000000000000000000000000000000000000000000000006", "0x0000000000000000000000000000000000000000000000000000000000000007", "0x0000000000000000000000000000000000000000000000000000000000000008", "0x0000000000000000000000000000000000000000000000000000000000000009", "0x000000000000000000000000000000000000000000000000000000000000000a", "0x000000000000000000000000000000000000000000000000000000000000000b", "0x000000000000000000000000000000000000000000000000000000000000000c", "0x000000000000000000000000000000000000000000000000000000000000000d", "0x000000000000000000000000000000000000000000000000000000000000000e", "0x000000000000000000000000000000000000000000000000000000000000000f", "0x0000000000000000000000000000000000000000000000000000000000000010", "0x00000000000000000000000000000060e430ad1c23bfcf3514323aae3f206e84", "0x00000000000000000000000000000000001b5c3ff4c2458d8f481b1c068f27ae", "0x000000000000000000000000000000bb510ab2112def34980e4fc6998ad9dd16", "0x00000000000000000000000000000000000576e7c105b43e061e13cb877fefe1", "0x000000000000000000000000000000ced074785d11857b065d8199e6669a601c", "0x00000000000000000000000000000000000053b48a4098c1c0ae268f273952f7", "0x000000000000000000000000000000d1d4b26e941db8168cee8f6de548ae0fd8", "0x00000000000000000000000000000000001a9adf5a6dadc3d948bb61dfd63f4c", "0x0000000000000000000000000000009ce1faac6f8de6ebb18f1db17372c82ad5", "0x00000000000000000000000000000000002002681bb417184b2df070a16a3858", "0x000000000000000000000000000000161baa651a8092e0e84725594de5aba511", "0x00000000000000000000000000000000000be0064399c2a1efff9eb0cdcb2223", "0x0000000000000000000000000000008673be6fd1bdbe980a29d8c1ded54381e7", "0x000000000000000000000000000000000008a5158a7d9648cf1d234524c9fa0c", "0x0000000000000000000000000000002b4fce6e4b1c72062b296d49bca2aa4130", "0x00000000000000000000000000000000002e45a9eff4b6769e55fb710cded44f", "0x00000000000000000000000000000072b85bf733758b76bcf97333efb85a23e3", "0x000000000000000000000000000000000017da0ea508994fc82862715e4b5592", "0x00000000000000000000000000000094fa74695cf058dba8ff35aec95456c6c3", "0x0000000000000000000000000000000000211acddb851061c24b8f159e832bd1", "0x000000000000000000000000000000303b5e5c531384b9a792e11702ad3bcab0", "0x00000000000000000000000000000000000d336dff51a60b8833d5d7f6d4314c", "0x0000000000000000000000000000009f825dde88092070747180d581c342444a", "0x0000000000000000000000000000000000237fbd6511a03cca8cac01b555fe01", "0x0000000000000000000000000000007c313205159495df6d8de292079a4844ff", "0x000000000000000000000000000000000018facdfc468530dd45e8f7a1d38ce9", "0x0000000000000000000000000000000d1ce33446fc3dc4ab40ca38d92dac74e1", "0x00000000000000000000000000000000000852d8e3e0e8f4435af3e94222688b", "0x0000000000000000000000000000006c04ee19ec1dfec87ed47d6d04aa158de2", "0x000000000000000000000000000000000013240f97a584b45184c8ec31319b5f", "0x000000000000000000000000000000cefb5d240b07ceb4be26ea429b6dc9d9e0", "0x00000000000000000000000000000000002dad22022121d689f57fb38ca21349", "0x000000000000000000000000000000c9f189f2a91aeb664ce376d8b157ba98f8", "0x00000000000000000000000000000000002531a51ad54f124d58094b219818d2", "0x000000000000000000000000000000ef1e6db71809307f677677e62b4163f556", "0x0000000000000000000000000000000000272da4396fb2a7ee0638b9140e523d", "0x0000000000000000000000000000002e54c0244a7732c87bc4712a76dd8c83fb", "0x000000000000000000000000000000000007db77b3e04b7eba9643da57cbbe4d", "0x000000000000000000000000000000e0dfe1ddd7f74ae0d636c910c3e85830d8", "0x00000000000000000000000000000000000466fa9b57ec4664abd1505b490862", "0x0000000000000000000000000000009ee55ae8a32fe5384c79907067cc27192e", "0x00000000000000000000000000000000000799d0e465cec07ecb5238c854e830", "0x0000000000000000000000000000001d5910ad361e76e1c241247a823733c39f", "0x00000000000000000000000000000000002b03f2ccf7507564da2e6678bef8fe", "0x000000000000000000000000000000ee40d90bea71fba7a412dd61fcf34e8ceb", "0x0000000000000000000000000000000000140b0936c323fd2471155617b6af56", "0x0000000000000000000000000000002b90071823185c5ff8e440fd3d73b6fefc", "0x00000000000000000000000000000000002b6c10790a5f6631c87d652e059df4", "0x00000000000000000000000000000029a17181c7934fc3fdbd352eac5cb521b9", "0x00000000000000000000000000000000001f497cbf5284ff29a2d336e5991999", "0x000000000000000000000000000000072bd9c0c6beda1fdee6d4ff0432ba9e1b", "0x000000000000000000000000000000000013ea38a0bd2aa751a490a724fac818", "0x000000000000000000000000000000c599f63dcd3edd49f08ae5c3141c1e3493", "0x00000000000000000000000000000000002bdb36be0bea09950dd32a8ccf6fbc", "0x00000000000000000000000000000047f27f29724e7f19eba0340256a0bd4b7d", "0x00000000000000000000000000000000001c1c5ccf87a962129ca785f8f35120", "0x000000000000000000000000000000c5c71efdae00679bbe4a95096e012b1817", "0x000000000000000000000000000000000017a365de041e317817d0135f2b48e0", "0x0000000000000000000000000000008ae711ac402f7848d719c93a89ba8d39f1", "0x00000000000000000000000000000000002b6fb40ed8a1935226f4f9786a0499", "0x0000000000000000000000000000002f03a71501d83de1da5715a4e9462d6198", "0x00000000000000000000000000000000001644064443b8546f48eae693af47b8", "0x00000000000000000000000000000083763ab1b6e8fe269b2fe4c7b9c448c08d", "0x000000000000000000000000000000000021d7cc18c59676a8eeb47c0111c251", "0x000000000000000000000000000000b5f937153073e03ea7d51a996e0ebc2e6b", "0x000000000000000000000000000000000011ddd0e26457373eb06e0493177672", "0x000000000000000000000000000000c5f6eb9f6fc8fa99811a4a88c74a6d018b", "0x000000000000000000000000000000000025bcd07a0732c123567834f5109558", "0x000000000000000000000000000000aeb08a0b1a4442189448b4e97490568146", "0x000000000000000000000000000000000002a1744e4771705536a88f07e0f90f", "0x000000000000000000000000000000b938568293bd0724b0ea76c2ec34c4a829", "0x0000000000000000000000000000000000053296e8f3b9ad3af877dfa9c7c2a7", "0x000000000000000000000000000000f0ca1db6323996eba26bdc86dafef9d10b", "0x00000000000000000000000000000000001441a46c58af03d5645d52721d956a", "0x0000000000000000000000000000008bbf8f884013c66c28ba09c2fbd573b656", "0x0000000000000000000000000000000000206c391ca06fac27d1908e94570243", "0x0000000000000000000000000000002d4f5aaed88ba4f79612d53b804ca8f194", "0x00000000000000000000000000000000001674011c96392df08970fa6b7b4cb8", "0x0000000000000000000000000000009f88297c1729d76c4d9306853598c91325", "0x0000000000000000000000000000000000256f51adfcacc3c1e340be4d32d3e9", "0x0000000000000000000000000000000ab9955eec0d74eb799afed2a802b24d75", "0x00000000000000000000000000000000001fcbe43ea105b30d36ed0b21b03411", "0x000000000000000000000000000000d66b1d5433f1aa5305cd1edce7c22de466", "0x00000000000000000000000000000000002331546a256b8a3b751956806680d4", "0x000000000000000000000000000000e97954ad6cd6f45fb15c91434121db4304", "0x00000000000000000000000000000000002e20a97e09d50f227ced47e7a98250", "0x0000000000000000000000000000001ebbc27eb9ebededefba79522eb58ae89b", "0x0000000000000000000000000000000000090efa4974e566e81d1177b85a30be", "0x0000000000000000000000000000005eafa070b9c9632404052642e3bc14f9fd", "0x00000000000000000000000000000000001489068864102daca6a6b8bc4d448b", "0x0000000000000000000000000000009ebc91aaaac036a6477cadbe54e8556dfd", "0x00000000000000000000000000000000000ef6d835e2ed3343b95c82c8c54037", "0x00000000000000000000000000000033b28b529dff46e93af4e7422530478e4a", "0x000000000000000000000000000000000020a86c2f8591bf190bcddcc03c42fb", "0x000000000000000000000000000000a9679d0acc088f7dc27bf6d866bcd2dda2", "0x00000000000000000000000000000000002fb9d0d2d4099402bed74f738f64cc", "0x00000000000000000000000000000023b09f876a29a061582848a8b9a5870c12", "0x00000000000000000000000000000000001d5bb906f03f0d49e9c4791bc43af9", "0x00000000000000000000000000000017aac9854ea240d8ec97bf760c4d4ba870", "0x00000000000000000000000000000000000b227a556c414ada0dc75bb303e30e", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000009b624fa65d1a24b7f14a8f25f3789622af", "0x000000000000000000000000000000000013d47bff8c630e847b70e2732fd3f0", "0x00000000000000000000000000000061d21663e93132f32921075f4c936a84df", "0x00000000000000000000000000000000001a74ca4e118fb480b9b999902989a3"] diff --git a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/src/main.nr b/noir/noir-repo/test_programs/execution_success/verify_honk_proof/src/main.nr deleted file mode 100644 index 6e96b459b0b..00000000000 --- a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/src/main.nr +++ /dev/null @@ -1,21 +0,0 @@ -// This circuit aggregates a single Honk proof from `assert_statement_recursive`. -global SIZE_OF_PROOF_IF_LOGN_IS_28: u32 = 463; -global HONK_IDENTIFIER: u32 = 1; -fn main( - verification_key: [Field; 128], - // This is the proof without public inputs attached. - // This means: the size of this does not change with the number of public inputs. - proof: [Field; SIZE_OF_PROOF_IF_LOGN_IS_28], - public_inputs: pub [Field; 1], - // This is currently not public. It is fine given that the vk is a part of the circuit definition. - // I believe we want to eventually make it public too though. - key_hash: Field, -) { - std::verify_proof_with_type( - verification_key, - proof, - public_inputs, - key_hash, - HONK_IDENTIFIER, - ); -} diff --git a/noir/noir-repo/tooling/debugger/src/repl.rs b/noir/noir-repo/tooling/debugger/src/repl.rs index 012af0e88e8..486e84060f0 100644 --- a/noir/noir-repo/tooling/debugger/src/repl.rs +++ b/noir/noir-repo/tooling/debugger/src/repl.rs @@ -5,6 +5,8 @@ use acvm::acir::circuit::brillig::{BrilligBytecode, BrilligFunctionId}; use acvm::acir::circuit::{Circuit, Opcode, OpcodeLocation}; use acvm::acir::native_types::{Witness, WitnessMap, WitnessStack}; use acvm::brillig_vm::brillig::Opcode as BrilligOpcode; +use acvm::brillig_vm::MemoryValue; +use acvm::AcirField; use acvm::{BlackBoxFunctionSolver, FieldElement}; use nargo::NargoError; use noirc_driver::CompiledProgram; @@ -369,6 +371,12 @@ impl<'a, B: BlackBoxFunctionSolver> ReplDebugger<'a, B> { }; for (index, value) in memory.iter().enumerate() { + // Zero field is the default value, we omit it when printing memory + if let MemoryValue::Field(field) = value { + if field == &FieldElement::zero() { + continue; + } + } println!("{index} = {}", value); } } diff --git a/noir/noir-repo/tooling/lsp/src/attribute_reference_finder.rs b/noir/noir-repo/tooling/lsp/src/attribute_reference_finder.rs index 39e1385a6e8..22afa086303 100644 --- a/noir/noir-repo/tooling/lsp/src/attribute_reference_finder.rs +++ b/noir/noir-repo/tooling/lsp/src/attribute_reference_finder.rs @@ -13,7 +13,10 @@ use noirc_frontend::{ graph::CrateId, hir::{ def_map::{CrateDefMap, LocalModuleId, ModuleId}, - resolution::path_resolver::{PathResolver, StandardPathResolver}, + resolution::{ + import::PathResolutionItem, + path_resolver::{PathResolver, StandardPathResolver}, + }, }, node_interner::ReferenceId, parser::{ParsedSubModule, Parser}, @@ -22,8 +25,6 @@ use noirc_frontend::{ ParsedModule, }; -use crate::modules::module_def_id_to_reference_id; - pub(crate) struct AttributeReferenceFinder<'a> { byte_index: usize, /// The module ID in scope. This might change as we traverse the AST @@ -106,6 +107,20 @@ impl<'a> Visitor for AttributeReferenceFinder<'a> { return; }; - self.reference_id = Some(module_def_id_to_reference_id(result.module_def_id)); + self.reference_id = Some(path_resolution_item_to_reference_id(result.item)); + } +} + +fn path_resolution_item_to_reference_id(item: PathResolutionItem) -> ReferenceId { + match item { + PathResolutionItem::Module(module_id) => ReferenceId::Module(module_id), + PathResolutionItem::Struct(struct_id) => ReferenceId::Struct(struct_id), + PathResolutionItem::TypeAlias(type_alias_id) => ReferenceId::Alias(type_alias_id), + PathResolutionItem::Trait(trait_id) => ReferenceId::Trait(trait_id), + PathResolutionItem::Global(global_id) => ReferenceId::Global(global_id), + PathResolutionItem::ModuleFunction(func_id) + | PathResolutionItem::StructFunction(_, _, func_id) + | PathResolutionItem::TypeAliasFunction(_, _, func_id) + | PathResolutionItem::TraitFunction(_, _, func_id) => ReferenceId::Function(func_id), } } diff --git a/noir/noir-repo/tooling/lsp/src/lib.rs b/noir/noir-repo/tooling/lsp/src/lib.rs index 39e14a74007..a85b9d043b9 100644 --- a/noir/noir-repo/tooling/lsp/src/lib.rs +++ b/noir/noir-repo/tooling/lsp/src/lib.rs @@ -67,8 +67,10 @@ mod modules; mod notifications; mod requests; mod solver; +mod tests; mod trait_impl_method_stub_generator; mod types; +mod use_segment_positions; mod utils; mod visibility; diff --git a/noir/noir-repo/tooling/lsp/src/modules.rs b/noir/noir-repo/tooling/lsp/src/modules.rs index 9f9a826d6ca..cadf71b2eec 100644 --- a/noir/noir-repo/tooling/lsp/src/modules.rs +++ b/noir/noir-repo/tooling/lsp/src/modules.rs @@ -1,14 +1,9 @@ -use std::collections::BTreeMap; - use noirc_frontend::{ - ast::ItemVisibility, graph::{CrateId, Dependency}, - hir::def_map::{CrateDefMap, ModuleDefId, ModuleId}, + hir::def_map::{ModuleDefId, ModuleId}, node_interner::{NodeInterner, ReferenceId}, }; -use crate::visibility::is_visible; - pub(crate) fn get_parent_module( interner: &NodeInterner, module_def_id: ModuleDefId, @@ -33,18 +28,12 @@ pub(crate) fn module_def_id_to_reference_id(module_def_id: ModuleDefId) -> Refer /// - Otherwise, that item's parent module's path is returned pub(crate) fn relative_module_full_path( module_def_id: ModuleDefId, - visibility: ItemVisibility, current_module_id: ModuleId, current_module_parent_id: Option, interner: &NodeInterner, - def_maps: &BTreeMap, ) -> Option { let full_path; if let ModuleDefId::ModuleId(module_id) = module_def_id { - if !is_visible(module_id, current_module_id, visibility, def_maps) { - return None; - } - full_path = relative_module_id_path( module_id, ¤t_module_id, @@ -56,10 +45,6 @@ pub(crate) fn relative_module_full_path( return None; }; - if !is_visible(parent_module, current_module_id, visibility, def_maps) { - return None; - } - full_path = relative_module_id_path( parent_module, ¤t_module_id, diff --git a/noir/noir-repo/tooling/lsp/src/requests/code_action.rs b/noir/noir-repo/tooling/lsp/src/requests/code_action.rs index 9299dc76368..5c2831be7e9 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/code_action.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/code_action.rs @@ -12,7 +12,10 @@ use lsp_types::{ }; use noirc_errors::Span; use noirc_frontend::{ - ast::{ConstructorExpression, ItemVisibility, NoirTraitImpl, Path, UseTree, Visitor}, + ast::{ + CallExpression, ConstructorExpression, ItemVisibility, MethodCallExpression, NoirTraitImpl, + Path, UseTree, Visitor, + }, graph::CrateId, hir::def_map::{CrateDefMap, LocalModuleId, ModuleId}, node_interner::NodeInterner, @@ -22,13 +25,14 @@ use noirc_frontend::{ ParsedModule, }; -use crate::{utils, LspState}; +use crate::{use_segment_positions::UseSegmentPositions, utils, LspState}; use super::{process_request, to_lsp_location}; mod fill_struct_fields; mod implement_missing_members; mod import_or_qualify; +mod remove_bang_from_call; mod remove_unused_import; mod tests; @@ -82,6 +86,7 @@ struct CodeActionFinder<'a> { nesting: usize, /// The line where an auto_import must be inserted auto_import_line: usize, + use_segment_positions: UseSegmentPositions, /// Text edits for the "Remove all unused imports" code action unused_imports_text_edits: Vec, code_actions: Vec, @@ -121,6 +126,7 @@ impl<'a> CodeActionFinder<'a> { interner, nesting: 0, auto_import_line: 0, + use_segment_positions: UseSegmentPositions::default(), unused_imports_text_edits: vec![], code_actions: vec![], } @@ -184,10 +190,11 @@ impl<'a> CodeActionFinder<'a> { impl<'a> Visitor for CodeActionFinder<'a> { fn visit_item(&mut self, item: &Item) -> bool { - if let ItemKind::Import(..) = &item.kind { + if let ItemKind::Import(use_tree, _) = &item.kind { if let Some(lsp_location) = to_lsp_location(self.files, self.file, item.span) { self.auto_import_line = (lsp_location.range.end.line + 1) as usize; } + self.use_segment_positions.add(use_tree); } self.includes_span(item.span) @@ -247,4 +254,32 @@ impl<'a> Visitor for CodeActionFinder<'a> { true } + + fn visit_call_expression(&mut self, call: &CallExpression, span: Span) -> bool { + if !self.includes_span(span) { + return false; + } + + if call.is_macro_call { + self.remove_bang_from_call(call.func.span); + } + + true + } + + fn visit_method_call_expression( + &mut self, + method_call: &MethodCallExpression, + span: Span, + ) -> bool { + if !self.includes_span(span) { + return false; + } + + if method_call.is_macro_call { + self.remove_bang_from_call(method_call.method_name.span()); + } + + true + } } diff --git a/noir/noir-repo/tooling/lsp/src/requests/code_action/import_or_qualify.rs b/noir/noir-repo/tooling/lsp/src/requests/code_action/import_or_qualify.rs index bf1fe906be3..ffc83b05a5b 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/code_action/import_or_qualify.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/code_action/import_or_qualify.rs @@ -1,4 +1,4 @@ -use lsp_types::{Position, Range, TextEdit}; +use lsp_types::TextEdit; use noirc_errors::Location; use noirc_frontend::{ ast::{Ident, Path}, @@ -8,6 +8,10 @@ use noirc_frontend::{ use crate::{ byte_span_to_range, modules::{relative_module_full_path, relative_module_id_path}, + use_segment_positions::{ + use_completion_item_additional_text_edits, UseCompletionItemAdditionTextEditsRequest, + }, + visibility::module_def_id_is_visible, }; use super::CodeActionFinder; @@ -38,6 +42,17 @@ impl<'a> CodeActionFinder<'a> { } for (module_def_id, visibility, defining_module) in entries { + if !module_def_id_is_visible( + *module_def_id, + self.module_id, + *visibility, + *defining_module, + self.interner, + self.def_maps, + ) { + continue; + } + let module_full_path = if let Some(defining_module) = defining_module { relative_module_id_path( *defining_module, @@ -48,11 +63,9 @@ impl<'a> CodeActionFinder<'a> { } else { let Some(module_full_path) = relative_module_full_path( *module_def_id, - *visibility, self.module_id, current_module_parent_id, self.interner, - self.def_maps, ) else { continue; }; @@ -82,25 +95,21 @@ impl<'a> CodeActionFinder<'a> { } fn push_import_code_action(&mut self, full_path: &str) { - let line = self.auto_import_line as u32; - let character = (self.nesting * 4) as u32; - let indent = " ".repeat(self.nesting * 4); - let mut newlines = "\n"; - - // If the line we are inserting into is not an empty line, insert an extra line to make some room - if let Some(line_text) = self.lines.get(line as usize) { - if !line_text.trim().is_empty() { - newlines = "\n\n"; - } - } - let title = format!("Import {}", full_path); - let text_edit = TextEdit { - range: Range { start: Position { line, character }, end: Position { line, character } }, - new_text: format!("use {};{}{}", full_path, newlines, indent), - }; - let code_action = self.new_quick_fix(title, text_edit); + let text_edits = use_completion_item_additional_text_edits( + UseCompletionItemAdditionTextEditsRequest { + full_path, + files: self.files, + file: self.file, + lines: &self.lines, + nesting: self.nesting, + auto_import_line: self.auto_import_line, + }, + &self.use_segment_positions, + ); + + let code_action = self.new_quick_fix_multiple_edits(title, text_edits); self.code_actions.push(code_action); } @@ -133,7 +142,7 @@ mod tests { let src = r#" mod foo { - mod bar { + pub mod bar { pub struct SomeTypeInBar {} } } @@ -143,7 +152,7 @@ mod tests { let expected = r#" mod foo { - mod bar { + pub mod bar { pub struct SomeTypeInBar {} } } @@ -159,7 +168,7 @@ mod tests { let title = "Import foo::bar::SomeTypeInBar"; let src = r#"mod foo { - mod bar { + pub mod bar { pub struct SomeTypeInBar {} } } @@ -169,7 +178,7 @@ fn foo(x: SomeType>|| CodeActionFinder<'a> { + pub(super) fn remove_bang_from_call(&mut self, span: Span) { + // If we can't find the referenced function, there's nothing we can do + let Some(ReferenceId::Function(func_id)) = + self.interner.find_referenced(Location::new(span, self.file)) + else { + return; + }; + + // If the return type is Quoted, all is good + let func_meta = self.interner.function_meta(&func_id); + if let Type::Quoted(QuotedType::Quoted) = func_meta.return_type() { + return; + } + + // The `!` comes right after the name + let byte_span = span.end() as usize..span.end() as usize + 1; + let Some(range) = byte_span_to_range(self.files, self.file, byte_span) else { + return; + }; + + let title = "Remove `!` from call".to_string(); + let text_edit = TextEdit { range, new_text: "".to_string() }; + + let code_action = self.new_quick_fix(title, text_edit); + self.code_actions.push(code_action); + } +} + +#[cfg(test)] +mod tests { + use tokio::test; + + use crate::requests::code_action::tests::assert_code_action; + + #[test] + async fn test_removes_bang_from_call() { + let title = "Remove `!` from call"; + + let src = r#" + fn foo() {} + + fn main() { + fo>|||<", ""), &text_edits[0]); + let result = apply_text_edits(&src.replace(">|<", ""), text_edits); if result != expected { println!("Expected:\n```\n{}\n```\n\nGot:\n```\n{}\n```", expected, result); assert_eq!(result, expected); } } - -fn apply_text_edit(src: &str, text_edit: &TextEdit) -> String { - let mut lines: Vec<_> = src.lines().collect(); - assert_eq!(text_edit.range.start.line, text_edit.range.end.line); - - let mut line = lines[text_edit.range.start.line as usize].to_string(); - line.replace_range( - text_edit.range.start.character as usize..text_edit.range.end.character as usize, - &text_edit.new_text, - ); - lines[text_edit.range.start.line as usize] = &line; - lines.join("\n") -} diff --git a/noir/noir-repo/tooling/lsp/src/requests/completion.rs b/noir/noir-repo/tooling/lsp/src/requests/completion.rs index 658033fc526..2dd42c740cd 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/completion.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/completion.rs @@ -19,9 +19,9 @@ use noirc_frontend::{ Expression, ExpressionKind, ForLoopStatement, GenericTypeArgs, Ident, IfExpression, IntegerBitSize, ItemVisibility, LValue, Lambda, LetStatement, MemberAccessExpression, MethodCallExpression, NoirFunction, NoirStruct, NoirTraitImpl, Path, PathKind, Pattern, - Signedness, Statement, TraitImplItemKind, TypeImpl, TypePath, UnresolvedGeneric, - UnresolvedGenerics, UnresolvedType, UnresolvedTypeData, UnresolvedTypeExpression, UseTree, - UseTreeKind, Visitor, + Signedness, Statement, TraitBound, TraitImplItemKind, TypeImpl, TypePath, + UnresolvedGeneric, UnresolvedGenerics, UnresolvedType, UnresolvedTypeData, + UnresolvedTypeExpression, UseTree, UseTreeKind, Visitor, }, graph::{CrateId, Dependency}, hir::{ @@ -38,7 +38,8 @@ use sort_text::underscore_sort_text; use crate::{ requests::to_lsp_location, trait_impl_method_stub_generator::TraitImplMethodStubGenerator, - utils, visibility::is_visible, LspState, + use_segment_positions::UseSegmentPositions, utils, visibility::item_in_module_is_visible, + LspState, }; use super::process_request; @@ -115,6 +116,7 @@ struct NodeFinder<'a> { nesting: usize, /// The line where an auto_import must be inserted auto_import_line: usize, + use_segment_positions: UseSegmentPositions, self_type: Option, in_comptime: bool, } @@ -159,6 +161,7 @@ impl<'a> NodeFinder<'a> { suggested_module_def_ids: HashSet::new(), nesting: 0, auto_import_line: 0, + use_segment_positions: UseSegmentPositions::default(), self_type: None, in_comptime: false, } @@ -381,7 +384,7 @@ impl<'a> NodeFinder<'a> { self.builtin_types_completion(&prefix); self.type_parameters_completion(&prefix); } - RequestedItems::OnlyAttributeFunctions(..) => (), + RequestedItems::OnlyTraits | RequestedItems::OnlyAttributeFunctions(..) => (), } self.complete_auto_imports(&prefix, requested_items, function_completion_kind); } @@ -795,7 +798,12 @@ impl<'a> NodeFinder<'a> { if name_matches(name, prefix) { let per_ns = module_data.find_name(ident); if let Some((module_def_id, visibility, _)) = per_ns.types { - if is_visible(module_id, self.module_id, visibility, self.def_maps) { + if item_in_module_is_visible( + module_id, + self.module_id, + visibility, + self.def_maps, + ) { let completion_items = self.module_def_id_completion_items( module_def_id, name.clone(), @@ -811,7 +819,12 @@ impl<'a> NodeFinder<'a> { } if let Some((module_def_id, visibility, _)) = per_ns.values { - if is_visible(module_id, self.module_id, visibility, self.def_maps) { + if item_in_module_is_visible( + module_id, + self.module_id, + visibility, + self.def_maps, + ) { let completion_items = self.module_def_id_completion_items( module_def_id, name.clone(), @@ -1035,6 +1048,8 @@ impl<'a> NodeFinder<'a> { } } + /// Determine where each segment in a `use` statement is located. + fn includes_span(&self, span: Span) -> bool { span.start() as usize <= self.byte_index && self.byte_index <= span.end() as usize } @@ -1042,10 +1057,11 @@ impl<'a> NodeFinder<'a> { impl<'a> Visitor for NodeFinder<'a> { fn visit_item(&mut self, item: &Item) -> bool { - if let ItemKind::Import(..) = &item.kind { + if let ItemKind::Import(use_tree, _) = &item.kind { if let Some(lsp_location) = to_lsp_location(self.files, self.file, item.span) { self.auto_import_line = (lsp_location.range.end.line + 1) as usize; } + self.use_segment_positions.add(use_tree); } self.includes_span(item.span) @@ -1108,6 +1124,10 @@ impl<'a> Visitor for NodeFinder<'a> { noir_function.def.return_type.accept(self); + for constraint in &noir_function.def.where_clause { + constraint.accept(self); + } + self.local_variables.clear(); for param in &noir_function.def.parameters { self.collect_local_variables(¶m.pattern); @@ -1215,7 +1235,7 @@ impl<'a> Visitor for NodeFinder<'a> { return_type.accept(self); for unresolved_trait_constraint in where_clause { - unresolved_trait_constraint.typ.accept(self); + unresolved_trait_constraint.accept(self); } if let Some(body) = body { @@ -1686,6 +1706,12 @@ impl<'a> Visitor for NodeFinder<'a> { last_was_dollar = false; } } + + fn visit_trait_bound(&mut self, trait_bound: &TraitBound) -> bool { + self.find_in_path(&trait_bound.trait_path, RequestedItems::OnlyTraits); + trait_bound.trait_generics.accept(self); + false + } } fn get_field_type(typ: &Type, name: &str) -> Option { diff --git a/noir/noir-repo/tooling/lsp/src/requests/completion/auto_import.rs b/noir/noir-repo/tooling/lsp/src/requests/completion/auto_import.rs index e2dd582f2f3..0e80b284f32 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/completion/auto_import.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/completion/auto_import.rs @@ -1,7 +1,12 @@ -use lsp_types::{Position, Range, TextEdit}; use noirc_frontend::hir::def_map::ModuleDefId; -use crate::modules::{relative_module_full_path, relative_module_id_path}; +use crate::{ + modules::{relative_module_full_path, relative_module_id_path}, + use_segment_positions::{ + use_completion_item_additional_text_edits, UseCompletionItemAdditionTextEditsRequest, + }, + visibility::module_def_id_is_visible, +}; use super::{ kinds::{FunctionCompletionKind, FunctionKind, RequestedItems}, @@ -29,6 +34,17 @@ impl<'a> NodeFinder<'a> { continue; } + if !module_def_id_is_visible( + *module_def_id, + self.module_id, + *visibility, + *defining_module, + self.interner, + self.def_maps, + ) { + continue; + } + let completion_items = self.module_def_id_completion_items( *module_def_id, name.clone(), @@ -54,11 +70,9 @@ impl<'a> NodeFinder<'a> { } else { let Some(module_full_path) = relative_module_full_path( *module_def_id, - *visibility, self.module_id, current_module_parent_id, self.interner, - self.def_maps, ) else { continue; }; @@ -76,27 +90,18 @@ impl<'a> NodeFinder<'a> { let mut label_details = completion_item.label_details.unwrap(); label_details.detail = Some(format!("(use {})", full_path)); completion_item.label_details = Some(label_details); - - let line = self.auto_import_line as u32; - let character = (self.nesting * 4) as u32; - let indent = " ".repeat(self.nesting * 4); - let mut newlines = "\n"; - - // If the line we are inserting into is not an empty line, insert an extra line to make some room - if let Some(line_text) = self.lines.get(line as usize) { - if !line_text.trim().is_empty() { - newlines = "\n\n"; - } - } - - completion_item.additional_text_edits = Some(vec![TextEdit { - range: Range { - start: Position { line, character }, - end: Position { line, character }, - }, - new_text: format!("use {};{}{}", full_path, newlines, indent), - }]); - + completion_item.additional_text_edits = + Some(use_completion_item_additional_text_edits( + UseCompletionItemAdditionTextEditsRequest { + full_path: &full_path, + files: self.files, + file: self.file, + lines: &self.lines, + nesting: self.nesting, + auto_import_line: self.auto_import_line, + }, + &self.use_segment_positions, + )); completion_item.sort_text = Some(auto_import_sort_text()); self.completion_items.push(completion_item); diff --git a/noir/noir-repo/tooling/lsp/src/requests/completion/completion_items.rs b/noir/noir-repo/tooling/lsp/src/requests/completion/completion_items.rs index f281f5e3abf..49e4474738e 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/completion/completion_items.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/completion/completion_items.rs @@ -35,6 +35,14 @@ impl<'a> NodeFinder<'a> { | ModuleDefId::TypeAliasId(_) | ModuleDefId::TraitId(_) => (), }, + RequestedItems::OnlyTraits => match module_def_id { + ModuleDefId::FunctionId(_) | ModuleDefId::GlobalId(_) | ModuleDefId::TypeId(_) => { + return Vec::new() + } + ModuleDefId::ModuleId(_) + | ModuleDefId::TypeAliasId(_) + | ModuleDefId::TraitId(_) => (), + }, RequestedItems::OnlyAttributeFunctions(..) => { if !matches!(module_def_id, ModuleDefId::FunctionId(..)) { return Vec::new(); diff --git a/noir/noir-repo/tooling/lsp/src/requests/completion/kinds.rs b/noir/noir-repo/tooling/lsp/src/requests/completion/kinds.rs index 6fa74ffdb1a..ba6faada6f4 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/completion/kinds.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/completion/kinds.rs @@ -25,8 +25,10 @@ pub(super) enum FunctionKind<'a> { pub(super) enum RequestedItems { // Suggest any items (types, functions, etc.). AnyItems, - // Only suggest types. + // Only suggest types (and modules, because they can contain types). OnlyTypes, + // Only suggest traits (and modules, because they can contain traits). + OnlyTraits, // Only attribute functions OnlyAttributeFunctions(AttributeTarget), } diff --git a/noir/noir-repo/tooling/lsp/src/requests/completion/tests.rs b/noir/noir-repo/tooling/lsp/src/requests/completion/tests.rs index 668255eb34d..745dacfc152 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/completion/tests.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/completion/tests.rs @@ -15,12 +15,13 @@ mod completion_tests { on_completion_request, }, test_utils, + tests::apply_text_edits, }; use lsp_types::{ CompletionItem, CompletionItemKind, CompletionItemLabelDetails, CompletionParams, - CompletionResponse, DidOpenTextDocumentParams, PartialResultParams, Position, Range, - TextDocumentIdentifier, TextDocumentItem, TextDocumentPositionParams, TextEdit, + CompletionResponse, DidOpenTextDocumentParams, PartialResultParams, Position, + TextDocumentIdentifier, TextDocumentItem, TextDocumentPositionParams, WorkDoneProgressParams, }; use tokio::test; @@ -1392,29 +1393,50 @@ mod completion_tests { #[test] async fn test_auto_imports() { - let src = r#" - mod foo { - mod bar { - pub fn hello_world() {} + let src = r#"mod foo { + pub mod bar { + pub fn hello_world() {} - struct Foo { - } + struct Foo { + } - impl Foo { - // This is here to make sure it's not offered for completion - fn hello_world() {} - } - } - } + impl Foo { + // This is here to make sure it's not offered for completion + fn hello_world() {} + } + } +} - fn main() { - hel>|< - } +fn main() { + hel>|< +} "#; - let items = get_completions(src).await; + + let expected = r#"use foo::bar::hello_world; + +mod foo { + pub mod bar { + pub fn hello_world() {} + + struct Foo { + } + + impl Foo { + // This is here to make sure it's not offered for completion + fn hello_world() {} + } + } +} + +fn main() { + hel +} + "#; + + let mut items = get_completions(src).await; assert_eq!(items.len(), 1); - let item = &items[0]; + let item = items.remove(0); assert_eq!(item.label, "hello_world()"); assert_eq!( item.label_details, @@ -1424,38 +1446,43 @@ mod completion_tests { }) ); - assert_eq!( - item.additional_text_edits, - Some(vec![TextEdit { - range: Range { - start: Position { line: 0, character: 0 }, - end: Position { line: 0, character: 0 }, - }, - new_text: "use foo::bar::hello_world;\n".to_string(), - }]) - ); - + let changed = + apply_text_edits(&src.replace(">|<", ""), &item.additional_text_edits.unwrap()); + assert_eq!(changed, expected); assert_eq!(item.sort_text, Some(auto_import_sort_text())); } #[test] async fn test_auto_imports_when_in_nested_module_and_item_is_further_nested() { - let src = r#" - #[something] - mod foo { - mod bar { - pub fn hello_world() {} - } + let src = r#"#[something] +mod foo { + pub mod bar { + pub fn hello_world() {} + } - fn foo() { - hel>|< - } - } + fn foo() { + hel>|< + } +} "#; - let items = get_completions(src).await; + + let expected = r#"#[something] +mod foo { + use bar::hello_world; + + pub mod bar { + pub fn hello_world() {} + } + + fn foo() { + hel + } +} + "#; + let mut items = get_completions(src).await; assert_eq!(items.len(), 1); - let item = &items[0]; + let item = items.remove(0); assert_eq!(item.label, "hello_world()"); assert_eq!( item.label_details, @@ -1465,37 +1492,42 @@ mod completion_tests { }) ); - assert_eq!( - item.additional_text_edits, - Some(vec![TextEdit { - range: Range { - start: Position { line: 3, character: 4 }, - end: Position { line: 3, character: 4 }, - }, - new_text: "use bar::hello_world;\n\n ".to_string(), - }]) - ); + let changed = + apply_text_edits(&src.replace(">|<", ""), &item.additional_text_edits.unwrap()); + assert_eq!(changed, expected); } #[test] async fn test_auto_imports_when_in_nested_module_and_item_is_not_further_nested() { - let src = r#" - mod foo { - mod bar { - pub fn hello_world() {} - } + let src = r#"mod foo { + pub mod bar { + pub fn hello_world() {} + } - mod baz { - fn foo() { - hel>|< - } - } - } - "#; - let items = get_completions(src).await; + pub mod baz { + fn foo() { + hel>|< + } + } +}"#; + + let expected = r#"mod foo { + pub mod bar { + pub fn hello_world() {} + } + + pub mod baz { + use super::bar::hello_world; + + fn foo() { + hel + } + } +}"#; + let mut items = get_completions(src).await; assert_eq!(items.len(), 1); - let item = &items[0]; + let item = items.remove(0); assert_eq!(item.label, "hello_world()"); assert_eq!( item.label_details, @@ -1505,23 +1537,61 @@ mod completion_tests { }) ); - assert_eq!( - item.additional_text_edits, - Some(vec![TextEdit { - range: Range { - start: Position { line: 7, character: 8 }, - end: Position { line: 7, character: 8 }, - }, - new_text: "use super::bar::hello_world;\n\n ".to_string(), - }]) - ); + let changed = + apply_text_edits(&src.replace(">|<", ""), &item.additional_text_edits.unwrap()); + assert_eq!(changed, expected); } #[test] async fn test_auto_import_inserts_after_last_use() { + let src = r#"mod foo { + pub mod bar { + pub fn hello_world() {} + } +} + +mod baz { + fn qux() {} +} + +use baz::qux; + +fn main() { + hel>|< +}"#; + + let expected = r#"mod foo { + pub mod bar { + pub fn hello_world() {} + } +} + +mod baz { + fn qux() {} +} + +use baz::qux; +use foo::bar::hello_world; + +fn main() { + hel +}"#; + let mut items = get_completions(src).await; + assert_eq!(items.len(), 1); + + let item = items.remove(0); + + let changed = + apply_text_edits(&src.replace(">|<", ""), &item.additional_text_edits.unwrap()); + assert_eq!(changed, expected); + } + + #[test] + async fn test_does_not_auto_import_test_functions() { let src = r#" mod foo { mod bar { + #[test] pub fn hello_world() {} } } @@ -1533,28 +1603,15 @@ mod completion_tests { } "#; let items = get_completions(src).await; - assert_eq!(items.len(), 1); - - let item = &items[0]; - assert_eq!( - item.additional_text_edits, - Some(vec![TextEdit { - range: Range { - start: Position { line: 8, character: 0 }, - end: Position { line: 8, character: 0 }, - }, - new_text: "use foo::bar::hello_world;\n".to_string(), - }]) - ); + assert!(items.is_empty()); } #[test] - async fn test_does_not_auto_import_test_functions() { + async fn test_does_not_auto_import_private_functions() { let src = r#" mod foo { mod bar { - #[test] - pub fn hello_world() {} + fn hello_world() {} } } @@ -1569,16 +1626,14 @@ mod completion_tests { } #[test] - async fn test_does_not_auto_import_private_functions() { + async fn test_does_not_auto_import_public_function_in_private_module() { let src = r#" mod foo { mod bar { - fn hello_world() {} + pub fn hello_world() {} } } - use foo::bar; - fn main() { hel>|< } @@ -1588,23 +1643,60 @@ mod completion_tests { } #[test] - async fn test_auto_import_suggests_modules_too() { + async fn checks_visibility_of_module_that_exports_item_if_any() { let src = r#" mod foo { - pub mod barbaz { - fn hello_world() {} + mod bar { + pub fn hello_world() {} } + + pub use bar::hello_world; } fn main() { - barb>|< + hello_w>|< } "#; - let items = get_completions(src).await; + let mut items = get_completions(src).await; assert_eq!(items.len(), 1); - let item = &items[0]; + let item = items.remove(0); + assert_eq!(item.label, "hello_world()"); + assert_eq!(item.label_details.unwrap().detail.unwrap(), "(use foo::hello_world)"); + } + + #[test] + async fn test_auto_import_suggests_modules_too() { + let src = r#"mod foo { + pub mod barbaz { + fn hello_world() {} + } + } + + fn main() { + barb>|< + } +}"#; + + let expected = r#"use foo::barbaz; + +mod foo { + pub mod barbaz { + fn hello_world() {} + } + } + + fn main() { + barb + } +}"#; + + let mut items = get_completions(src).await; + assert_eq!(items.len(), 1); + + let item = items.remove(0); assert_eq!(item.label, "barbaz"); + assert_eq!( item.label_details, Some(CompletionItemLabelDetails { @@ -1612,6 +1704,286 @@ mod completion_tests { description: None }) ); + + let changed = + apply_text_edits(&src.replace(">|<", ""), &item.additional_text_edits.unwrap()); + assert_eq!(changed, expected); + } + + #[test] + async fn test_auto_imports_expands_existing_use_before_one_segment_not_in_list() { + let src = r#"use foo::bar::one_hello_world; + +mod foo { + pub mod bar { + pub fn one_hello_world() {} + pub fn two_hello_world() {} + } +} + +fn main() { + two_hello_>|< +}"#; + + let expected = r#"use foo::bar::{one_hello_world, two_hello_world}; + +mod foo { + pub mod bar { + pub fn one_hello_world() {} + pub fn two_hello_world() {} + } +} + +fn main() { + two_hello_ +}"#; + + let mut items = get_completions(src).await; + assert_eq!(items.len(), 1); + + let item = items.remove(0); + let changed = + apply_text_edits(&src.replace(">|<", ""), &item.additional_text_edits.unwrap()); + assert_eq!(changed, expected); + assert_eq!(item.sort_text, Some(auto_import_sort_text())); + } + + #[test] + async fn test_auto_imports_expands_existing_use_before_two_segments() { + let src = r#"use foo::bar::one_hello_world; + +mod foo { + pub mod bar { + pub fn one_hello_world() {} + } + pub fn two_hello_world() {} +} + +fn main() { + two_hello_>|< +}"#; + + let expected = r#"use foo::{bar::one_hello_world, two_hello_world}; + +mod foo { + pub mod bar { + pub fn one_hello_world() {} + } + pub fn two_hello_world() {} +} + +fn main() { + two_hello_ +}"#; + + let mut items = get_completions(src).await; + assert_eq!(items.len(), 1); + + let item = items.remove(0); + let changed = + apply_text_edits(&src.replace(">|<", ""), &item.additional_text_edits.unwrap()); + assert_eq!(changed, expected); + assert_eq!(item.sort_text, Some(auto_import_sort_text())); + } + + #[test] + async fn test_auto_imports_expands_existing_use_before_one_segment_inside_list() { + let src = r#"use foo::{bar::one_hello_world, baz}; + +mod foo { + pub mod bar { + pub fn one_hello_world() {} + pub fn two_hello_world() {} + } + pub mod baz {} +} + +fn main() { + two_hello_>|< +}"#; + + let expected = r#"use foo::{bar::{one_hello_world, two_hello_world}, baz}; + +mod foo { + pub mod bar { + pub fn one_hello_world() {} + pub fn two_hello_world() {} + } + pub mod baz {} +} + +fn main() { + two_hello_ +}"#; + + let mut items = get_completions(src).await; + assert_eq!(items.len(), 1); + + let item = items.remove(0); + let changed = + apply_text_edits(&src.replace(">|<", ""), &item.additional_text_edits.unwrap()); + assert_eq!(changed, expected); + assert_eq!(item.sort_text, Some(auto_import_sort_text())); + } + + #[test] + async fn test_auto_imports_expands_existing_use_before_one_segment_checks_parents() { + let src = r#"use foo::bar::baz; + +mod foo { + pub mod bar { + pub mod baz { + pub fn one_hello_world() {} + } + pub mod qux { + pub fn two_hello_world() {} + } + } +} + +fn main() { + two_hello_>|< +}"#; + + let expected = r#"use foo::bar::{baz, qux::two_hello_world}; + +mod foo { + pub mod bar { + pub mod baz { + pub fn one_hello_world() {} + } + pub mod qux { + pub fn two_hello_world() {} + } + } +} + +fn main() { + two_hello_ +}"#; + + let mut items = get_completions(src).await; + assert_eq!(items.len(), 1); + + let item = items.remove(0); + let changed = + apply_text_edits(&src.replace(">|<", ""), &item.additional_text_edits.unwrap()); + assert_eq!(changed, expected); + assert_eq!(item.sort_text, Some(auto_import_sort_text())); + } + + #[test] + async fn test_auto_imports_expands_existing_use_last_segment() { + let src = r#"use foo::bar; + +mod foo { + pub mod bar { + pub fn one_hello_world() {} + pub fn two_hello_world() {} + } +} + +fn main() { + two_hello_>|< +}"#; + + let expected = r#"use foo::bar::{self, two_hello_world}; + +mod foo { + pub mod bar { + pub fn one_hello_world() {} + pub fn two_hello_world() {} + } +} + +fn main() { + two_hello_ +}"#; + + let mut items = get_completions(src).await; + assert_eq!(items.len(), 1); + + let item = items.remove(0); + let changed = + apply_text_edits(&src.replace(">|<", ""), &item.additional_text_edits.unwrap()); + assert_eq!(changed, expected); + assert_eq!(item.sort_text, Some(auto_import_sort_text())); + } + + #[test] + async fn test_auto_imports_expands_existing_use_before_list() { + let src = r#"use foo::bar::{one_hello_world, three_hello_world}; + +mod foo { + pub mod bar { + pub fn one_hello_world() {} + pub fn two_hello_world() {} + pub fn three_hello_world() {} + } +} + +fn main() { + two_hello_>|< +}"#; + + let expected = r#"use foo::bar::{two_hello_world, one_hello_world, three_hello_world}; + +mod foo { + pub mod bar { + pub fn one_hello_world() {} + pub fn two_hello_world() {} + pub fn three_hello_world() {} + } +} + +fn main() { + two_hello_ +}"#; + + let mut items = get_completions(src).await; + assert_eq!(items.len(), 1); + + let item = items.remove(0); + let changed = + apply_text_edits(&src.replace(">|<", ""), &item.additional_text_edits.unwrap()); + assert_eq!(changed, expected); + assert_eq!(item.sort_text, Some(auto_import_sort_text())); + } + + #[test] + async fn test_auto_imports_expands_existing_use_before_empty_list() { + let src = r#"use foo::bar::{}; + +mod foo { + pub mod bar { + pub fn two_hello_world() {} + } +} + +fn main() { + two_hello_>|< +}"#; + + let expected = r#"use foo::bar::{two_hello_world}; + +mod foo { + pub mod bar { + pub fn two_hello_world() {} + } +} + +fn main() { + two_hello_ +}"#; + + let mut items = get_completions(src).await; + assert_eq!(items.len(), 1); + + let item = items.remove(0); + let changed = + apply_text_edits(&src.replace(">|<", ""), &item.additional_text_edits.unwrap()); + assert_eq!(changed, expected); + assert_eq!(item.sort_text, Some(auto_import_sort_text())); } #[test] @@ -1901,7 +2273,7 @@ mod completion_tests { async fn test_auto_import_suggests_pub_use_for_function() { let src = r#" mod bar { - mod baz { + pub mod baz { pub fn coco() {} } @@ -2370,4 +2742,42 @@ mod completion_tests { assert_completion(src, Vec::new()).await; } + + #[test] + async fn test_suggests_trait_in_trait_parent_bounds() { + let src = r#" + trait Foobar {} + struct Foobarbaz {} + + trait Bar: Foob>|< {} + "#; + assert_completion( + src, + vec![simple_completion_item( + "Foobar", + CompletionItemKind::INTERFACE, + Some("Foobar".to_string()), + )], + ) + .await; + } + + #[test] + async fn test_suggests_trait_in_function_where_clause() { + let src = r#" + trait Foobar {} + struct Foobarbaz {} + + fn foo() where T: Foob>|< {} + "#; + assert_completion( + src, + vec![simple_completion_item( + "Foobar", + CompletionItemKind::INTERFACE, + Some("Foobar".to_string()), + )], + ) + .await; + } } diff --git a/noir/noir-repo/tooling/lsp/src/requests/hover.rs b/noir/noir-repo/tooling/lsp/src/requests/hover.rs index 5087955ea77..64974a42133 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/hover.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/hover.rs @@ -4,7 +4,7 @@ use async_lsp::ResponseError; use fm::{FileMap, PathString}; use lsp_types::{Hover, HoverContents, HoverParams, MarkupContent, MarkupKind}; use noirc_frontend::{ - ast::Visibility, + ast::{ItemVisibility, Visibility}, elaborator::types::try_eval_array_length_id, hir::def_map::ModuleId, hir_def::{ @@ -13,9 +13,9 @@ use noirc_frontend::{ traits::Trait, }, node_interner::{ - DefinitionId, DefinitionKind, ExprId, FuncId, GlobalId, ReferenceId, TraitId, TypeAliasId, + DefinitionId, DefinitionKind, ExprId, FuncId, GlobalId, NodeInterner, ReferenceId, + StructId, TraitId, TypeAliasId, }, - node_interner::{NodeInterner, StructId}, Generics, Shared, StructType, Type, TypeAlias, TypeBinding, TypeVariable, }; @@ -300,26 +300,113 @@ fn get_exprs_global_value(interner: &NodeInterner, exprs: &[ExprId]) -> Option String { let func_meta = args.interner.function_meta(&id); + let func_modifiers = args.interner.function_modifiers(&id); + let func_name_definition_id = args.interner.definition(func_meta.name.id); let mut string = String::new(); let formatted_parent_module = format_parent_module(ReferenceId::Function(id), args, &mut string); - let formatted_parent_struct = if let Some(struct_id) = func_meta.struct_id { + + let formatted_parent_type = if let Some(trait_impl_id) = func_meta.trait_impl { + let trait_impl = args.interner.get_trait_implementation(trait_impl_id); + let trait_impl = trait_impl.borrow(); + let trait_ = args.interner.get_trait(trait_impl.trait_id); + + let generics: Vec<_> = + trait_impl + .trait_generics + .iter() + .filter_map(|generic| { + if let Type::NamedGeneric(_, name) = generic { + Some(name) + } else { + None + } + }) + .collect(); + + string.push('\n'); + string.push_str(" impl"); + if !generics.is_empty() { + string.push('<'); + for (index, generic) in generics.into_iter().enumerate() { + if index > 0 { + string.push_str(", "); + } + string.push_str(generic); + } + string.push('>'); + } + + string.push(' '); + string.push_str(&trait_.name.0.contents); + if !trait_impl.trait_generics.is_empty() { + string.push('<'); + for (index, generic) in trait_impl.trait_generics.iter().enumerate() { + if index > 0 { + string.push_str(", "); + } + string.push_str(&generic.to_string()); + } + string.push('>'); + } + + string.push_str(" for "); + string.push_str(&trait_impl.typ.to_string()); + + true + } else if let Some(trait_id) = func_meta.trait_id { + let trait_ = args.interner.get_trait(trait_id); + string.push('\n'); + string.push_str(" trait "); + string.push_str(&trait_.name.0.contents); + format_generics(&trait_.generics, &mut string); + + true + } else if let Some(struct_id) = func_meta.struct_id { let struct_type = args.interner.get_struct(struct_id); let struct_type = struct_type.borrow(); if formatted_parent_module { string.push_str("::"); } string.push_str(&struct_type.name.0.contents); + string.push('\n'); + string.push_str(" "); + string.push_str("impl"); + + let impl_generics: Vec<_> = func_meta + .all_generics + .iter() + .take(func_meta.all_generics.len() - func_meta.direct_generics.len()) + .cloned() + .collect(); + format_generics(&impl_generics, &mut string); + + string.push(' '); + string.push_str(&struct_type.name.0.contents); + format_generic_names(&impl_generics, &mut string); + true } else { false }; - if formatted_parent_module || formatted_parent_struct { + if formatted_parent_module || formatted_parent_type { string.push('\n'); } string.push_str(" "); + + if func_modifiers.visibility != ItemVisibility::Private { + string.push_str(&func_modifiers.visibility.to_string()); + string.push(' '); + } + if func_modifiers.is_unconstrained { + string.push_str("unconstrained "); + } + if func_modifiers.is_comptime { + string.push_str("comptime "); + } + string.push_str("fn "); string.push_str(&func_name_definition_id.name); format_generics(&func_meta.direct_generics, &mut string); @@ -411,21 +498,55 @@ fn format_local(id: DefinitionId, args: &ProcessRequestCallbackArgs) -> String { string } -/// Some doc comments fn format_generics(generics: &Generics, string: &mut String) { + format_generics_impl( + generics, false, // only show names + string, + ); +} + +fn format_generic_names(generics: &Generics, string: &mut String) { + format_generics_impl( + generics, true, // only show names + string, + ); +} + +fn format_generics_impl(generics: &Generics, only_show_names: bool, string: &mut String) { if generics.is_empty() { return; } string.push('<'); for (index, generic) in generics.iter().enumerate() { - string.push_str(&generic.name); - if index != generics.len() - 1 { + if index > 0 { string.push_str(", "); } + + if only_show_names { + string.push_str(&generic.name); + } else { + match generic.kind() { + noirc_frontend::Kind::Any | noirc_frontend::Kind::Normal => { + string.push_str(&generic.name); + } + noirc_frontend::Kind::IntegerOrField | noirc_frontend::Kind::Integer => { + string.push_str("let "); + string.push_str(&generic.name); + string.push_str(": u32"); + } + noirc_frontend::Kind::Numeric(typ) => { + string.push_str("let "); + string.push_str(&generic.name); + string.push_str(": "); + string.push_str(&typ.to_string()); + } + } + } } string.push('>'); } + fn format_pattern(pattern: &HirPattern, interner: &NodeInterner, string: &mut String) { match pattern { HirPattern::Identifier(ident) => { @@ -647,6 +768,11 @@ mod hover_tests { use tokio::test; async fn assert_hover(directory: &str, file: &str, position: Position, expected_text: &str) { + let hover_text = get_hover_text(directory, file, position).await; + assert_eq!(hover_text, expected_text); + } + + async fn get_hover_text(directory: &str, file: &str, position: Position) -> String { let (mut state, noir_text_document) = test_utils::init_lsp_server(directory).await; // noir_text_document is always `src/main.nr` in the workspace directory, so let's go to the workspace dir @@ -673,7 +799,7 @@ mod hover_tests { panic!("Expected hover contents to be Markup"); }; - assert_eq!(markup.value, expected_text); + markup.value } #[test] @@ -759,7 +885,7 @@ mod hover_tests { "two/src/lib.nr", Position { line: 3, character: 4 }, r#" one - fn function_one()"#, + pub fn function_one()"#, ) .await; } @@ -771,7 +897,7 @@ mod hover_tests { "two/src/lib.nr", Position { line: 2, character: 7 }, r#" two - fn function_two()"#, + pub fn function_two()"#, ) .await; } @@ -783,6 +909,7 @@ mod hover_tests { "two/src/lib.nr", Position { line: 20, character: 6 }, r#" one::subone::SubOneStruct + impl SubOneStruct fn foo(self, x: i32, y: i32) -> Field"#, ) .await; @@ -892,7 +1019,7 @@ mod hover_tests { assert_hover( "workspace", "two/src/lib.nr", - Position { line: 43, character: 4 }, + Position { line: 42, character: 4 }, r#" two mod other"#, ) @@ -904,7 +1031,7 @@ mod hover_tests { assert_hover( "workspace", "two/src/lib.nr", - Position { line: 44, character: 11 }, + Position { line: 43, character: 11 }, r#" two mod other"#, ) @@ -955,8 +1082,32 @@ mod hover_tests { "workspace", "two/src/lib.nr", Position { line: 54, character: 2 }, - " two\n fn attr(_: FunctionDefinition) -> Quoted", + " two\n comptime fn attr(_: FunctionDefinition) -> Quoted", ) .await; } + + #[test] + async fn hover_on_generic_struct_function() { + let hover_text = + get_hover_text("workspace", "two/src/lib.nr", Position { line: 70, character: 11 }) + .await; + assert!(hover_text.starts_with( + " two::Foo + impl Foo + fn new() -> Foo" + )); + } + + #[test] + async fn hover_on_trait_impl_function_call() { + let hover_text = + get_hover_text("workspace", "two/src/lib.nr", Position { line: 83, character: 16 }) + .await; + assert!(hover_text.starts_with( + " two + impl Bar for Foo + pub fn bar_stuff(self)" + )); + } } diff --git a/noir/noir-repo/tooling/lsp/src/requests/mod.rs b/noir/noir-repo/tooling/lsp/src/requests/mod.rs index 597d8355468..0ee66f1f618 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/mod.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/mod.rs @@ -378,7 +378,7 @@ fn character_to_line_offset(line: &str, character: u32) -> Result } } -fn to_lsp_location<'a, F>( +pub(crate) fn to_lsp_location<'a, F>( files: &'a F, file_id: F::FileId, definition_span: noirc_errors::Span, diff --git a/noir/noir-repo/tooling/lsp/src/tests.rs b/noir/noir-repo/tooling/lsp/src/tests.rs new file mode 100644 index 00000000000..7f2d48cd23f --- /dev/null +++ b/noir/noir-repo/tooling/lsp/src/tests.rs @@ -0,0 +1,33 @@ +#![cfg(test)] + +use lsp_types::TextEdit; + +pub(crate) fn apply_text_edit(src: &str, text_edit: &TextEdit) -> String { + let mut lines: Vec<_> = src.lines().collect(); + assert_eq!(text_edit.range.start.line, text_edit.range.end.line); + + let mut line = lines[text_edit.range.start.line as usize].to_string(); + line.replace_range( + text_edit.range.start.character as usize..text_edit.range.end.character as usize, + &text_edit.new_text, + ); + lines[text_edit.range.start.line as usize] = &line; + lines.join("\n") +} + +pub(crate) fn apply_text_edits(src: &str, text_edits: &[TextEdit]) -> String { + let mut text = src.to_string(); + + // Text edits must be applied from last to first, otherwise if we apply a text edit + // that comes before another one, that other one becomes invalid (it will edit the wrong + // piece of code). + let mut text_edits = text_edits.to_vec(); + text_edits.sort_by_key(|edit| (edit.range.start.line, edit.range.start.character)); + text_edits.reverse(); + + for text_edit in text_edits { + text = apply_text_edit(&text, &text_edit); + } + + text +} diff --git a/noir/noir-repo/tooling/lsp/src/use_segment_positions.rs b/noir/noir-repo/tooling/lsp/src/use_segment_positions.rs new file mode 100644 index 00000000000..f9a3f429029 --- /dev/null +++ b/noir/noir-repo/tooling/lsp/src/use_segment_positions.rs @@ -0,0 +1,336 @@ +use std::collections::HashMap; + +use fm::{FileId, FileMap}; +use lsp_types::{Position, Range, TextEdit}; +use noirc_errors::Span; +use noirc_frontend::ast::{PathKind, UseTree, UseTreeKind}; + +use crate::requests::to_lsp_location; + +/// The position of a segment in a `use` statement. +/// We use this to determine how an auto-import should be inserted. +#[derive(Debug, Default, Copy, Clone)] +pub(crate) enum UseSegmentPosition { + /// The segment either doesn't exist in the source code or there are multiple segments. + /// In this case auto-import will add a new use statement. + #[default] + NoneOrMultiple, + /// The segment is the last one in the `use` statement (or nested use statement): + /// + /// use foo::bar; + /// ^^^ + /// + /// Auto-import will transform it to this: + /// + /// use foo::bar::{self, baz}; + Last { span: Span }, + /// The segment happens before another simple (ident) segment: + /// + /// use foo::bar::qux; + /// ^^^ + /// + /// Auto-import will transform it to this: + /// + /// use foo::bar::{qux, baz}; + BeforeSegment { segment_span_until_end: Span }, + /// The segment happens before a list: + /// + /// use foo::bar::{qux, another}; + /// + /// Auto-import will transform it to this: + /// + /// use foo::bar::{qux, another, baz}; + BeforeList { first_entry_span: Span, list_is_empty: bool }, +} + +/// Remembers where each segment in a `use` statement is located. +/// The key is the full segment, so for `use foo::bar::baz` we'll have three +/// segments: `foo`, `foo::bar` and `foo::bar::baz`, where the span is just +/// for the last identifier (`foo`, `bar` and `baz` in the previous example). +#[derive(Default)] +pub(crate) struct UseSegmentPositions { + use_segment_positions: HashMap, +} + +impl UseSegmentPositions { + pub(crate) fn add(&mut self, use_tree: &UseTree) { + self.gather_use_tree_segments(use_tree, String::new()); + } + + /// Given a full path like `foo::bar::baz`, returns the first non-"NoneOrMultiple" segment position + /// trying each successive parent, together with the name after the parent. + /// + /// For example, first we'll check if `foo::bar` has a single position. If not, we'll try with `foo`. + pub(crate) fn get(&self, full_path: &str) -> (UseSegmentPosition, String) { + // Build a parent path to know in which full segment we need to add this import + let mut segments: Vec<_> = full_path.split("::").collect(); + let mut name = segments.pop().unwrap().to_string(); + let mut parent_path = segments.join("::"); + + loop { + let use_segment_position = + self.use_segment_positions.get(&parent_path).cloned().unwrap_or_default(); + + if let UseSegmentPosition::NoneOrMultiple = use_segment_position { + if let Some(next_name) = segments.pop() { + name = format!("{next_name}::{name}"); + parent_path = segments.join("::"); + } else { + return (UseSegmentPosition::NoneOrMultiple, String::new()); + } + } else { + return (use_segment_position, name); + } + } + } + + fn gather_use_tree_segments(&mut self, use_tree: &UseTree, mut prefix: String) { + let kind_string = match use_tree.prefix.kind { + PathKind::Crate => Some("crate".to_string()), + PathKind::Super => Some("super".to_string()), + PathKind::Dep | PathKind::Plain => None, + }; + if let Some(kind_string) = kind_string { + if let Some(segment) = use_tree.prefix.segments.first() { + self.insert_use_segment_position( + kind_string, + UseSegmentPosition::BeforeSegment { + segment_span_until_end: Span::from( + segment.ident.span().start()..use_tree.span.end() - 1, + ), + }, + ); + } else { + self.insert_use_segment_position_before_use_tree_kind(use_tree, kind_string); + } + } + + let prefix_segments_len = use_tree.prefix.segments.len(); + for (index, segment) in use_tree.prefix.segments.iter().enumerate() { + let ident = &segment.ident; + if !prefix.is_empty() { + prefix.push_str("::"); + }; + prefix.push_str(&ident.0.contents); + + if index < prefix_segments_len - 1 { + self.insert_use_segment_position( + prefix.clone(), + UseSegmentPosition::BeforeSegment { + segment_span_until_end: Span::from( + use_tree.prefix.segments[index + 1].ident.span().start() + ..use_tree.span.end() - 1, + ), + }, + ); + } else { + self.insert_use_segment_position_before_use_tree_kind(use_tree, prefix.clone()); + } + } + + match &use_tree.kind { + UseTreeKind::Path(ident, alias) => { + if !prefix.is_empty() { + prefix.push_str("::"); + } + prefix.push_str(&ident.0.contents); + + if alias.is_none() { + self.insert_use_segment_position( + prefix, + UseSegmentPosition::Last { span: ident.span() }, + ); + } else { + self.insert_use_segment_position(prefix, UseSegmentPosition::NoneOrMultiple); + } + } + UseTreeKind::List(use_trees) => { + for use_tree in use_trees { + self.gather_use_tree_segments(use_tree, prefix.clone()); + } + } + } + } + + fn insert_use_segment_position_before_use_tree_kind( + &mut self, + use_tree: &UseTree, + prefix: String, + ) { + match &use_tree.kind { + UseTreeKind::Path(ident, _alias) => { + self.insert_use_segment_position( + prefix, + UseSegmentPosition::BeforeSegment { + segment_span_until_end: Span::from( + ident.span().start()..use_tree.span.end() - 1, + ), + }, + ); + } + UseTreeKind::List(use_trees) => { + if let Some(first_use_tree) = use_trees.first() { + self.insert_use_segment_position( + prefix, + UseSegmentPosition::BeforeList { + first_entry_span: first_use_tree.prefix.span(), + list_is_empty: false, + }, + ); + } else { + self.insert_use_segment_position( + prefix, + UseSegmentPosition::BeforeList { + first_entry_span: Span::from( + use_tree.span.end() - 1..use_tree.span.end() - 1, + ), + list_is_empty: true, + }, + ); + } + } + } + } + + fn insert_use_segment_position(&mut self, segment: String, position: UseSegmentPosition) { + if self.use_segment_positions.get(&segment).is_none() { + self.use_segment_positions.insert(segment, position); + } else { + self.use_segment_positions.insert(segment, UseSegmentPosition::NoneOrMultiple); + } + } +} + +pub(crate) struct UseCompletionItemAdditionTextEditsRequest<'a> { + /// The full path of the use statement to insert + pub(crate) full_path: &'a str, + pub(crate) files: &'a FileMap, + pub(crate) file: FileId, + /// All of the current source lines + pub(crate) lines: &'a Vec<&'a str>, + /// How many nested `mod` we are in deep + pub(crate) nesting: usize, + /// The line where an auto_import must be inserted + pub(crate) auto_import_line: usize, +} + +/// Returns the text edits needed to add an auto-import for a given full path. +pub(crate) fn use_completion_item_additional_text_edits( + request: UseCompletionItemAdditionTextEditsRequest, + positions: &UseSegmentPositions, +) -> Vec { + let (use_segment_position, name) = positions.get(request.full_path); + match use_segment_position { + UseSegmentPosition::NoneOrMultiple => { + // The parent path either isn't in any use statement, or it exists in multiple + // use statements. In either case we'll add a new use statement. + + new_use_completion_item_additional_text_edits(request) + } + UseSegmentPosition::Last { span } => { + // We have + // + // use foo::bar; + // ^^^ -> span + // + // and we want to transform it to: + // + // use foo::bar::{self, baz}; + // ^^^^^^^^^^^^^ + // + // So we need one text edit: + // 1. insert "::{self, baz}" right after the span + if let Some(lsp_location) = to_lsp_location(request.files, request.file, span) { + let range = lsp_location.range; + vec![TextEdit { + new_text: format!("::{{self, {}}}", name), + range: Range { start: range.end, end: range.end }, + }] + } else { + new_use_completion_item_additional_text_edits(request) + } + } + UseSegmentPosition::BeforeSegment { segment_span_until_end } => { + // Go past the end + let segment_span_until_end = + Span::from(segment_span_until_end.start()..segment_span_until_end.end() + 1); + + // We have + // + // use foo::bar::{one, two}; + // ^^^^^^^^^^^^^^^ -> segment_span_until_end + // + // and we want to transform it to: + // + // use foo::{bar::{one, two}, baz}; + // ^ ^^^^^^ + // + // So we need two text edits: + // 1. insert "{" right before the segment span + // 2. insert ", baz}" right after the segment span + if let Some(lsp_location) = + to_lsp_location(request.files, request.file, segment_span_until_end) + { + let range = lsp_location.range; + vec![ + TextEdit { + new_text: "{".to_string(), + range: Range { start: range.start, end: range.start }, + }, + TextEdit { + new_text: format!(", {}}}", name), + range: Range { start: range.end, end: range.end }, + }, + ] + } else { + new_use_completion_item_additional_text_edits(request) + } + } + UseSegmentPosition::BeforeList { first_entry_span, list_is_empty } => { + // We have + // + // use foo::bar::{one, two}; + // ^^^ -> first_entry_span + // + // and we want to transform it to: + // + // use foo::bar::{baz, one, two}; + // ^^^^ + // + // So we need one text edit: + // 1. insert "baz, " right before the first entry span + if let Some(lsp_location) = + to_lsp_location(request.files, request.file, first_entry_span) + { + let range = lsp_location.range; + vec![TextEdit { + new_text: if list_is_empty { name } else { format!("{}, ", name) }, + range: Range { start: range.start, end: range.start }, + }] + } else { + new_use_completion_item_additional_text_edits(request) + } + } + } +} + +fn new_use_completion_item_additional_text_edits( + request: UseCompletionItemAdditionTextEditsRequest, +) -> Vec { + let line = request.auto_import_line as u32; + let character = (request.nesting * 4) as u32; + let indent = " ".repeat(request.nesting * 4); + let mut newlines = "\n"; + + // If the line we are inserting into is not an empty line, insert an extra line to make some room + if let Some(line_text) = request.lines.get(line as usize) { + if !line_text.trim().is_empty() { + newlines = "\n\n"; + } + } + + vec![TextEdit { + range: Range { start: Position { line, character }, end: Position { line, character } }, + new_text: format!("use {};{}{}", request.full_path, newlines, indent), + }] +} diff --git a/noir/noir-repo/tooling/lsp/src/visibility.rs b/noir/noir-repo/tooling/lsp/src/visibility.rs index 207302f327e..6a21525f069 100644 --- a/noir/noir-repo/tooling/lsp/src/visibility.rs +++ b/noir/noir-repo/tooling/lsp/src/visibility.rs @@ -4,12 +4,23 @@ use noirc_frontend::{ ast::ItemVisibility, graph::CrateId, hir::{ - def_map::{CrateDefMap, ModuleId}, + def_map::{CrateDefMap, ModuleDefId, ModuleId}, resolution::visibility::can_reference_module_id, }, + node_interner::NodeInterner, }; -pub(super) fn is_visible( +use crate::modules::get_parent_module; + +/// Returns true if an item with the given visibility in the target module +/// is visible from the current module. For example: +/// +/// mod foo { +/// ^^^ <-- target module +/// pub(crate) fn bar() {} +/// ^^^^^^^^^^ <- visibility +/// } +pub(super) fn item_in_module_is_visible( target_module_id: ModuleId, current_module_id: ModuleId, visibility: ItemVisibility, @@ -23,3 +34,45 @@ pub(super) fn is_visible( visibility, ) } + +/// Returns true if the given ModuleDefId is visible from the current module, given its visibility. +/// This will in turn check if the ModuleDefId parent modules are visible from the current module. +/// If `defining_module` is Some, it will be considered as the parent of the item to check +/// (this is the case when the item is re-exported with `pub use` or similar). +pub(super) fn module_def_id_is_visible( + module_def_id: ModuleDefId, + current_module_id: ModuleId, + mut visibility: ItemVisibility, + mut defining_module: Option, + interner: &NodeInterner, + def_maps: &BTreeMap, +) -> bool { + // First find out which module we need to check. + // If a module is trying to be referenced, it's that module. Otherwise it's the module that contains the item. + let mut target_module_id = if let ModuleDefId::ModuleId(module_id) = module_def_id { + Some(module_id) + } else { + std::mem::take(&mut defining_module).or_else(|| get_parent_module(interner, module_def_id)) + }; + + // Then check if it's visible, and upwards + while let Some(module_id) = target_module_id { + if !item_in_module_is_visible(module_id, current_module_id, visibility, def_maps) { + return false; + } + + target_module_id = std::mem::take(&mut defining_module).or_else(|| { + let module_data = &def_maps[&module_id.krate].modules()[module_id.local_id.0]; + let parent_local_id = module_data.parent; + parent_local_id.map(|local_id| ModuleId { krate: module_id.krate, local_id }) + }); + + // This is a bit strange, but the visibility is always that of the item inside another module, + // so the visibility we update here is for the next loop check. + visibility = interner + .try_module_attributes(&module_id) + .map_or(ItemVisibility::Public, |attributes| attributes.visibility); + } + + true +} diff --git a/noir/noir-repo/tooling/lsp/test_programs/workspace/two/src/lib.nr b/noir/noir-repo/tooling/lsp/test_programs/workspace/two/src/lib.nr index c6b516d88ab..2dec902f327 100644 --- a/noir/noir-repo/tooling/lsp/test_programs/workspace/two/src/lib.nr +++ b/noir/noir-repo/tooling/lsp/test_programs/workspace/two/src/lib.nr @@ -41,8 +41,8 @@ fn use_impl_method() { } mod other; -use other::another_function; use crate::other::other_function; +use other::another_function; use one::subone::GenericStruct; @@ -57,4 +57,30 @@ pub fn foo() {} comptime fn attr(_: FunctionDefinition) -> Quoted { quote { pub fn hello() {} } -} \ No newline at end of file +} + +struct Foo {} + +impl Foo { + fn new() -> Self { + Foo {} + } +} + +fn new_foo() -> Foo { + Foo::new() +} + +trait Bar { + fn bar_stuff(self); +} + +impl Bar for Foo { + fn bar_stuff(self) {} +} + +fn bar_stuff() { + let foo = Foo::new(); + foo.bar_stuff(); +} + diff --git a/noir/noir-repo/tooling/nargo/src/ops/execute.rs b/noir/noir-repo/tooling/nargo/src/ops/execute.rs index eb03bdf01c1..09ef554d2aa 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/execute.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/execute.rs @@ -3,7 +3,9 @@ use acvm::acir::circuit::{ OpcodeLocation, Program, ResolvedAssertionPayload, ResolvedOpcodeLocation, }; use acvm::acir::native_types::WitnessStack; -use acvm::pwg::{ACVMStatus, ErrorLocation, OpcodeNotSolvable, OpcodeResolutionError, ACVM}; +use acvm::pwg::{ + ACVMStatus, ErrorLocation, OpcodeNotSolvable, OpcodeResolutionError, ProfilingSamples, ACVM, +}; use acvm::{acir::circuit::Circuit, acir::native_types::WitnessMap}; use acvm::{AcirField, BlackBoxFunctionSolver}; @@ -32,6 +34,10 @@ struct ProgramExecutor<'a, F, B: BlackBoxFunctionSolver, E: ForeignCallExecut // This is used to fetch the function we want to execute // and to resolve call stack locations across many function calls. current_function_index: usize, + + // Flag that states whether we want to profile the VM. Profiling can add extra + // execution costs so we want to make sure we only trigger it explicitly. + profiling_active: bool, } impl<'a, F: AcirField, B: BlackBoxFunctionSolver, E: ForeignCallExecutor> @@ -42,6 +48,7 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver, E: ForeignCallExecutor> unconstrained_functions: &'a [BrilligBytecode], blackbox_solver: &'a B, foreign_call_executor: &'a mut E, + profiling_active: bool, ) -> Self { ProgramExecutor { functions, @@ -51,6 +58,7 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver, E: ForeignCallExecutor> foreign_call_executor, call_stack: Vec::default(), current_function_index: 0, + profiling_active, } } @@ -62,7 +70,7 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver, E: ForeignCallExecutor> fn execute_circuit( &mut self, initial_witness: WitnessMap, - ) -> Result, NargoError> { + ) -> Result<(WitnessMap, ProfilingSamples), NargoError> { let circuit = &self.functions[self.current_function_index]; let mut acvm = ACVM::new( self.blackbox_solver, @@ -71,6 +79,7 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver, E: ForeignCallExecutor> self.unconstrained_functions, &circuit.assert_messages, ); + acvm.with_profiler(self.profiling_active); loop { let solver_status = acvm.solve(); @@ -155,7 +164,8 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver, E: ForeignCallExecutor> // Execute the ACIR call let acir_to_call = &self.functions[call_info.id.as_usize()]; let initial_witness = call_info.initial_witness; - let call_solved_witness = self.execute_circuit(initial_witness)?; + // TODO: Profiling among multiple circuits is not supported + let (call_solved_witness, _) = self.execute_circuit(initial_witness)?; // Set tracking index back to the parent function after ACIR call execution self.current_function_index = acir_function_caller; @@ -184,25 +194,67 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver, E: ForeignCallExecutor> // included in a failure case. self.call_stack.clear(); - Ok(acvm.finalize()) + let profiling_samples = acvm.take_profiling_samples(); + Ok((acvm.finalize(), profiling_samples)) } } -#[tracing::instrument(level = "trace", skip_all)] pub fn execute_program, E: ForeignCallExecutor>( program: &Program, initial_witness: WitnessMap, blackbox_solver: &B, foreign_call_executor: &mut E, ) -> Result, NargoError> { + let profiling_active = false; + let (witness_stack, profiling_samples) = execute_program_inner( + program, + initial_witness, + blackbox_solver, + foreign_call_executor, + profiling_active, + )?; + assert!(profiling_samples.is_empty(), "Expected no profiling samples"); + + Ok(witness_stack) +} + +pub fn execute_program_with_profiling< + F: AcirField, + B: BlackBoxFunctionSolver, + E: ForeignCallExecutor, +>( + program: &Program, + initial_witness: WitnessMap, + blackbox_solver: &B, + foreign_call_executor: &mut E, +) -> Result<(WitnessStack, ProfilingSamples), NargoError> { + let profiling_active = true; + execute_program_inner( + program, + initial_witness, + blackbox_solver, + foreign_call_executor, + profiling_active, + ) +} + +#[tracing::instrument(level = "trace", skip_all)] +fn execute_program_inner, E: ForeignCallExecutor>( + program: &Program, + initial_witness: WitnessMap, + blackbox_solver: &B, + foreign_call_executor: &mut E, + profiling_active: bool, +) -> Result<(WitnessStack, ProfilingSamples), NargoError> { let mut executor = ProgramExecutor::new( &program.functions, &program.unconstrained_functions, blackbox_solver, foreign_call_executor, + profiling_active, ); - let main_witness = executor.execute_circuit(initial_witness)?; + let (main_witness, profiling_samples) = executor.execute_circuit(initial_witness)?; executor.witness_stack.push(0, main_witness); - Ok(executor.finalize()) + Ok((executor.finalize(), profiling_samples)) } diff --git a/noir/noir-repo/tooling/nargo/src/ops/mod.rs b/noir/noir-repo/tooling/nargo/src/ops/mod.rs index cada2f0e915..16680dab980 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/mod.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/mod.rs @@ -2,7 +2,7 @@ pub use self::compile::{ collect_errors, compile_contract, compile_program, compile_program_with_debug_instrumenter, compile_workspace, report_errors, }; -pub use self::execute::execute_program; +pub use self::execute::{execute_program, execute_program_with_profiling}; pub use self::foreign_calls::{DefaultForeignCallExecutor, ForeignCall, ForeignCallExecutor}; pub use self::optimize::{optimize_contract, optimize_program}; pub use self::transform::{transform_contract, transform_program}; diff --git a/noir/noir-repo/tooling/nargo_cli/Cargo.toml b/noir/noir-repo/tooling/nargo_cli/Cargo.toml index d72556ab936..d48e44415b0 100644 --- a/noir/noir-repo/tooling/nargo_cli/Cargo.toml +++ b/noir/noir-repo/tooling/nargo_cli/Cargo.toml @@ -86,6 +86,7 @@ sha2.workspace = true sha3.workspace = true iai = "0.1.1" test-binary = "3.0.2" +test-case.workspace = true light-poseidon = "0.2.0" diff --git a/noir/noir-repo/tooling/nargo_cli/tests/stdlib-tests.rs b/noir/noir-repo/tooling/nargo_cli/tests/stdlib-tests.rs index d27a2961a62..bdc92e625ab 100644 --- a/noir/noir-repo/tooling/nargo_cli/tests/stdlib-tests.rs +++ b/noir/noir-repo/tooling/nargo_cli/tests/stdlib-tests.rs @@ -1,4 +1,5 @@ //! Execute unit tests in the Noir standard library. +#![allow(clippy::items_after_test_module)] use clap::Parser; use fm::FileManager; use noirc_driver::{check_crate, file_manager_with_stdlib, CompileOptions}; @@ -12,6 +13,7 @@ use nargo::{ parse_all, prepare_package, }; use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; +use test_case::test_matrix; #[derive(Parser, Debug)] #[command(ignore_errors = true)] @@ -29,14 +31,22 @@ pub struct Options { impl Options { pub fn function_name_match(&self) -> FunctionNameMatch { match self.args.as_slice() { - [_, lib] => FunctionNameMatch::Contains(lib.as_str()), + [_test_name, lib] => FunctionNameMatch::Contains(lib.as_str()), _ => FunctionNameMatch::Anything, } } } -#[test] -fn run_stdlib_tests() { +/// Inliner aggressiveness results in different SSA. +/// Inlining happens if `inline_cost - retain_cost < aggressiveness` (see `inlining.rs`). +/// NB the CLI uses maximum aggressiveness. +/// +/// Even with the same inlining aggressiveness, forcing Brillig can trigger different behaviour. +#[test_matrix( + [false, true], + [i64::MIN, 0, i64::MAX] +)] +fn run_stdlib_tests(force_brillig: bool, inliner_aggressiveness: i64) { let opts = Options::parse(); let mut file_manager = file_manager_with_stdlib(&PathBuf::from(".")); @@ -76,11 +86,11 @@ fn run_stdlib_tests() { &bn254_blackbox_solver::Bn254BlackBoxSolver, &mut context, &test_function, - false, + true, None, Some(dummy_package.root_dir.clone()), Some(dummy_package.name.to_string()), - &CompileOptions::default(), + &CompileOptions { force_brillig, inliner_aggressiveness, ..Default::default() }, ); (test_name, status) }) diff --git a/noir/noir-repo/tooling/nargo_fmt/src/chunks.rs b/noir/noir-repo/tooling/nargo_fmt/src/chunks.rs index 073e03ea74a..0e55dfad3b7 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/chunks.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/chunks.rs @@ -466,7 +466,11 @@ pub(crate) enum GroupKind { /// fit in the current line and it's not a block, instead of splitting that expression /// somewhere that's probably undesired, we'll "turn it" into a block /// (write the "{" and "}" delimiters) and write the lambda body in the next line. - LambdaBody { is_block: bool }, + LambdaBody { + block_statement_count: Option, + has_comments: bool, + lambda_has_return_type: bool, + }, /// A method call. /// We track all this information to see, if we end up needing to format this call /// in multiple lines, if we can write everything up to the left parentheses (inclusive) @@ -762,14 +766,14 @@ impl<'a> Formatter<'a> { // If a lambda body doesn't fit in the current line and it's not a block, // we can turn it into a block and write it in the next line, so its contents fit. - if let GroupKind::LambdaBody { is_block: false } = group.kind { + if let GroupKind::LambdaBody { block_statement_count: None, .. } = group.kind { // Try to format it again in the next line, but we don't want to recurse // infinitely so we change the group kind. group.kind = GroupKind::Regular; self.write("{"); self.trim_spaces(); self.increase_indentation(); - self.write_line(); + self.write_line_without_skipping_whitespace_and_comments(); self.write_indentation(); self.format_chunk_group_impl(group); @@ -803,7 +807,7 @@ impl<'a> Formatter<'a> { // ) let comma_trimmed = self.trim_comma(); self.decrease_indentation(); - self.write_line(); + self.write_line_without_skipping_whitespace_and_comments(); self.write_indentation(); self.write("}"); if comma_trimmed { @@ -816,6 +820,24 @@ impl<'a> Formatter<'a> { return; } + // At this point we determined we are going to write this group in a single line. + // If the current group is a lambda body that is a block with a single statement, like this: + // + // |x| { 1 + 2 } + // + // given that we determined the block fits the current line, if we remove the surrounding + // `{ .. }` it will still fit the current line, and reduce some noise from the code + // (this is what rustfmt seems to do too). + if let GroupKind::LambdaBody { + block_statement_count: Some(1), + has_comments: false, + lambda_has_return_type: false, + } = group.kind + { + self.format_lambda_body_removing_braces(group); + return; + } + self.format_chunk_group_in_one_line(group); } @@ -827,10 +849,10 @@ impl<'a> Formatter<'a> { } Chunk::TrailingComment(text_chunk) | Chunk::LeadingComment(text_chunk) => { self.write(&text_chunk.string); - self.write(" "); + self.write_space_without_skipping_whitespace_and_comments(); } Chunk::Group(chunks) => self.format_chunk_group_impl(chunks), - Chunk::SpaceOrLine => self.write(" "), + Chunk::SpaceOrLine => self.write_space_without_skipping_whitespace_and_comments(), Chunk::IncreaseIndentation => self.increase_indentation(), Chunk::DecreaseIndentation => self.decrease_indentation(), Chunk::PushIndentation => self.push_indentation(), @@ -893,9 +915,16 @@ impl<'a> Formatter<'a> { self.write_indentation(); } Chunk::LeadingComment(text_chunk) => { + let ends_with_newline = text_chunk.string.ends_with('\n'); self.write_chunk_lines(text_chunk.string.trim()); - self.write_line_without_skipping_whitespace_and_comments(); - self.write_indentation(); + + // Respect whether the leading comment had a newline before what comes next or not + if ends_with_newline { + self.write_line_without_skipping_whitespace_and_comments(); + self.write_indentation(); + } else { + self.write_space_without_skipping_whitespace_and_comments(); + } } Chunk::Group(mut group) => { if chunks.force_multiline_on_children_with_same_tag_if_multiline @@ -939,9 +968,39 @@ impl<'a> Formatter<'a> { } } + fn format_lambda_body_removing_braces(&mut self, group: ChunkGroup) { + // Write to an intermediate string so we can remove the braces if needed. + let text_chunk = self.chunk_formatter().chunk(|formatter| { + formatter.format_chunk_group_in_one_line(group); + }); + let string = text_chunk.string; + + // Don't remove the braces if the lambda's body is a Semi expression. + if string.ends_with("; }") || string.ends_with("; },") { + self.write(&string); + return; + } + + let string = string.strip_prefix("{ ").unwrap(); + + // The lambda might have a trailing comma if it's inside an arguments list + if let Some(string) = string.strip_suffix(" },") { + self.write(string); + self.write(","); + } else { + let string = string.strip_suffix(" }").unwrap(); + self.write(string); + } + } + /// Appends the string to the current buffer line by line, with some pre-checks. fn write_chunk_lines(&mut self, string: &str) { - for (index, line) in string.lines().enumerate() { + let lines: Vec<_> = string.lines().collect(); + + let mut index = 0; + while index < lines.len() { + let line = &lines[index]; + // Don't indent the first line (it should already be indented). // Also don't indent if the current line already has a space as the last char // (it means it's already indented) @@ -961,6 +1020,14 @@ impl<'a> Formatter<'a> { } else { self.write(line); } + + index += 1; + + // If a newline comes next too, write multiple lines to preserve original formatting + while index < lines.len() && lines[index].is_empty() { + self.write_multiple_lines_without_skipping_whitespace_and_comments(); + index += 1; + } } } diff --git a/noir/noir-repo/tooling/nargo_fmt/src/formatter/comments_and_whitespace.rs b/noir/noir-repo/tooling/nargo_fmt/src/formatter/comments_and_whitespace.rs index e5f15bc397e..547d33348b8 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/formatter/comments_and_whitespace.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/formatter/comments_and_whitespace.rs @@ -301,8 +301,8 @@ mod tests { let src = "global x = [ /* hello */ 1 , 2 ] ;"; let expected = "global x = [ - /* hello */ - 1, 2, + /* hello */ 1, + 2, ]; "; assert_format_with_max_width(src, expected, 20); @@ -643,7 +643,10 @@ mod foo; /* hello */ } "; - let expected = "struct Foo { /* hello */ }\n"; + let expected = "struct Foo { + /* hello */ +} +"; assert_format(src, expected); } diff --git a/noir/noir-repo/tooling/nargo_fmt/src/formatter/expression.rs b/noir/noir-repo/tooling/nargo_fmt/src/formatter/expression.rs index 6f7ebf56348..239b52b7d04 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/formatter/expression.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/formatter/expression.rs @@ -198,6 +198,8 @@ impl<'a, 'b> ChunkFormatter<'a, 'b> { fn format_lambda(&mut self, lambda: Lambda) -> FormattedLambda { let mut group = ChunkGroup::new(); + let lambda_has_return_type = lambda.return_type.typ != UnresolvedTypeData::Unspecified; + let params_and_return_type_chunk = self.chunk(|formatter| { formatter.write_token(Token::Pipe); for (index, (pattern, typ)) in lambda.parameters.into_iter().enumerate() { @@ -218,7 +220,7 @@ impl<'a, 'b> ChunkFormatter<'a, 'b> { } formatter.write_token(Token::Pipe); formatter.write_space(); - if lambda.return_type.typ != UnresolvedTypeData::Unspecified { + if lambda_has_return_type { formatter.write_token(Token::Arrow); formatter.write_space(); formatter.format_type(lambda.return_type); @@ -230,16 +232,27 @@ impl<'a, 'b> ChunkFormatter<'a, 'b> { group.text(params_and_return_type_chunk); - let body_is_block = matches!(lambda.body.kind, ExpressionKind::Block(..)); + let block_statement_count = if let ExpressionKind::Block(block) = &lambda.body.kind { + Some(block.statements.len()) + } else { + None + }; let mut body_group = ChunkGroup::new(); - body_group.kind = GroupKind::LambdaBody { is_block: body_is_block }; + let comments_count_before_body = self.written_comments_count; self.format_expression(lambda.body, &mut body_group); + + body_group.kind = GroupKind::LambdaBody { + block_statement_count, + has_comments: self.written_comments_count > comments_count_before_body, + lambda_has_return_type, + }; + group.group(body_group); let first_line_width = params_and_return_type_chunk_width - + (if body_is_block { + + (if block_statement_count.is_some() { // 1 because we already have `|param1, param2, ..., paramN| ` (including the space) // so all that's left is a `{`. 1 @@ -297,6 +310,24 @@ impl<'a, 'b> ChunkFormatter<'a, 'b> { } pub(super) fn format_quote(&mut self) -> ChunkGroup { + // A quote's prefix isn't captured in the token, so let's figure it out which one + // is it by looking at the source code. + let mut quote_source_code = + &self.source[self.token_span.start() as usize..self.token_span.end() as usize]; + + // Remove "quote" and any whitespace following it + quote_source_code = quote_source_code.strip_prefix("quote").unwrap(); + quote_source_code = quote_source_code.trim_start(); + + // The first char is the delimiter + let delimiter_start = quote_source_code.chars().next().unwrap(); + let delimiter_end = match delimiter_start { + '(' => ')', + '{' => '}', + '[' => ']', + _ => panic!("Unexpected delimiter: {}", delimiter_start), + }; + // We use the current token rather than the Tokens we got from `Token::Quote` because // the current token has whitespace and comments in it, while the one we got from // the parser doesn't. @@ -306,11 +337,13 @@ impl<'a, 'b> ChunkFormatter<'a, 'b> { let mut group = ChunkGroup::new(); group.verbatim(self.chunk(|formatter| { - formatter.write("quote {"); + formatter.write("quote"); + formatter.write_space(); + formatter.write(&delimiter_start.to_string()); for token in tokens.0 { formatter.write_source_span(token.to_span()); } - formatter.write("}"); + formatter.write(&delimiter_end.to_string()); })); group } @@ -433,23 +466,22 @@ impl<'a, 'b> ChunkFormatter<'a, 'b> { { let mut comments_chunk = self.skip_comments_and_whitespace_chunk(); - // If the comment is not empty but doesn't have newlines, it's surely `/* comment */`. - // We format that with spaces surrounding it so it looks, for example, like `Foo { /* comment */ field ..`. - if !comments_chunk.string.trim().is_empty() && !comments_chunk.has_newlines { - // Note: there's no space after `{}` because space will be produced by format_items_separated_by_comma - comments_chunk.string = if surround_with_spaces { - format!(" {}", comments_chunk.string.trim()) - } else { - format!(" {} ", comments_chunk.string.trim()) - }; - group.text(comments_chunk); - + // Handle leading block vs. line comments a bit differently. + if comments_chunk.string.trim().starts_with("/*") { group.increase_indentation(); if surround_with_spaces { group.space_or_line(); } else { group.line(); } + + // Note: there's no space before `{}` because it was just produced + comments_chunk.string = if surround_with_spaces { + comments_chunk.string.trim().to_string() + } else { + format!("{} ", comments_chunk.string.trim()) + }; + group.leading_comment(comments_chunk); } else { group.increase_indentation(); if surround_with_spaces { @@ -466,7 +498,24 @@ impl<'a, 'b> ChunkFormatter<'a, 'b> { group.text_attached_to_last_group(self.chunk(|formatter| { formatter.write_comma(); })); - group.trailing_comment(self.skip_comments_and_whitespace_chunk()); + let newlines_count_before_comment = self.following_newlines_count(); + group.text(self.chunk(|formatter| { + formatter.skip_whitespace(); + })); + if let Token::BlockComment(..) = &self.token { + // We let block comments be part of the item that's going to be formatted + } else { + // Line comments can be trailing or leading, depending on whether there are newlines before them + let comments_and_whitespace_chunk = self.skip_comments_and_whitespace_chunk(); + if !comments_and_whitespace_chunk.string.trim().is_empty() { + if newlines_count_before_comment > 0 { + group.line(); + group.leading_comment(comments_and_whitespace_chunk); + } else { + group.trailing_comment(comments_and_whitespace_chunk); + } + } + } group.space_or_line(); } format_item(self, expr, group); @@ -1113,6 +1162,9 @@ impl<'a, 'b> ChunkFormatter<'a, 'b> { pub(super) fn empty_block_contents_chunk(&mut self) -> Option { let mut group = ChunkGroup::new(); group.increase_indentation(); + + let newlines_count = self.following_newlines_count(); + let mut chunk = self.chunk(|formatter| { formatter.skip_comments_and_whitespace_writing_multiple_lines_if_found(); }); @@ -1122,15 +1174,13 @@ impl<'a, 'b> ChunkFormatter<'a, 'b> { // so there's nothing to write. None } else { - if chunk.string.trim_start().starts_with("//") { - group.text(chunk); - group.decrease_indentation(); - group.line(); - } else { + // If we have a trailing comment, preserve it in the same line + if newlines_count == 0 && !chunk.string.trim_start().starts_with("//") { chunk.string = format!(" {} ", chunk.string.trim()); - group.text(chunk); - group.decrease_indentation(); } + group.text(chunk); + group.decrease_indentation(); + group.line(); Some(group) } } @@ -1313,6 +1363,56 @@ global y = 1; assert_format_with_config(src, expected, config); } + #[test] + fn format_short_array_with_block_comment_before_elements() { + let src = "global x = [ /* one */ 1, /* two */ 2 ] ;"; + let expected = "global x = [/* one */ 1, /* two */ 2];\n"; + + assert_format(src, expected); + } + + #[test] + fn format_long_array_with_block_comment_before_elements() { + let src = "global x = [ /* one */ 1, /* two */ 123456789012345, 3, 4 ] ;"; + let expected = "global x = [ + /* one */ 1, + /* two */ 123456789012345, + 3, + 4, +]; +"; + + let config = + Config { short_array_element_width_threshold: 5, max_width: 30, ..Config::default() }; + assert_format_with_config(src, expected, config); + } + + #[test] + fn format_long_array_with_line_comment_before_elements() { + let src = "global x = [ + // one + 1, + // two + 123456789012345, + 3, + 4, +]; +"; + let expected = "global x = [ + // one + 1, + // two + 123456789012345, + 3, + 4, +]; +"; + + let config = + Config { short_array_element_width_threshold: 5, max_width: 30, ..Config::default() }; + assert_format_with_config(src, expected, config); + } + #[test] fn format_cast() { let src = "global x = 1 as u8 ;"; @@ -1965,6 +2065,13 @@ global y = 1; assert_format(src, expected); } + #[test] + fn format_quote_with_bracket_delimiter() { + let src = "global x = quote [ 1 2 3 $four $(five) ];"; + let expected = "global x = quote [ 1 2 3 $four $(five) ];\n"; + assert_format(src, expected); + } + #[test] fn format_lambda_no_parameters() { let src = "global x = | | 1 ;"; @@ -1980,12 +2087,44 @@ global y = 1; } #[test] - fn format_lambda_with_block() { + fn format_lambda_with_block_simplifies() { let src = "global x = | | { 1 } ;"; - let expected = "global x = || { 1 };\n"; + let expected = "global x = || 1;\n"; + assert_format(src, expected); + } + + #[test] + fn format_lambda_with_block_does_not_simplify_if_it_ends_with_semicolon() { + let src = "global x = | | { 1; } ;"; + let expected = "global x = || { 1; };\n"; + assert_format(src, expected); + } + + #[test] + fn format_lambda_with_block_does_not_simplify_if_it_has_return_type() { + let src = "global x = | | -> i32 { 1 } ;"; + let expected = "global x = || -> i32 { 1 };\n"; assert_format(src, expected); } + #[test] + fn format_lambda_with_simplifies_block_with_quote() { + let src = "global x = | | { quote { 1 } } ;"; + let expected = "global x = || quote { 1 };\n"; + assert_format(src, expected); + } + + #[test] + fn format_lambda_with_block_simplifies_inside_arguments_list() { + let src = "global x = some_call(this_is_a_long_argument, | | { 1 });"; + let expected = "global x = some_call( + this_is_a_long_argument, + || 1, +); +"; + assert_format_with_max_width(src, expected, 20); + } + #[test] fn format_lambda_with_block_multiple_statements() { let src = "global x = | a, b | { 1; 2 } ;"; diff --git a/noir/noir-repo/tooling/nargo_fmt/src/formatter/module.rs b/noir/noir-repo/tooling/nargo_fmt/src/formatter/module.rs index 00ac9fe2f47..3df9b7e0c90 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/formatter/module.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/formatter/module.rs @@ -31,27 +31,17 @@ impl<'a> Formatter<'a> { self.write_space(); self.write_identifier(submodule.name); self.write_space(); + self.write_left_brace(); if parsed_module_is_empty(&submodule.contents) { - self.write_left_brace(); - self.increase_indentation(); - - let comments_count_before = self.written_comments_count; - self.skip_comments_and_whitespace_writing_multiple_lines_if_found(); - self.decrease_indentation(); - if self.written_comments_count > comments_count_before { - self.write_line(); - self.write_indentation(); - } - self.write_right_brace(); + self.format_empty_block_contents(); } else { - self.write_left_brace(); self.increase_indentation(); self.write_line(); self.format_parsed_module(submodule.contents, self.ignore_next); self.decrease_indentation(); self.write_indentation(); - self.write_right_brace(); } + self.write_right_brace(); } } @@ -102,6 +92,18 @@ mod foo;\n"; assert_format(src, expected); } + #[test] + fn format_empty_submodule_2() { + let src = "mod foo { mod bar { + + } }"; + let expected = "mod foo { + mod bar {} +} +"; + assert_format(src, expected); + } + #[test] fn format_empty_subcontract() { let src = "contract foo { }"; diff --git a/noir/noir-repo/tooling/nargo_fmt/src/formatter/statement.rs b/noir/noir-repo/tooling/nargo_fmt/src/formatter/statement.rs index b0692d2d631..28107294909 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/formatter/statement.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/formatter/statement.rs @@ -568,10 +568,10 @@ mod tests { #[test] fn format_two_for_separated_by_multiple_lines() { - let src = " fn foo() { for x in array { 1 } - + let src = " fn foo() { for x in array { 1 } + for x in array { 1 } - + } "; let expected = "fn foo() { for x in array { diff --git a/noir/noir-repo/tooling/nargo_fmt/src/formatter/use_tree.rs b/noir/noir-repo/tooling/nargo_fmt/src/formatter/use_tree.rs index bc8dc3fcabb..98d63ef6611 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/formatter/use_tree.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/formatter/use_tree.rs @@ -211,7 +211,7 @@ mod tests { #[test] fn format_use_list_one_item_with_comments() { let src = " use foo::{ /* do not remove me */ bar, };"; - let expected = "use foo::{ /* do not remove me */ bar};\n"; + let expected = "use foo::{/* do not remove me */ bar};\n"; assert_format(src, expected); } diff --git a/noir/noir-repo/tooling/nargo_fmt/src/formatter/use_tree_merge.rs b/noir/noir-repo/tooling/nargo_fmt/src/formatter/use_tree_merge.rs index e24b7b8cbf6..834280ddba3 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/formatter/use_tree_merge.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/formatter/use_tree_merge.rs @@ -397,7 +397,7 @@ mod tests { #[test] fn format_use_list_one_item_with_comments() { let src = " use foo::{ /* do not remove me */ bar, };"; - let expected = "use foo::{ /* do not remove me */ bar};\n"; + let expected = "use foo::{/* do not remove me */ bar};\n"; assert_format(src, expected); } diff --git a/noir/noir-repo/tooling/nargo_fmt/tests/expected/contract.nr b/noir/noir-repo/tooling/nargo_fmt/tests/expected/contract.nr index ad53e61c911..86f8d56b62d 100644 --- a/noir/noir-repo/tooling/nargo_fmt/tests/expected/contract.nr +++ b/noir/noir-repo/tooling/nargo_fmt/tests/expected/contract.nr @@ -34,7 +34,7 @@ contract Benchmarking { notes: Map::new( context, 1, - |context, slot| { PrivateSet::new(context, slot, ValueNoteMethods) }, + |context, slot| PrivateSet::new(context, slot, ValueNoteMethods), ), balances: Map::new( context, diff --git a/noir/noir-repo/tooling/nargo_fmt/tests/expected/tuple.nr b/noir/noir-repo/tooling/nargo_fmt/tests/expected/tuple.nr index d4b8b239815..29f32f83e55 100644 --- a/noir/noir-repo/tooling/nargo_fmt/tests/expected/tuple.nr +++ b/noir/noir-repo/tooling/nargo_fmt/tests/expected/tuple.nr @@ -4,13 +4,13 @@ fn main() { // hello 1, ); - ( /*hello*/ 1,); + (/*hello*/ 1,); (1/*hello*/,); (1,); - ( /*test*/ 1,); - ( /*a*/ 1/*b*/,); - ( /*a*/ 1/*b*/, /*c*/ 2/*d*/, /*c*/ 2/*d*/); - ( /*a*/ 1/*b*/, /*c*/ 2/*d*/, /*c*/ 2/*d*/, /*e*/ 3/*f*/); + (/*test*/ 1,); + (/*a*/ 1/*b*/,); + (/*a*/ 1/*b*/, /*c*/ 2/*d*/, /*c*/ 2/*d*/); + (/*a*/ 1/*b*/, /*c*/ 2/*d*/, /*c*/ 2/*d*/, /*e*/ 3/*f*/); (1 /*1*/, 2 /* 2*/); @@ -28,7 +28,7 @@ fn main() { 2, ); - ( /*1*/ 1, /*2*/ 2); + (/*1*/ 1, /*2*/ 2); ( ( @@ -39,14 +39,8 @@ fn main() { ), ); ( - /*a*/ - 1 - /*b*/, - /*c*/ - 2/*d*/, - /*c*/ - 2/*d*/, - /*e*/ - 3,/*f*/ + /*a*/ 1 + /*b*/, /*c*/ + 2/*d*/, /*c*/ 2/*d*/, /*e*/ 3,/*f*/ ); } diff --git a/noir/noir-repo/tooling/noirc_abi_wasm/build.sh b/noir/noir-repo/tooling/noirc_abi_wasm/build.sh index c07d2d8a4c1..16fb26e55db 100755 --- a/noir/noir-repo/tooling/noirc_abi_wasm/build.sh +++ b/noir/noir-repo/tooling/noirc_abi_wasm/build.sh @@ -25,7 +25,7 @@ function run_if_available { require_command jq require_command cargo require_command wasm-bindgen -#require_command wasm-opt +require_command wasm-opt self_path=$(dirname "$(readlink -f "$0")") pname=$(cargo read-manifest | jq -r '.name') diff --git a/noir/noir-repo/tooling/noirc_abi_wasm/test/browser/errors.test.ts b/noir/noir-repo/tooling/noirc_abi_wasm/test/browser/errors.test.ts index 0f75ff64a3e..cc060cff4d6 100644 --- a/noir/noir-repo/tooling/noirc_abi_wasm/test/browser/errors.test.ts +++ b/noir/noir-repo/tooling/noirc_abi_wasm/test/browser/errors.test.ts @@ -9,7 +9,7 @@ it('errors when an integer input overflows', async () => { const { abi, inputs } = await import('../shared/uint_overflow'); expect(() => abiEncode(abi, inputs)).to.throw( - 'The value passed for parameter `foo` does not match the specified type:\nValue Field(2³⁸) does not fall within range of allowable values for a Integer { sign: Unsigned, width: 32 }', + 'The value passed for parameter `foo` does not match the specified type:\nValue Field(274877906944) does not fall within range of allowable values for a Integer { sign: Unsigned, width: 32 }', ); }); diff --git a/noir/noir-repo/tooling/noirc_abi_wasm/test/node/errors.test.ts b/noir/noir-repo/tooling/noirc_abi_wasm/test/node/errors.test.ts index fba451b4a8c..491fd5a5671 100644 --- a/noir/noir-repo/tooling/noirc_abi_wasm/test/node/errors.test.ts +++ b/noir/noir-repo/tooling/noirc_abi_wasm/test/node/errors.test.ts @@ -5,7 +5,7 @@ it('errors when an integer input overflows', async () => { const { abi, inputs } = await import('../shared/uint_overflow'); expect(() => abiEncode(abi, inputs)).to.throw( - 'The value passed for parameter `foo` does not match the specified type:\nValue Field(2³⁸) does not fall within range of allowable values for a Integer { sign: Unsigned, width: 32 }', + 'The value passed for parameter `foo` does not match the specified type:\nValue Field(274877906944) does not fall within range of allowable values for a Integer { sign: Unsigned, width: 32 }', ); }); diff --git a/noir/noir-repo/tooling/profiler/Cargo.toml b/noir/noir-repo/tooling/profiler/Cargo.toml index 136775d5831..c76b4c73e65 100644 --- a/noir/noir-repo/tooling/profiler/Cargo.toml +++ b/noir/noir-repo/tooling/profiler/Cargo.toml @@ -18,8 +18,10 @@ name = "noir-profiler" path = "src/main.rs" [dependencies] +bn254_blackbox_solver.workspace = true color-eyre.workspace = true clap.workspace = true +fxhash.workspace = true noirc_artifacts.workspace = true const_format.workspace = true serde.workspace = true @@ -28,7 +30,9 @@ fm.workspace = true inferno = "0.11.19" im.workspace = true acir.workspace = true +nargo.workspace = true noirc_errors.workspace = true +noirc_abi.workspace = true # Logs tracing-subscriber.workspace = true diff --git a/noir/noir-repo/tooling/profiler/src/cli/execution_flamegraph_cmd.rs b/noir/noir-repo/tooling/profiler/src/cli/execution_flamegraph_cmd.rs new file mode 100644 index 00000000000..a0b3d6a3128 --- /dev/null +++ b/noir/noir-repo/tooling/profiler/src/cli/execution_flamegraph_cmd.rs @@ -0,0 +1,96 @@ +use std::path::{Path, PathBuf}; + +use acir::circuit::OpcodeLocation; +use acir::FieldElement; +use clap::Args; +use color_eyre::eyre::{self, Context}; + +use crate::flamegraph::{FlamegraphGenerator, InfernoFlamegraphGenerator, Sample}; +use crate::fs::{read_inputs_from_file, read_program_from_file}; +use crate::opcode_formatter::AcirOrBrilligOpcode; +use bn254_blackbox_solver::Bn254BlackBoxSolver; +use nargo::ops::DefaultForeignCallExecutor; +use noirc_abi::input_parser::Format; +use noirc_artifacts::debug::DebugArtifact; + +#[derive(Debug, Clone, Args)] +pub(crate) struct ExecutionFlamegraphCommand { + /// The path to the artifact JSON file + #[clap(long, short)] + artifact_path: PathBuf, + + /// The path to the Prover.toml file + #[clap(long, short)] + prover_toml_path: PathBuf, + + /// The output folder for the flamegraph svg files + #[clap(long, short)] + output: PathBuf, +} + +pub(crate) fn run(args: ExecutionFlamegraphCommand) -> eyre::Result<()> { + run_with_generator( + &args.artifact_path, + &args.prover_toml_path, + &InfernoFlamegraphGenerator { count_name: "samples".to_string() }, + &args.output, + ) +} + +fn run_with_generator( + artifact_path: &Path, + prover_toml_path: &Path, + flamegraph_generator: &impl FlamegraphGenerator, + output_path: &Path, +) -> eyre::Result<()> { + let program = + read_program_from_file(artifact_path).context("Error reading program from file")?; + + let (inputs_map, _) = read_inputs_from_file(prover_toml_path, Format::Toml, &program.abi)?; + + let initial_witness = program.abi.encode(&inputs_map, None)?; + + println!("Executing"); + let (_, profiling_samples) = nargo::ops::execute_program_with_profiling( + &program.bytecode, + initial_witness, + &Bn254BlackBoxSolver, + &mut DefaultForeignCallExecutor::new(true, None, None, None), + )?; + println!("Executed"); + + let profiling_samples: Vec> = profiling_samples + .into_iter() + .map(|sample| { + let call_stack = sample.call_stack; + let brillig_function_id = sample.brillig_function_id; + let last_entry = call_stack.last(); + let opcode = brillig_function_id + .and_then(|id| program.bytecode.unconstrained_functions.get(id.0 as usize)) + .and_then(|func| { + if let Some(OpcodeLocation::Brillig { brillig_index, .. }) = last_entry { + func.bytecode.get(*brillig_index) + } else { + None + } + }) + .map(|opcode| AcirOrBrilligOpcode::Brillig(opcode.clone())); + Sample { opcode, call_stack, count: 1, brillig_function_id } + }) + .collect(); + + let debug_artifact: DebugArtifact = program.into(); + + println!("Generating flamegraph with {} samples", profiling_samples.len()); + + flamegraph_generator.generate_flamegraph( + profiling_samples, + &debug_artifact.debug_symbols[0], + &debug_artifact, + artifact_path.to_str().unwrap(), + "main", + &Path::new(&output_path).join(Path::new(&format!("{}.svg", "main"))), + )?; + + Ok(()) +} diff --git a/noir/noir-repo/tooling/profiler/src/cli/gates_flamegraph_cmd.rs b/noir/noir-repo/tooling/profiler/src/cli/gates_flamegraph_cmd.rs index d5fefc4ecda..20cc1b747c3 100644 --- a/noir/noir-repo/tooling/profiler/src/cli/gates_flamegraph_cmd.rs +++ b/noir/noir-repo/tooling/profiler/src/cli/gates_flamegraph_cmd.rs @@ -84,7 +84,7 @@ fn run_with_provider( .zip(bytecode.opcodes) .enumerate() .map(|(index, (gates, opcode))| Sample { - opcode: AcirOrBrilligOpcode::Acir(opcode), + opcode: Some(AcirOrBrilligOpcode::Acir(opcode)), call_stack: vec![OpcodeLocation::Acir(index)], count: gates, brillig_function_id: None, diff --git a/noir/noir-repo/tooling/profiler/src/cli/mod.rs b/noir/noir-repo/tooling/profiler/src/cli/mod.rs index 7cfc6ed7c9e..80c6bceb3ce 100644 --- a/noir/noir-repo/tooling/profiler/src/cli/mod.rs +++ b/noir/noir-repo/tooling/profiler/src/cli/mod.rs @@ -2,6 +2,7 @@ use clap::{Parser, Subcommand}; use color_eyre::eyre; use const_format::formatcp; +mod execution_flamegraph_cmd; mod gates_flamegraph_cmd; mod opcodes_flamegraph_cmd; @@ -19,15 +20,17 @@ struct ProfilerCli { #[non_exhaustive] #[derive(Subcommand, Clone, Debug)] enum ProfilerCommand { - GatesFlamegraph(gates_flamegraph_cmd::GatesFlamegraphCommand), - OpcodesFlamegraph(opcodes_flamegraph_cmd::OpcodesFlamegraphCommand), + Gates(gates_flamegraph_cmd::GatesFlamegraphCommand), + Opcodes(opcodes_flamegraph_cmd::OpcodesFlamegraphCommand), + ExecutionOpcodes(execution_flamegraph_cmd::ExecutionFlamegraphCommand), } pub(crate) fn start_cli() -> eyre::Result<()> { let ProfilerCli { command } = ProfilerCli::parse(); match command { - ProfilerCommand::GatesFlamegraph(args) => gates_flamegraph_cmd::run(args), - ProfilerCommand::OpcodesFlamegraph(args) => opcodes_flamegraph_cmd::run(args), + ProfilerCommand::Gates(args) => gates_flamegraph_cmd::run(args), + ProfilerCommand::Opcodes(args) => opcodes_flamegraph_cmd::run(args), + ProfilerCommand::ExecutionOpcodes(args) => execution_flamegraph_cmd::run(args), } } diff --git a/noir/noir-repo/tooling/profiler/src/cli/opcodes_flamegraph_cmd.rs b/noir/noir-repo/tooling/profiler/src/cli/opcodes_flamegraph_cmd.rs index 863d45b96d1..bb3df86c339 100644 --- a/noir/noir-repo/tooling/profiler/src/cli/opcodes_flamegraph_cmd.rs +++ b/noir/noir-repo/tooling/profiler/src/cli/opcodes_flamegraph_cmd.rs @@ -60,7 +60,7 @@ fn run_with_generator( .iter() .enumerate() .map(|(index, opcode)| Sample { - opcode: AcirOrBrilligOpcode::Acir(opcode.clone()), + opcode: Some(AcirOrBrilligOpcode::Acir(opcode.clone())), call_stack: vec![OpcodeLocation::Acir(index)], count: 1, brillig_function_id: None, @@ -97,7 +97,7 @@ fn run_with_generator( .into_iter() .enumerate() .map(|(brillig_index, opcode)| Sample { - opcode: AcirOrBrilligOpcode::Brillig(opcode), + opcode: Some(AcirOrBrilligOpcode::Brillig(opcode)), call_stack: vec![OpcodeLocation::Brillig { acir_index: acir_opcode_index, brillig_index, diff --git a/noir/noir-repo/tooling/profiler/src/flamegraph.rs b/noir/noir-repo/tooling/profiler/src/flamegraph.rs index 488079de50a..a72168a20af 100644 --- a/noir/noir-repo/tooling/profiler/src/flamegraph.rs +++ b/noir/noir-repo/tooling/profiler/src/flamegraph.rs @@ -6,6 +6,7 @@ use acir::circuit::OpcodeLocation; use acir::AcirField; use color_eyre::eyre::{self}; use fm::codespan_files::Files; +use fxhash::FxHashMap as HashMap; use inferno::flamegraph::{from_lines, Options, TextTruncateDirection}; use noirc_errors::debug_info::DebugInfo; use noirc_errors::reporter::line_and_column_from_span; @@ -17,7 +18,7 @@ use super::opcode_formatter::format_opcode; #[derive(Debug)] pub(crate) struct Sample { - pub(crate) opcode: AcirOrBrilligOpcode, + pub(crate) opcode: Option>, pub(crate) call_stack: Vec, pub(crate) count: usize, pub(crate) brillig_function_id: Option, @@ -88,41 +89,61 @@ fn generate_folded_sorted_lines<'files, F: AcirField>( // Create a nested hashmap with the stack items, folding the gates for all the callsites that are equal let mut folded_stack_items = BTreeMap::new(); - samples.into_iter().for_each(|sample| { - let mut location_names: Vec = sample - .call_stack - .into_iter() - .flat_map(|opcode_location| { - debug_symbols.opcode_location(&opcode_location).unwrap_or_else(|| { - if let (Some(brillig_function_id), Some(brillig_location)) = - (sample.brillig_function_id, opcode_location.to_brillig_location()) - { - let brillig_locations = - debug_symbols.brillig_locations.get(&brillig_function_id); - if let Some(brillig_locations) = brillig_locations { - brillig_locations.get(&brillig_location).cloned().unwrap_or_default() - } else { - vec![] - } - } else { - vec![] - } + let mut resolution_cache: HashMap> = HashMap::default(); + for sample in samples { + let mut location_names = Vec::with_capacity(sample.call_stack.len()); + for opcode_location in sample.call_stack { + let callsite_labels = resolution_cache + .entry(opcode_location) + .or_insert_with(|| { + find_callsite_labels( + debug_symbols, + &opcode_location, + sample.brillig_function_id, + files, + ) }) - }) - .map(|location| location_to_callsite_label(location, files)) - .collect(); + .clone(); - if location_names.is_empty() { - location_names.push("unknown".to_string()); + location_names.extend(callsite_labels); } - location_names.push(format_opcode(&sample.opcode)); + if let Some(opcode) = &sample.opcode { + location_names.push(format_opcode(opcode)); + } add_locations_to_folded_stack_items(&mut folded_stack_items, location_names, sample.count); - }); + } to_folded_sorted_lines(&folded_stack_items, Default::default()) } +fn find_callsite_labels<'files>( + debug_symbols: &DebugInfo, + opcode_location: &OpcodeLocation, + brillig_function_id: Option, + files: &'files impl Files<'files, FileId = fm::FileId>, +) -> Vec { + let source_locations = debug_symbols.opcode_location(opcode_location).unwrap_or_else(|| { + if let (Some(brillig_function_id), Some(brillig_location)) = + (brillig_function_id, opcode_location.to_brillig_location()) + { + let brillig_locations = debug_symbols.brillig_locations.get(&brillig_function_id); + if let Some(brillig_locations) = brillig_locations { + brillig_locations.get(&brillig_location).cloned().unwrap_or_default() + } else { + vec![] + } + } else { + vec![] + } + }); + let callsite_labels: Vec<_> = source_locations + .into_iter() + .map(|location| location_to_callsite_label(location, files)) + .collect(); + callsite_labels +} + fn location_to_callsite_label<'files>( location: Location, files: &'files impl Files<'files, FileId = fm::FileId>, @@ -300,23 +321,27 @@ mod tests { let samples: Vec> = vec![ Sample { - opcode: AcirOrBrilligOpcode::Acir(AcirOpcode::AssertZero(Expression::default())), + opcode: Some(AcirOrBrilligOpcode::Acir(AcirOpcode::AssertZero( + Expression::default(), + ))), call_stack: vec![OpcodeLocation::Acir(0)], count: 10, brillig_function_id: None, }, Sample { - opcode: AcirOrBrilligOpcode::Acir(AcirOpcode::AssertZero(Expression::default())), + opcode: Some(AcirOrBrilligOpcode::Acir(AcirOpcode::AssertZero( + Expression::default(), + ))), call_stack: vec![OpcodeLocation::Acir(1)], count: 20, brillig_function_id: None, }, Sample { - opcode: AcirOrBrilligOpcode::Acir(AcirOpcode::MemoryInit { + opcode: Some(AcirOrBrilligOpcode::Acir(AcirOpcode::MemoryInit { block_id: BlockId(0), init: vec![], block_type: acir::circuit::opcodes::BlockType::Memory, - }), + })), call_stack: vec![OpcodeLocation::Acir(2)], count: 30, brillig_function_id: None, diff --git a/noir/noir-repo/tooling/profiler/src/fs.rs b/noir/noir-repo/tooling/profiler/src/fs.rs index e8eec2cbb14..43848504a7f 100644 --- a/noir/noir-repo/tooling/profiler/src/fs.rs +++ b/noir/noir-repo/tooling/profiler/src/fs.rs @@ -1,6 +1,10 @@ -use std::path::Path; +use std::{collections::BTreeMap, path::Path}; use color_eyre::eyre; +use noirc_abi::{ + input_parser::{Format, InputValue}, + Abi, InputMap, MAIN_RETURN_NAME, +}; use noirc_artifacts::program::ProgramArtifact; pub(crate) fn read_program_from_file>( @@ -13,3 +17,26 @@ pub(crate) fn read_program_from_file>( Ok(program) } + +/// Returns the circuit's parameters and its return value, if one exists. +/// # Examples +/// +/// ```ignore +/// let (input_map, return_value): (InputMap, Option) = +/// read_inputs_from_file(path, "Verifier", Format::Toml, &abi)?; +/// ``` +pub(crate) fn read_inputs_from_file( + file_path: &Path, + format: Format, + abi: &Abi, +) -> eyre::Result<(InputMap, Option)> { + if abi.is_empty() { + return Ok((BTreeMap::new(), None)); + } + + let input_string = std::fs::read_to_string(file_path)?; + let mut input_map = format.parse(&input_string, abi)?; + let return_value = input_map.remove(MAIN_RETURN_NAME); + + Ok((input_map, return_value)) +} diff --git a/noir/noir-repo/yarn.lock b/noir/noir-repo/yarn.lock index 03cea21026e..b39f9c257c6 100644 --- a/noir/noir-repo/yarn.lock +++ b/noir/noir-repo/yarn.lock @@ -221,9 +221,9 @@ __metadata: languageName: node linkType: hard -"@aztec/bb.js@portal:../../../../barretenberg/ts::locator=integration-tests%40workspace%3Acompiler%2Fintegration-tests": - version: 0.0.0-use.local - resolution: "@aztec/bb.js@portal:../../../../barretenberg/ts::locator=integration-tests%40workspace%3Acompiler%2Fintegration-tests" +"@aztec/bb.js@npm:0.60.0": + version: 0.60.0 + resolution: "@aztec/bb.js@npm:0.60.0" dependencies: comlink: ^4.4.1 commander: ^10.0.1 @@ -231,9 +231,10 @@ __metadata: fflate: ^0.8.0 tslib: ^2.4.0 bin: - bb.js: ./dest/node/main.js + bb.js: dest/node/main.js + checksum: 74ab79d060624362e9d44dda11dc2445973460577b93dc0c16801158db7efb71cd612966d6169b46bfbbb4fd7c9c1b95ad8b6198b3c69d9f6de0ab0fb92387aa languageName: node - linkType: soft + linkType: hard "@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.11, @babel/code-frame@npm:^7.16.0, @babel/code-frame@npm:^7.22.13, @babel/code-frame@npm:^7.23.5, @babel/code-frame@npm:^7.8.3": version: 7.23.5 @@ -14122,7 +14123,7 @@ __metadata: version: 0.0.0-use.local resolution: "integration-tests@workspace:compiler/integration-tests" dependencies: - "@aztec/bb.js": "portal:../../../../barretenberg/ts" + "@aztec/bb.js": 0.60.0 "@noir-lang/noir_js": "workspace:*" "@noir-lang/noir_wasm": "workspace:*" "@nomicfoundation/hardhat-chai-matchers": ^2.0.0