From fa3fba9a6676e1eb5b1e67a5458c99752e25d8b3 Mon Sep 17 00:00:00 2001 From: AztecBot Date: Wed, 2 Oct 2024 22:43:03 +0000 Subject: [PATCH 1/8] chore: apply sync fixes --- .aztec-sync-commit | 2 +- .github/workflows/gates_report_brillig.yml | 2 +- .github/workflows/mirror-external_libs.yml | 8 - .github/workflows/test-js-packages.yml | 14 +- Cargo.lock | 1 + compiler/noirc_driver/src/lib.rs | 2 +- .../src/brillig/brillig_gen/brillig_block.rs | 15 +- .../brillig_gen/constant_allocation.rs | 115 +++++- .../brillig/brillig_gen/variable_liveness.rs | 20 +- .../brillig/brillig_ir/codegen_intrinsic.rs | 8 +- .../src/ssa/function_builder/data_bus.rs | 39 +- .../src/ssa/ir/function_inserter.rs | 11 +- .../src/ssa/ir/instruction/cast.rs | 22 +- .../noirc_evaluator/src/ssa/opt/array_set.rs | 198 ++++++++- compiler/noirc_evaluator/src/ssa/opt/die.rs | 384 +++++++++++++++++- compiler/noirc_evaluator/src/ssa/opt/rc.rs | 37 +- compiler/noirc_frontend/src/ast/statement.rs | 1 + compiler/noirc_frontend/src/ast/type_alias.rs | 6 +- compiler/noirc_frontend/src/ast/visitor.rs | 2 +- .../noirc_frontend/src/elaborator/comptime.rs | 3 +- .../src/elaborator/expressions.rs | 8 + compiler/noirc_frontend/src/elaborator/mod.rs | 144 ++++++- .../src/hir/comptime/interpreter/builtin.rs | 22 +- .../src/hir/def_collector/dc_crate.rs | 2 +- .../src/hir/def_collector/dc_mod.rs | 49 ++- .../src/hir/def_collector/errors.rs | 13 - .../noirc_frontend/src/hir/def_map/mod.rs | 8 +- .../src/hir/def_map/module_data.rs | 15 +- .../src/hir/resolution/errors.rs | 40 +- .../src/hir/resolution/import.rs | 4 +- compiler/noirc_frontend/src/lib.rs | 1 - compiler/noirc_frontend/src/node_interner.rs | 8 +- compiler/noirc_frontend/src/parser/mod.rs | 40 +- compiler/noirc_frontend/src/parser/parser.rs | 59 ++- compiler/noirc_frontend/src/tests.rs | 158 +++++-- .../noirc_frontend/src/tests/unused_items.rs | 121 +++++- .../noirc_frontend/src/tests/visibility.rs | 113 ++++++ compiler/noirc_frontend/src/usage_tracker.rs | 37 +- docs/docs/how_to/how-to-solidity-verifier.md | 2 + docs/docs/noir/concepts/data_types/index.md | 8 + docs/docs/noir/concepts/globals.md | 10 + .../noir/modules_packages_crates/modules.md | 12 +- .../how_to/how-to-solidity-verifier.md | 2 + .../how_to/how-to-solidity-verifier.md | 2 + noir_stdlib/src/collections/mod.nr | 8 +- noir_stdlib/src/ec/consts/mod.nr | 2 +- noir_stdlib/src/ec/consts/te.nr | 1 + noir_stdlib/src/ec/mod.nr | 8 +- noir_stdlib/src/ec/montcurve.nr | 4 +- noir_stdlib/src/ec/swcurve.nr | 4 +- noir_stdlib/src/ec/tecurve.nr | 5 +- noir_stdlib/src/field/bn254.nr | 2 +- noir_stdlib/src/field/mod.nr | 2 +- noir_stdlib/src/hash/mimc.nr | 2 + noir_stdlib/src/hash/mod.nr | 34 +- noir_stdlib/src/hash/poseidon/bn254.nr | 4 +- noir_stdlib/src/hash/poseidon/mod.nr | 2 +- noir_stdlib/src/hash/sha256.nr | 2 +- noir_stdlib/src/lib.nr | 62 +-- noir_stdlib/src/meta/mod.nr | 40 +- noir_stdlib/src/ops/mod.nr | 4 +- noir_stdlib/src/schnorr.nr | 13 +- noir_stdlib/src/sha256.nr | 11 +- noir_stdlib/src/sha512.nr | 6 +- .../comptime_module/src/main.nr | 22 +- .../src/main.nr | 7 + .../aes128_encrypt/src/main.nr | 27 +- .../databus_in_fn_with_empty_arr/Nargo.toml | 6 + .../databus_in_fn_with_empty_arr/Prover.toml | 3 + .../databus_in_fn_with_empty_arr/src/main.nr | 3 + .../verify_honk_proof/Nargo.toml | 6 + .../verify_honk_proof/Prover.toml | 4 + .../verify_honk_proof/src/main.nr | 23 ++ tooling/lsp/Cargo.toml | 1 + tooling/lsp/src/attribute_reference_finder.rs | 115 ++++++ tooling/lsp/src/lib.rs | 1 + tooling/lsp/src/modules.rs | 9 - .../requests/code_action/import_or_qualify.rs | 4 +- .../code_action/remove_unused_import.rs | 4 +- .../src/requests/completion/auto_import.rs | 4 +- tooling/lsp/src/requests/completion/tests.rs | 30 +- tooling/lsp/src/requests/goto_definition.rs | 64 ++- tooling/lsp/src/requests/hover.rs | 61 ++- .../src/trait_impl_method_stub_generator.rs | 7 +- .../go_to_definition/src/main.nr | 7 + .../test_programs/workspace/two/src/lib.nr | 7 + tooling/nargo/src/errors.rs | 2 +- tooling/nargo/src/package.rs | 2 +- tooling/nargo_cli/build.rs | 84 +++- tooling/nargo_cli/src/cli/check_cmd.rs | 14 +- tooling/nargo_cli/src/cli/compile_cmd.rs | 4 +- tooling/nargo_cli/src/cli/debug_cmd.rs | 3 +- tooling/nargo_cli/src/cli/execute_cmd.rs | 3 +- tooling/nargo_cli/src/cli/fs/program.rs | 2 +- tooling/nargo_cli/src/cli/info_cmd.rs | 3 +- tooling/nargo_cli/src/cli/init_cmd.rs | 3 +- tooling/nargo_cli/src/cli/new_cmd.rs | 3 +- tooling/nargo_cli/src/cli/test_cmd.rs | 11 +- tooling/nargo_fmt/src/visitor/item.rs | 10 +- tooling/nargo_fmt/tests/expected/module.nr | 4 + tooling/nargo_fmt/tests/input/module.nr | 4 + .../src/backend.ts | 47 +-- .../src/verifier.ts | 27 +- 103 files changed, 2075 insertions(+), 550 deletions(-) delete mode 100644 .github/workflows/mirror-external_libs.yml create mode 100644 compiler/noirc_frontend/src/tests/visibility.rs create mode 100644 test_programs/execution_success/databus_in_fn_with_empty_arr/Nargo.toml create mode 100644 test_programs/execution_success/databus_in_fn_with_empty_arr/Prover.toml create mode 100644 test_programs/execution_success/databus_in_fn_with_empty_arr/src/main.nr create mode 100644 test_programs/execution_success/verify_honk_proof/Nargo.toml create mode 100644 test_programs/execution_success/verify_honk_proof/Prover.toml create mode 100644 test_programs/execution_success/verify_honk_proof/src/main.nr create mode 100644 tooling/lsp/src/attribute_reference_finder.rs diff --git a/.aztec-sync-commit b/.aztec-sync-commit index 42ef1037b17..258eb260471 100644 --- a/.aztec-sync-commit +++ b/.aztec-sync-commit @@ -1 +1 @@ -b0d1bab1f02819e7efbe0db73c3c805b5927b66a +670af8a158633d106a3f1df82dbd28ef9a9e4ceb diff --git a/.github/workflows/gates_report_brillig.yml b/.github/workflows/gates_report_brillig.yml index 4e12a6fcbca..e7ec30923f0 100644 --- a/.github/workflows/gates_report_brillig.yml +++ b/.github/workflows/gates_report_brillig.yml @@ -74,7 +74,7 @@ jobs: - name: Compare Brillig bytecode size reports id: brillig_bytecode_diff - uses: noir-lang/noir-gates-diff@3fb844067b25d1b59727ea600b614503b33503f4 + uses: noir-lang/noir-gates-diff@d88f7523b013b9edd3f31c5cfddaef87a3fe1b48 with: report: gates_report_brillig.json header: | diff --git a/.github/workflows/mirror-external_libs.yml b/.github/workflows/mirror-external_libs.yml deleted file mode 100644 index e577ac0ed92..00000000000 --- a/.github/workflows/mirror-external_libs.yml +++ /dev/null @@ -1,8 +0,0 @@ -name: Mirror Repositories -on: - workflow_dispatch: {} -jobs: - lint: - runs-on: ubuntu-latest - steps: - - run: echo Dummy workflow TODO \ No newline at end of file diff --git a/.github/workflows/test-js-packages.yml b/.github/workflows/test-js-packages.yml index e45a482cc59..ff894f061ee 100644 --- a/.github/workflows/test-js-packages.yml +++ b/.github/workflows/test-js-packages.yml @@ -519,16 +519,12 @@ jobs: fail-fast: false matrix: project: - # Disabled as these are currently failing with many visibility errors - # - { repo: AztecProtocol/aztec-nr, path: ./ } - # - { repo: AztecProtocol/aztec-packages, path: ./noir-projects/noir-contracts } - # Disabled as aztec-packages requires a setup-step in order to generate a `Nargo.toml` - #- { repo: AztecProtocol/aztec-packages, path: ./noir-projects/noir-protocol-circuits } + # Disabled as these are currently failing with many visibility errors + - { repo: AztecProtocol/aztec-nr, path: ./ } + - { repo: AztecProtocol/aztec-packages, path: ./noir-projects/noir-contracts } + # Disabled as aztec-packages requires a setup-step in order to generate a `Nargo.toml` + #- { repo: AztecProtocol/aztec-packages, path: ./noir-projects/noir-protocol-circuits } - { repo: zac-williamson/noir-edwards, path: ./, ref: 037e44b2ee8557c51f6aef9bb9d63ea9e32722d1 } - # TODO: Enable these once they're passing against master again. - # - { repo: zac-williamson/noir-bignum, path: ./, ref: 030c2acce1e6b97c44a3bbbf3429ed96f20d72d3 } - # - { repo: vlayer-xyz/monorepo, path: ./, ref: ee46af88c025863872234eb05d890e1e447907cb } - # - { repo: hashcloak/noir-bigint, path: ./, ref: 940ddba3a5201b508e7b37a2ef643551afcf5ed8 } name: Check external repo - ${{ matrix.project.repo }} steps: - name: Checkout diff --git a/Cargo.lock b/Cargo.lock index 6a469bd67f4..cdc1d75a421 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2753,6 +2753,7 @@ version = "0.34.0" dependencies = [ "acvm", "async-lsp", + "chumsky", "codespan-lsp", "convert_case 0.6.0", "fm", diff --git a/compiler/noirc_driver/src/lib.rs b/compiler/noirc_driver/src/lib.rs index 74916d65264..1d69e435738 100644 --- a/compiler/noirc_driver/src/lib.rs +++ b/compiler/noirc_driver/src/lib.rs @@ -14,7 +14,6 @@ use noirc_evaluator::create_program; use noirc_evaluator::errors::RuntimeError; use noirc_evaluator::ssa::SsaProgramArtifact; use noirc_frontend::debug::build_debug_crate_file; -use noirc_frontend::graph::{CrateId, CrateName}; use noirc_frontend::hir::def_map::{Contract, CrateDefMap}; use noirc_frontend::hir::Context; use noirc_frontend::monomorphization::{ @@ -35,6 +34,7 @@ use debug::filter_relevant_files; pub use contract::{CompiledContract, CompiledContractOutputs, ContractFunction}; pub use debug::DebugFile; +pub use noirc_frontend::graph::{CrateId, CrateName}; pub use program::CompiledProgram; const STD_CRATE_NAME: &str = "std"; diff --git a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs index 8929122f515..e764c81b023 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs @@ -553,14 +553,7 @@ impl<'block> BrilligBlock<'block> { let results = dfg.instruction_results(instruction_id); let source = self.convert_ssa_single_addr_value(arguments[0], dfg); - - let radix: u32 = dfg - .get_numeric_constant(arguments[1]) - .expect("Radix should be known") - .try_to_u64() - .expect("Radix should fit in u64") - .try_into() - .expect("Radix should be u32"); + let radix = self.convert_ssa_single_addr_value(arguments[1], dfg); let target_array = self .variables @@ -595,13 +588,17 @@ impl<'block> BrilligBlock<'block> { ) .extract_array(); + let two = self.brillig_context.make_usize_constant_instruction(2_usize.into()); + self.brillig_context.codegen_to_radix( source, target_array, - 2, + two, matches!(endianness, Endian::Big), true, ); + + self.brillig_context.deallocate_single_addr(two); } // `Intrinsic::AsWitness` is used to provide hints to acir-gen on optimal expression splitting. diff --git a/compiler/noirc_evaluator/src/brillig/brillig_gen/constant_allocation.rs b/compiler/noirc_evaluator/src/brillig/brillig_gen/constant_allocation.rs index cf484fa5038..f9ded224b33 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_gen/constant_allocation.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_gen/constant_allocation.rs @@ -1,7 +1,7 @@ //! This module analyzes the usage of constants in a given function and decides an allocation point for them. //! The allocation point will be the common dominator of all the places where the constant is used. //! By allocating in the common dominator, we can cache the constants for all subsequent uses. -use fxhash::FxHashMap as HashMap; +use fxhash::{FxHashMap as HashMap, FxHashSet as HashSet}; use crate::ssa::ir::{ basic_block::BasicBlockId, @@ -26,20 +26,23 @@ pub(crate) struct ConstantAllocation { constant_usage: HashMap>>, allocation_points: HashMap>>, dominator_tree: DominatorTree, + blocks_within_loops: HashSet, } impl ConstantAllocation { pub(crate) fn from_function(func: &Function) -> Self { let cfg = ControlFlowGraph::with_function(func); let post_order = PostOrder::with_function(func); - let dominator_tree = DominatorTree::with_cfg_and_post_order(&cfg, &post_order); + let mut dominator_tree = DominatorTree::with_cfg_and_post_order(&cfg, &post_order); + let blocks_within_loops = find_all_blocks_within_loops(func, &cfg, &mut dominator_tree); let mut instance = ConstantAllocation { constant_usage: HashMap::default(), allocation_points: HashMap::default(), dominator_tree, + blocks_within_loops, }; instance.collect_constant_usage(func); - instance.decide_allocation_points(); + instance.decide_allocation_points(func); instance } @@ -95,16 +98,16 @@ impl ConstantAllocation { } } - fn decide_allocation_points(&mut self) { + fn decide_allocation_points(&mut self, func: &Function) { for (constant_id, usage_in_blocks) in self.constant_usage.iter() { let block_ids: Vec<_> = usage_in_blocks.iter().map(|(block_id, _)| *block_id).collect(); - let common_dominator = self.common_dominator(&block_ids); + let allocation_point = self.decide_allocation_point(*constant_id, &block_ids, func); - // If the common dominator is one of the places where it's used, we take the first usage in the common dominator. - // Otherwise, we allocate it at the terminator of the common dominator. + // If the allocation point is one of the places where it's used, we take the first usage in the allocation point. + // Otherwise, we allocate it at the terminator of the allocation point. let location = if let Some(locations_in_common_dominator) = - usage_in_blocks.get(&common_dominator) + usage_in_blocks.get(&allocation_point) { *locations_in_common_dominator .first() @@ -114,7 +117,7 @@ impl ConstantAllocation { }; self.allocation_points - .entry(common_dominator) + .entry(allocation_point) .or_default() .entry(location) .or_default() @@ -122,21 +125,97 @@ impl ConstantAllocation { } } - fn common_dominator(&self, block_ids: &[BasicBlockId]) -> BasicBlockId { - if block_ids.len() == 1 { - return block_ids[0]; - } - - let mut common_dominator = block_ids[0]; + fn decide_allocation_point( + &self, + constant_id: ValueId, + blocks_where_is_used: &[BasicBlockId], + func: &Function, + ) -> BasicBlockId { + // Find the common dominator of all the blocks where the constant is used. + let common_dominator = if blocks_where_is_used.len() == 1 { + blocks_where_is_used[0] + } else { + let mut common_dominator = blocks_where_is_used[0]; + + for block_id in blocks_where_is_used.iter().skip(1) { + common_dominator = + self.dominator_tree.common_dominator(common_dominator, *block_id); + } - for block_id in block_ids.iter().skip(1) { - common_dominator = self.dominator_tree.common_dominator(common_dominator, *block_id); + common_dominator + }; + // If the value only contains constants, it's safe to hoist outside of any loop + if func.dfg.is_constant(constant_id) { + self.exit_loops(common_dominator) + } else { + common_dominator } + } - common_dominator + /// Returns the nearest dominator that is outside of any loop. + fn exit_loops(&self, block: BasicBlockId) -> BasicBlockId { + let mut current_block = block; + while self.blocks_within_loops.contains(¤t_block) { + current_block = self + .dominator_tree + .immediate_dominator(current_block) + .expect("No dominator found when trying to allocate a constant outside of a loop"); + } + current_block } } pub(crate) fn is_constant_value(id: ValueId, dfg: &DataFlowGraph) -> bool { matches!(&dfg[dfg.resolve(id)], Value::NumericConstant { .. } | Value::Array { .. }) } + +/// For a given function, finds all the blocks that are within loops +fn find_all_blocks_within_loops( + func: &Function, + cfg: &ControlFlowGraph, + dominator_tree: &mut DominatorTree, +) -> HashSet { + let mut blocks_in_loops = HashSet::default(); + for block_id in func.reachable_blocks() { + let block = &func.dfg[block_id]; + let successors = block.successors(); + for successor_id in successors { + if dominator_tree.dominates(successor_id, block_id) { + blocks_in_loops.extend(find_blocks_in_loop(successor_id, block_id, cfg)); + } + } + } + + blocks_in_loops +} + +/// Return each block that is in a loop starting in the given header block. +/// Expects back_edge_start -> header to be the back edge of the loop. +fn find_blocks_in_loop( + header: BasicBlockId, + back_edge_start: BasicBlockId, + cfg: &ControlFlowGraph, +) -> HashSet { + let mut blocks = HashSet::default(); + blocks.insert(header); + + let mut insert = |block, stack: &mut Vec| { + if !blocks.contains(&block) { + blocks.insert(block); + stack.push(block); + } + }; + + // Starting from the back edge of the loop, each predecessor of this block until + // the header is within the loop. + let mut stack = vec![]; + insert(back_edge_start, &mut stack); + + while let Some(block) = stack.pop() { + for predecessor in cfg.predecessors(block) { + insert(predecessor, &mut stack); + } + } + + blocks +} diff --git a/compiler/noirc_evaluator/src/brillig/brillig_gen/variable_liveness.rs b/compiler/noirc_evaluator/src/brillig/brillig_gen/variable_liveness.rs index 73e88cee676..92595292bf0 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_gen/variable_liveness.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_gen/variable_liveness.rs @@ -570,28 +570,34 @@ mod test { let liveness = VariableLiveness::from_function(func, &constants); assert!(liveness.get_live_in(&func.entry_block()).is_empty()); - assert_eq!(liveness.get_live_in(&b1), &FxHashSet::from_iter([v0, v1, v3, v4].into_iter())); + assert_eq!( + liveness.get_live_in(&b1), + &FxHashSet::from_iter([v0, v1, v3, v4, twenty_seven, one].into_iter()) + ); assert_eq!(liveness.get_live_in(&b3), &FxHashSet::from_iter([v3].into_iter())); - assert_eq!(liveness.get_live_in(&b2), &FxHashSet::from_iter([v0, v1, v3, v4].into_iter())); + assert_eq!( + liveness.get_live_in(&b2), + &FxHashSet::from_iter([v0, v1, v3, v4, twenty_seven, one].into_iter()) + ); assert_eq!( liveness.get_live_in(&b4), - &FxHashSet::from_iter([v0, v1, v3, v4, v6, v7].into_iter()) + &FxHashSet::from_iter([v0, v1, v3, v4, v6, v7, twenty_seven, one].into_iter()) ); assert_eq!( liveness.get_live_in(&b6), - &FxHashSet::from_iter([v0, v1, v3, v4, one].into_iter()) + &FxHashSet::from_iter([v0, v1, v3, v4, twenty_seven, one].into_iter()) ); assert_eq!( liveness.get_live_in(&b5), - &FxHashSet::from_iter([v0, v1, v3, v4, v6, v7, one].into_iter()) + &FxHashSet::from_iter([v0, v1, v3, v4, v6, v7, twenty_seven, one].into_iter()) ); assert_eq!( liveness.get_live_in(&b7), - &FxHashSet::from_iter([v0, v1, v3, v4, v6, v7, one].into_iter()) + &FxHashSet::from_iter([v0, v1, v3, v4, v6, v7, twenty_seven, one].into_iter()) ); assert_eq!( liveness.get_live_in(&b8), - &FxHashSet::from_iter([v0, v1, v3, v4, v6, v7, one].into_iter()) + &FxHashSet::from_iter([v0, v1, v3, v4, v6, v7, twenty_seven, one].into_iter()) ); let block_3 = &func.dfg[b3]; diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_intrinsic.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_intrinsic.rs index c9c31267d7b..5f4781788f5 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_intrinsic.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_intrinsic.rs @@ -68,21 +68,20 @@ impl BrilligContext< &mut self, source_field: SingleAddrVariable, target_array: BrilligArray, - radix: u32, + radix: SingleAddrVariable, big_endian: bool, output_bits: bool, // If true will generate bit limbs, if false will generate byte limbs ) { assert!(source_field.bit_size == F::max_num_bits()); + assert!(radix.bit_size == 32); self.codegen_initialize_array(target_array); let heap_array = self.codegen_brillig_array_to_heap_array(target_array); - let radix_var = self.make_constant_instruction(F::from(radix as u128), 32); - self.black_box_op_instruction(BlackBoxOp::ToRadix { input: source_field.address, - radix: radix_var.address, + radix: radix.address, output: heap_array, output_bits, }); @@ -93,6 +92,5 @@ impl BrilligContext< self.deallocate_single_addr(items_len); } self.deallocate_register(heap_array.pointer); - self.deallocate_register(radix_var.address); } } diff --git a/compiler/noirc_evaluator/src/ssa/function_builder/data_bus.rs b/compiler/noirc_evaluator/src/ssa/function_builder/data_bus.rs index 38895bb977e..3056fb5973d 100644 --- a/compiler/noirc_evaluator/src/ssa/function_builder/data_bus.rs +++ b/compiler/noirc_evaluator/src/ssa/function_builder/data_bus.rs @@ -9,7 +9,7 @@ use serde::{Deserialize, Serialize}; use super::FunctionBuilder; -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] pub(crate) enum DatabusVisibility { None, CallData(u32), @@ -214,34 +214,27 @@ impl FunctionBuilder { fn deflatten_databus_visibilities( &self, ssa_params: &[ValueId], - flattened_params_databus_visibility: Vec, + mut flattened_params_databus_visibility: Vec, ) -> Vec { - // To do so, create a vec the size of the flattened arguments where the items are the ssa param index they correspond to - let ssa_param_indices: Vec<_> = ssa_params + let ssa_param_sizes: Vec<_> = ssa_params .iter() - .enumerate() - .flat_map(|(ssa_param_index, ssa_param)| { - let flattened_size = - self.current_function.dfg[*ssa_param].get_type().flattened_size(); - std::iter::repeat(ssa_param_index).take(flattened_size) - }) + .map(|ssa_param| self.current_function.dfg[*ssa_param].get_type().flattened_size()) .collect(); let mut is_ssa_params_databus = Vec::with_capacity(ssa_params.len()); - assert!(flattened_params_databus_visibility.len() == ssa_param_indices.len()); - for (databus_visibility, ssa_index) in - flattened_params_databus_visibility.into_iter().zip(ssa_param_indices) - { - if let Some(previous_databus_visibility) = is_ssa_params_databus.get(ssa_index) { - assert!( - *previous_databus_visibility == databus_visibility, - "inconsistent databus visibility for ssa param" - ); - } else { - assert!(ssa_index == is_ssa_params_databus.len()); - is_ssa_params_databus.push(databus_visibility); - } + for size in ssa_param_sizes { + let visibilities: Vec = + flattened_params_databus_visibility.drain(0..size).collect(); + let visibility = visibilities.get(0).copied().unwrap_or(DatabusVisibility::None); + assert!( + visibilities.iter().all(|v| *v == visibility), + "inconsistent databus visibility for ssa param" + ); + is_ssa_params_databus.push(visibility); } + + assert_eq!(is_ssa_params_databus.len(), ssa_params.len()); + is_ssa_params_databus } } diff --git a/compiler/noirc_evaluator/src/ssa/ir/function_inserter.rs b/compiler/noirc_evaluator/src/ssa/ir/function_inserter.rs index 9221a925aa8..991ff22c902 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/function_inserter.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/function_inserter.rs @@ -5,7 +5,7 @@ use crate::ssa::ir::types::Type; use super::{ basic_block::BasicBlockId, dfg::{CallStack, InsertInstructionResult}, - function::{Function, RuntimeType}, + function::Function, instruction::{Instruction, InstructionId}, value::ValueId, }; @@ -46,14 +46,7 @@ impl<'f> FunctionInserter<'f> { if let Some(fetched_value) = self.const_arrays.get(&(new_array.clone(), typ.clone())) { - // Arrays in ACIR are immutable, but in Brillig arrays are copy-on-write - // so for function's with a Brillig runtime we make sure to check that value - // in our constants array map matches the resolved array value id. - if matches!(self.function.runtime(), RuntimeType::Acir(_)) { - return *fetched_value; - } else if *fetched_value == value { - return value; - } + return *fetched_value; }; let new_array_clone = new_array.clone(); diff --git a/compiler/noirc_evaluator/src/ssa/ir/instruction/cast.rs b/compiler/noirc_evaluator/src/ssa/ir/instruction/cast.rs index d0ed5a1fa9c..ed588def1d7 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/instruction/cast.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/instruction/cast.rs @@ -27,10 +27,10 @@ pub(super) fn simplify_cast( SimplifiedTo(value) } ( - Type::Numeric(NumericType::Unsigned { .. }), + Type::Numeric(NumericType::Unsigned { .. } | NumericType::Signed { .. }), Type::Numeric(NumericType::NativeField), ) => { - // Unsigned -> Field: redefine same constant as Field + // Unsigned/Signed -> Field: redefine same constant as Field SimplifiedTo(dfg.make_constant(constant, dst_typ.clone())) } ( @@ -48,6 +48,24 @@ pub(super) fn simplify_cast( let truncated = FieldElement::from_be_bytes_reduce(&truncated.to_bytes_be()); SimplifiedTo(dfg.make_constant(truncated, dst_typ.clone())) } + ( + Type::Numeric( + NumericType::NativeField + | NumericType::Unsigned { .. } + | NumericType::Signed { .. }, + ), + Type::Numeric(NumericType::Signed { bit_size }), + ) => { + // Field/Unsigned -> signed + // We only simplify to signed when we are below the maximum signed integer of the destination type. + let integer_modulus = BigUint::from(2u128).pow(*bit_size - 1); + let constant_uint: BigUint = BigUint::from_bytes_be(&constant.to_be_bytes()); + if constant_uint < integer_modulus { + SimplifiedTo(dfg.make_constant(constant, dst_typ.clone())) + } else { + None + } + } _ => None, } } else if *dst_typ == dfg.type_of_value(value) { diff --git a/compiler/noirc_evaluator/src/ssa/opt/array_set.rs b/compiler/noirc_evaluator/src/ssa/opt/array_set.rs index 491a17adb66..6d48b8c0d67 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/array_set.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/array_set.rs @@ -2,12 +2,13 @@ use crate::ssa::{ ir::{ basic_block::BasicBlockId, dfg::DataFlowGraph, - instruction::{Instruction, InstructionId}, + instruction::{Instruction, InstructionId, TerminatorInstruction}, types::Type::{Array, Slice}, + value::ValueId, }, ssa_gen::Ssa, }; -use fxhash::{FxHashMap as HashMap, FxHashSet}; +use fxhash::{FxHashMap as HashMap, FxHashSet as HashSet}; impl Ssa { /// Map arrays with the last instruction that uses it @@ -16,28 +17,42 @@ impl Ssa { #[tracing::instrument(level = "trace", skip(self))] pub(crate) fn array_set_optimization(mut self) -> Self { for func in self.functions.values_mut() { - let mut reachable_blocks = func.reachable_blocks(); - let block = if !func.runtime().is_entry_point() { + let reachable_blocks = func.reachable_blocks(); + + if !func.runtime().is_entry_point() { assert_eq!(reachable_blocks.len(), 1, "Expected there to be 1 block remaining in Acir function for array_set optimization"); - reachable_blocks.pop_first().unwrap() - } else { - // We only apply the array set optimization in the return block of Brillig functions - func.find_last_block() - }; + } + let mut array_to_last_use = HashMap::default(); + let mut instructions_to_update = HashSet::default(); + let mut arrays_from_load = HashSet::default(); - let instructions_to_update = analyze_last_uses(&func.dfg, block); - make_mutable(&mut func.dfg, block, instructions_to_update); + for block in reachable_blocks.iter() { + analyze_last_uses( + &func.dfg, + *block, + &mut array_to_last_use, + &mut instructions_to_update, + &mut arrays_from_load, + ); + } + for block in reachable_blocks { + make_mutable(&mut func.dfg, block, &instructions_to_update); + } } self } } -/// Returns the set of ArraySet instructions that can be made mutable +/// Builds the set of ArraySet instructions that can be made mutable /// because their input value is unused elsewhere afterward. -fn analyze_last_uses(dfg: &DataFlowGraph, block_id: BasicBlockId) -> FxHashSet { +fn analyze_last_uses( + dfg: &DataFlowGraph, + block_id: BasicBlockId, + array_to_last_use: &mut HashMap, + instructions_that_can_be_made_mutable: &mut HashSet, + arrays_from_load: &mut HashSet, +) { let block = &dfg[block_id]; - let mut array_to_last_use = HashMap::default(); - let mut instructions_that_can_be_made_mutable = FxHashSet::default(); for instruction_id in block.instructions() { match &dfg[*instruction_id] { @@ -54,7 +69,22 @@ fn analyze_last_uses(dfg: &DataFlowGraph, block_id: BasicBlockId) -> FxHashSet { for argument in arguments { @@ -68,18 +98,22 @@ fn analyze_last_uses(dfg: &DataFlowGraph, block_id: BasicBlockId) -> FxHashSet { + let result = dfg.instruction_results(*instruction_id)[0]; + if matches!(dfg.type_of_value(result), Array { .. } | Slice { .. }) { + arrays_from_load.insert(result); + } + } _ => (), } } - - instructions_that_can_be_made_mutable } /// Make each ArraySet instruction in `instructions_to_update` mutable. fn make_mutable( dfg: &mut DataFlowGraph, block_id: BasicBlockId, - instructions_to_update: FxHashSet, + instructions_to_update: &HashSet, ) { if instructions_to_update.is_empty() { return; @@ -105,3 +139,129 @@ fn make_mutable( *dfg[block_id].instructions_mut() = instructions; } + +#[cfg(test)] +mod tests { + use std::sync::Arc; + + use im::vector; + + use crate::ssa::{ + function_builder::FunctionBuilder, + ir::{ + function::RuntimeType, + instruction::{BinaryOp, Instruction}, + map::Id, + types::Type, + }, + }; + + #[test] + fn array_set_in_loop_with_conditional_clone() { + // We want to make sure that we do not mark a single array set mutable which is loaded + // from and cloned in a loop. If the array is inadvertently marked mutable, and is cloned in a previous iteration + // of the loop, its clone will also be altered. + // + // acir(inline) fn main f0 { + // b0(): + // v2 = allocate + // store [Field 0, Field 0, Field 0, Field 0, Field 0] at v2 + // v3 = allocate + // store [Field 0, Field 0, Field 0, Field 0, Field 0] at v3 + // jmp b1(u32 0) + // b1(v5: u32): + // v7 = lt v5, u32 5 + // jmpif v7 then: b3, else: b2 + // b3(): + // v8 = eq v5, u32 5 + // jmpif v8 then: b4, else: b5 + // b4(): + // v9 = load v2 + // store v9 at v3 + // jmp b5() + // b5(): + // v10 = load v2 + // v12 = array_set v10, index v5, value Field 20 + // store v12 at v2 + // v14 = add v5, u32 1 + // jmp b1(v14) + // b2(): + // return + // } + let main_id = Id::test_new(0); + let mut builder = FunctionBuilder::new("main".into(), main_id); + builder.set_runtime(RuntimeType::Brillig); + + let array_type = Type::Array(Arc::new(vec![Type::field()]), 5); + let zero = builder.field_constant(0u128); + let array_constant = + builder.array_constant(vector![zero, zero, zero, zero, zero], array_type.clone()); + + let v2 = builder.insert_allocate(array_type.clone()); + + builder.insert_store(v2, array_constant); + + let v3 = builder.insert_allocate(array_type.clone()); + builder.insert_store(v3, array_constant); + + let b1 = builder.insert_block(); + let zero_u32 = builder.numeric_constant(0u128, Type::unsigned(32)); + builder.terminate_with_jmp(b1, vec![zero_u32]); + + // Loop header + builder.switch_to_block(b1); + let v5 = builder.add_block_parameter(b1, Type::unsigned(32)); + let five = builder.numeric_constant(5u128, Type::unsigned(32)); + let v7 = builder.insert_binary(v5, BinaryOp::Lt, five); + + let b2 = builder.insert_block(); + let b3 = builder.insert_block(); + let b4 = builder.insert_block(); + let b5 = builder.insert_block(); + builder.terminate_with_jmpif(v7, b3, b2); + + // Loop body + // b3 is the if statement conditional + builder.switch_to_block(b3); + let two = builder.numeric_constant(5u128, Type::unsigned(32)); + let v8 = builder.insert_binary(v5, BinaryOp::Eq, two); + builder.terminate_with_jmpif(v8, b4, b5); + + // b4 is the rest of the loop after the if statement + builder.switch_to_block(b4); + let v9 = builder.insert_load(v2, array_type.clone()); + builder.insert_store(v3, v9); + builder.terminate_with_jmp(b5, vec![]); + + builder.switch_to_block(b5); + let v10 = builder.insert_load(v2, array_type.clone()); + let twenty = builder.field_constant(20u128); + let v12 = builder.insert_array_set(v10, v5, twenty); + builder.insert_store(v2, v12); + let one = builder.numeric_constant(1u128, Type::unsigned(32)); + let v14 = builder.insert_binary(v5, BinaryOp::Add, one); + builder.terminate_with_jmp(b1, vec![v14]); + + builder.switch_to_block(b2); + builder.terminate_with_return(vec![]); + + let ssa = builder.finish(); + // We expect the same result as above + let ssa = ssa.array_set_optimization(); + + let main = ssa.main(); + assert_eq!(main.reachable_blocks().len(), 6); + + let array_set_instructions = main.dfg[b5] + .instructions() + .iter() + .filter(|instruction| matches!(&main.dfg[**instruction], Instruction::ArraySet { .. })) + .collect::>(); + + assert_eq!(array_set_instructions.len(), 1); + if let Instruction::ArraySet { mutable, .. } = &main.dfg[*array_set_instructions[0]] { + // The single array set should not be marked mutable + assert!(!mutable); + } + } +} diff --git a/compiler/noirc_evaluator/src/ssa/opt/die.rs b/compiler/noirc_evaluator/src/ssa/opt/die.rs index 7356998ceb8..33351405606 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/die.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/die.rs @@ -1,7 +1,6 @@ //! Dead Instruction Elimination (DIE) pass: Removes any instruction without side-effects for //! which the results are unused. -use std::collections::HashSet; - +use fxhash::{FxHashMap as HashMap, FxHashSet as HashSet}; use im::Vector; use noirc_errors::Location; @@ -18,6 +17,8 @@ use crate::ssa::{ ssa_gen::{Ssa, SSA_WORD_SIZE}, }; +use super::rc::{pop_rc_for, RcInstruction}; + impl Ssa { /// Performs Dead Instruction Elimination (DIE) to remove any instructions with /// unused results. @@ -105,6 +106,8 @@ impl Context { let instructions_len = block.instructions().len(); + let mut rc_tracker = RcTracker::default(); + // Indexes of instructions that might be out of bounds. // We'll remove those, but before that we'll insert bounds checks for them. let mut possible_index_out_of_bounds_indexes = Vec::new(); @@ -131,8 +134,13 @@ impl Context { }); } } + + rc_tracker.track_inc_rcs_to_remove(*instruction_id, function); } + self.instructions_to_remove.extend(rc_tracker.get_non_mutated_arrays()); + self.instructions_to_remove.extend(rc_tracker.rc_pairs_to_remove); + // If there are some instructions that might trigger an out of bounds error, // first add constrain checks. Then run the DIE pass again, which will remove those // but leave the constrains (any any value needed by those constrains) @@ -155,6 +163,45 @@ impl Context { false } + fn track_inc_rcs_to_remove( + &self, + instruction_id: InstructionId, + function: &Function, + inc_rcs: &mut HashMap>, + inc_rcs_to_remove: &mut HashSet, + ) { + let instruction = &function.dfg[instruction_id]; + // DIE loops over a block in reverse order, so we insert an RC instruction for possible removal + // when we see a DecrementRc and check whether it was possibly mutated when we see an IncrementRc. + match instruction { + Instruction::IncrementRc { value } => { + if let Some(inc_rc) = pop_rc_for(*value, function, inc_rcs) { + if !inc_rc.possibly_mutated { + inc_rcs_to_remove.insert(inc_rc.id); + inc_rcs_to_remove.insert(instruction_id); + } + } + } + Instruction::DecrementRc { value } => { + let typ = function.dfg.type_of_value(*value); + + // We assume arrays aren't mutated until we find an array_set + let inc_rc = + RcInstruction { id: instruction_id, array: *value, possibly_mutated: false }; + inc_rcs.entry(typ).or_default().push(inc_rc); + } + Instruction::ArraySet { array, .. } => { + let typ = function.dfg.type_of_value(*array); + if let Some(inc_rcs) = inc_rcs.get_mut(&typ) { + for inc_rc in inc_rcs { + inc_rc.possibly_mutated = true; + } + } + } + _ => {} + } + } + /// Returns true if an instruction can be removed. /// /// An instruction can be removed as long as it has no side-effects, and none of its result @@ -507,12 +554,113 @@ fn apply_side_effects( (lhs, rhs) } +#[derive(Default)] +struct RcTracker { + // We can track IncrementRc instructions per block to determine whether they are useless. + // IncrementRc and DecrementRc instructions are normally side effectual instructions, but we remove + // them if their value is not used anywhere in the function. However, even when their value is used, their existence + // is pointless logic if there is no array set between the increment and the decrement of the reference counter. + // We track per block whether an IncrementRc instruction has a paired DecrementRc instruction + // with the same value but no array set in between. + // If we see an inc/dec RC pair within a block we can safely remove both instructions. + rcs_with_possible_pairs: HashMap>, + rc_pairs_to_remove: HashSet, + // We also separately track all IncrementRc instructions and all arrays which have been mutably borrowed. + // If an array has not been mutably borrowed we can then safely remove all IncrementRc instructions on that array. + inc_rcs: HashMap>, + mut_borrowed_arrays: HashSet, + // The SSA often creates patterns where after simplifications we end up with repeat + // IncrementRc instructions on the same value. We track whether the previous instruction was an IncrementRc, + // and if the current instruction is also an IncrementRc on the same value we remove the current instruction. + // `None` if the previous instruction was anything other than an IncrementRc + previous_inc_rc: Option, +} + +impl RcTracker { + fn track_inc_rcs_to_remove(&mut self, instruction_id: InstructionId, function: &Function) { + let instruction = &function.dfg[instruction_id]; + + if let Instruction::IncrementRc { value } = instruction { + if let Some(previous_value) = self.previous_inc_rc { + if previous_value == *value { + self.rc_pairs_to_remove.insert(instruction_id); + } + } + self.previous_inc_rc = Some(*value); + } else { + self.previous_inc_rc = None; + } + + // DIE loops over a block in reverse order, so we insert an RC instruction for possible removal + // when we see a DecrementRc and check whether it was possibly mutated when we see an IncrementRc. + match instruction { + Instruction::IncrementRc { value } => { + if let Some(inc_rc) = + pop_rc_for(*value, function, &mut self.rcs_with_possible_pairs) + { + if !inc_rc.possibly_mutated { + self.rc_pairs_to_remove.insert(inc_rc.id); + self.rc_pairs_to_remove.insert(instruction_id); + } + } + + self.inc_rcs.entry(*value).or_default().insert(instruction_id); + } + Instruction::DecrementRc { value } => { + let typ = function.dfg.type_of_value(*value); + + // We assume arrays aren't mutated until we find an array_set + let dec_rc = + RcInstruction { id: instruction_id, array: *value, possibly_mutated: false }; + self.rcs_with_possible_pairs.entry(typ).or_default().push(dec_rc); + } + Instruction::ArraySet { array, .. } => { + let typ = function.dfg.type_of_value(*array); + if let Some(dec_rcs) = self.rcs_with_possible_pairs.get_mut(&typ) { + for dec_rc in dec_rcs { + dec_rc.possibly_mutated = true; + } + } + + self.mut_borrowed_arrays.insert(*array); + } + Instruction::Store { value, .. } => { + // We are very conservative and say that any store of an array value means it has the potential + // to be mutated. This is done due to the tracking of mutable borrows still being per block. + let typ = function.dfg.type_of_value(*value); + if matches!(&typ, Type::Array(..) | Type::Slice(..)) { + self.mut_borrowed_arrays.insert(*value); + } + } + _ => {} + } + } + + fn get_non_mutated_arrays(&self) -> HashSet { + self.inc_rcs + .keys() + .filter_map(|value| { + if !self.mut_borrowed_arrays.contains(value) { + Some(&self.inc_rcs[value]) + } else { + None + } + }) + .flatten() + .copied() + .collect() + } +} #[cfg(test)] mod test { + use std::sync::Arc; + + use im::vector; + use crate::ssa::{ function_builder::FunctionBuilder, ir::{ - instruction::{BinaryOp, Intrinsic}, + instruction::{BinaryOp, Instruction, Intrinsic}, map::Id, types::Type, }, @@ -642,4 +790,234 @@ mod test { assert_eq!(main.dfg[main.entry_block()].instructions().len(), 1); } + + #[test] + fn remove_useless_paired_rcs_even_when_used() { + // acir(inline) fn main f0 { + // b0(v0: [Field; 2]): + // inc_rc v0 + // v2 = array_get v0, index u32 0 + // dec_rc v0 + // return v2 + // } + let main_id = Id::test_new(0); + + // Compiling main + let mut builder = FunctionBuilder::new("main".into(), main_id); + let v0 = builder.add_parameter(Type::Array(Arc::new(vec![Type::field()]), 2)); + builder.increment_array_reference_count(v0); + let zero = builder.numeric_constant(0u128, Type::unsigned(32)); + let v1 = builder.insert_array_get(v0, zero, Type::field()); + builder.decrement_array_reference_count(v0); + builder.terminate_with_return(vec![v1]); + + let ssa = builder.finish(); + let main = ssa.main(); + + // The instruction count never includes the terminator instruction + assert_eq!(main.dfg[main.entry_block()].instructions().len(), 3); + + // Expected output: + // + // acir(inline) fn main f0 { + // b0(v0: [Field; 2]): + // v2 = array_get v0, index u32 0 + // return v2 + // } + let ssa = ssa.dead_instruction_elimination(); + let main = ssa.main(); + + let instructions = main.dfg[main.entry_block()].instructions(); + assert_eq!(instructions.len(), 1); + assert!(matches!(&main.dfg[instructions[0]], Instruction::ArrayGet { .. })); + } + + #[test] + fn keep_paired_rcs_with_array_set() { + // acir(inline) fn main f0 { + // b0(v0: [Field; 2]): + // inc_rc v0 + // v2 = array_set v0, index u32 0, value u32 0 + // dec_rc v0 + // return v2 + // } + let main_id = Id::test_new(0); + + // Compiling main + let mut builder = FunctionBuilder::new("main".into(), main_id); + let v0 = builder.add_parameter(Type::Array(Arc::new(vec![Type::field()]), 2)); + builder.increment_array_reference_count(v0); + let zero = builder.numeric_constant(0u128, Type::unsigned(32)); + let v1 = builder.insert_array_set(v0, zero, zero); + builder.decrement_array_reference_count(v0); + builder.terminate_with_return(vec![v1]); + + let ssa = builder.finish(); + let main = ssa.main(); + + // The instruction count never includes the terminator instruction + assert_eq!(main.dfg[main.entry_block()].instructions().len(), 3); + + // We expect the output to be unchanged + let ssa = ssa.dead_instruction_elimination(); + let main = ssa.main(); + + assert_eq!(main.dfg[main.entry_block()].instructions().len(), 3); + } + + #[test] + fn keep_inc_rc_on_borrowed_array_store() { + // acir(inline) fn main f0 { + // b0(): + // v2 = allocate + // inc_rc [u32 0, u32 0] + // store [u32 0, u32 0] at v2 + // inc_rc [u32 0, u32 0] + // jmp b1() + // b1(): + // v3 = load v2 + // v5 = array_set v3, index u32 0, value u32 1 + // return v5 + // } + let main_id = Id::test_new(0); + + // Compiling main + let mut builder = FunctionBuilder::new("main".into(), main_id); + let zero = builder.numeric_constant(0u128, Type::unsigned(32)); + let array_type = Type::Array(Arc::new(vec![Type::unsigned(32)]), 2); + let array = builder.array_constant(vector![zero, zero], array_type.clone()); + let v2 = builder.insert_allocate(array_type.clone()); + builder.increment_array_reference_count(array); + builder.insert_store(v2, array); + builder.increment_array_reference_count(array); + + let b1 = builder.insert_block(); + builder.terminate_with_jmp(b1, vec![]); + builder.switch_to_block(b1); + + let v3 = builder.insert_load(v2, array_type); + let one = builder.numeric_constant(1u128, Type::unsigned(32)); + let v5 = builder.insert_array_set(v3, zero, one); + builder.terminate_with_return(vec![v5]); + + let ssa = builder.finish(); + let main = ssa.main(); + + // The instruction count never includes the terminator instruction + assert_eq!(main.dfg[main.entry_block()].instructions().len(), 4); + assert_eq!(main.dfg[b1].instructions().len(), 2); + + // We expect the output to be unchanged + let ssa = ssa.dead_instruction_elimination(); + let main = ssa.main(); + + assert_eq!(main.dfg[main.entry_block()].instructions().len(), 4); + assert_eq!(main.dfg[b1].instructions().len(), 2); + } + + #[test] + fn keep_inc_rc_on_borrowed_array_set() { + // acir(inline) fn main f0 { + // b0(v0: [u32; 2]): + // inc_rc v0 + // v3 = array_set v0, index u32 0, value u32 1 + // inc_rc v0 + // inc_rc v0 + // inc_rc v0 + // v4 = array_get v3, index u32 1 + // return v4 + // } + let main_id = Id::test_new(0); + + // Compiling main + let mut builder = FunctionBuilder::new("main".into(), main_id); + let array_type = Type::Array(Arc::new(vec![Type::unsigned(32)]), 2); + let v0 = builder.add_parameter(array_type.clone()); + builder.increment_array_reference_count(v0); + let zero = builder.numeric_constant(0u128, Type::unsigned(32)); + let one = builder.numeric_constant(1u128, Type::unsigned(32)); + let v3 = builder.insert_array_set(v0, zero, one); + builder.increment_array_reference_count(v0); + builder.increment_array_reference_count(v0); + builder.increment_array_reference_count(v0); + + let v4 = builder.insert_array_get(v3, one, Type::unsigned(32)); + + builder.terminate_with_return(vec![v4]); + + let ssa = builder.finish(); + let main = ssa.main(); + + // The instruction count never includes the terminator instruction + assert_eq!(main.dfg[main.entry_block()].instructions().len(), 6); + + // We expect the output to be unchanged + // Expected output: + // + // acir(inline) fn main f0 { + // b0(v0: [u32; 2]): + // inc_rc v0 + // v3 = array_set v0, index u32 0, value u32 1 + // inc_rc v0 + // v4 = array_get v3, index u32 1 + // return v4 + // } + let ssa = ssa.dead_instruction_elimination(); + let main = ssa.main(); + + let instructions = main.dfg[main.entry_block()].instructions(); + // We expect only the repeated inc_rc instructions to be collapsed into a single inc_rc. + assert_eq!(instructions.len(), 4); + + assert!(matches!(&main.dfg[instructions[0]], Instruction::IncrementRc { .. })); + assert!(matches!(&main.dfg[instructions[1]], Instruction::ArraySet { .. })); + assert!(matches!(&main.dfg[instructions[2]], Instruction::IncrementRc { .. })); + assert!(matches!(&main.dfg[instructions[3]], Instruction::ArrayGet { .. })); + } + + #[test] + fn remove_inc_rcs_that_are_never_mutably_borrowed() { + // acir(inline) fn main f0 { + // b0(v0: [Field; 2]): + // inc_rc v0 + // inc_rc v0 + // inc_rc v0 + // v2 = array_get v0, index u32 0 + // inc_rc v0 + // return v2 + // } + let main_id = Id::test_new(0); + + // Compiling main + let mut builder = FunctionBuilder::new("main".into(), main_id); + let v0 = builder.add_parameter(Type::Array(Arc::new(vec![Type::field()]), 2)); + builder.increment_array_reference_count(v0); + builder.increment_array_reference_count(v0); + builder.increment_array_reference_count(v0); + + let zero = builder.numeric_constant(0u128, Type::unsigned(32)); + let v2 = builder.insert_array_get(v0, zero, Type::field()); + builder.increment_array_reference_count(v0); + builder.terminate_with_return(vec![v2]); + + let ssa = builder.finish(); + let main = ssa.main(); + + // The instruction count never includes the terminator instruction + assert_eq!(main.dfg[main.entry_block()].instructions().len(), 5); + + // Expected output: + // + // acir(inline) fn main f0 { + // b0(v0: [Field; 2]): + // v2 = array_get v0, index u32 0 + // return v2 + // } + let ssa = ssa.dead_instruction_elimination(); + let main = ssa.main(); + + let instructions = main.dfg[main.entry_block()].instructions(); + assert_eq!(instructions.len(), 1); + assert!(matches!(&main.dfg[instructions[0]], Instruction::ArrayGet { .. })); + } } diff --git a/compiler/noirc_evaluator/src/ssa/opt/rc.rs b/compiler/noirc_evaluator/src/ssa/opt/rc.rs index 1750f2d80a5..06025fd9e8b 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/rc.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/rc.rs @@ -1,4 +1,4 @@ -use std::collections::{HashMap, HashSet}; +use fxhash::{FxHashMap as HashMap, FxHashSet as HashSet}; use crate::ssa::{ ir::{ @@ -35,13 +35,13 @@ struct Context { // // The type of the array being operated on is recorded. // If an array_set to that array type is encountered, that is also recorded. - inc_rcs: HashMap>, + inc_rcs: HashMap>, } -struct IncRc { - id: InstructionId, - array: ValueId, - possibly_mutated: bool, +pub(crate) struct RcInstruction { + pub(crate) id: InstructionId, + pub(crate) array: ValueId, + pub(crate) possibly_mutated: bool, } /// This function is very simplistic for now. It takes advantage of the fact that dec_rc @@ -80,7 +80,8 @@ impl Context { let typ = function.dfg.type_of_value(*value); // We assume arrays aren't mutated until we find an array_set - let inc_rc = IncRc { id: *instruction, array: *value, possibly_mutated: false }; + let inc_rc = + RcInstruction { id: *instruction, array: *value, possibly_mutated: false }; self.inc_rcs.entry(typ).or_default().push(inc_rc); } } @@ -107,11 +108,11 @@ impl Context { /// is not possibly mutated, then we can remove them both. Returns each such pair. fn find_rcs_to_remove(&mut self, function: &Function) -> HashSet { let last_block = function.find_last_block(); - let mut to_remove = HashSet::new(); + let mut to_remove = HashSet::default(); for instruction in function.dfg[last_block].instructions() { if let Instruction::DecrementRc { value } = &function.dfg[*instruction] { - if let Some(inc_rc) = self.pop_rc_for(*value, function) { + if let Some(inc_rc) = pop_rc_for(*value, function, &mut self.inc_rcs) { if !inc_rc.possibly_mutated { to_remove.insert(inc_rc.id); to_remove.insert(*instruction); @@ -122,16 +123,20 @@ impl Context { to_remove } +} - /// Finds and pops the IncRc for the given array value if possible. - fn pop_rc_for(&mut self, value: ValueId, function: &Function) -> Option { - let typ = function.dfg.type_of_value(value); +/// Finds and pops the IncRc for the given array value if possible. +pub(crate) fn pop_rc_for( + value: ValueId, + function: &Function, + inc_rcs: &mut HashMap>, +) -> Option { + let typ = function.dfg.type_of_value(value); - let rcs = self.inc_rcs.get_mut(&typ)?; - let position = rcs.iter().position(|inc_rc| inc_rc.array == value)?; + let rcs = inc_rcs.get_mut(&typ)?; + let position = rcs.iter().position(|inc_rc| inc_rc.array == value)?; - Some(rcs.remove(position)) - } + Some(rcs.remove(position)) } fn remove_instructions(to_remove: HashSet, function: &mut Function) { diff --git a/compiler/noirc_frontend/src/ast/statement.rs b/compiler/noirc_frontend/src/ast/statement.rs index 38cf2cb1d80..4abea8cebb4 100644 --- a/compiler/noirc_frontend/src/ast/statement.rs +++ b/compiler/noirc_frontend/src/ast/statement.rs @@ -294,6 +294,7 @@ pub trait Recoverable { #[derive(Debug, PartialEq, Eq, Clone)] pub struct ModuleDeclaration { + pub visibility: ItemVisibility, pub ident: Ident, pub outer_attributes: Vec, } diff --git a/compiler/noirc_frontend/src/ast/type_alias.rs b/compiler/noirc_frontend/src/ast/type_alias.rs index 3228765170e..b279d86f19e 100644 --- a/compiler/noirc_frontend/src/ast/type_alias.rs +++ b/compiler/noirc_frontend/src/ast/type_alias.rs @@ -1,4 +1,4 @@ -use super::{Ident, UnresolvedGenerics, UnresolvedType}; +use super::{Ident, ItemVisibility, UnresolvedGenerics, UnresolvedType}; use iter_extended::vecmap; use noirc_errors::Span; use std::fmt::Display; @@ -9,6 +9,7 @@ pub struct NoirTypeAlias { pub name: Ident, pub generics: UnresolvedGenerics, pub typ: UnresolvedType, + pub visibility: ItemVisibility, pub span: Span, } @@ -17,9 +18,10 @@ impl NoirTypeAlias { name: Ident, generics: UnresolvedGenerics, typ: UnresolvedType, + visibility: ItemVisibility, span: Span, ) -> NoirTypeAlias { - NoirTypeAlias { name, generics, typ, span } + NoirTypeAlias { name, generics, typ, visibility, span } } } diff --git a/compiler/noirc_frontend/src/ast/visitor.rs b/compiler/noirc_frontend/src/ast/visitor.rs index 6ce8a70a0c5..ed4d17cadd8 100644 --- a/compiler/noirc_frontend/src/ast/visitor.rs +++ b/compiler/noirc_frontend/src/ast/visitor.rs @@ -500,7 +500,7 @@ impl Item { noir_trait_impl.accept(self.span, visitor); } ItemKind::Impl(type_impl) => type_impl.accept(self.span, visitor), - ItemKind::Global(let_statement) => { + ItemKind::Global(let_statement, _visibility) => { if visitor.visit_global(let_statement, self.span) { let_statement.accept(visitor); } diff --git a/compiler/noirc_frontend/src/elaborator/comptime.rs b/compiler/noirc_frontend/src/elaborator/comptime.rs index ca441758322..560be895628 100644 --- a/compiler/noirc_frontend/src/elaborator/comptime.rs +++ b/compiler/noirc_frontend/src/elaborator/comptime.rs @@ -439,11 +439,12 @@ impl<'context> Elaborator<'context> { resolved_trait_generics: Vec::new(), }); } - TopLevelStatementKind::Global(global) => { + TopLevelStatementKind::Global(global, visibility) => { let (global, error) = dc_mod::collect_global( self.interner, self.def_maps.get_mut(&self.crate_id).unwrap(), Documented::new(global, item.doc_comments), + visibility, self.file, self.local_module, self.crate_id, diff --git a/compiler/noirc_frontend/src/elaborator/expressions.rs b/compiler/noirc_frontend/src/elaborator/expressions.rs index 9a74e77215a..46a22bb232f 100644 --- a/compiler/noirc_frontend/src/elaborator/expressions.rs +++ b/compiler/noirc_frontend/src/elaborator/expressions.rs @@ -535,6 +535,8 @@ impl<'context> Elaborator<'context> { } }; + self.mark_struct_as_constructed(r#type.clone()); + let turbofish_span = last_segment.turbofish_span(); let struct_generics = self.resolve_struct_turbofish_generics( @@ -564,6 +566,12 @@ impl<'context> Elaborator<'context> { (expr, Type::Struct(struct_type, generics)) } + pub(super) fn mark_struct_as_constructed(&mut self, struct_type: Shared) { + let struct_type = struct_type.borrow(); + let parent_module_id = struct_type.id.parent_module_id(self.def_maps); + self.interner.usage_tracker.mark_as_used(parent_module_id, &struct_type.name); + } + /// Resolve all the fields of a struct constructor expression. /// Ensures all fields are present, none are repeated, and all /// are part of the struct. diff --git a/compiler/noirc_frontend/src/elaborator/mod.rs b/compiler/noirc_frontend/src/elaborator/mod.rs index c36231bcf3b..c5e457c405b 100644 --- a/compiler/noirc_frontend/src/elaborator/mod.rs +++ b/compiler/noirc_frontend/src/elaborator/mod.rs @@ -95,7 +95,7 @@ pub struct Elaborator<'context> { pub(crate) interner: &'context mut NodeInterner, - def_maps: &'context mut DefMaps, + pub(crate) def_maps: &'context mut DefMaps, pub(crate) file: FileId, @@ -759,6 +759,10 @@ impl<'context> Elaborator<'context> { type_span, ); + if is_entry_point { + self.mark_parameter_type_as_used(&typ); + } + let pattern = self.elaborate_pattern_and_store_ids( pattern, typ.clone(), @@ -837,6 +841,57 @@ impl<'context> Elaborator<'context> { self.current_item = None; } + fn mark_parameter_type_as_used(&mut self, typ: &Type) { + match typ { + Type::Array(_n, typ) => self.mark_parameter_type_as_used(typ), + Type::Slice(typ) => self.mark_parameter_type_as_used(typ), + Type::Tuple(types) => { + for typ in types { + self.mark_parameter_type_as_used(typ); + } + } + Type::Struct(struct_type, generics) => { + self.mark_struct_as_constructed(struct_type.clone()); + for generic in generics { + self.mark_parameter_type_as_used(generic); + } + } + Type::Alias(alias_type, generics) => { + self.mark_parameter_type_as_used(&alias_type.borrow().get_type(generics)); + } + Type::MutableReference(typ) => { + self.mark_parameter_type_as_used(typ); + } + Type::InfixExpr(left, _op, right) => { + self.mark_parameter_type_as_used(left); + self.mark_parameter_type_as_used(right); + } + Type::FieldElement + | Type::Integer(..) + | Type::Bool + | Type::String(_) + | Type::FmtString(_, _) + | Type::Unit + | Type::Quoted(..) + | Type::Constant(..) + | Type::TraitAsType(..) + | Type::TypeVariable(..) + | Type::NamedGeneric(..) + | Type::Function(..) + | Type::Forall(..) + | Type::Error => (), + } + + if let Type::Alias(alias_type, generics) = typ { + self.mark_parameter_type_as_used(&alias_type.borrow().get_type(generics)); + return; + } + + if let Type::Struct(struct_type, _generics) = typ { + self.mark_struct_as_constructed(struct_type.clone()); + } + } + fn run_function_lints(&mut self, func: &FuncMeta, modifiers: &FunctionModifiers) { self.run_lint(|_| lints::inlining_attributes(func, modifiers).map(Into::into)); self.run_lint(|_| lints::missing_pub(func, modifiers).map(Into::into)); @@ -1131,13 +1186,100 @@ impl<'context> Elaborator<'context> { self.file = alias.file_id; self.local_module = alias.module_id; + let name = &alias.type_alias_def.name; + let visibility = alias.type_alias_def.visibility; + let span = alias.type_alias_def.typ.span; + let generics = self.add_generics(&alias.type_alias_def.generics); self.current_item = Some(DependencyId::Alias(alias_id)); let typ = self.resolve_type(alias.type_alias_def.typ); + + if visibility != ItemVisibility::Private { + self.check_aliased_type_is_not_more_private(name, visibility, &typ, span); + } + self.interner.set_type_alias(alias_id, typ, generics); self.generics.clear(); } + fn check_aliased_type_is_not_more_private( + &mut self, + name: &Ident, + visibility: ItemVisibility, + typ: &Type, + span: Span, + ) { + match typ { + Type::Struct(struct_type, generics) => { + let struct_type = struct_type.borrow(); + let struct_module_id = struct_type.id.module_id(); + + // We only check this in types in the same crate. If it's in a different crate + // then it's either accessible (all good) or it's not, in which case a different + // error will happen somewhere else, but no need to error again here. + if struct_module_id.krate == self.crate_id { + // Find the struct in the parent module so we can know its visibility + let parent_module_id = struct_type.id.parent_module_id(self.def_maps); + let parent_module_data = self.get_module(parent_module_id); + let per_ns = parent_module_data.find_name(&struct_type.name); + if let Some((_, aliased_visibility, _)) = per_ns.types { + if aliased_visibility < visibility { + self.push_err(ResolverError::TypeIsMorePrivateThenItem { + typ: struct_type.name.to_string(), + item: name.to_string(), + span, + }); + } + } + } + + for generic in generics { + self.check_aliased_type_is_not_more_private(name, visibility, generic, span); + } + } + Type::Tuple(types) => { + for typ in types { + self.check_aliased_type_is_not_more_private(name, visibility, typ, span); + } + } + Type::Alias(alias_type, generics) => { + self.check_aliased_type_is_not_more_private( + name, + visibility, + &alias_type.borrow().get_type(generics), + span, + ); + } + Type::Function(args, return_type, env, _) => { + for arg in args { + self.check_aliased_type_is_not_more_private(name, visibility, arg, span); + } + self.check_aliased_type_is_not_more_private(name, visibility, return_type, span); + self.check_aliased_type_is_not_more_private(name, visibility, env, span); + } + Type::MutableReference(typ) | Type::Array(_, typ) | Type::Slice(typ) => { + self.check_aliased_type_is_not_more_private(name, visibility, typ, span); + } + Type::InfixExpr(left, _op, right) => { + self.check_aliased_type_is_not_more_private(name, visibility, left, span); + self.check_aliased_type_is_not_more_private(name, visibility, right, span); + } + Type::FieldElement + | Type::Integer(..) + | Type::Bool + | Type::String(..) + | Type::FmtString(..) + | Type::Unit + | Type::Quoted(..) + | Type::TypeVariable(..) + | Type::Forall(..) + | Type::TraitAsType(..) + | Type::Constant(..) + | Type::NamedGeneric(..) + | Type::Error => (), + } + } + fn collect_struct_definitions(&mut self, structs: &BTreeMap) { // This is necessary to avoid cloning the entire struct map // when adding checks after each struct field is resolved. diff --git a/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs b/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs index c21ca353e07..9960486120e 100644 --- a/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs +++ b/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs @@ -30,7 +30,6 @@ use crate::{ InterpreterError, Value, }, def_collector::dc_crate::CollectedItems, - def_map::ModuleId, }, hir_def::function::FunctionBody, macros_api::{HirExpression, HirLiteral, Ident, ModuleDefId, NodeInterner, Signedness}, @@ -505,14 +504,7 @@ fn struct_def_module( ) -> IResult { let self_argument = check_one_argument(arguments, location)?; let struct_id = get_struct(self_argument)?; - let struct_module_id = struct_id.module_id(); - - // A struct's module is its own module. To get the module where its defined we need - // to look for its parent. - let module_data = interpreter.elaborator.get_module(struct_module_id); - let parent_local_id = module_data.parent.expect("Expected struct module parent to exist"); - let parent = ModuleId { krate: struct_module_id.krate, local_id: parent_local_id }; - + let parent = struct_id.parent_module_id(interpreter.elaborator.def_maps); Ok(Value::ModuleDefinition(parent)) } @@ -2466,10 +2458,12 @@ fn module_functions( let module_id = get_module(self_argument)?; let module_data = interpreter.elaborator.get_module(module_id); let func_ids = module_data - .value_definitions() + .definitions() + .definitions() + .iter() .filter_map(|module_def_id| { if let ModuleDefId::FunctionId(func_id) = module_def_id { - Some(Value::FunctionDefinition(func_id)) + Some(Value::FunctionDefinition(*func_id)) } else { None } @@ -2490,10 +2484,12 @@ fn module_structs( let module_id = get_module(self_argument)?; let module_data = interpreter.elaborator.get_module(module_id); let struct_ids = module_data - .type_definitions() + .definitions() + .definitions() + .iter() .filter_map(|module_def_id| { if let ModuleDefId::TypeId(id) = module_def_id { - Some(Value::StructDefinition(id)) + Some(Value::StructDefinition(*id)) } else { None } diff --git a/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs b/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs index d365e5807c2..faf72e86fb4 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs @@ -498,7 +498,7 @@ impl DefCollector { let ident = ident.clone(); let error = CompilationError::ResolverError(ResolverError::UnusedItem { ident, - item_type: unused_item.item_type(), + item: *unused_item, }); (error, module.location.file) }) diff --git a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs index f50a0608fab..b530e023152 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs @@ -139,15 +139,16 @@ impl<'a> ModCollector<'a> { fn collect_globals( &mut self, context: &mut Context, - globals: Vec>, + globals: Vec<(Documented, ItemVisibility)>, crate_id: CrateId, ) -> Vec<(CompilationError, fm::FileId)> { let mut errors = vec![]; - for global in globals { + for (global, visibility) in globals { let (global, error) = collect_global( &mut context.def_interner, &mut self.def_collector.def_map, global, + visibility, self.file_id, self.module_id, crate_id, @@ -306,6 +307,7 @@ impl<'a> ModCollector<'a> { let doc_comments = type_alias.doc_comments; let type_alias = type_alias.item; let name = type_alias.name.clone(); + let visibility = type_alias.visibility; // And store the TypeId -> TypeAlias mapping somewhere it is reachable let unresolved = UnresolvedTypeAlias { @@ -327,8 +329,19 @@ impl<'a> ModCollector<'a> { context.def_interner.set_doc_comments(ReferenceId::Alias(type_alias_id), doc_comments); // Add the type alias to scope so its path can be looked up later - let result = self.def_collector.def_map.modules[self.module_id.0] - .declare_type_alias(name.clone(), type_alias_id); + let result = self.def_collector.def_map.modules[self.module_id.0].declare_type_alias( + name.clone(), + visibility, + type_alias_id, + ); + + let parent_module_id = ModuleId { krate, local_id: self.module_id }; + context.def_interner.usage_tracker.add_unused_item( + parent_module_id, + name.clone(), + UnusedItem::TypeAlias(type_alias_id), + visibility, + ); if let Err((first_def, second_def)) = result { let err = DefCollectorErrorKind::Duplicate { @@ -368,6 +381,7 @@ impl<'a> ModCollector<'a> { let trait_id = match self.push_child_module( context, &name, + ItemVisibility::Public, Location::new(name.span(), self.file_id), Vec::new(), Vec::new(), @@ -503,7 +517,7 @@ impl<'a> ModCollector<'a> { if let Err((first_def, second_def)) = self.def_collector.def_map.modules [trait_id.0.local_id.0] - .declare_global(name.clone(), global_id) + .declare_global(name.clone(), ItemVisibility::Public, global_id) { let error = DefCollectorErrorKind::Duplicate { typ: DuplicateType::TraitAssociatedConst, @@ -526,7 +540,11 @@ impl<'a> ModCollector<'a> { TraitItem::Type { name } => { if let Err((first_def, second_def)) = self.def_collector.def_map.modules [trait_id.0.local_id.0] - .declare_type_alias(name.clone(), TypeAliasId::dummy_id()) + .declare_type_alias( + name.clone(), + ItemVisibility::Public, + TypeAliasId::dummy_id(), + ) { let error = DefCollectorErrorKind::Duplicate { typ: DuplicateType::TraitAssociatedType, @@ -595,6 +613,7 @@ impl<'a> ModCollector<'a> { match self.push_child_module( context, &submodule.name, + submodule.visibility, Location::new(submodule.name.span(), file_id), submodule.outer_attributes.clone(), submodule.contents.inner_attributes.clone(), @@ -694,6 +713,7 @@ impl<'a> ModCollector<'a> { match self.push_child_module( context, &mod_decl.ident, + mod_decl.visibility, Location::new(Span::empty(0), child_file_id), mod_decl.outer_attributes.clone(), ast.inner_attributes.clone(), @@ -744,6 +764,7 @@ impl<'a> ModCollector<'a> { &mut self, context: &mut Context, mod_name: &Ident, + visibility: ItemVisibility, mod_location: Location, outer_attributes: Vec, inner_attributes: Vec, @@ -755,6 +776,7 @@ impl<'a> ModCollector<'a> { &mut self.def_collector.def_map, self.module_id, mod_name, + visibility, mod_location, outer_attributes, inner_attributes, @@ -789,6 +811,7 @@ fn push_child_module( def_map: &mut CrateDefMap, parent: LocalModuleId, mod_name: &Ident, + visibility: ItemVisibility, mod_location: Location, outer_attributes: Vec, inner_attributes: Vec, @@ -823,7 +846,7 @@ fn push_child_module( // the struct name. if add_to_parent_scope { if let Err((first_def, second_def)) = - modules[parent.0].declare_child_module(mod_name.to_owned(), mod_id) + modules[parent.0].declare_child_module(mod_name.to_owned(), visibility, mod_id) { let err = DefCollectorErrorKind::Duplicate { typ: DuplicateType::Module, @@ -935,6 +958,7 @@ pub fn collect_struct( def_map, module_id, &name, + ItemVisibility::Public, location, Vec::new(), Vec::new(), @@ -1144,6 +1168,7 @@ pub(crate) fn collect_global( interner: &mut NodeInterner, def_map: &mut CrateDefMap, global: Documented, + visibility: ItemVisibility, file_id: FileId, module_id: LocalModuleId, crate_id: CrateId, @@ -1164,7 +1189,15 @@ pub(crate) fn collect_global( ); // Add the statement to the scope so its path can be looked up later - let result = def_map.modules[module_id.0].declare_global(name, global_id); + let result = def_map.modules[module_id.0].declare_global(name.clone(), visibility, global_id); + + let parent_module_id = ModuleId { krate: crate_id, local_id: module_id }; + interner.usage_tracker.add_unused_item( + parent_module_id, + name, + UnusedItem::Global(global_id), + visibility, + ); let error = result.err().map(|(first_def, second_def)| { let err = diff --git a/compiler/noirc_frontend/src/hir/def_collector/errors.rs b/compiler/noirc_frontend/src/hir/def_collector/errors.rs index f931a7cdf41..2f47505db94 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/errors.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/errors.rs @@ -71,8 +71,6 @@ pub enum DefCollectorErrorKind { "Either the type or the trait must be from the same crate as the trait implementation" )] TraitImplOrphaned { span: Span }, - #[error("macro error : {0:?}")] - MacroError(MacroError), #[error("The only supported types of numeric generics are integers, fields, and booleans")] UnsupportedNumericGenericType { ident: Ident, typ: UnresolvedTypeData }, #[error("impl has stricter requirements than trait")] @@ -86,14 +84,6 @@ pub enum DefCollectorErrorKind { }, } -/// An error struct that macro processors can return. -#[derive(Debug, Clone)] -pub struct MacroError { - pub primary_message: String, - pub secondary_message: Option, - pub span: Option, -} - impl DefCollectorErrorKind { pub fn into_file_diagnostic(&self, file: fm::FileId) -> FileDiagnostic { Diagnostic::from(self).in_file(file) @@ -276,9 +266,6 @@ impl<'a> From<&'a DefCollectorErrorKind> for Diagnostic { "Either the type or the trait must be from the same crate as the trait implementation".into(), *span, ), - DefCollectorErrorKind::MacroError(macro_error) => { - Diagnostic::simple_error(macro_error.primary_message.clone(), macro_error.secondary_message.clone().unwrap_or_default(), macro_error.span.unwrap_or_default()) - }, DefCollectorErrorKind::UnsupportedNumericGenericType { ident, typ } => { let name = &ident.0.contents; diff --git a/compiler/noirc_frontend/src/hir/def_map/mod.rs b/compiler/noirc_frontend/src/hir/def_map/mod.rs index d810e95218c..9afe897a167 100644 --- a/compiler/noirc_frontend/src/hir/def_map/mod.rs +++ b/compiler/noirc_frontend/src/hir/def_map/mod.rs @@ -42,12 +42,16 @@ impl ModuleId { pub fn dummy_id() -> ModuleId { ModuleId { krate: CrateId::dummy_id(), local_id: LocalModuleId::dummy_id() } } -} -impl ModuleId { pub fn module(self, def_maps: &DefMaps) -> &ModuleData { &def_maps[&self.krate].modules()[self.local_id.0] } + + /// Returns this module's parent, if there's any. + pub fn parent(self, def_maps: &DefMaps) -> Option { + let module_data = &def_maps[&self.krate].modules()[self.local_id.0]; + module_data.parent.map(|local_id| ModuleId { krate: self.krate, local_id }) + } } pub type DefMaps = BTreeMap; diff --git a/compiler/noirc_frontend/src/hir/def_map/module_data.rs b/compiler/noirc_frontend/src/hir/def_map/module_data.rs index 645d8650c7e..ff36bcf27d6 100644 --- a/compiler/noirc_frontend/src/hir/def_map/module_data.rs +++ b/compiler/noirc_frontend/src/hir/def_map/module_data.rs @@ -96,8 +96,13 @@ impl ModuleData { self.definitions.remove_definition(name); } - pub fn declare_global(&mut self, name: Ident, id: GlobalId) -> Result<(), (Ident, Ident)> { - self.declare(name, ItemVisibility::Public, id.into(), None) + pub fn declare_global( + &mut self, + name: Ident, + visibility: ItemVisibility, + id: GlobalId, + ) -> Result<(), (Ident, Ident)> { + self.declare(name, visibility, id.into(), None) } pub fn declare_struct( @@ -112,9 +117,10 @@ impl ModuleData { pub fn declare_type_alias( &mut self, name: Ident, + visibility: ItemVisibility, id: TypeAliasId, ) -> Result<(), (Ident, Ident)> { - self.declare(name, ItemVisibility::Public, id.into(), None) + self.declare(name, visibility, id.into(), None) } pub fn declare_trait( @@ -129,9 +135,10 @@ impl ModuleData { pub fn declare_child_module( &mut self, name: Ident, + visibility: ItemVisibility, child_id: ModuleId, ) -> Result<(), (Ident, Ident)> { - self.declare(name, ItemVisibility::Public, child_id.into(), None) + self.declare(name, visibility, child_id.into(), None) } pub fn find_func_with_name(&self, name: &Ident) -> Option { diff --git a/compiler/noirc_frontend/src/hir/resolution/errors.rs b/compiler/noirc_frontend/src/hir/resolution/errors.rs index 1e7f29527e2..f3c61a7fbe2 100644 --- a/compiler/noirc_frontend/src/hir/resolution/errors.rs +++ b/compiler/noirc_frontend/src/hir/resolution/errors.rs @@ -2,7 +2,10 @@ pub use noirc_errors::Span; use noirc_errors::{CustomDiagnostic as Diagnostic, FileDiagnostic}; use thiserror::Error; -use crate::{ast::Ident, hir::comptime::InterpreterError, parser::ParserError, Type}; +use crate::{ + ast::Ident, hir::comptime::InterpreterError, parser::ParserError, usage_tracker::UnusedItem, + Type, +}; use super::import::PathResolutionError; @@ -20,8 +23,8 @@ pub enum ResolverError { DuplicateDefinition { name: String, first_span: Span, second_span: Span }, #[error("Unused variable")] UnusedVariable { ident: Ident }, - #[error("Unused {item_type}")] - UnusedItem { ident: Ident, item_type: &'static str }, + #[error("Unused {}", item.item_type())] + UnusedItem { ident: Ident, item: UnusedItem }, #[error("Could not find variable in this scope")] VariableNotDeclared { name: String, span: Span }, #[error("path is not an identifier")] @@ -130,6 +133,8 @@ pub enum ResolverError { MutatingComptimeInNonComptimeContext { name: String, span: Span }, #[error("Failed to parse `{statement}` as an expression")] InvalidInternedStatementInExpr { statement: String, span: Span }, + #[error("Type `{typ}` is more private than item `{item}`")] + TypeIsMorePrivateThenItem { typ: String, item: String, span: Span }, } impl ResolverError { @@ -164,14 +169,24 @@ impl<'a> From<&'a ResolverError> for Diagnostic { diagnostic.unnecessary = true; diagnostic } - ResolverError::UnusedItem { ident, item_type } => { + ResolverError::UnusedItem { ident, item} => { let name = &ident.0.contents; + let item_type = item.item_type(); - let mut diagnostic = Diagnostic::simple_warning( - format!("unused {item_type} {name}"), - format!("unused {item_type}"), - ident.span(), - ); + let mut diagnostic = + if let UnusedItem::Struct(..) = item { + Diagnostic::simple_warning( + format!("{item_type} `{name}` is never constructed"), + format!("{item_type} is never constructed"), + ident.span(), + ) + } else { + Diagnostic::simple_warning( + format!("unused {item_type} {name}"), + format!("unused {item_type}"), + ident.span(), + ) + }; diagnostic.unnecessary = true; diagnostic } @@ -529,6 +544,13 @@ impl<'a> From<&'a ResolverError> for Diagnostic { *span, ) }, + ResolverError::TypeIsMorePrivateThenItem { typ, item, span } => { + Diagnostic::simple_warning( + format!("Type `{typ}` is more private than item `{item}`"), + String::new(), + *span, + ) + }, } } } diff --git a/compiler/noirc_frontend/src/hir/resolution/import.rs b/compiler/noirc_frontend/src/hir/resolution/import.rs index 938da0a879f..73a1b1ccb7c 100644 --- a/compiler/noirc_frontend/src/hir/resolution/import.rs +++ b/compiler/noirc_frontend/src/hir/resolution/import.rs @@ -289,7 +289,7 @@ fn resolve_name_in_module( return Err(PathResolutionError::Unresolved(first_segment.clone())); } - usage_tracker.mark_as_used(current_mod_id, first_segment); + usage_tracker.mark_as_referenced(current_mod_id, first_segment); let mut warning: Option = None; for (index, (last_segment, current_segment)) in @@ -356,7 +356,7 @@ fn resolve_name_in_module( return Err(PathResolutionError::Unresolved(current_segment.clone())); } - usage_tracker.mark_as_used(current_mod_id, current_segment); + usage_tracker.mark_as_referenced(current_mod_id, current_segment); current_ns = found_ns; } diff --git a/compiler/noirc_frontend/src/lib.rs b/compiler/noirc_frontend/src/lib.rs index b2d7c297b8c..4391c760701 100644 --- a/compiler/noirc_frontend/src/lib.rs +++ b/compiler/noirc_frontend/src/lib.rs @@ -45,7 +45,6 @@ pub mod macros_api { pub use noirc_errors::Span; pub use crate::graph::CrateId; - pub use crate::hir::def_collector::errors::MacroError; pub use crate::hir_def::expr::{HirExpression, HirLiteral}; pub use crate::hir_def::stmt::HirStatement; pub use crate::node_interner::{NodeInterner, StructId}; diff --git a/compiler/noirc_frontend/src/node_interner.rs b/compiler/noirc_frontend/src/node_interner.rs index 75178df319d..a95282a1ec9 100644 --- a/compiler/noirc_frontend/src/node_interner.rs +++ b/compiler/noirc_frontend/src/node_interner.rs @@ -23,6 +23,7 @@ use crate::graph::CrateId; use crate::hir::comptime; use crate::hir::def_collector::dc_crate::CompilationError; use crate::hir::def_collector::dc_crate::{UnresolvedStruct, UnresolvedTrait, UnresolvedTypeAlias}; +use crate::hir::def_map::DefMaps; use crate::hir::def_map::{LocalModuleId, ModuleId}; use crate::hir::type_check::generics::TraitGenerics; use crate::hir_def::traits::NamedType; @@ -489,6 +490,11 @@ impl StructId { pub fn local_module_id(self) -> LocalModuleId { self.0.local_id } + + /// Returns the module where this struct is defined. + pub fn parent_module_id(self, def_maps: &DefMaps) -> ModuleId { + self.module_id().parent(def_maps).expect("Expected struct module parent to exist") + } } #[derive(Debug, Eq, PartialEq, Hash, Copy, Clone, PartialOrd, Ord)] @@ -676,7 +682,7 @@ impl Default for NodeInterner { auto_import_names: HashMap::default(), comptime_scopes: vec![HashMap::default()], trait_impl_associated_types: HashMap::default(), - usage_tracker: UsageTracker::new(), + usage_tracker: UsageTracker::default(), doc_comments: HashMap::default(), } } diff --git a/compiler/noirc_frontend/src/parser/mod.rs b/compiler/noirc_frontend/src/parser/mod.rs index 968af82a8b3..ad6dd1459e9 100644 --- a/compiler/noirc_frontend/src/parser/mod.rs +++ b/compiler/noirc_frontend/src/parser/mod.rs @@ -47,7 +47,7 @@ pub enum TopLevelStatementKind { Impl(TypeImpl), TypeAlias(NoirTypeAlias), SubModule(ParsedSubModule), - Global(LetStatement), + Global(LetStatement, ItemVisibility), InnerAttribute(SecondaryAttribute), Error, } @@ -64,7 +64,7 @@ impl TopLevelStatementKind { TopLevelStatementKind::Impl(i) => Some(ItemKind::Impl(i)), TopLevelStatementKind::TypeAlias(t) => Some(ItemKind::TypeAlias(t)), TopLevelStatementKind::SubModule(s) => Some(ItemKind::Submodules(s)), - TopLevelStatementKind::Global(c) => Some(ItemKind::Global(c)), + TopLevelStatementKind::Global(c, visibility) => Some(ItemKind::Global(c, visibility)), TopLevelStatementKind::InnerAttribute(a) => Some(ItemKind::InnerAttribute(a)), TopLevelStatementKind::Error => None, } @@ -249,7 +249,7 @@ pub struct SortedModule { pub trait_impls: Vec, pub impls: Vec, pub type_aliases: Vec>, - pub globals: Vec>, + pub globals: Vec<(Documented, ItemVisibility)>, /// Module declarations like `mod foo;` pub module_decls: Vec>, @@ -271,7 +271,7 @@ impl std::fmt::Display for SortedModule { write!(f, "{import}")?; } - for global_const in &self.globals { + for (global_const, _visibility) in &self.globals { write!(f, "{global_const}")?; } @@ -321,7 +321,9 @@ impl ParsedModule { ItemKind::TypeAlias(type_alias) => { module.push_type_alias(type_alias, item.doc_comments); } - ItemKind::Global(global) => module.push_global(global, item.doc_comments), + ItemKind::Global(global, visibility) => { + module.push_global(global, visibility, item.doc_comments); + } ItemKind::ModuleDecl(mod_name) => { module.push_module_decl(mod_name, item.doc_comments); } @@ -354,7 +356,7 @@ pub enum ItemKind { TraitImpl(NoirTraitImpl), Impl(TypeImpl), TypeAlias(NoirTypeAlias), - Global(LetStatement), + Global(LetStatement, ItemVisibility), ModuleDecl(ModuleDeclaration), Submodules(ParsedSubModule), InnerAttribute(SecondaryAttribute), @@ -364,6 +366,7 @@ pub enum ItemKind { /// These submodules always share the same file as some larger ParsedModule #[derive(Clone, Debug)] pub struct ParsedSubModule { + pub visibility: ItemVisibility, pub name: Ident, pub contents: ParsedModule, pub outer_attributes: Vec, @@ -373,6 +376,7 @@ pub struct ParsedSubModule { impl ParsedSubModule { pub fn into_sorted(self) -> SortedSubModule { SortedSubModule { + visibility: self.visibility, name: self.name, contents: self.contents.into_sorted(), outer_attributes: self.outer_attributes, @@ -396,6 +400,7 @@ impl std::fmt::Display for SortedSubModule { #[derive(Clone)] pub struct SortedSubModule { pub name: Ident, + pub visibility: ItemVisibility, pub contents: SortedModule, pub outer_attributes: Vec, pub is_contract: bool, @@ -438,8 +443,13 @@ impl SortedModule { self.submodules.push(Documented::new(submodule, doc_comments)); } - fn push_global(&mut self, global: LetStatement, doc_comments: Vec) { - self.globals.push(Documented::new(global, doc_comments)); + fn push_global( + &mut self, + global: LetStatement, + visibility: ItemVisibility, + doc_comments: Vec, + ) { + self.globals.push((Documented::new(global, doc_comments), visibility)); } } @@ -526,11 +536,10 @@ impl std::fmt::Display for TopLevelStatementKind { TopLevelStatementKind::Function(fun) => fun.fmt(f), TopLevelStatementKind::Module(m) => m.fmt(f), TopLevelStatementKind::Import(tree, visibility) => { - if visibility == &ItemVisibility::Private { - write!(f, "use {tree}") - } else { - write!(f, "{visibility} use {tree}") + if visibility != &ItemVisibility::Private { + write!(f, "{visibility} ")?; } + write!(f, "use {tree}") } TopLevelStatementKind::Trait(t) => t.fmt(f), TopLevelStatementKind::TraitImpl(i) => i.fmt(f), @@ -538,7 +547,12 @@ impl std::fmt::Display for TopLevelStatementKind { TopLevelStatementKind::Impl(i) => i.fmt(f), TopLevelStatementKind::TypeAlias(t) => t.fmt(f), TopLevelStatementKind::SubModule(s) => s.fmt(f), - TopLevelStatementKind::Global(c) => c.fmt(f), + TopLevelStatementKind::Global(c, visibility) => { + if visibility != &ItemVisibility::Private { + write!(f, "{visibility} ")?; + } + c.fmt(f) + } TopLevelStatementKind::InnerAttribute(a) => write!(f, "#![{}]", a), TopLevelStatementKind::Error => write!(f, "error"), } diff --git a/compiler/noirc_frontend/src/parser/parser.rs b/compiler/noirc_frontend/src/parser/parser.rs index 0eb49ae975a..df656dc5a7d 100644 --- a/compiler/noirc_frontend/src/parser/parser.rs +++ b/compiler/noirc_frontend/src/parser/parser.rs @@ -220,6 +220,7 @@ fn implementation() -> impl NoirParser { /// global_declaration: 'global' ident global_type_annotation '=' literal fn global_declaration() -> impl NoirParser { let p = attributes::attributes() + .then(item_visibility()) .then(maybe_comp_time()) .then(spanned(keyword(Keyword::Mut)).or_not()) .then_ignore(keyword(Keyword::Global).labelled(ParsingRuleLabel::Global)) @@ -229,7 +230,9 @@ fn global_declaration() -> impl NoirParser { let p = then_commit_ignore(p, just(Token::Assign)); let p = then_commit(p, expression()); p.validate( - |(((((attributes, comptime), mutable), mut pattern), r#type), expression), span, emit| { + |((((((attributes, visibility), comptime), mutable), mut pattern), r#type), expression), + span, + emit| { let global_attributes = attributes::validate_secondary_attributes(attributes, span, emit); @@ -239,10 +242,19 @@ fn global_declaration() -> impl NoirParser { let span = mut_span.merge(pattern.span()); pattern = Pattern::Mutable(Box::new(pattern), span, false); } - LetStatement { pattern, r#type, comptime, expression, attributes: global_attributes } + ( + LetStatement { + pattern, + r#type, + comptime, + expression, + attributes: global_attributes, + }, + visibility, + ) }, ) - .map(TopLevelStatementKind::Global) + .map(|(let_statement, visibility)| TopLevelStatementKind::Global(let_statement, visibility)) } /// submodule: 'mod' ident '{' module '}' @@ -250,14 +262,16 @@ fn submodule( module_parser: impl NoirParser, ) -> impl NoirParser { attributes() + .then(item_visibility()) .then_ignore(keyword(Keyword::Mod)) .then(ident()) .then_ignore(just(Token::LeftBrace)) .then(module_parser) .then_ignore(just(Token::RightBrace)) - .validate(|((attributes, name), contents), span, emit| { + .validate(|(((attributes, visibility), name), contents), span, emit| { let attributes = validate_secondary_attributes(attributes, span, emit); TopLevelStatementKind::SubModule(ParsedSubModule { + visibility, name, contents, outer_attributes: attributes, @@ -271,14 +285,16 @@ fn contract( module_parser: impl NoirParser, ) -> impl NoirParser { attributes() + .then(item_visibility()) .then_ignore(keyword(Keyword::Contract)) .then(ident()) .then_ignore(just(Token::LeftBrace)) .then(module_parser) .then_ignore(just(Token::RightBrace)) - .validate(|((attributes, name), contents), span, emit| { + .validate(|(((attributes, visibility), name), contents), span, emit| { let attributes = validate_secondary_attributes(attributes, span, emit); TopLevelStatementKind::SubModule(ParsedSubModule { + visibility, name, contents, outer_attributes: attributes, @@ -290,14 +306,21 @@ fn contract( fn type_alias_definition() -> impl NoirParser { use self::Keyword::Type; - let p = ignore_then_commit(keyword(Type), ident()); - let p = then_commit(p, function::generics()); - let p = then_commit_ignore(p, just(Token::Assign)); - let p = then_commit(p, parse_type()); - - p.map_with_span(|((name, generics), typ), span| { - TopLevelStatementKind::TypeAlias(NoirTypeAlias { name, generics, typ, span }) - }) + item_visibility() + .then_ignore(keyword(Type)) + .then(ident()) + .then(function::generics()) + .then_ignore(just(Token::Assign)) + .then(parse_type()) + .map_with_span(|(((visibility, name), generics), typ), span| { + TopLevelStatementKind::TypeAlias(NoirTypeAlias { + name, + generics, + typ, + visibility, + span, + }) + }) } fn self_parameter() -> impl NoirParser { @@ -412,10 +435,14 @@ fn optional_type_annotation<'a>() -> impl NoirParser + 'a { } fn module_declaration() -> impl NoirParser { - attributes().then_ignore(keyword(Keyword::Mod)).then(ident()).validate( - |(attributes, ident), span, emit| { + attributes().then(item_visibility()).then_ignore(keyword(Keyword::Mod)).then(ident()).validate( + |((attributes, visibility), ident), span, emit| { let attributes = validate_secondary_attributes(attributes, span, emit); - TopLevelStatementKind::Module(ModuleDeclaration { ident, outer_attributes: attributes }) + TopLevelStatementKind::Module(ModuleDeclaration { + visibility, + ident, + outer_attributes: attributes, + }) }, ) } diff --git a/compiler/noirc_frontend/src/tests.rs b/compiler/noirc_frontend/src/tests.rs index cb291902ae2..a27cd1087c4 100644 --- a/compiler/noirc_frontend/src/tests.rs +++ b/compiler/noirc_frontend/src/tests.rs @@ -6,6 +6,7 @@ mod name_shadowing; mod references; mod turbofish; mod unused_items; +mod visibility; // XXX: These tests repeat a lot of code // what we should do is have test cases which are passed to a test harness @@ -195,8 +196,10 @@ fn check_trait_implementation_duplicate_method() { x + 2 * y } } - - fn main() {}"; + + fn main() { + let _ = Foo { bar: 1, array: [2, 3] }; // silence Foo never constructed warning + }"; let errors = get_program_errors(src); assert!(!has_parser_error(&errors)); @@ -237,6 +240,7 @@ fn check_trait_wrong_method_return_type() { } fn main() { + let _ = Foo {}; // silence Foo never constructed warning } "; let errors = get_program_errors(src); @@ -279,6 +283,7 @@ fn check_trait_wrong_method_return_type2() { } fn main() { + let _ = Foo { bar: 1, array: [2, 3] }; // silence Foo never constructed warning }"; let errors = get_program_errors(src); assert!(!has_parser_error(&errors)); @@ -401,6 +406,7 @@ fn check_trait_wrong_method_name() { } fn main() { + let _ = Foo { bar: 1, array: [2, 3] }; // silence Foo never constructed warning }"; let compilation_errors = get_program_errors(src); assert!(!has_parser_error(&compilation_errors)); @@ -639,8 +645,10 @@ fn check_impl_struct_not_trait() { Self { bar: x, array: [x,y] } } } - - fn main() {} + + fn main() { + let _ = Default { x: 1, z: 1 }; // silence Default never constructed warning + } "; let errors = get_program_errors(src); assert!(!has_parser_error(&errors)); @@ -719,6 +727,7 @@ fn check_trait_duplicate_implementation() { impl Default for Foo { } fn main() { + let _ = Foo { bar: 1 }; // silence Foo never constructed warning } "; let errors = get_program_errors(src); @@ -757,6 +766,7 @@ fn check_trait_duplicate_implementation_with_alias() { } fn main() { + let _ = MyStruct {}; // silence MyStruct never constructed warning } "; let errors = get_program_errors(src); @@ -1367,7 +1377,9 @@ fn ban_mutable_globals() { // Mutable globals are only allowed in a comptime context let src = r#" mut global FOO: Field = 0; - fn main() {} + fn main() { + let _ = FOO; // silence FOO never used warning + } "#; assert_eq!(get_program_errors(src).len(), 1); } @@ -1549,7 +1561,9 @@ fn struct_numeric_generic_in_function() { inner: u64 } - pub fn bar() { } + pub fn bar() { + let _ = Foo { inner: 1 }; // silence Foo never constructed warning + } "#; let errors = get_program_errors(src); assert_eq!(errors.len(), 1); @@ -1724,7 +1738,7 @@ fn numeric_generic_used_in_nested_type_fails() { a: Field, b: Bar, } - struct Bar { + pub struct Bar { inner: N } "#; @@ -1879,6 +1893,10 @@ fn constant_used_with_numeric_generic() { [self.value] } } + + fn main() { + let _ = ValueNote { value: 1 }; // silence ValueNote never constructed warning + } "#; assert_no_errors(src); } @@ -1985,6 +2003,10 @@ fn numeric_generics_value_kind_mismatch_u32_u64() { self.len += 1; } } + + fn main() { + let _ = BoundedVec { storage: [1], len: 1 }; // silence never constructed warning + } "#; let errors = get_program_errors(src); assert_eq!(errors.len(), 1); @@ -2060,6 +2082,10 @@ fn impl_stricter_than_trait_no_trait_method_constraints() { process_array(serialize_thing(self)) } } + + fn main() { + let _ = MyType { a: 1, b: 1 }; // silence MyType never constructed warning + } "#; let errors = get_program_errors(src); @@ -2150,6 +2176,10 @@ fn impl_stricter_than_trait_different_object_generics() { fn tuple_bad() where (Option, Option): MyTrait { } } + + fn main() { + let _ = OtherOption { inner: Option { inner: 1 } }; // silence unused warnings + } "#; let errors = get_program_errors(src); @@ -2211,6 +2241,10 @@ fn impl_stricter_than_trait_different_trait() { // types are the same. fn bar() where Option: OtherDefault {} } + + fn main() { + let _ = Option { inner: 1 }; // silence Option never constructed warning + } "#; let errors = get_program_errors(src); @@ -2248,6 +2282,10 @@ fn trait_impl_where_clause_stricter_pass() { fn bad_foo() where A: OtherTrait { } } + + fn main() { + let _ = Option { inner: 1 }; // silence Option never constructed warning + } "#; let errors = get_program_errors(src); @@ -2333,6 +2371,10 @@ fn impl_not_found_for_inner_impl() { process_array(serialize_thing(self)) } } + + fn main() { + let _ = MyType { a: 1, b: 1 }; // silence MyType never constructed warning + } "#; let errors = get_program_errors(src); @@ -2639,7 +2681,9 @@ fn incorrect_generic_count_on_struct_impl() { let src = r#" struct Foo {} impl Foo {} - fn main() {} + fn main() { + let _ = Foo {}; // silence Foo never constructed warning + } "#; let errors = get_program_errors(src); @@ -2659,9 +2703,11 @@ fn incorrect_generic_count_on_struct_impl() { #[test] fn incorrect_generic_count_on_type_alias() { let src = r#" - struct Foo {} - type Bar = Foo; - fn main() {} + pub struct Foo {} + pub type Bar = Foo; + fn main() { + let _ = Foo {}; // silence Foo never constructed warning + } "#; let errors = get_program_errors(src); @@ -2693,7 +2739,9 @@ fn uses_self_type_for_struct_function_call() { } } - fn main() {} + fn main() { + let _ = S {}; // silence S never constructed warning + } "#; assert_no_errors(src); } @@ -2743,7 +2791,9 @@ fn uses_self_type_in_trait_where_clause() { } - fn main() {} + fn main() { + let _ = Bar {}; // silence Bar never constructed warning + } "#; let errors = get_program_errors(src); @@ -2903,6 +2953,8 @@ fn as_trait_path_syntax_resolves_outside_impl() { // AsTraitPath syntax is a bit silly when associated types // are explicitly specified let _: i64 = 1 as >::Assoc; + + let _ = Bar {}; // silence Bar never constructed warning } "#; @@ -2934,6 +2986,8 @@ fn as_trait_path_syntax_no_impl() { fn main() { let _: i64 = 1 as >::Assoc; + + let _ = Bar {}; // silence Bar never constructed warning } "#; @@ -3039,27 +3093,6 @@ fn use_numeric_generic_in_trait_method() { assert_eq!(errors.len(), 0); } -#[test] -fn errors_once_on_unused_import_that_is_not_accessible() { - // Tests that we don't get an "unused import" here given that the import is not accessible - let src = r#" - mod moo { - struct Foo {} - } - use moo::Foo; - fn main() {} - "#; - - let errors = get_program_errors(src); - assert_eq!(errors.len(), 1); - assert!(matches!( - errors[0].0, - CompilationError::DefinitionError(DefCollectorErrorKind::PathResolutionError( - PathResolutionError::Private { .. } - )) - )); -} - #[test] fn trait_unconstrained_methods_typechecked_correctly() { // This test checks that we properly track whether a method has been declared as unconstrained on the trait definition @@ -3088,3 +3121,60 @@ fn trait_unconstrained_methods_typechecked_correctly() { println!("{errors:?}"); assert_eq!(errors.len(), 0); } + +#[test] +fn errors_if_type_alias_aliases_more_private_type() { + let src = r#" + struct Foo {} + pub type Bar = Foo; + + pub fn no_unused_warnings(_b: Bar) { + let _ = Foo {}; + } + + fn main() {} + "#; + + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); + + let CompilationError::ResolverError(ResolverError::TypeIsMorePrivateThenItem { + typ, item, .. + }) = &errors[0].0 + else { + panic!("Expected an unused item error"); + }; + + assert_eq!(typ, "Foo"); + assert_eq!(item, "Bar"); +} + +#[test] +fn errors_if_type_alias_aliases_more_private_type_in_generic() { + let src = r#" + pub struct Generic { value: T } + + struct Foo {} + pub type Bar = Generic; + + pub fn no_unused_warnings(_b: Bar) { + let _ = Foo {}; + let _ = Generic { value: 1 }; + } + + fn main() {} + "#; + + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); + + let CompilationError::ResolverError(ResolverError::TypeIsMorePrivateThenItem { + typ, item, .. + }) = &errors[0].0 + else { + panic!("Expected an unused item error"); + }; + + assert_eq!(typ, "Foo"); + assert_eq!(item, "Bar"); +} diff --git a/compiler/noirc_frontend/src/tests/unused_items.rs b/compiler/noirc_frontend/src/tests/unused_items.rs index da0a40d93cf..a4d379b6358 100644 --- a/compiler/noirc_frontend/src/tests/unused_items.rs +++ b/compiler/noirc_frontend/src/tests/unused_items.rs @@ -31,14 +31,13 @@ fn errors_on_unused_private_import() { let errors = get_program_errors(src); assert_eq!(errors.len(), 1); - let CompilationError::ResolverError(ResolverError::UnusedItem { ident, item_type }) = - &errors[0].0 + let CompilationError::ResolverError(ResolverError::UnusedItem { ident, item }) = &errors[0].0 else { panic!("Expected an unused item error"); }; assert_eq!(ident.to_string(), "bar"); - assert_eq!(*item_type, "import"); + assert_eq!(item.item_type(), "import"); } #[test] @@ -67,14 +66,13 @@ fn errors_on_unused_pub_crate_import() { let errors = get_program_errors(src); assert_eq!(errors.len(), 1); - let CompilationError::ResolverError(ResolverError::UnusedItem { ident, item_type }) = - &errors[0].0 + let CompilationError::ResolverError(ResolverError::UnusedItem { ident, item }) = &errors[0].0 else { panic!("Expected an unused item error"); }; assert_eq!(ident.to_string(), "bar"); - assert_eq!(*item_type, "import"); + assert_eq!(item.item_type(), "import"); } #[test] @@ -99,14 +97,13 @@ fn errors_on_unused_function() { let errors = get_program_errors(src); assert_eq!(errors.len(), 1); - let CompilationError::ResolverError(ResolverError::UnusedItem { ident, item_type }) = - &errors[0].0 + let CompilationError::ResolverError(ResolverError::UnusedItem { ident, item }) = &errors[0].0 else { panic!("Expected an unused item error"); }; assert_eq!(ident.to_string(), "foo"); - assert_eq!(*item_type, "function"); + assert_eq!(item.item_type(), "function"); } #[test] @@ -123,14 +120,13 @@ fn errors_on_unused_struct() { let errors = get_program_errors(src); assert_eq!(errors.len(), 1); - let CompilationError::ResolverError(ResolverError::UnusedItem { ident, item_type }) = - &errors[0].0 + let CompilationError::ResolverError(ResolverError::UnusedItem { ident, item }) = &errors[0].0 else { panic!("Expected an unused item error"); }; assert_eq!(ident.to_string(), "Foo"); - assert_eq!(*item_type, "struct"); + assert_eq!(item.item_type(), "struct"); } #[test] @@ -151,14 +147,13 @@ fn errors_on_unused_trait() { let errors = get_program_errors(src); assert_eq!(errors.len(), 1); - let CompilationError::ResolverError(ResolverError::UnusedItem { ident, item_type }) = - &errors[0].0 + let CompilationError::ResolverError(ResolverError::UnusedItem { ident, item }) = &errors[0].0 else { panic!("Expected an unused item error"); }; assert_eq!(ident.to_string(), "Foo"); - assert_eq!(*item_type, "trait"); + assert_eq!(item.item_type(), "trait"); } #[test] @@ -171,3 +166,99 @@ fn silences_unused_variable_warning() { "#; assert_no_errors(src); } + +#[test] +fn errors_on_unused_type_alias() { + let src = r#" + type Foo = Field; + type Bar = Field; + pub fn bar(_: Bar) {} + fn main() {} + "#; + + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); + + let CompilationError::ResolverError(ResolverError::UnusedItem { ident, item }) = &errors[0].0 + else { + panic!("Expected an unused item error"); + }; + + assert_eq!(ident.to_string(), "Foo"); + assert_eq!(item.item_type(), "type alias"); +} + +#[test] +fn errors_if_type_alias_aliases_more_private_type() { + let src = r#" + struct Foo {} + pub type Bar = Foo; + pub fn no_unused_warnings(_b: Bar) { + let _ = Foo {}; + } + fn main() {} + "#; + + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); + + let CompilationError::ResolverError(ResolverError::TypeIsMorePrivateThenItem { + typ, item, .. + }) = &errors[0].0 + else { + panic!("Expected an unused item error"); + }; + + assert_eq!(typ, "Foo"); + assert_eq!(item, "Bar"); +} + +#[test] +fn errors_if_type_alias_aliases_more_private_type_in_generic() { + let src = r#" + pub struct Generic { value: T } + struct Foo {} + pub type Bar = Generic; + pub fn no_unused_warnings(_b: Bar) { + let _ = Foo {}; + let _ = Generic { value: 1 }; + } + fn main() {} + "#; + + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); + + let CompilationError::ResolverError(ResolverError::TypeIsMorePrivateThenItem { + typ, item, .. + }) = &errors[0].0 + else { + panic!("Expected an unused item error"); + }; + + assert_eq!(typ, "Foo"); + assert_eq!(item, "Bar"); +} + +#[test] +fn warns_on_unused_global() { + let src = r#" + global foo = 1; + global bar = 1; + + fn main() { + let _ = bar; + } + "#; + + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); + + let CompilationError::ResolverError(ResolverError::UnusedItem { ident, item }) = &errors[0].0 + else { + panic!("Expected an unused item warning"); + }; + + assert_eq!(ident.to_string(), "foo"); + assert_eq!(item.item_type(), "global"); +} diff --git a/compiler/noirc_frontend/src/tests/visibility.rs b/compiler/noirc_frontend/src/tests/visibility.rs new file mode 100644 index 00000000000..e6c2680ea19 --- /dev/null +++ b/compiler/noirc_frontend/src/tests/visibility.rs @@ -0,0 +1,113 @@ +use crate::{ + hir::{ + def_collector::{dc_crate::CompilationError, errors::DefCollectorErrorKind}, + resolution::{errors::ResolverError, import::PathResolutionError}, + }, + tests::get_program_errors, +}; + +#[test] +fn errors_once_on_unused_import_that_is_not_accessible() { + // Tests that we don't get an "unused import" here given that the import is not accessible + let src = r#" + mod moo { + struct Foo {} + } + use moo::Foo; + fn main() { + let _ = Foo {}; + } + "#; + + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); + assert!(matches!( + errors[0].0, + CompilationError::DefinitionError(DefCollectorErrorKind::PathResolutionError( + PathResolutionError::Private { .. } + )) + )); +} + +#[test] +fn errors_if_type_alias_aliases_more_private_type() { + let src = r#" + struct Foo {} + pub type Bar = Foo; + + pub fn no_unused_warnings(_b: Bar) { + let _ = Foo {}; + } + + fn main() {} + "#; + + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); + + let CompilationError::ResolverError(ResolverError::TypeIsMorePrivateThenItem { + typ, item, .. + }) = &errors[0].0 + else { + panic!("Expected an unused item error"); + }; + + assert_eq!(typ, "Foo"); + assert_eq!(item, "Bar"); +} + +#[test] +fn errors_if_type_alias_aliases_more_private_type_in_generic() { + let src = r#" + pub struct Generic { value: T } + + struct Foo {} + pub type Bar = Generic; + + pub fn no_unused_warnings(_b: Bar) { + let _ = Foo {}; + let _ = Generic { value: 1 }; + } + + fn main() {} + "#; + + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); + + let CompilationError::ResolverError(ResolverError::TypeIsMorePrivateThenItem { + typ, item, .. + }) = &errors[0].0 + else { + panic!("Expected an unused item error"); + }; + + assert_eq!(typ, "Foo"); + assert_eq!(item, "Bar"); +} + +#[test] +fn errors_if_trying_to_access_public_function_inside_private_module() { + let src = r#" + mod foo { + mod bar { + pub fn baz() {} + } + } + fn main() { + foo::bar::baz() + } + "#; + + let errors = get_program_errors(src); + assert_eq!(errors.len(), 2); // There's a bug that duplicates this error + + let CompilationError::ResolverError(ResolverError::PathResolutionError( + PathResolutionError::Private(ident), + )) = &errors[0].0 + else { + panic!("Expected a private error"); + }; + + assert_eq!(ident.to_string(), "bar"); +} diff --git a/compiler/noirc_frontend/src/usage_tracker.rs b/compiler/noirc_frontend/src/usage_tracker.rs index b6f41dc72f2..275ca1f964b 100644 --- a/compiler/noirc_frontend/src/usage_tracker.rs +++ b/compiler/noirc_frontend/src/usage_tracker.rs @@ -4,15 +4,17 @@ use crate::{ ast::{Ident, ItemVisibility}, hir::def_map::ModuleId, macros_api::StructId, - node_interner::{FuncId, TraitId}, + node_interner::{FuncId, GlobalId, TraitId, TypeAliasId}, }; -#[derive(Debug)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum UnusedItem { Import, Function(FuncId), Struct(StructId), Trait(TraitId), + TypeAlias(TypeAliasId), + Global(GlobalId), } impl UnusedItem { @@ -22,20 +24,18 @@ impl UnusedItem { UnusedItem::Function(_) => "function", UnusedItem::Struct(_) => "struct", UnusedItem::Trait(_) => "trait", + UnusedItem::TypeAlias(_) => "type alias", + UnusedItem::Global(_) => "global", } } } -#[derive(Debug)] +#[derive(Debug, Default)] pub struct UsageTracker { unused_items: HashMap>, } impl UsageTracker { - pub(crate) fn new() -> Self { - Self { unused_items: HashMap::new() } - } - pub(crate) fn add_unused_item( &mut self, module_id: ModuleId, @@ -49,8 +49,29 @@ impl UsageTracker { } } + /// Marks an item as being referenced. This doesn't always makes the item as used. For example + /// if a struct is referenced it will still be considered unused unless it's constructed somewhere. + pub(crate) fn mark_as_referenced(&mut self, current_mod_id: ModuleId, name: &Ident) { + let Some(items) = self.unused_items.get_mut(¤t_mod_id) else { + return; + }; + + let Some(unused_item) = items.get(name) else { + return; + }; + + if let UnusedItem::Struct(_) = unused_item { + return; + } + + items.remove(name); + } + + /// Marks an item as being used. pub(crate) fn mark_as_used(&mut self, current_mod_id: ModuleId, name: &Ident) { - self.unused_items.entry(current_mod_id).or_default().remove(name); + if let Some(items) = self.unused_items.get_mut(¤t_mod_id) { + items.remove(name); + }; } pub(crate) fn unused_items(&self) -> &HashMap> { diff --git a/docs/docs/how_to/how-to-solidity-verifier.md b/docs/docs/how_to/how-to-solidity-verifier.md index 3bb96c66795..a8169595b3d 100644 --- a/docs/docs/how_to/how-to-solidity-verifier.md +++ b/docs/docs/how_to/how-to-solidity-verifier.md @@ -57,6 +57,8 @@ bb contract replacing `` with the name of your Noir project. A new `contract` folder would then be generated in your project directory, containing the Solidity file `contract.sol`. It can be deployed to any EVM blockchain acting as a verifier smart contract. +You can find more information about `bb` and the default Noir proving backend on [this page](../getting_started/hello_noir/index.md#proving-backend). + :::info It is possible to generate verifier contracts of Noir programs for other smart contract platforms as long as the proving backend supplies an implementation. diff --git a/docs/docs/noir/concepts/data_types/index.md b/docs/docs/noir/concepts/data_types/index.md index 3eadb2dc8a4..11f51e2b65a 100644 --- a/docs/docs/noir/concepts/data_types/index.md +++ b/docs/docs/noir/concepts/data_types/index.md @@ -105,6 +105,14 @@ type Bad2 = Bad1; // ^^^^^^^^^^^ 'Bad2' recursively depends on itself: Bad2 -> Bad1 -> Bad2 ``` +By default, like functions, type aliases are private to the module the exist in. You can use `pub` +to make the type alias public or `pub(crate)` to make it public to just its crate: + +```rust +// This type alias is now public +pub type Id = u8; +``` + ## Wildcard Type Noir can usually infer the type of the variable from the context, so specifying the type of a variable is only required when it cannot be inferred. However, specifying a complex type can be tedious, especially when it has multiple generic arguments. Often some of the generic types can be inferred from the context, and Noir only needs a hint to properly infer the other types. We can partially specify a variable's type by using `_` as a marker, indicating where we still want the compiler to infer the type. diff --git a/docs/docs/noir/concepts/globals.md b/docs/docs/noir/concepts/globals.md index 97a92a86e72..1145c55dfc7 100644 --- a/docs/docs/noir/concepts/globals.md +++ b/docs/docs/noir/concepts/globals.md @@ -70,3 +70,13 @@ fn foo() -> [Field; 100] { ... } This is usually fine since Noir will generally optimize any function call that does not refer to a program input into a constant. It should be kept in mind however, if the called function performs side-effects like `println`, as these will still occur on each use. + +### Visibility + +By default, like functions, globals are private to the module the exist in. You can use `pub` +to make the global public or `pub(crate)` to make it public to just its crate: + +```rust +// This global is now public +pub global N = 5; +``` \ No newline at end of file diff --git a/docs/docs/noir/modules_packages_crates/modules.md b/docs/docs/noir/modules_packages_crates/modules.md index d21b009be3b..05399c38b4c 100644 --- a/docs/docs/noir/modules_packages_crates/modules.md +++ b/docs/docs/noir/modules_packages_crates/modules.md @@ -208,4 +208,14 @@ fn main() { } ``` -In this example, the module `some_module` re-exports two public names defined in `foo`. \ No newline at end of file +In this example, the module `some_module` re-exports two public names defined in `foo`. + +### Visibility + +By default, like functions, modules are private to the module (or crate) the exist in. You can use `pub` +to make the module public or `pub(crate)` to make it public to just its crate: + +```rust +// This module is now public and can be seen by other crates. +pub mod foo; +``` \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.32.0/how_to/how-to-solidity-verifier.md b/docs/versioned_docs/version-v0.32.0/how_to/how-to-solidity-verifier.md index 3bb96c66795..a8169595b3d 100644 --- a/docs/versioned_docs/version-v0.32.0/how_to/how-to-solidity-verifier.md +++ b/docs/versioned_docs/version-v0.32.0/how_to/how-to-solidity-verifier.md @@ -57,6 +57,8 @@ bb contract replacing `` with the name of your Noir project. A new `contract` folder would then be generated in your project directory, containing the Solidity file `contract.sol`. It can be deployed to any EVM blockchain acting as a verifier smart contract. +You can find more information about `bb` and the default Noir proving backend on [this page](../getting_started/hello_noir/index.md#proving-backend). + :::info It is possible to generate verifier contracts of Noir programs for other smart contract platforms as long as the proving backend supplies an implementation. diff --git a/docs/versioned_docs/version-v0.33.0/how_to/how-to-solidity-verifier.md b/docs/versioned_docs/version-v0.33.0/how_to/how-to-solidity-verifier.md index c800d91ac69..063538f1fc2 100644 --- a/docs/versioned_docs/version-v0.33.0/how_to/how-to-solidity-verifier.md +++ b/docs/versioned_docs/version-v0.33.0/how_to/how-to-solidity-verifier.md @@ -57,6 +57,8 @@ bb contract replacing `` with the name of your Noir project. A new `contract` folder would then be generated in your project directory, containing the Solidity file `contract.sol`. It can be deployed to any EVM blockchain acting as a verifier smart contract. +You can find more information about `bb` and the default Noir proving backend on [this page](../getting_started/hello_noir/index.md#proving-backend). + :::info It is possible to generate verifier contracts of Noir programs for other smart contract platforms as long as the proving backend supplies an implementation. diff --git a/noir_stdlib/src/collections/mod.nr b/noir_stdlib/src/collections/mod.nr index 29f3e8cc854..d11e9f2febb 100644 --- a/noir_stdlib/src/collections/mod.nr +++ b/noir_stdlib/src/collections/mod.nr @@ -1,4 +1,4 @@ -mod vec; -mod bounded_vec; -mod map; -mod umap; +pub mod vec; +pub mod bounded_vec; +pub mod map; +pub mod umap; diff --git a/noir_stdlib/src/ec/consts/mod.nr b/noir_stdlib/src/ec/consts/mod.nr index f4d67e7a92c..73c594c6a26 100644 --- a/noir_stdlib/src/ec/consts/mod.nr +++ b/noir_stdlib/src/ec/consts/mod.nr @@ -1 +1 @@ -mod te; +pub mod te; diff --git a/noir_stdlib/src/ec/consts/te.nr b/noir_stdlib/src/ec/consts/te.nr index 349e518cdb2..e82302eadee 100644 --- a/noir_stdlib/src/ec/consts/te.nr +++ b/noir_stdlib/src/ec/consts/te.nr @@ -8,6 +8,7 @@ pub struct BabyJubjub { } #[field(bn254)] +#[deprecated = "It's recommmended to use the external noir-edwards library (https://github.com/noir-lang/noir-edwards)"] pub fn baby_jubjub() -> BabyJubjub { BabyJubjub { // Baby Jubjub (ERC-2494) parameters in affine representation diff --git a/noir_stdlib/src/ec/mod.nr b/noir_stdlib/src/ec/mod.nr index 3c1ba87eb9f..112f39f74eb 100644 --- a/noir_stdlib/src/ec/mod.nr +++ b/noir_stdlib/src/ec/mod.nr @@ -2,10 +2,10 @@ // Overview // ======== // The following three elliptic curve representations are admissible: -mod tecurve; // Twisted Edwards curves -mod swcurve; // Elliptic curves in Short Weierstrass form -mod montcurve; // Montgomery curves -mod consts; // Commonly used curve presets +pub mod tecurve; // Twisted Edwards curves +pub mod swcurve; // Elliptic curves in Short Weierstrass form +pub mod montcurve; // Montgomery curves +pub mod consts; // Commonly used curve presets // // Note that Twisted Edwards and Montgomery curves are (birationally) equivalent, so that // they may be freely converted between one another, whereas Short Weierstrass curves are diff --git a/noir_stdlib/src/ec/montcurve.nr b/noir_stdlib/src/ec/montcurve.nr index 395e8528b45..b8077b6b639 100644 --- a/noir_stdlib/src/ec/montcurve.nr +++ b/noir_stdlib/src/ec/montcurve.nr @@ -1,4 +1,4 @@ -mod affine { +pub mod affine { // Affine representation of Montgomery curves // Points are represented by two-dimensional Cartesian coordinates. // All group operations are induced by those of the corresponding Twisted Edwards curve. @@ -210,7 +210,7 @@ mod affine { } } } -mod curvegroup { +pub mod curvegroup { // Affine representation of Montgomery curves // Points are represented by three-dimensional projective (homogeneous) coordinates. // All group operations are induced by those of the corresponding Twisted Edwards curve. diff --git a/noir_stdlib/src/ec/swcurve.nr b/noir_stdlib/src/ec/swcurve.nr index 839069e1fd8..9c40ddd1adc 100644 --- a/noir_stdlib/src/ec/swcurve.nr +++ b/noir_stdlib/src/ec/swcurve.nr @@ -1,4 +1,4 @@ -mod affine { +pub mod affine { // Affine representation of Short Weierstrass curves // Points are represented by two-dimensional Cartesian coordinates. // Group operations are implemented in terms of those in CurveGroup (in this case, extended Twisted Edwards) coordinates @@ -186,7 +186,7 @@ mod affine { } } -mod curvegroup { +pub mod curvegroup { // CurveGroup representation of Weierstrass curves // Points are represented by three-dimensional Jacobian coordinates. // See for details. diff --git a/noir_stdlib/src/ec/tecurve.nr b/noir_stdlib/src/ec/tecurve.nr index b306873806d..c37b7c94a54 100644 --- a/noir_stdlib/src/ec/tecurve.nr +++ b/noir_stdlib/src/ec/tecurve.nr @@ -1,4 +1,4 @@ -mod affine { +pub mod affine { // Affine coordinate representation of Twisted Edwards curves // Points are represented by two-dimensional Cartesian coordinates. // Group operations are implemented in terms of those in CurveGroup (in this case, extended Twisted Edwards) coordinates @@ -27,6 +27,7 @@ mod affine { impl Point { // Point constructor + #[deprecated = "It's recommmended to use the external noir-edwards library (https://github.com/noir-lang/noir-edwards)"] pub fn new(x: Field, y: Field) -> Self { Self { x, y } } @@ -192,7 +193,7 @@ mod affine { } } } -mod curvegroup { +pub mod curvegroup { // CurveGroup coordinate representation of Twisted Edwards curves // Points are represented by four-dimensional projective coordinates, viz. extended Twisted Edwards coordinates. // See section 3 of for details. diff --git a/noir_stdlib/src/field/bn254.nr b/noir_stdlib/src/field/bn254.nr index 0aa5ca0717b..8ff62062d5c 100644 --- a/noir_stdlib/src/field/bn254.nr +++ b/noir_stdlib/src/field/bn254.nr @@ -4,7 +4,7 @@ use crate::runtime::is_unconstrained; global PLO: Field = 53438638232309528389504892708671455233; global PHI: Field = 64323764613183177041862057485226039389; -global TWO_POW_128: Field = 0x100000000000000000000000000000000; +pub(crate) global TWO_POW_128: Field = 0x100000000000000000000000000000000; // Decomposes a single field into two 16 byte fields. fn compute_decomposition(x: Field) -> (Field, Field) { diff --git a/noir_stdlib/src/field/mod.nr b/noir_stdlib/src/field/mod.nr index e1d08c6c230..93245e18072 100644 --- a/noir_stdlib/src/field/mod.nr +++ b/noir_stdlib/src/field/mod.nr @@ -1,4 +1,4 @@ -mod bn254; +pub mod bn254; use bn254::lt as bn254_lt; impl Field { diff --git a/noir_stdlib/src/hash/mimc.nr b/noir_stdlib/src/hash/mimc.nr index 8c43536d18b..1bcc9e3fcc7 100644 --- a/noir_stdlib/src/hash/mimc.nr +++ b/noir_stdlib/src/hash/mimc.nr @@ -6,6 +6,7 @@ use crate::default::Default; // You must use constants generated for the native field // Rounds number should be ~ log(p)/log(exp) // For 254 bit primes, exponent 7 and 91 rounds seems to be recommended +#[deprecated = "It's recommmended to use the external MiMC library (https://github.com/noir-lang/mimc)"] fn mimc(x: Field, k: Field, constants: [Field; N], exp: Field) -> Field { //round 0 let mut t = x + k; @@ -116,6 +117,7 @@ global MIMC_BN254_CONSTANTS: [Field; MIMC_BN254_ROUNDS] = [ //mimc implementation with hardcoded parameters for BN254 curve. #[field(bn254)] +#[deprecated = "It's recommmended to use the external MiMC library (https://github.com/noir-lang/mimc)"] pub fn mimc_bn254(array: [Field; N]) -> Field { let exponent = 7; let mut r = 0; diff --git a/noir_stdlib/src/hash/mod.nr b/noir_stdlib/src/hash/mod.nr index 93bce3c20e1..e8c0ce81a16 100644 --- a/noir_stdlib/src/hash/mod.nr +++ b/noir_stdlib/src/hash/mod.nr @@ -1,9 +1,9 @@ -mod poseidon; -mod mimc; -mod poseidon2; -mod keccak; -mod sha256; -mod sha512; +pub mod poseidon; +pub mod mimc; +pub mod poseidon2; +pub mod keccak; +pub mod sha256; +pub mod sha512; use crate::default::Default; use crate::uint128::U128; @@ -33,10 +33,10 @@ pub fn pedersen_commitment(input: [Field; N]) -> EmbeddedCurvePoint } pub fn pedersen_hash_with_separator(input: [Field; N], separator: u32) -> Field { - __pedersen_hash_with_separator(input, separator) + pedersen_hash_with_separator_noir(input, separator) } -fn pedersen_commitment_with_separator(input: [Field; N], separator: u32) -> EmbeddedCurvePoint { +pub fn pedersen_commitment_with_separator(input: [Field; N], separator: u32) -> EmbeddedCurvePoint { let value = __pedersen_commitment_with_separator(input, separator); if (value[0] == 0) & (value[1] == 0) { EmbeddedCurvePoint { x: 0, y: 0, is_infinite: true } @@ -78,7 +78,7 @@ fn pedersen_hash_with_separator_noir(input: [Field; N], separator: u pub fn pedersen_hash(input: [Field; N]) -> Field // docs:end:pedersen_hash { - __pedersen_hash_with_separator(input, 0) + pedersen_hash_with_separator_noir(input, 0) } #[foreign(pedersen_hash)] @@ -88,7 +88,7 @@ fn __pedersen_hash_with_separator(input: [Field; N], separator: u32) fn __pedersen_commitment_with_separator(input: [Field; N], separator: u32) -> [Field; 2] {} #[field(bn254)] -fn derive_generators(domain_separator_bytes: [u8; M], starting_index: u32) -> [EmbeddedCurvePoint; N] { +pub fn derive_generators(domain_separator_bytes: [u8; M], starting_index: u32) -> [EmbeddedCurvePoint; N] { crate::assert_constant(domain_separator_bytes); // TODO(https://github.com/noir-lang/noir/issues/5672): Add back assert_constant on starting_index __derive_generators(domain_separator_bytes, starting_index) @@ -96,16 +96,13 @@ fn derive_generators(domain_separator_bytes: [u8; M], st #[builtin(derive_pedersen_generators)] #[field(bn254)] -fn __derive_generators( - domain_separator_bytes: [u8; M], - starting_index: u32 -) -> [EmbeddedCurvePoint; N] {} +fn __derive_generators(domain_separator_bytes: [u8; M], starting_index: u32) -> [EmbeddedCurvePoint; N] {} #[field(bn254)] - // Same as from_field but: - // does not assert the limbs are 128 bits - // does not assert the decomposition does not overflow the EmbeddedCurveScalar - fn from_field_unsafe(scalar: Field) -> EmbeddedCurveScalar { +// Same as from_field but: +// does not assert the limbs are 128 bits +// does not assert the decomposition does not overflow the EmbeddedCurveScalar +fn from_field_unsafe(scalar: Field) -> EmbeddedCurveScalar { let (xlo, xhi) = unsafe { crate::field::bn254::decompose_hint(scalar) }; @@ -419,4 +416,3 @@ fn assert_pedersen() { } ); } - diff --git a/noir_stdlib/src/hash/poseidon/bn254.nr b/noir_stdlib/src/hash/poseidon/bn254.nr index a1c78a9b31c..ce4b904ed5c 100644 --- a/noir_stdlib/src/hash/poseidon/bn254.nr +++ b/noir_stdlib/src/hash/poseidon/bn254.nr @@ -1,6 +1,6 @@ // Instantiations of Poseidon constants, permutations and sponge for prime field of the same order as BN254 -mod perm; -mod consts; +pub mod perm; +pub mod consts; use crate::hash::poseidon::absorb; diff --git a/noir_stdlib/src/hash/poseidon/mod.nr b/noir_stdlib/src/hash/poseidon/mod.nr index 8a1025ada71..9553d352d28 100644 --- a/noir_stdlib/src/hash/poseidon/mod.nr +++ b/noir_stdlib/src/hash/poseidon/mod.nr @@ -1,4 +1,4 @@ -mod bn254; // Instantiations of Poseidon for prime field of the same order as BN254 +pub mod bn254; // Instantiations of Poseidon for prime field of the same order as BN254 use crate::hash::Hasher; use crate::default::Default; diff --git a/noir_stdlib/src/hash/sha256.nr b/noir_stdlib/src/hash/sha256.nr index e712019b5cc..413c26d6f6b 100644 --- a/noir_stdlib/src/hash/sha256.nr +++ b/noir_stdlib/src/hash/sha256.nr @@ -8,7 +8,7 @@ use crate::runtime::is_unconstrained; pub fn sha256(input: [u8; N]) -> [u8; 32] // docs:end:sha256 { - crate::sha256::digest(input) + digest(input) } #[foreign(sha256_compression)] diff --git a/noir_stdlib/src/lib.nr b/noir_stdlib/src/lib.nr index 714079d306a..3d1dd3e90eb 100644 --- a/noir_stdlib/src/lib.nr +++ b/noir_stdlib/src/lib.nr @@ -1,34 +1,34 @@ -mod hash; -mod aes128; -mod array; -mod slice; -mod merkle; -mod schnorr; -mod ecdsa_secp256k1; -mod ecdsa_secp256r1; -mod eddsa; -mod embedded_curve_ops; -mod sha256; -mod sha512; -mod field; -mod ec; -mod collections; -mod compat; -mod convert; -mod option; -mod string; -mod test; -mod cmp; -mod ops; -mod default; -mod prelude; -mod uint128; -mod bigint; -mod runtime; -mod meta; -mod append; -mod mem; -mod panic; +pub mod hash; +pub mod aes128; +pub mod array; +pub mod slice; +pub mod merkle; +pub mod schnorr; +pub mod ecdsa_secp256k1; +pub mod ecdsa_secp256r1; +pub mod eddsa; +pub mod embedded_curve_ops; +pub mod sha256; +pub mod sha512; +pub mod field; +pub mod ec; +pub mod collections; +pub mod compat; +pub mod convert; +pub mod option; +pub mod string; +pub mod test; +pub mod cmp; +pub mod ops; +pub mod default; +pub mod prelude; +pub mod uint128; +pub mod bigint; +pub mod runtime; +pub mod meta; +pub mod append; +pub mod mem; +pub mod panic; // Oracle calls are required to be wrapped in an unconstrained function // Thus, the only argument to the `println` oracle is expected to always be an ident diff --git a/noir_stdlib/src/meta/mod.nr b/noir_stdlib/src/meta/mod.nr index 1d787ebcdc1..378f0df1ba8 100644 --- a/noir_stdlib/src/meta/mod.nr +++ b/noir_stdlib/src/meta/mod.nr @@ -1,17 +1,17 @@ -mod ctstring; -mod expr; -mod format_string; -mod function_def; -mod module; -mod op; -mod struct_def; -mod trait_constraint; -mod trait_def; -mod trait_impl; -mod typ; -mod typed_expr; -mod quoted; -mod unresolved_type; +pub mod ctstring; +pub mod expr; +pub mod format_string; +pub mod function_def; +pub mod module; +pub mod op; +pub mod struct_def; +pub mod trait_constraint; +pub mod trait_def; +pub mod trait_impl; +pub mod typ; +pub mod typed_expr; +pub mod quoted; +pub mod unresolved_type; /// Calling unquote as a macro (via `unquote!(arg)`) will unquote /// its argument. Since this is the effect `!` already does, `unquote` @@ -36,7 +36,7 @@ use crate::hash::poseidon2::Poseidon2Hasher; // A derive function is one that given a struct definition can // create us a quoted trait impl from it. -type DeriveFunction = fn(StructDefinition) -> Quoted; +pub type DeriveFunction = fn(StructDefinition) -> Quoted; // We'll keep a global HANDLERS map to keep track of the derive handler for each trait comptime mut global HANDLERS: UHashMap> = UHashMap::default(); @@ -243,11 +243,15 @@ mod tests { } // docs:end:big-derive-usage-example + impl DoNothing for Bar { + fn do_nothing(_: Self) {} + } + // This function is just to remove unused warnings fn remove_unused_warnings() { - let _: Bar = crate::panic::panic(f""); - let _: MyStruct = crate::panic::panic(f""); - let _: MyOtherStruct = crate::panic::panic(f""); + let _: Bar = Bar { x: 1, y: [2, 3] }; + let _: MyStruct = MyStruct { my_field: 1 }; + let _: MyOtherStruct = MyOtherStruct { my_other_field: 2 }; let _ = derive_do_nothing(crate::panic::panic(f"")); let _ = derive_do_nothing_alt(crate::panic::panic(f"")); remove_unused_warnings(); diff --git a/noir_stdlib/src/ops/mod.nr b/noir_stdlib/src/ops/mod.nr index 6cf20432468..bf908ea4b27 100644 --- a/noir_stdlib/src/ops/mod.nr +++ b/noir_stdlib/src/ops/mod.nr @@ -1,5 +1,5 @@ -mod arith; -mod bit; +pub(crate) mod arith; +pub(crate) mod bit; pub use arith::{Add, Sub, Mul, Div, Rem, Neg}; pub use bit::{Not, BitOr, BitAnd, BitXor, Shl, Shr}; diff --git a/noir_stdlib/src/schnorr.nr b/noir_stdlib/src/schnorr.nr index 336041fec19..e24aabf3cda 100644 --- a/noir_stdlib/src/schnorr.nr +++ b/noir_stdlib/src/schnorr.nr @@ -1,4 +1,3 @@ -use crate::collections::vec::Vec; use crate::embedded_curve_ops::{EmbeddedCurvePoint, EmbeddedCurveScalar}; #[foreign(schnorr_verify)] @@ -23,7 +22,11 @@ pub fn verify_signature_slice( // docs:end:schnorr_verify_slice {} -pub fn verify_signature_noir(public_key: EmbeddedCurvePoint, signature: [u8; 64], message: [u8; N]) -> bool { +pub fn verify_signature_noir( + public_key: EmbeddedCurvePoint, + signature: [u8; 64], + message: [u8; N] +) -> bool { //scalar lo/hi from bytes let sig_s = EmbeddedCurveScalar::from_bytes(signature, 0); let sig_e = EmbeddedCurveScalar::from_bytes(signature, 32); @@ -42,7 +45,11 @@ pub fn verify_signature_noir(public_key: EmbeddedCurvePoint, signatu is_ok } -pub fn assert_valid_signature(public_key: EmbeddedCurvePoint, signature: [u8; 64], message: [u8; N]) { +pub fn assert_valid_signature( + public_key: EmbeddedCurvePoint, + signature: [u8; 64], + message: [u8; N] +) { //scalar lo/hi from bytes let sig_s = EmbeddedCurveScalar::from_bytes(signature, 0); let sig_e = EmbeddedCurveScalar::from_bytes(signature, 32); diff --git a/noir_stdlib/src/sha256.nr b/noir_stdlib/src/sha256.nr index ce217f7a689..7679e517317 100644 --- a/noir_stdlib/src/sha256.nr +++ b/noir_stdlib/src/sha256.nr @@ -1,2 +1,11 @@ // This file is kept for backwards compatibility. -pub use crate::hash::sha256::{digest, sha256_var}; + +#[deprecated = "replace with std::hash::sha256::digest"] +pub fn digest(msg: [u8; N]) -> [u8; 32] { + crate::hash::sha256::digest(msg) +} + +#[deprecated = "replace with std::hash::sha256::sha256_var"] +pub fn sha256_var(msg: [u8; N], message_size: u64) -> [u8; 32] { + crate::hash::sha256::sha256_var(msg, message_size) +} diff --git a/noir_stdlib/src/sha512.nr b/noir_stdlib/src/sha512.nr index b474e27b416..0a8a5bf4760 100644 --- a/noir_stdlib/src/sha512.nr +++ b/noir_stdlib/src/sha512.nr @@ -1,2 +1,6 @@ // This file is kept for backwards compatibility. -pub use crate::hash::sha512::digest; + +#[deprecated = "replace with std::hash::sha512::digest"] +pub fn digest(msg: [u8; N]) -> [u8; 64] { + crate::hash::sha512::digest(msg) +} diff --git a/test_programs/compile_success_empty/comptime_module/src/main.nr b/test_programs/compile_success_empty/comptime_module/src/main.nr index 9443b59fb0a..5099f3b7acb 100644 --- a/test_programs/compile_success_empty/comptime_module/src/main.nr +++ b/test_programs/compile_success_empty/comptime_module/src/main.nr @@ -3,8 +3,11 @@ mod foo { #![some_attribute] pub fn x() {} pub fn y() {} + pub fn z() {} - struct Struct1 {} + pub struct Struct1 {} + pub struct Struct2 {} + pub struct Struct3 {} } contract bar {} @@ -61,6 +64,8 @@ comptime fn add_function(m: Module) { } fn main() { + let _ = foo::Struct1 {}; + comptime { // Check Module::is_contract @@ -73,11 +78,20 @@ fn main() { let another_module = quote { another_module }.as_module().unwrap(); // Check Module::functions - assert_eq(foo.functions().len(), 2); + let foo_functions = foo.functions(); + assert_eq(foo_functions.len(), 3); + assert_eq(foo_functions[0].name(), quote { x }); + assert_eq(foo_functions[1].name(), quote { y }); + assert_eq(foo_functions[2].name(), quote { z }); + assert_eq(bar.functions().len(), 0); // Check Module::structs - assert_eq(foo.structs().len(), 1); + let foo_structs = foo.structs(); + assert_eq(foo_structs.len(), 3); + assert_eq(foo_structs[0].name(), quote { Struct1 }); + assert_eq(foo_structs[1].name(), quote { Struct2 }); + assert_eq(foo_structs[2].name(), quote { Struct3 }); assert_eq(bar.structs().len(), 0); // Check Module::name @@ -101,7 +115,7 @@ fn main() { // docs:start:as_module_example mod baz { - mod qux {} + pub mod qux {} } #[test] diff --git a/test_programs/compile_success_empty/field_or_integer_static_trait_method/src/main.nr b/test_programs/compile_success_empty/field_or_integer_static_trait_method/src/main.nr index f5a54c82ce5..64eb564cda1 100644 --- a/test_programs/compile_success_empty/field_or_integer_static_trait_method/src/main.nr +++ b/test_programs/compile_success_empty/field_or_integer_static_trait_method/src/main.nr @@ -23,3 +23,10 @@ fn main() { let value: Field = Field::read(data); assert_eq(value, 10); } + +#[attr] +pub fn foo() {} + +comptime fn attr(_: FunctionDefinition) -> Quoted { + quote { pub fn hello() {} } +} diff --git a/test_programs/execution_success/aes128_encrypt/src/main.nr b/test_programs/execution_success/aes128_encrypt/src/main.nr index b937c801860..31d907fea10 100644 --- a/test_programs/execution_success/aes128_encrypt/src/main.nr +++ b/test_programs/execution_success/aes128_encrypt/src/main.nr @@ -21,29 +21,20 @@ unconstrained fn decode_hex(s: str) -> [u8; M] { } unconstrained fn cipher(plaintext: [u8; 12], iv: [u8; 16], key: [u8; 16]) -> [u8; 16] { - let slice_res = std::aes128::aes128_encrypt(plaintext, iv, key); - let mut result = [0; 16]; - for i in 0..16 { - result[i] = slice_res[i]; - } - result + let result = std::aes128::aes128_encrypt(plaintext, iv, key); + result.as_array() } fn main(inputs: str<12>, iv: str<16>, key: str<16>, output: str<32>) { - let result = std::aes128::aes128_encrypt(inputs.as_bytes(), iv.as_bytes(), key.as_bytes()); + let result: [u8; 16] = std::aes128::aes128_encrypt(inputs.as_bytes(), iv.as_bytes(), key.as_bytes()).as_array(); let output_bytes: [u8; 16] = unsafe { - let output_bytes: [u8; 16] = decode_hex(output); - for i in 0..16 { - assert(result[i] == output_bytes[i]); - } - output_bytes + decode_hex(output) }; + assert(result == output_bytes); - unsafe { - let unconstrained_result = cipher(inputs.as_bytes(), iv.as_bytes(), key.as_bytes()); - for i in 0..16 { - assert(unconstrained_result[i] == output_bytes[i]); - } - } + let unconstrained_result = unsafe { + cipher(inputs.as_bytes(), iv.as_bytes(), key.as_bytes()) + }; + assert(unconstrained_result == output_bytes); } diff --git a/test_programs/execution_success/databus_in_fn_with_empty_arr/Nargo.toml b/test_programs/execution_success/databus_in_fn_with_empty_arr/Nargo.toml new file mode 100644 index 00000000000..7c5caf7c771 --- /dev/null +++ b/test_programs/execution_success/databus_in_fn_with_empty_arr/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "databus_in_fn_with_empty_arr" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/databus_in_fn_with_empty_arr/Prover.toml b/test_programs/execution_success/databus_in_fn_with_empty_arr/Prover.toml new file mode 100644 index 00000000000..e84e0dd7eec --- /dev/null +++ b/test_programs/execution_success/databus_in_fn_with_empty_arr/Prover.toml @@ -0,0 +1,3 @@ +_empty = [] +value_1 = "1" +value_2 = "2" diff --git a/test_programs/execution_success/databus_in_fn_with_empty_arr/src/main.nr b/test_programs/execution_success/databus_in_fn_with_empty_arr/src/main.nr new file mode 100644 index 00000000000..85671978a33 --- /dev/null +++ b/test_programs/execution_success/databus_in_fn_with_empty_arr/src/main.nr @@ -0,0 +1,3 @@ +fn main(_empty: [u32; 0], value_1: u32, value_2: call_data(0) u32) { + assert_eq(value_1 + 1, value_2); +} diff --git a/test_programs/execution_success/verify_honk_proof/Nargo.toml b/test_programs/execution_success/verify_honk_proof/Nargo.toml new file mode 100644 index 00000000000..8fce1bf44b6 --- /dev/null +++ b/test_programs/execution_success/verify_honk_proof/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "verify_honk_proof" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/verify_honk_proof/Prover.toml b/test_programs/execution_success/verify_honk_proof/Prover.toml new file mode 100644 index 00000000000..45a84c26eb8 --- /dev/null +++ b/test_programs/execution_success/verify_honk_proof/Prover.toml @@ -0,0 +1,4 @@ +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/test_programs/execution_success/verify_honk_proof/src/main.nr b/test_programs/execution_success/verify_honk_proof/src/main.nr new file mode 100644 index 00000000000..40559b64c7c --- /dev/null +++ b/test_programs/execution_success/verify_honk_proof/src/main.nr @@ -0,0 +1,23 @@ + +// 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/tooling/lsp/Cargo.toml b/tooling/lsp/Cargo.toml index c15895d801f..209f2afe4a4 100644 --- a/tooling/lsp/Cargo.toml +++ b/tooling/lsp/Cargo.toml @@ -14,6 +14,7 @@ workspace = true [dependencies] acvm.workspace = true +chumsky.workspace = true codespan-lsp.workspace = true lsp-types.workspace = true nargo.workspace = true diff --git a/tooling/lsp/src/attribute_reference_finder.rs b/tooling/lsp/src/attribute_reference_finder.rs new file mode 100644 index 00000000000..f08c8073a79 --- /dev/null +++ b/tooling/lsp/src/attribute_reference_finder.rs @@ -0,0 +1,115 @@ +/// If the cursor is on an custom attribute, this struct will try to resolve its +/// underlying function and return a ReferenceId to it. +/// This is needed in hover and go-to-definition because when an annotation generates +/// code, that code ends up residing in the attribute definition (it ends up having the +/// attribute's span) so using the usual graph to locate what points to that location +/// will give not only the attribute function but also any type generated by it. +use std::collections::BTreeMap; + +use chumsky::Parser; +use fm::FileId; +use noirc_errors::Span; +use noirc_frontend::{ + ast::{AttributeTarget, Visitor}, + graph::CrateId, + hir::{ + def_map::{CrateDefMap, LocalModuleId, ModuleId}, + resolution::path_resolver::{PathResolver, StandardPathResolver}, + }, + lexer::Lexer, + node_interner::ReferenceId, + parser::{path_no_turbofish, ParsedSubModule}, + token::CustomAttribute, + usage_tracker::UsageTracker, + 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 + /// if we are analyzing something inside an inline module declaration. + module_id: ModuleId, + def_maps: &'a BTreeMap, + reference_id: Option, +} + +impl<'a> AttributeReferenceFinder<'a> { + #[allow(clippy::too_many_arguments)] + pub(crate) fn new( + file: FileId, + byte_index: usize, + krate: CrateId, + def_maps: &'a BTreeMap, + ) -> Self { + // Find the module the current file belongs to + let def_map = &def_maps[&krate]; + let local_id = if let Some((module_index, _)) = + def_map.modules().iter().find(|(_, module_data)| module_data.location.file == file) + { + LocalModuleId(module_index) + } else { + def_map.root() + }; + let module_id = ModuleId { krate, local_id }; + Self { byte_index, module_id, def_maps, reference_id: None } + } + + pub(crate) fn find(&mut self, parsed_module: &ParsedModule) -> Option { + parsed_module.accept(self); + + self.reference_id + } + + fn includes_span(&self, span: Span) -> bool { + span.start() as usize <= self.byte_index && self.byte_index <= span.end() as usize + } +} + +impl<'a> Visitor for AttributeReferenceFinder<'a> { + fn visit_parsed_submodule(&mut self, parsed_sub_module: &ParsedSubModule, _span: Span) -> bool { + // Switch `self.module_id` to the submodule + let previous_module_id = self.module_id; + + let def_map = &self.def_maps[&self.module_id.krate]; + if let Some(module_data) = def_map.modules().get(self.module_id.local_id.0) { + if let Some(child_module) = module_data.children.get(&parsed_sub_module.name) { + self.module_id = ModuleId { krate: self.module_id.krate, local_id: *child_module }; + } + } + + parsed_sub_module.accept_children(self); + + // Restore the old module before continuing + self.module_id = previous_module_id; + + false + } + + fn visit_custom_attribute(&mut self, attribute: &CustomAttribute, _target: AttributeTarget) { + if !self.includes_span(attribute.contents_span) { + return; + } + + let name = match attribute.contents.split_once('(') { + Some((left, _right)) => left.to_string(), + None => attribute.contents.to_string(), + }; + let (tokens, _) = Lexer::lex(&name); + + let parser = path_no_turbofish(); + let Ok(path) = parser.parse(tokens) else { + return; + }; + + let resolver = StandardPathResolver::new(self.module_id); + let mut usage_tracker = UsageTracker::default(); + let Ok(result) = resolver.resolve(self.def_maps, path, &mut usage_tracker, &mut None) + else { + return; + }; + + self.reference_id = Some(module_def_id_to_reference_id(result.module_def_id)); + } +} diff --git a/tooling/lsp/src/lib.rs b/tooling/lsp/src/lib.rs index 39d4c3faa61..771f67e1fa2 100644 --- a/tooling/lsp/src/lib.rs +++ b/tooling/lsp/src/lib.rs @@ -62,6 +62,7 @@ use serde_json::Value as JsonValue; use thiserror::Error; use tower::Service; +mod attribute_reference_finder; mod modules; mod notifications; mod requests; diff --git a/tooling/lsp/src/modules.rs b/tooling/lsp/src/modules.rs index c8f7430c997..f1eff3b5a7d 100644 --- a/tooling/lsp/src/modules.rs +++ b/tooling/lsp/src/modules.rs @@ -18,15 +18,6 @@ pub(crate) fn get_parent_module( interner.reference_module(reference_id).copied() } -pub(crate) fn get_parent_module_id( - def_maps: &BTreeMap, - module_id: ModuleId, -) -> Option { - let crate_def_map = &def_maps[&module_id.krate]; - let module_data = &crate_def_map.modules()[module_id.local_id.0]; - module_data.parent.map(|parent| ModuleId { krate: module_id.krate, local_id: parent }) -} - pub(crate) fn module_def_id_to_reference_id(module_def_id: ModuleDefId) -> ReferenceId { match module_def_id { ModuleDefId::ModuleId(id) => ReferenceId::Module(id), diff --git a/tooling/lsp/src/requests/code_action/import_or_qualify.rs b/tooling/lsp/src/requests/code_action/import_or_qualify.rs index 03a953bde85..0d97ccde2ed 100644 --- a/tooling/lsp/src/requests/code_action/import_or_qualify.rs +++ b/tooling/lsp/src/requests/code_action/import_or_qualify.rs @@ -7,7 +7,7 @@ use noirc_frontend::{ use crate::{ byte_span_to_range, - modules::{get_parent_module_id, relative_module_full_path, relative_module_id_path}, + modules::{relative_module_full_path, relative_module_id_path}, }; use super::CodeActionFinder; @@ -28,7 +28,7 @@ impl<'a> CodeActionFinder<'a> { return; } - let current_module_parent_id = get_parent_module_id(self.def_maps, self.module_id); + let current_module_parent_id = self.module_id.parent(self.def_maps); // The Path doesn't resolve to anything so it means it's an error and maybe we // can suggest an import or to fully-qualify the path. diff --git a/tooling/lsp/src/requests/code_action/remove_unused_import.rs b/tooling/lsp/src/requests/code_action/remove_unused_import.rs index f1e12d64ef5..f5f0b520149 100644 --- a/tooling/lsp/src/requests/code_action/remove_unused_import.rs +++ b/tooling/lsp/src/requests/code_action/remove_unused_import.rs @@ -189,7 +189,7 @@ mod tests { let title = "Remove the whole `use` item"; let src = r#" - mod moo { + pub(crate) mod moo { pub fn foo() {} } @@ -202,7 +202,7 @@ mod tests { "#; let expected = r#" - mod moo { + pub(crate) mod moo { pub fn foo() {} } diff --git a/tooling/lsp/src/requests/completion/auto_import.rs b/tooling/lsp/src/requests/completion/auto_import.rs index 2713ae252bf..20b126a248d 100644 --- a/tooling/lsp/src/requests/completion/auto_import.rs +++ b/tooling/lsp/src/requests/completion/auto_import.rs @@ -1,7 +1,7 @@ use lsp_types::{Position, Range, TextEdit}; use noirc_frontend::macros_api::ModuleDefId; -use crate::modules::{get_parent_module_id, relative_module_full_path, relative_module_id_path}; +use crate::modules::{relative_module_full_path, relative_module_id_path}; use super::{ kinds::{FunctionCompletionKind, FunctionKind, RequestedItems}, @@ -17,7 +17,7 @@ impl<'a> NodeFinder<'a> { requested_items: RequestedItems, function_completion_kind: FunctionCompletionKind, ) { - let current_module_parent_id = get_parent_module_id(self.def_maps, self.module_id); + let current_module_parent_id = self.module_id.parent(self.def_maps); for (name, entries) in self.interner.get_auto_import_names() { if !name_matches(name, prefix) { diff --git a/tooling/lsp/src/requests/completion/tests.rs b/tooling/lsp/src/requests/completion/tests.rs index 68cb3870f63..147fb5be4f3 100644 --- a/tooling/lsp/src/requests/completion/tests.rs +++ b/tooling/lsp/src/requests/completion/tests.rs @@ -149,8 +149,8 @@ mod completion_tests { async fn test_use_second_segment() { let src = r#" mod foo { - mod bar {} - mod baz {} + pub mod bar {} + pub mod baz {} } use foo::>|< "#; @@ -163,8 +163,8 @@ mod completion_tests { async fn test_use_second_segment_after_typing() { let src = r#" mod foo { - mod bar {} - mod brave {} + pub mod bar {} + pub mod brave {} } use foo::ba>|< "#; @@ -239,7 +239,7 @@ mod completion_tests { async fn test_use_in_tree_after_letter() { let src = r#" mod foo { - mod bar {} + pub mod bar {} } use foo::{b>|<} "#; @@ -251,8 +251,8 @@ mod completion_tests { async fn test_use_in_tree_after_colons() { let src = r#" mod foo { - mod bar { - mod baz {} + pub mod bar { + pub mod baz {} } } use foo::{bar::>|<} @@ -265,8 +265,8 @@ mod completion_tests { async fn test_use_in_tree_after_colons_after_another_segment() { let src = r#" mod foo { - mod bar {} - mod qux {} + pub mod bar {} + pub mod qux {} } use foo::{bar, q>|<} "#; @@ -350,7 +350,7 @@ mod completion_tests { async fn test_complete_path_after_colons_shows_submodule() { let src = r#" mod foo { - mod bar {} + pub mod bar {} } fn main() { @@ -364,7 +364,7 @@ mod completion_tests { async fn test_complete_path_after_colons_and_letter_shows_submodule() { let src = r#" mod foo { - mod qux {} + pub mod qux {} } fn main() { @@ -1809,8 +1809,8 @@ mod completion_tests { async fn test_suggests_pub_use() { let src = r#" mod bar { - mod baz { - mod coco {} + pub mod baz { + pub mod coco {} } pub use baz::coco; @@ -1827,8 +1827,8 @@ mod completion_tests { async fn test_auto_import_suggests_pub_use_for_module() { let src = r#" mod bar { - mod baz { - mod coco {} + pub mod baz { + pub mod coco {} } pub use baz::coco as foobar; diff --git a/tooling/lsp/src/requests/goto_definition.rs b/tooling/lsp/src/requests/goto_definition.rs index 6538e64dc90..a2443ea165d 100644 --- a/tooling/lsp/src/requests/goto_definition.rs +++ b/tooling/lsp/src/requests/goto_definition.rs @@ -1,8 +1,11 @@ use std::future::{self, Future}; +use crate::attribute_reference_finder::AttributeReferenceFinder; +use crate::utils; use crate::{types::GotoDefinitionResult, LspState}; use async_lsp::ResponseError; +use fm::PathString; use lsp_types::request::GotoTypeDefinitionParams; use lsp_types::{GotoDefinitionParams, GotoDefinitionResponse}; @@ -29,21 +32,42 @@ fn on_goto_definition_inner( params: GotoDefinitionParams, return_type_location_instead: bool, ) -> Result { + let uri = params.text_document_position_params.text_document.uri.clone(); + let position = params.text_document_position_params.position; process_request(state, params.text_document_position_params, |args| { - args.interner - .get_definition_location_from(args.location, return_type_location_instead) - .or_else(|| { - args.interner - .reference_at_location(args.location) - .map(|reference| args.interner.reference_location(reference)) - }) - .and_then(|found_location| { - let file_id = found_location.file; - let definition_position = - to_lsp_location(args.files, file_id, found_location.span)?; - let response = GotoDefinitionResponse::from(definition_position).to_owned(); - Some(response) + let path = PathString::from_path(uri.to_file_path().unwrap()); + let reference_id = args.files.get_file_id(&path).and_then(|file_id| { + utils::position_to_byte_index(args.files, file_id, &position).and_then(|byte_index| { + let file = args.files.get_file(file_id).unwrap(); + let source = file.source(); + let (parsed_module, _errors) = noirc_frontend::parse_program(source); + + let mut finder = AttributeReferenceFinder::new( + file_id, + byte_index, + args.crate_id, + args.def_maps, + ); + finder.find(&parsed_module) }) + }); + let location = if let Some(reference_id) = reference_id { + Some(args.interner.reference_location(reference_id)) + } else { + args.interner + .get_definition_location_from(args.location, return_type_location_instead) + .or_else(|| { + args.interner + .reference_at_location(args.location) + .map(|reference| args.interner.reference_location(reference)) + }) + }; + location.and_then(|found_location| { + let file_id = found_location.file; + let definition_position = to_lsp_location(args.files, file_id, found_location.span)?; + let response = GotoDefinitionResponse::from(definition_position).to_owned(); + Some(response) + }) }) } @@ -249,4 +273,18 @@ mod goto_definition_tests { ) .await; } + + #[test] + async fn goto_attribute_function() { + expect_goto( + "go_to_definition", + Position { line: 31, character: 3 }, // "attr" + "src/main.nr", + Range { + start: Position { line: 34, character: 12 }, + end: Position { line: 34, character: 16 }, + }, + ) + .await; + } } diff --git a/tooling/lsp/src/requests/hover.rs b/tooling/lsp/src/requests/hover.rs index 46d2a5cfc8f..2628c9b2ab6 100644 --- a/tooling/lsp/src/requests/hover.rs +++ b/tooling/lsp/src/requests/hover.rs @@ -1,7 +1,7 @@ use std::future::{self, Future}; use async_lsp::ResponseError; -use fm::FileMap; +use fm::{FileMap, PathString}; use lsp_types::{Hover, HoverContents, HoverParams, MarkupContent, MarkupKind}; use noirc_frontend::{ ast::Visibility, @@ -15,7 +15,10 @@ use noirc_frontend::{ Generics, Shared, StructType, Type, TypeAlias, TypeBinding, TypeVariable, }; -use crate::{modules::module_full_path, LspState}; +use crate::{ + attribute_reference_finder::AttributeReferenceFinder, modules::module_full_path, utils, + LspState, +}; use super::{process_request, to_lsp_location, ProcessRequestCallbackArgs}; @@ -23,18 +26,41 @@ pub(crate) fn on_hover_request( state: &mut LspState, params: HoverParams, ) -> impl Future, ResponseError>> { + let uri = params.text_document_position_params.text_document.uri.clone(); + let position = params.text_document_position_params.position; let result = process_request(state, params.text_document_position_params, |args| { - args.interner.reference_at_location(args.location).and_then(|reference| { - let location = args.interner.reference_location(reference); - let lsp_location = to_lsp_location(args.files, location.file, location.span); - format_reference(reference, &args).map(|formatted| Hover { - range: lsp_location.map(|location| location.range), - contents: HoverContents::Markup(MarkupContent { - kind: MarkupKind::Markdown, - value: formatted, - }), + let path = PathString::from_path(uri.to_file_path().unwrap()); + args.files + .get_file_id(&path) + .and_then(|file_id| { + utils::position_to_byte_index(args.files, file_id, &position).and_then( + |byte_index| { + let file = args.files.get_file(file_id).unwrap(); + let source = file.source(); + let (parsed_module, _errors) = noirc_frontend::parse_program(source); + + let mut finder = AttributeReferenceFinder::new( + file_id, + byte_index, + args.crate_id, + args.def_maps, + ); + finder.find(&parsed_module) + }, + ) + }) + .or_else(|| args.interner.reference_at_location(args.location)) + .and_then(|reference| { + let location = args.interner.reference_location(reference); + let lsp_location = to_lsp_location(args.files, location.file, location.span); + format_reference(reference, &args).map(|formatted| Hover { + range: lsp_location.map(|location| location.range), + contents: HoverContents::Markup(MarkupContent { + kind: MarkupKind::Markdown, + value: formatted, + }), + }) }) - }) }); future::ready(result) @@ -918,4 +944,15 @@ mod hover_tests { ) .await; } + + #[test] + async fn hover_on_attribute_function() { + assert_hover( + "workspace", + "two/src/lib.nr", + Position { line: 54, character: 2 }, + " two\n fn attr(_: FunctionDefinition) -> Quoted", + ) + .await; + } } diff --git a/tooling/lsp/src/trait_impl_method_stub_generator.rs b/tooling/lsp/src/trait_impl_method_stub_generator.rs index ae12bac4c06..56d2e5e1ea1 100644 --- a/tooling/lsp/src/trait_impl_method_stub_generator.rs +++ b/tooling/lsp/src/trait_impl_method_stub_generator.rs @@ -197,12 +197,7 @@ impl<'a> TraitImplMethodStubGenerator<'a> { } } - let module_id = struct_type.id.module_id(); - let module_data = &self.def_maps[&module_id.krate].modules()[module_id.local_id.0]; - let parent_module_local_id = module_data.parent.unwrap(); - let parent_module_id = - ModuleId { krate: module_id.krate, local_id: parent_module_local_id }; - + let parent_module_id = struct_type.id.parent_module_id(self.def_maps); let current_module_parent_id = current_module_data .parent .map(|parent| ModuleId { krate: self.module_id.krate, local_id: parent }); diff --git a/tooling/lsp/test_programs/go_to_definition/src/main.nr b/tooling/lsp/test_programs/go_to_definition/src/main.nr index 4550324c182..cb04fe04eaa 100644 --- a/tooling/lsp/test_programs/go_to_definition/src/main.nr +++ b/tooling/lsp/test_programs/go_to_definition/src/main.nr @@ -28,3 +28,10 @@ trait Trait { } use dependency::something; + +#[attr] +pub fn foo() {} + +comptime fn attr(_: FunctionDefinition) -> Quoted { + quote { pub fn hello() {} } +} \ No newline at end of file diff --git a/tooling/lsp/test_programs/workspace/two/src/lib.nr b/tooling/lsp/test_programs/workspace/two/src/lib.nr index 3f0f0f117b7..c6b516d88ab 100644 --- a/tooling/lsp/test_programs/workspace/two/src/lib.nr +++ b/tooling/lsp/test_programs/workspace/two/src/lib.nr @@ -51,3 +51,10 @@ use std::collections::bounded_vec::BoundedVec; fn instantiate_generic() { let x: BoundedVec = BoundedVec::new(); } + +#[attr] +pub fn foo() {} + +comptime fn attr(_: FunctionDefinition) -> Quoted { + quote { pub fn hello() {} } +} \ No newline at end of file diff --git a/tooling/nargo/src/errors.rs b/tooling/nargo/src/errors.rs index 313f29517d6..5256f28e36c 100644 --- a/tooling/nargo/src/errors.rs +++ b/tooling/nargo/src/errors.rs @@ -15,7 +15,7 @@ use noirc_errors::{ pub use noirc_errors::Location; -use noirc_frontend::graph::CrateName; +use noirc_driver::CrateName; use noirc_printable_type::ForeignCallError; use thiserror::Error; diff --git a/tooling/nargo/src/package.rs b/tooling/nargo/src/package.rs index f55ca5550a3..cd1d5e2a84f 100644 --- a/tooling/nargo/src/package.rs +++ b/tooling/nargo/src/package.rs @@ -1,7 +1,7 @@ use std::{collections::BTreeMap, fmt::Display, path::PathBuf}; use acvm::acir::circuit::ExpressionWidth; -use noirc_frontend::graph::CrateName; +pub use noirc_driver::CrateName; use crate::constants::PROVER_INPUT_FILE; diff --git a/tooling/nargo_cli/build.rs b/tooling/nargo_cli/build.rs index 7469c8be0f8..9f694080cf5 100644 --- a/tooling/nargo_cli/build.rs +++ b/tooling/nargo_cli/build.rs @@ -81,7 +81,6 @@ fn read_test_cases( fn generate_test_case( test_file: &mut File, - test_type: &str, test_name: &str, test_dir: &std::path::Display, test_content: &str, @@ -90,7 +89,7 @@ fn generate_test_case( test_file, r#" #[test] -fn {test_type}_{test_name}() {{ +fn test_{test_name}() {{ let test_program_dir = PathBuf::from("{test_dir}"); let mut nargo = Command::cargo_bin("nargo").unwrap(); @@ -105,12 +104,19 @@ fn {test_type}_{test_name}() {{ fn generate_execution_success_tests(test_file: &mut File, test_data_dir: &Path) { let test_type = "execution_success"; let test_cases = read_test_cases(test_data_dir, test_type); + + writeln!( + test_file, + "mod {test_type} {{ + use super::*; + " + ) + .unwrap(); for (test_name, test_dir) in test_cases { let test_dir = test_dir.display(); generate_test_case( test_file, - test_type, &test_name, &test_dir, r#" @@ -122,7 +128,6 @@ fn generate_execution_success_tests(test_file: &mut File, test_data_dir: &Path) if !IGNORED_BRILLIG_TESTS.contains(&test_name.as_str()) { generate_test_case( test_file, - test_type, &format!("{test_name}_brillig"), &test_dir, r#" @@ -132,17 +137,25 @@ fn generate_execution_success_tests(test_file: &mut File, test_data_dir: &Path) ); } } + writeln!(test_file, "}}").unwrap(); } fn generate_execution_failure_tests(test_file: &mut File, test_data_dir: &Path) { let test_type = "execution_failure"; let test_cases = read_test_cases(test_data_dir, test_type); + + writeln!( + test_file, + "mod {test_type} {{ + use super::*; + " + ) + .unwrap(); for (test_name, test_dir) in test_cases { let test_dir = test_dir.display(); generate_test_case( test_file, - test_type, &test_name, &test_dir, r#" @@ -151,17 +164,25 @@ fn generate_execution_failure_tests(test_file: &mut File, test_data_dir: &Path) nargo.assert().failure().stderr(predicate::str::contains("The application panicked (crashed).").not());"#, ); } + writeln!(test_file, "}}").unwrap(); } fn generate_noir_test_success_tests(test_file: &mut File, test_data_dir: &Path) { let test_type = "noir_test_success"; let test_cases = read_test_cases(test_data_dir, "noir_test_success"); + + writeln!( + test_file, + "mod {test_type} {{ + use super::*; + " + ) + .unwrap(); for (test_name, test_dir) in test_cases { let test_dir = test_dir.display(); generate_test_case( test_file, - test_type, &test_name, &test_dir, r#" @@ -170,16 +191,24 @@ fn generate_noir_test_success_tests(test_file: &mut File, test_data_dir: &Path) nargo.assert().success();"#, ); } + writeln!(test_file, "}}").unwrap(); } fn generate_noir_test_failure_tests(test_file: &mut File, test_data_dir: &Path) { let test_type = "noir_test_failure"; let test_cases = read_test_cases(test_data_dir, test_type); + + writeln!( + test_file, + "mod {test_type} {{ + use super::*; + " + ) + .unwrap(); for (test_name, test_dir) in test_cases { let test_dir = test_dir.display(); generate_test_case( test_file, - test_type, &test_name, &test_dir, r#" @@ -188,11 +217,20 @@ fn generate_noir_test_failure_tests(test_file: &mut File, test_data_dir: &Path) nargo.assert().failure();"#, ); } + writeln!(test_file, "}}").unwrap(); } fn generate_compile_success_empty_tests(test_file: &mut File, test_data_dir: &Path) { let test_type = "compile_success_empty"; let test_cases = read_test_cases(test_data_dir, test_type); + + writeln!( + test_file, + "mod {test_type} {{ + use super::*; + " + ) + .unwrap(); for (test_name, test_dir) in test_cases { let test_dir = test_dir.display(); @@ -213,7 +251,6 @@ fn generate_compile_success_empty_tests(test_file: &mut File, test_data_dir: &Pa generate_test_case( test_file, - test_type, &test_name, &test_dir, &format!( @@ -224,17 +261,25 @@ fn generate_compile_success_empty_tests(test_file: &mut File, test_data_dir: &Pa ), ); } + writeln!(test_file, "}}").unwrap(); } fn generate_compile_success_contract_tests(test_file: &mut File, test_data_dir: &Path) { let test_type = "compile_success_contract"; let test_cases = read_test_cases(test_data_dir, test_type); + + writeln!( + test_file, + "mod {test_type} {{ + use super::*; + " + ) + .unwrap(); for (test_name, test_dir) in test_cases { let test_dir = test_dir.display(); generate_test_case( test_file, - test_type, &test_name, &test_dir, r#" @@ -242,18 +287,26 @@ fn generate_compile_success_contract_tests(test_file: &mut File, test_data_dir: nargo.assert().success();"#, ); } + writeln!(test_file, "}}").unwrap(); } /// Generate tests for checking that the contract compiles and there are no "bugs" in stderr fn generate_compile_success_no_bug_tests(test_file: &mut File, test_data_dir: &Path) { let test_type = "compile_success_no_bug"; let test_cases = read_test_cases(test_data_dir, test_type); + + writeln!( + test_file, + "mod {test_type} {{ + use super::*; + " + ) + .unwrap(); for (test_name, test_dir) in test_cases { let test_dir = test_dir.display(); generate_test_case( test_file, - test_type, &test_name, &test_dir, r#" @@ -261,17 +314,25 @@ fn generate_compile_success_no_bug_tests(test_file: &mut File, test_data_dir: &P nargo.assert().success().stderr(predicate::str::contains("bug:").not());"#, ); } + writeln!(test_file, "}}").unwrap(); } fn generate_compile_failure_tests(test_file: &mut File, test_data_dir: &Path) { let test_type = "compile_failure"; let test_cases = read_test_cases(test_data_dir, test_type); + + writeln!( + test_file, + "mod {test_type} {{ + use super::*; + " + ) + .unwrap(); for (test_name, test_dir) in test_cases { let test_dir = test_dir.display(); generate_test_case( test_file, - test_type, &test_name, &test_dir, r#"nargo.arg("compile").arg("--force"); @@ -279,4 +340,5 @@ fn generate_compile_failure_tests(test_file: &mut File, test_data_dir: &Path) { nargo.assert().failure().stderr(predicate::str::contains("The application panicked (crashed).").not());"#, ); } + writeln!(test_file, "}}").unwrap(); } diff --git a/tooling/nargo_cli/src/cli/check_cmd.rs b/tooling/nargo_cli/src/cli/check_cmd.rs index 65a09dcdd11..9059f1dd8e8 100644 --- a/tooling/nargo_cli/src/cli/check_cmd.rs +++ b/tooling/nargo_cli/src/cli/check_cmd.rs @@ -4,18 +4,18 @@ use clap::Args; use fm::FileManager; use iter_extended::btree_map; use nargo::{ - errors::CompileError, insert_all_files_for_workspace_into_file_manager, ops::report_errors, - package::Package, parse_all, prepare_package, + errors::CompileError, + insert_all_files_for_workspace_into_file_manager, + ops::report_errors, + package::{CrateName, Package}, + parse_all, prepare_package, }; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; use noirc_abi::{AbiParameter, AbiType, MAIN_RETURN_NAME}; use noirc_driver::{ - check_crate, compute_function_abi, CompileOptions, NOIR_ARTIFACT_VERSION_STRING, -}; -use noirc_frontend::{ - graph::{CrateId, CrateName}, - hir::{Context, ParsedFiles}, + check_crate, compute_function_abi, CompileOptions, CrateId, NOIR_ARTIFACT_VERSION_STRING, }; +use noirc_frontend::hir::{Context, ParsedFiles}; use super::fs::write_to_file; use super::NargoConfig; diff --git a/tooling/nargo_cli/src/cli/compile_cmd.rs b/tooling/nargo_cli/src/cli/compile_cmd.rs index ae96f6436e2..0ad07c91ff4 100644 --- a/tooling/nargo_cli/src/cli/compile_cmd.rs +++ b/tooling/nargo_cli/src/cli/compile_cmd.rs @@ -5,7 +5,7 @@ use std::time::Duration; use acvm::acir::circuit::ExpressionWidth; use fm::FileManager; use nargo::ops::{collect_errors, compile_contract, compile_program, report_errors}; -use nargo::package::Package; +use nargo::package::{CrateName, Package}; use nargo::workspace::Workspace; use nargo::{insert_all_files_for_workspace_into_file_manager, parse_all}; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; @@ -13,8 +13,6 @@ use noirc_driver::DEFAULT_EXPRESSION_WIDTH; use noirc_driver::NOIR_ARTIFACT_VERSION_STRING; use noirc_driver::{CompilationResult, CompileOptions, CompiledContract}; -use noirc_frontend::graph::CrateName; - use clap::Args; use noirc_frontend::hir::ParsedFiles; use notify::{EventKind, RecursiveMode, Watcher}; diff --git a/tooling/nargo_cli/src/cli/debug_cmd.rs b/tooling/nargo_cli/src/cli/debug_cmd.rs index 0a593e09c17..e837f297475 100644 --- a/tooling/nargo_cli/src/cli/debug_cmd.rs +++ b/tooling/nargo_cli/src/cli/debug_cmd.rs @@ -9,7 +9,7 @@ use fm::FileManager; use nargo::constants::PROVER_INPUT_FILE; use nargo::errors::CompileError; use nargo::ops::{compile_program, compile_program_with_debug_instrumenter, report_errors}; -use nargo::package::Package; +use nargo::package::{CrateName, Package}; use nargo::workspace::Workspace; use nargo::{insert_all_files_for_workspace_into_file_manager, parse_all}; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; @@ -19,7 +19,6 @@ use noirc_driver::{ file_manager_with_stdlib, CompileOptions, CompiledProgram, NOIR_ARTIFACT_VERSION_STRING, }; use noirc_frontend::debug::DebugInstrumenter; -use noirc_frontend::graph::CrateName; use noirc_frontend::hir::ParsedFiles; use super::compile_cmd::get_target_width; diff --git a/tooling/nargo_cli/src/cli/execute_cmd.rs b/tooling/nargo_cli/src/cli/execute_cmd.rs index c145ae9dbca..8dc71b1c7e5 100644 --- a/tooling/nargo_cli/src/cli/execute_cmd.rs +++ b/tooling/nargo_cli/src/cli/execute_cmd.rs @@ -8,13 +8,12 @@ use clap::Args; use nargo::constants::PROVER_INPUT_FILE; use nargo::errors::try_to_diagnose_runtime_error; use nargo::ops::DefaultForeignCallExecutor; -use nargo::package::Package; +use nargo::package::{CrateName, Package}; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; use noirc_abi::input_parser::{Format, InputValue}; use noirc_abi::InputMap; use noirc_artifacts::debug::DebugArtifact; use noirc_driver::{CompileOptions, CompiledProgram, NOIR_ARTIFACT_VERSION_STRING}; -use noirc_frontend::graph::CrateName; use super::compile_cmd::compile_workspace_full; use super::fs::{inputs::read_inputs_from_file, witness::save_witness_to_dir}; diff --git a/tooling/nargo_cli/src/cli/fs/program.rs b/tooling/nargo_cli/src/cli/fs/program.rs index 323cd2c6a06..0b30d23db2b 100644 --- a/tooling/nargo_cli/src/cli/fs/program.rs +++ b/tooling/nargo_cli/src/cli/fs/program.rs @@ -1,7 +1,7 @@ use std::path::{Path, PathBuf}; +use nargo::package::CrateName; use noirc_artifacts::{contract::ContractArtifact, program::ProgramArtifact}; -use noirc_frontend::graph::CrateName; use crate::errors::FilesystemError; diff --git a/tooling/nargo_cli/src/cli/info_cmd.rs b/tooling/nargo_cli/src/cli/info_cmd.rs index 7e4a8b4117d..f2e44fa893c 100644 --- a/tooling/nargo_cli/src/cli/info_cmd.rs +++ b/tooling/nargo_cli/src/cli/info_cmd.rs @@ -3,12 +3,11 @@ use std::collections::HashMap; use acvm::acir::circuit::ExpressionWidth; use clap::Args; use iter_extended::vecmap; -use nargo::package::Package; +use nargo::package::{CrateName, Package}; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; use noirc_artifacts::{debug::DebugArtifact, program::ProgramArtifact}; use noirc_driver::{CompileOptions, NOIR_ARTIFACT_VERSION_STRING}; use noirc_errors::{debug_info::OpCodesCount, Location}; -use noirc_frontend::graph::CrateName; use prettytable::{row, table, Row}; use rayon::prelude::*; use serde::Serialize; diff --git a/tooling/nargo_cli/src/cli/init_cmd.rs b/tooling/nargo_cli/src/cli/init_cmd.rs index dd3af97ecd6..c69775d3323 100644 --- a/tooling/nargo_cli/src/cli/init_cmd.rs +++ b/tooling/nargo_cli/src/cli/init_cmd.rs @@ -4,9 +4,8 @@ use super::fs::{create_named_dir, write_to_file}; use super::NargoConfig; use clap::Args; use nargo::constants::{PKG_FILE, SRC_DIR}; -use nargo::package::PackageType; +use nargo::package::{CrateName, PackageType}; use noirc_driver::NOIRC_VERSION; -use noirc_frontend::graph::CrateName; use std::path::PathBuf; /// Create a Noir project in the current directory. diff --git a/tooling/nargo_cli/src/cli/new_cmd.rs b/tooling/nargo_cli/src/cli/new_cmd.rs index 21951f27260..db9257b8aa0 100644 --- a/tooling/nargo_cli/src/cli/new_cmd.rs +++ b/tooling/nargo_cli/src/cli/new_cmd.rs @@ -2,8 +2,7 @@ use crate::errors::CliError; use super::{init_cmd::initialize_project, NargoConfig}; use clap::Args; -use nargo::package::PackageType; -use noirc_frontend::graph::CrateName; +use nargo::package::{CrateName, PackageType}; use std::path::PathBuf; /// Create a Noir project in a new directory. diff --git a/tooling/nargo_cli/src/cli/test_cmd.rs b/tooling/nargo_cli/src/cli/test_cmd.rs index 8b3c0e29c7d..7b0201226ef 100644 --- a/tooling/nargo_cli/src/cli/test_cmd.rs +++ b/tooling/nargo_cli/src/cli/test_cmd.rs @@ -5,15 +5,14 @@ use bn254_blackbox_solver::Bn254BlackBoxSolver; use clap::Args; use fm::FileManager; use nargo::{ - insert_all_files_for_workspace_into_file_manager, ops::TestStatus, package::Package, parse_all, - prepare_package, + insert_all_files_for_workspace_into_file_manager, + ops::TestStatus, + package::{CrateName, Package}, + parse_all, prepare_package, }; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; use noirc_driver::{check_crate, CompileOptions, NOIR_ARTIFACT_VERSION_STRING}; -use noirc_frontend::{ - graph::CrateName, - hir::{FunctionNameMatch, ParsedFiles}, -}; +use noirc_frontend::hir::{FunctionNameMatch, ParsedFiles}; use rayon::prelude::{IntoParallelIterator, ParallelBridge, ParallelIterator}; use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; diff --git a/tooling/nargo_fmt/src/visitor/item.rs b/tooling/nargo_fmt/src/visitor/item.rs index 7d5e1886072..2feae4b390c 100644 --- a/tooling/nargo_fmt/src/visitor/item.rs +++ b/tooling/nargo_fmt/src/visitor/item.rs @@ -7,7 +7,7 @@ use crate::{ visitor::expr::{format_seq, NewlineMode}, }; use noirc_frontend::{ - ast::{NoirFunction, TraitImplItemKind, Visibility}, + ast::{ItemVisibility, NoirFunction, TraitImplItemKind, Visibility}, macros_api::UnresolvedTypeData, }; use noirc_frontend::{ @@ -179,8 +179,12 @@ impl super::FmtVisitor<'_> { let after_brace = self.span_after(span, Token::LeftBrace).start(); self.last_position = after_brace; - let keyword = if module.is_contract { "contract" } else { "mod" }; + let visibility = module.visibility; + if visibility != ItemVisibility::Private { + self.push_str(&format!("{visibility} ")); + } + let keyword = if module.is_contract { "contract" } else { "mod" }; self.push_str(&format!("{keyword} {name} ")); if module.contents.items.is_empty() { @@ -276,7 +280,7 @@ impl super::FmtVisitor<'_> { ItemKind::Struct(_) | ItemKind::Trait(_) | ItemKind::TypeAlias(_) - | ItemKind::Global(_) + | ItemKind::Global(..) | ItemKind::ModuleDecl(_) | ItemKind::InnerAttribute(_) => { self.push_rewrite(self.slice(span).to_string(), span); diff --git a/tooling/nargo_fmt/tests/expected/module.nr b/tooling/nargo_fmt/tests/expected/module.nr index 0a051a1b50f..1d153b02078 100644 --- a/tooling/nargo_fmt/tests/expected/module.nr +++ b/tooling/nargo_fmt/tests/expected/module.nr @@ -33,3 +33,7 @@ mod a { #![inner] } } + +pub(crate) mod one {} + +pub mod two {} diff --git a/tooling/nargo_fmt/tests/input/module.nr b/tooling/nargo_fmt/tests/input/module.nr index 0a051a1b50f..3e01b81bcf0 100644 --- a/tooling/nargo_fmt/tests/input/module.nr +++ b/tooling/nargo_fmt/tests/input/module.nr @@ -33,3 +33,7 @@ mod a { #![inner] } } + +pub(crate) mod one { } + +pub mod two { } diff --git a/tooling/noir_js_backend_barretenberg/src/backend.ts b/tooling/noir_js_backend_barretenberg/src/backend.ts index 2569c7d868d..812a7173ad2 100644 --- a/tooling/noir_js_backend_barretenberg/src/backend.ts +++ b/tooling/noir_js_backend_barretenberg/src/backend.ts @@ -1,8 +1,14 @@ import { acirToUint8Array } from './serialize.js'; import { Backend, CompiledCircuit, ProofData, VerifierBackend } from '@noir-lang/types'; -import { deflattenFields } from './public_inputs.js'; -import { reconstructProofWithPublicInputs, reconstructProofWithPublicInputsHonk } from './verifier.js'; -import { BackendOptions, UltraPlonkBackend, UltraHonkBackend as UltraHonkBackendInternal } from '@aztec/bb.js'; +import { deflattenFields, flattenFieldsAsArray } from './public_inputs.js'; +import { reconstructProofWithPublicInputs } from './verifier.js'; +import { + BackendOptions, + reconstructHonkProof, + splitHonkProof, + UltraPlonkBackend, + UltraHonkBackend as UltraHonkBackendInternal, +} from '@aztec/bb.js'; import { decompressSync as gunzip } from 'fflate'; // This is the number of bytes in a UltraPlonk proof @@ -74,12 +80,6 @@ export class BarretenbergBackend implements Backend, VerifierBackend { } } -// Buffers are prepended with their size. The size takes 4 bytes. -const serializedBufferSize = 4; -const fieldByteSize = 32; -const publicInputOffset = 3; -const publicInputsOffsetBytes = publicInputOffset * fieldByteSize; - export class UltraHonkBackend implements Backend, VerifierBackend { // These type assertions are used so that we don't // have to initialize `api` in the constructor. @@ -96,32 +96,16 @@ export class UltraHonkBackend implements Backend, VerifierBackend { async generateProof(compressedWitness: Uint8Array): Promise { const proofWithPublicInputs = await this.backend.generateProof(gunzip(compressedWitness)); - const proofAsStrings = deflattenFields(proofWithPublicInputs.slice(4)); - - const numPublicInputs = Number(proofAsStrings[1]); - - // Account for the serialized buffer size at start - const publicInputsOffset = publicInputsOffsetBytes + serializedBufferSize; - // Get the part before and after the public inputs - const proofStart = proofWithPublicInputs.slice(0, publicInputsOffset); - const publicInputsSplitIndex = numPublicInputs * fieldByteSize; - const proofEnd = proofWithPublicInputs.slice(publicInputsOffset + publicInputsSplitIndex); - // Construct the proof without the public inputs - const proof = new Uint8Array([...proofStart, ...proofEnd]); - - // Fetch the number of public inputs out of the proof string - const publicInputsConcatenated = proofWithPublicInputs.slice( - publicInputsOffset, - publicInputsOffset + publicInputsSplitIndex, - ); - const publicInputs = deflattenFields(publicInputsConcatenated); + + const { proof, publicInputs: flatPublicInputs } = splitHonkProof(proofWithPublicInputs); + const publicInputs = deflattenFields(flatPublicInputs); return { proof, publicInputs }; } async verifyProof(proofData: ProofData): Promise { - const proof = reconstructProofWithPublicInputsHonk(proofData); - + const flattenedPublicInputs = flattenFieldsAsArray(proofData.publicInputs); + const proof = reconstructHonkProof(flattenedPublicInputs, proofData.proof); return this.backend.verifyProof(proof); } @@ -134,7 +118,8 @@ export class UltraHonkBackend implements Backend, VerifierBackend { proofData: ProofData, numOfPublicInputs: number, ): Promise<{ proofAsFields: string[]; vkAsFields: string[]; vkHash: string }> { - const proof = reconstructProofWithPublicInputsHonk(proofData); + const flattenedPublicInputs = flattenFieldsAsArray(proofData.publicInputs); + const proof = reconstructHonkProof(flattenedPublicInputs, proofData.proof); return this.backend.generateRecursiveProofArtifacts(proof, numOfPublicInputs); } diff --git a/tooling/noir_js_backend_barretenberg/src/verifier.ts b/tooling/noir_js_backend_barretenberg/src/verifier.ts index 885ec80caa8..7a8fe01d3a2 100644 --- a/tooling/noir_js_backend_barretenberg/src/verifier.ts +++ b/tooling/noir_js_backend_barretenberg/src/verifier.ts @@ -1,6 +1,10 @@ import { ProofData } from '@noir-lang/types'; import { flattenFieldsAsArray } from './public_inputs.js'; -import { BackendOptions, BarretenbergVerifier as BarretenbergVerifierInternal } from '@aztec/bb.js'; +import { + BackendOptions, + BarretenbergVerifier as BarretenbergVerifierInternal, + reconstructHonkProof, +} from '@aztec/bb.js'; export class BarretenbergVerifier { private verifier!: BarretenbergVerifierInternal; @@ -39,7 +43,8 @@ export class UltraHonkVerifier { /** @description Verifies a proof */ async verifyProof(proofData: ProofData, verificationKey: Uint8Array): Promise { - const proof = reconstructProofWithPublicInputsHonk(proofData); + const flattenedPublicInputs = flattenFieldsAsArray(proofData.publicInputs); + const proof = reconstructHonkProof(flattenedPublicInputs, proofData.proof); return this.verifier.verifyUltrahonkProof(proof, verificationKey); } @@ -47,21 +52,3 @@ export class UltraHonkVerifier { await this.verifier.destroy(); } } - -const serializedBufferSize = 4; -const fieldByteSize = 32; -const publicInputOffset = 3; -const publicInputsOffsetBytes = publicInputOffset * fieldByteSize; - -export function reconstructProofWithPublicInputsHonk(proofData: ProofData): Uint8Array { - // Flatten publicInputs - const publicInputsConcatenated = flattenFieldsAsArray(proofData.publicInputs); - - const proofStart = proofData.proof.slice(0, publicInputsOffsetBytes + serializedBufferSize); - const proofEnd = proofData.proof.slice(publicInputsOffsetBytes + serializedBufferSize); - - // Concatenate publicInputs and proof - const proofWithPublicInputs = Uint8Array.from([...proofStart, ...publicInputsConcatenated, ...proofEnd]); - - return proofWithPublicInputs; -} From 5c21dd37b6c84699cb95d28fcbef87978913dff9 Mon Sep 17 00:00:00 2001 From: Tom French Date: Wed, 2 Oct 2024 23:48:25 +0100 Subject: [PATCH 2/8] . --- compiler/noirc_evaluator/src/ssa/opt/die.rs | 39 --------------------- 1 file changed, 39 deletions(-) diff --git a/compiler/noirc_evaluator/src/ssa/opt/die.rs b/compiler/noirc_evaluator/src/ssa/opt/die.rs index 21b10e918f9..beca7c41e5c 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/die.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/die.rs @@ -165,45 +165,6 @@ impl Context { false } - fn track_inc_rcs_to_remove( - &self, - instruction_id: InstructionId, - function: &Function, - inc_rcs: &mut HashMap>, - inc_rcs_to_remove: &mut HashSet, - ) { - let instruction = &function.dfg[instruction_id]; - // DIE loops over a block in reverse order, so we insert an RC instruction for possible removal - // when we see a DecrementRc and check whether it was possibly mutated when we see an IncrementRc. - match instruction { - Instruction::IncrementRc { value } => { - if let Some(inc_rc) = pop_rc_for(*value, function, inc_rcs) { - if !inc_rc.possibly_mutated { - inc_rcs_to_remove.insert(inc_rc.id); - inc_rcs_to_remove.insert(instruction_id); - } - } - } - Instruction::DecrementRc { value } => { - let typ = function.dfg.type_of_value(*value); - - // We assume arrays aren't mutated until we find an array_set - let inc_rc = - RcInstruction { id: instruction_id, array: *value, possibly_mutated: false }; - inc_rcs.entry(typ).or_default().push(inc_rc); - } - Instruction::ArraySet { array, .. } => { - let typ = function.dfg.type_of_value(*array); - if let Some(inc_rcs) = inc_rcs.get_mut(&typ) { - for inc_rc in inc_rcs { - inc_rc.possibly_mutated = true; - } - } - } - _ => {} - } - } - /// Returns true if an instruction can be removed. /// /// An instruction can be removed as long as it has no side-effects, and none of its result From c0439cf4a7616d0b3d849aac354535cc9473971a Mon Sep 17 00:00:00 2001 From: Tom French Date: Wed, 2 Oct 2024 23:50:04 +0100 Subject: [PATCH 3/8] . --- compiler/noirc_frontend/src/tests.rs | 57 ------------------- .../noirc_frontend/src/tests/unused_items.rs | 52 ----------------- .../noirc_frontend/src/tests/visibility.rs | 6 -- 3 files changed, 115 deletions(-) diff --git a/compiler/noirc_frontend/src/tests.rs b/compiler/noirc_frontend/src/tests.rs index 5bce82a84f9..f7ef9955550 100644 --- a/compiler/noirc_frontend/src/tests.rs +++ b/compiler/noirc_frontend/src/tests.rs @@ -3193,60 +3193,3 @@ fn trait_unconstrained_methods_typechecked_correctly() { println!("{errors:?}"); assert_eq!(errors.len(), 0); } - -#[test] -fn errors_if_type_alias_aliases_more_private_type() { - let src = r#" - struct Foo {} - pub type Bar = Foo; - - pub fn no_unused_warnings(_b: Bar) { - let _ = Foo {}; - } - - fn main() {} - "#; - - let errors = get_program_errors(src); - assert_eq!(errors.len(), 1); - - let CompilationError::ResolverError(ResolverError::TypeIsMorePrivateThenItem { - typ, item, .. - }) = &errors[0].0 - else { - panic!("Expected an unused item error"); - }; - - assert_eq!(typ, "Foo"); - assert_eq!(item, "Bar"); -} - -#[test] -fn errors_if_type_alias_aliases_more_private_type_in_generic() { - let src = r#" - pub struct Generic { value: T } - - struct Foo {} - pub type Bar = Generic; - - pub fn no_unused_warnings(_b: Bar) { - let _ = Foo {}; - let _ = Generic { value: 1 }; - } - - fn main() {} - "#; - - let errors = get_program_errors(src); - assert_eq!(errors.len(), 1); - - let CompilationError::ResolverError(ResolverError::TypeIsMorePrivateThenItem { - typ, item, .. - }) = &errors[0].0 - else { - panic!("Expected an unused item error"); - }; - - assert_eq!(typ, "Foo"); - assert_eq!(item, "Bar"); -} diff --git a/compiler/noirc_frontend/src/tests/unused_items.rs b/compiler/noirc_frontend/src/tests/unused_items.rs index a4d379b6358..4d8e504b705 100644 --- a/compiler/noirc_frontend/src/tests/unused_items.rs +++ b/compiler/noirc_frontend/src/tests/unused_items.rs @@ -188,58 +188,6 @@ fn errors_on_unused_type_alias() { assert_eq!(item.item_type(), "type alias"); } -#[test] -fn errors_if_type_alias_aliases_more_private_type() { - let src = r#" - struct Foo {} - pub type Bar = Foo; - pub fn no_unused_warnings(_b: Bar) { - let _ = Foo {}; - } - fn main() {} - "#; - - let errors = get_program_errors(src); - assert_eq!(errors.len(), 1); - - let CompilationError::ResolverError(ResolverError::TypeIsMorePrivateThenItem { - typ, item, .. - }) = &errors[0].0 - else { - panic!("Expected an unused item error"); - }; - - assert_eq!(typ, "Foo"); - assert_eq!(item, "Bar"); -} - -#[test] -fn errors_if_type_alias_aliases_more_private_type_in_generic() { - let src = r#" - pub struct Generic { value: T } - struct Foo {} - pub type Bar = Generic; - pub fn no_unused_warnings(_b: Bar) { - let _ = Foo {}; - let _ = Generic { value: 1 }; - } - fn main() {} - "#; - - let errors = get_program_errors(src); - assert_eq!(errors.len(), 1); - - let CompilationError::ResolverError(ResolverError::TypeIsMorePrivateThenItem { - typ, item, .. - }) = &errors[0].0 - else { - panic!("Expected an unused item error"); - }; - - assert_eq!(typ, "Foo"); - assert_eq!(item, "Bar"); -} - #[test] fn warns_on_unused_global() { let src = r#" diff --git a/compiler/noirc_frontend/src/tests/visibility.rs b/compiler/noirc_frontend/src/tests/visibility.rs index e6c2680ea19..bca1c9af829 100644 --- a/compiler/noirc_frontend/src/tests/visibility.rs +++ b/compiler/noirc_frontend/src/tests/visibility.rs @@ -28,17 +28,14 @@ fn errors_once_on_unused_import_that_is_not_accessible() { )) )); } - #[test] fn errors_if_type_alias_aliases_more_private_type() { let src = r#" struct Foo {} pub type Bar = Foo; - pub fn no_unused_warnings(_b: Bar) { let _ = Foo {}; } - fn main() {} "#; @@ -60,15 +57,12 @@ fn errors_if_type_alias_aliases_more_private_type() { fn errors_if_type_alias_aliases_more_private_type_in_generic() { let src = r#" pub struct Generic { value: T } - struct Foo {} pub type Bar = Generic; - pub fn no_unused_warnings(_b: Bar) { let _ = Foo {}; let _ = Generic { value: 1 }; } - fn main() {} "#; From 99fb94c5d13268aeb3744d1e5a0b776e88ae3ffc Mon Sep 17 00:00:00 2001 From: Tom French Date: Wed, 2 Oct 2024 23:50:36 +0100 Subject: [PATCH 4/8] . --- .../verify_honk_proof/Nargo.toml | 6 ----- .../verify_honk_proof/Prover.toml | 4 ---- .../verify_honk_proof/src/main.nr | 23 ------------------- 3 files changed, 33 deletions(-) delete mode 100644 test_programs/execution_success/verify_honk_proof/Nargo.toml delete mode 100644 test_programs/execution_success/verify_honk_proof/Prover.toml delete mode 100644 test_programs/execution_success/verify_honk_proof/src/main.nr diff --git a/test_programs/execution_success/verify_honk_proof/Nargo.toml b/test_programs/execution_success/verify_honk_proof/Nargo.toml deleted file mode 100644 index 8fce1bf44b6..00000000000 --- a/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/test_programs/execution_success/verify_honk_proof/Prover.toml b/test_programs/execution_success/verify_honk_proof/Prover.toml deleted file mode 100644 index 45a84c26eb8..00000000000 --- a/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/test_programs/execution_success/verify_honk_proof/src/main.nr b/test_programs/execution_success/verify_honk_proof/src/main.nr deleted file mode 100644 index 40559b64c7c..00000000000 --- a/test_programs/execution_success/verify_honk_proof/src/main.nr +++ /dev/null @@ -1,23 +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 - ); -} From f727522bb666707c1ecf6c023d8f2d8e8f2b9a8f Mon Sep 17 00:00:00 2001 From: Tom French Date: Wed, 2 Oct 2024 23:55:13 +0100 Subject: [PATCH 5/8] . --- .../src/backend.ts | 36 +++++++++++++++---- .../src/verifier.ts | 27 ++++++++++---- 2 files changed, 49 insertions(+), 14 deletions(-) diff --git a/tooling/noir_js_backend_barretenberg/src/backend.ts b/tooling/noir_js_backend_barretenberg/src/backend.ts index 812a7173ad2..8171a4f6f52 100644 --- a/tooling/noir_js_backend_barretenberg/src/backend.ts +++ b/tooling/noir_js_backend_barretenberg/src/backend.ts @@ -1,7 +1,8 @@ import { acirToUint8Array } from './serialize.js'; import { Backend, CompiledCircuit, ProofData, VerifierBackend } from '@noir-lang/types'; import { deflattenFields, flattenFieldsAsArray } from './public_inputs.js'; -import { reconstructProofWithPublicInputs } from './verifier.js'; +import { reconstructProofWithPublicInputs, reconstructProofWithPublicInputsHonk } from './verifier.js'; +import { BackendOptions, UltraPlonkBackend, UltraHonkBackend as UltraHonkBackendInternal } from '@aztec/bb.js'; import { BackendOptions, reconstructHonkProof, @@ -80,6 +81,12 @@ export class BarretenbergBackend implements Backend, VerifierBackend { } } +// Buffers are prepended with their size. The size takes 4 bytes. +const serializedBufferSize = 4; +const fieldByteSize = 32; +const publicInputOffset = 3; +const publicInputsOffsetBytes = publicInputOffset * fieldByteSize; + export class UltraHonkBackend implements Backend, VerifierBackend { // These type assertions are used so that we don't // have to initialize `api` in the constructor. @@ -97,15 +104,31 @@ export class UltraHonkBackend implements Backend, VerifierBackend { async generateProof(compressedWitness: Uint8Array): Promise { const proofWithPublicInputs = await this.backend.generateProof(gunzip(compressedWitness)); - const { proof, publicInputs: flatPublicInputs } = splitHonkProof(proofWithPublicInputs); - const publicInputs = deflattenFields(flatPublicInputs); + const proofAsStrings = deflattenFields(proofWithPublicInputs.slice(4)); + + const numPublicInputs = Number(proofAsStrings[1]); + + // Account for the serialized buffer size at start + const publicInputsOffset = publicInputsOffsetBytes + serializedBufferSize; + // Get the part before and after the public inputs + const proofStart = proofWithPublicInputs.slice(0, publicInputsOffset); + const publicInputsSplitIndex = numPublicInputs * fieldByteSize; + const proofEnd = proofWithPublicInputs.slice(publicInputsOffset + publicInputsSplitIndex); + // Construct the proof without the public inputs + const proof = new Uint8Array([...proofStart, ...proofEnd]); + + // Fetch the number of public inputs out of the proof string + const publicInputsConcatenated = proofWithPublicInputs.slice( + publicInputsOffset, + publicInputsOffset + publicInputsSplitIndex, + ); + const publicInputs = deflattenFields(publicInputsConcatenated); return { proof, publicInputs }; } async verifyProof(proofData: ProofData): Promise { - const flattenedPublicInputs = flattenFieldsAsArray(proofData.publicInputs); - const proof = reconstructHonkProof(flattenedPublicInputs, proofData.proof); + const proof = reconstructProofWithPublicInputsHonk(proofData); return this.backend.verifyProof(proof); } @@ -118,8 +141,7 @@ export class UltraHonkBackend implements Backend, VerifierBackend { proofData: ProofData, numOfPublicInputs: number, ): Promise<{ proofAsFields: string[]; vkAsFields: string[]; vkHash: string }> { - const flattenedPublicInputs = flattenFieldsAsArray(proofData.publicInputs); - const proof = reconstructHonkProof(flattenedPublicInputs, proofData.proof); + const proof = reconstructProofWithPublicInputsHonk(proofData); return this.backend.generateRecursiveProofArtifacts(proof, numOfPublicInputs); } diff --git a/tooling/noir_js_backend_barretenberg/src/verifier.ts b/tooling/noir_js_backend_barretenberg/src/verifier.ts index 7a8fe01d3a2..885ec80caa8 100644 --- a/tooling/noir_js_backend_barretenberg/src/verifier.ts +++ b/tooling/noir_js_backend_barretenberg/src/verifier.ts @@ -1,10 +1,6 @@ import { ProofData } from '@noir-lang/types'; import { flattenFieldsAsArray } from './public_inputs.js'; -import { - BackendOptions, - BarretenbergVerifier as BarretenbergVerifierInternal, - reconstructHonkProof, -} from '@aztec/bb.js'; +import { BackendOptions, BarretenbergVerifier as BarretenbergVerifierInternal } from '@aztec/bb.js'; export class BarretenbergVerifier { private verifier!: BarretenbergVerifierInternal; @@ -43,8 +39,7 @@ export class UltraHonkVerifier { /** @description Verifies a proof */ async verifyProof(proofData: ProofData, verificationKey: Uint8Array): Promise { - const flattenedPublicInputs = flattenFieldsAsArray(proofData.publicInputs); - const proof = reconstructHonkProof(flattenedPublicInputs, proofData.proof); + const proof = reconstructProofWithPublicInputsHonk(proofData); return this.verifier.verifyUltrahonkProof(proof, verificationKey); } @@ -52,3 +47,21 @@ export class UltraHonkVerifier { await this.verifier.destroy(); } } + +const serializedBufferSize = 4; +const fieldByteSize = 32; +const publicInputOffset = 3; +const publicInputsOffsetBytes = publicInputOffset * fieldByteSize; + +export function reconstructProofWithPublicInputsHonk(proofData: ProofData): Uint8Array { + // Flatten publicInputs + const publicInputsConcatenated = flattenFieldsAsArray(proofData.publicInputs); + + const proofStart = proofData.proof.slice(0, publicInputsOffsetBytes + serializedBufferSize); + const proofEnd = proofData.proof.slice(publicInputsOffsetBytes + serializedBufferSize); + + // Concatenate publicInputs and proof + const proofWithPublicInputs = Uint8Array.from([...proofStart, ...publicInputsConcatenated, ...proofEnd]); + + return proofWithPublicInputs; +} From 0e72516493ada5028ea8244478a69832adc9d177 Mon Sep 17 00:00:00 2001 From: Tom French Date: Wed, 2 Oct 2024 23:55:49 +0100 Subject: [PATCH 6/8] . --- tooling/noir_js_backend_barretenberg/src/backend.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/tooling/noir_js_backend_barretenberg/src/backend.ts b/tooling/noir_js_backend_barretenberg/src/backend.ts index 8171a4f6f52..785b0c73421 100644 --- a/tooling/noir_js_backend_barretenberg/src/backend.ts +++ b/tooling/noir_js_backend_barretenberg/src/backend.ts @@ -1,15 +1,8 @@ import { acirToUint8Array } from './serialize.js'; import { Backend, CompiledCircuit, ProofData, VerifierBackend } from '@noir-lang/types'; -import { deflattenFields, flattenFieldsAsArray } from './public_inputs.js'; +import { deflattenFields } from './public_inputs.js'; import { reconstructProofWithPublicInputs, reconstructProofWithPublicInputsHonk } from './verifier.js'; import { BackendOptions, UltraPlonkBackend, UltraHonkBackend as UltraHonkBackendInternal } from '@aztec/bb.js'; -import { - BackendOptions, - reconstructHonkProof, - splitHonkProof, - UltraPlonkBackend, - UltraHonkBackend as UltraHonkBackendInternal, -} from '@aztec/bb.js'; import { decompressSync as gunzip } from 'fflate'; // This is the number of bytes in a UltraPlonk proof From bf3e754b6b069d6a0a138240ad0c7437cdf18703 Mon Sep 17 00:00:00 2001 From: Tom French Date: Wed, 2 Oct 2024 23:58:08 +0100 Subject: [PATCH 7/8] . --- tooling/nargo_fmt/src/visitor/item.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tooling/nargo_fmt/src/visitor/item.rs b/tooling/nargo_fmt/src/visitor/item.rs index 428f143141f..8ab470bc779 100644 --- a/tooling/nargo_fmt/src/visitor/item.rs +++ b/tooling/nargo_fmt/src/visitor/item.rs @@ -7,7 +7,8 @@ use crate::{ visitor::expr::{format_seq, NewlineMode}, }; use noirc_frontend::ast::{ - ItemVisibility, ModuleDeclaration, NoirFunction, NoirStruct, TraitImplItemKind, Visibility, + ItemVisibility, ModuleDeclaration, NoirFunction, TraitImplItemKind, UnresolvedTypeData, + Visibility, }; use noirc_frontend::{ hir::resolution::errors::Span, @@ -276,7 +277,7 @@ impl super::FmtVisitor<'_> { self.push_rewrite(use_tree, span); self.last_position = span.end(); } - ItemKind::ModuleDecl(ModuleDeclaration { visibility, ident, outer_attributes }) => { + ItemKind::ModuleDecl(ModuleDeclaration { outer_attributes, .. }) => { if !outer_attributes.is_empty() { self.push_rewrite(self.slice(span).to_string(), span); self.last_position = span.end(); From d918a3c408ea4ab4f43593100df9af3c5bf17e5f Mon Sep 17 00:00:00 2001 From: Tom French Date: Thu, 3 Oct 2024 00:00:06 +0100 Subject: [PATCH 8/8] . --- tooling/nargo_fmt/src/visitor/item.rs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/tooling/nargo_fmt/src/visitor/item.rs b/tooling/nargo_fmt/src/visitor/item.rs index 8ab470bc779..b71ea801752 100644 --- a/tooling/nargo_fmt/src/visitor/item.rs +++ b/tooling/nargo_fmt/src/visitor/item.rs @@ -7,8 +7,7 @@ use crate::{ visitor::expr::{format_seq, NewlineMode}, }; use noirc_frontend::ast::{ - ItemVisibility, ModuleDeclaration, NoirFunction, TraitImplItemKind, UnresolvedTypeData, - Visibility, + ItemVisibility, NoirFunction, TraitImplItemKind, UnresolvedTypeData, Visibility, }; use noirc_frontend::{ hir::resolution::errors::Span, @@ -277,18 +276,12 @@ impl super::FmtVisitor<'_> { self.push_rewrite(use_tree, span); self.last_position = span.end(); } - ItemKind::ModuleDecl(ModuleDeclaration { outer_attributes, .. }) => { - if !outer_attributes.is_empty() { - self.push_rewrite(self.slice(span).to_string(), span); - self.last_position = span.end(); - continue; - } - } ItemKind::Struct(_) | ItemKind::Trait(_) | ItemKind::TypeAlias(_) | ItemKind::Global(..) + | ItemKind::ModuleDecl(_) | ItemKind::InnerAttribute(_) => { self.push_rewrite(self.slice(span).to_string(), span); self.last_position = span.end();