From a01b3ac6dacf7f583f6e51afd0ea99afe47cea9c Mon Sep 17 00:00:00 2001 From: AztecBot Date: Mon, 23 Sep 2024 19:22:19 +0000 Subject: [PATCH] [1 changes] fix: handle parenthesized expressions in array length (https://github.com/noir-lang/noir/pull/6132) chore: remove bubble_up_constrains (https://github.com/noir-lang/noir/pull/6127) fix: Consider constants as used values to keep their rc ops (https://github.com/noir-lang/noir/pull/6122) --- .noir-sync-commit | 2 +- noir/noir-repo/.release-please-manifest.json | 4 +- noir/noir-repo/CHANGELOG.md | 207 ++++ noir/noir-repo/Cargo.lock | 58 +- noir/noir-repo/Cargo.toml | 16 +- noir/noir-repo/acvm-repo/CHANGELOG.md | 90 ++ noir/noir-repo/acvm-repo/acir/Cargo.toml | 2 +- .../acir/src/circuit/black_box_functions.rs | 10 +- .../noir-repo/acvm-repo/acir_field/Cargo.toml | 2 +- noir/noir-repo/acvm-repo/acvm/Cargo.toml | 2 +- noir/noir-repo/acvm-repo/acvm_js/Cargo.toml | 2 +- noir/noir-repo/acvm-repo/acvm_js/build.sh | 2 +- noir/noir-repo/acvm-repo/acvm_js/package.json | 2 +- .../acvm-repo/blackbox_solver/Cargo.toml | 2 +- .../bn254_blackbox_solver/Cargo.toml | 2 +- noir/noir-repo/acvm-repo/brillig/Cargo.toml | 2 +- .../noir-repo/acvm-repo/brillig_vm/Cargo.toml | 2 +- .../aztec_macros/src/transforms/functions.rs | 44 +- .../src/transforms/note_interface.rs | 1 + .../aztec_macros/src/transforms/storage.rs | 9 +- .../aztec_macros/src/utils/hir_utils.rs | 6 +- .../aztec_macros/src/utils/parse_utils.rs | 26 +- .../compiler/noirc_driver/src/abi_gen.rs | 2 +- .../compiler/noirc_errors/src/lib.rs | 11 +- .../compiler/noirc_errors/src/reporter.rs | 17 +- .../src/brillig/brillig_gen/brillig_block.rs | 24 +- .../src/brillig/brillig_ir/codegen_stack.rs | 286 +++++- .../compiler/noirc_evaluator/src/errors.rs | 6 +- .../src/ssa/acir_gen/acir_ir/acir_variable.rs | 10 + .../noirc_evaluator/src/ssa/acir_gen/mod.rs | 75 +- .../noirc_evaluator/src/ssa/ir/function.rs | 11 + .../src/ssa/ir/function_inserter.rs | 8 + .../noirc_evaluator/src/ssa/opt/array_set.rs | 15 +- .../src/ssa/opt/bubble_up_constrains.rs | 152 --- .../noirc_evaluator/src/ssa/opt/die.rs | 4 + .../src/ssa/opt/flatten_cfg.rs | 54 +- .../noirc_evaluator/src/ssa/opt/mem2reg.rs | 939 +++++++++++++++++- .../noirc_evaluator/src/ssa/opt/mod.rs | 1 - .../noirc_evaluator/src/ssa/opt/rc.rs | 19 +- .../noirc_frontend/src/ast/expression.rs | 31 +- .../compiler/noirc_frontend/src/ast/mod.rs | 14 + .../noirc_frontend/src/ast/statement.rs | 67 +- .../noirc_frontend/src/ast/structure.rs | 3 +- .../compiler/noirc_frontend/src/ast/traits.rs | 28 +- .../noirc_frontend/src/ast/visitor.rs | 47 +- .../noirc_frontend/src/elaborator/comptime.rs | 5 +- .../src/elaborator/expressions.rs | 133 ++- .../noirc_frontend/src/elaborator/mod.rs | 69 +- .../noirc_frontend/src/elaborator/patterns.rs | 46 +- .../noirc_frontend/src/elaborator/scope.rs | 11 +- .../src/elaborator/statements.rs | 54 +- .../noirc_frontend/src/elaborator/traits.rs | 25 +- .../noirc_frontend/src/elaborator/types.rs | 320 +++--- .../src/hir/comptime/display.rs | 865 ++++++++++++++++ .../noirc_frontend/src/hir/comptime/errors.rs | 19 +- .../src/hir/comptime/hir_to_display_ast.rs | 54 +- .../src/hir/comptime/interpreter.rs | 61 +- .../src/hir/comptime/interpreter/builtin.rs | 324 ++++-- .../interpreter/builtin/builtin_helpers.rs | 34 +- .../noirc_frontend/src/hir/comptime/mod.rs | 1 + .../noirc_frontend/src/hir/comptime/value.rs | 613 +----------- .../src/hir/def_collector/dc_mod.rs | 38 +- .../src/hir/def_map/module_data.rs | 18 +- .../src/hir/resolution/errors.rs | 22 +- .../src/hir/type_check/errors.rs | 25 +- .../src/hir/type_check/generics.rs | 24 +- .../noirc_frontend/src/hir_def/expr.rs | 19 +- .../noirc_frontend/src/hir_def/function.rs | 4 +- .../noirc_frontend/src/hir_def/types.rs | 358 +++---- .../src/hir_def/types/arithmetic.rs | 52 +- .../noirc_frontend/src/lexer/lexer.rs | 6 +- .../noirc_frontend/src/lexer/token.rs | 28 +- .../compiler/noirc_frontend/src/locations.rs | 3 +- .../src/monomorphization/errors.rs | 7 +- .../src/monomorphization/mod.rs | 10 +- .../noirc_frontend/src/node_interner.rs | 90 +- .../noirc_frontend/src/parser/errors.rs | 8 +- .../noirc_frontend/src/parser/parser.rs | 54 +- .../noirc_frontend/src/parser/parser.rs:28:9 | 45 - .../src/parser/parser/assertion.rs | 83 +- .../src/parser/parser/function.rs | 80 +- .../noirc_frontend/src/parser/parser/path.rs | 34 +- .../src/parser/parser/primitives.rs | 22 +- .../src/parser/parser/structs.rs | 13 +- .../src/parser/parser/traits.rs | 56 +- .../noirc_frontend/src/parser/parser/types.rs | 25 +- .../compiler/noirc_frontend/src/tests.rs | 416 ++++++-- .../noirc_frontend/src/usage_tracker.rs | 7 +- noir/noir-repo/compiler/wasm/package.json | 2 +- noir/noir-repo/cspell.json | 1 + .../docs/docs/noir/concepts/comptime.md | 11 + .../docs/noir/concepts/data_types/arrays.md | 1 - .../docs/noir/concepts/data_types/slices.mdx | 2 +- .../docs/noir/concepts/data_types/structs.md | 12 + .../docs/docs/noir/concepts/generics.md | 63 +- .../docs/docs/noir/concepts/globals.md | 2 +- .../docs/docs/noir/concepts/traits.md | 12 +- .../cryptographic_primitives/hashes.mdx | 2 +- .../noir/standard_library/meta/ctstring.md | 71 ++ .../docs/noir/standard_library/meta/expr.md | 34 + .../version-v0.17.0/examples/merkle-proof.mdx | 48 - .../getting_started/00_nargo_installation.md | 249 ----- .../getting_started/01_hello_world.md | 147 --- .../getting_started/02_breakdown.md | 198 ---- .../versioned_docs/version-v0.17.0/index.md | 99 -- .../language_concepts/01_functions.md | 225 ----- .../language_concepts/02_control_flow.md | 44 - .../language_concepts/03_ops.md | 97 -- .../language_concepts/04_assert.md | 26 - .../language_concepts/05_unconstrained.md | 96 -- .../language_concepts/06_generics.md | 113 --- .../language_concepts/07_mutability.md | 92 -- .../language_concepts/08_lambdas.md | 80 -- .../language_concepts/09_comments.md | 32 - .../language_concepts/10_distinct.md | 63 -- .../language_concepts/11_shadowing.md | 43 - .../language_concepts/data_types.md | 96 -- .../language_concepts/data_types/00_fields.md | 165 --- .../data_types/01_integers.md | 33 - .../data_types/02_booleans.md | 30 - .../data_types/03_strings.md | 63 -- .../language_concepts/data_types/04_arrays.md | 244 ----- .../data_types/05_slices.mdx | 146 --- .../data_types/06_vectors.mdx | 172 ---- .../language_concepts/data_types/07_tuples.md | 47 - .../data_types/08_structs.md | 73 -- .../data_types/09_references.md | 22 - .../data_types/10_function_types.md | 25 - .../version-v0.17.0/migration_notes.md | 83 -- .../crates_and_packages.md | 42 - .../modules_packages_crates/dependencies.md | 123 --- .../modules_packages_crates/modules.md | 104 -- .../modules_packages_crates/workspaces.md | 41 - .../version-v0.17.0/nargo/01_commands.md | 250 ----- .../version-v0.17.0/nargo/02_testing.md | 61 -- .../nargo/03_solidity_verifier.md | 129 --- .../nargo/04_language_server.md | 42 - .../getting_started/01_tiny_noir_app.md | 256 ----- .../version-v0.17.0/noir_js/noir_js.md | 36 - .../noir_js/reference/01_noirjs.md | 143 --- .../noir_js/reference/02_bb_backend.md | 272 ----- .../standard_library/black_box_fns.md | 45 - .../cryptographic_primitives.md | 14 - .../cryptographic_primitives/00_hashes.mdx | 146 --- .../cryptographic_primitives/01_scalar.mdx | 27 - .../cryptographic_primitives/02_schnorr.mdx | 37 - .../03_ecdsa_sig_verification.mdx | 45 - .../04_ec_primitives.md | 101 -- .../cryptographic_primitives/05_eddsa.mdx | 17 - .../standard_library/logging.md | 62 -- .../standard_library/merkle_trees.md | 58 -- .../standard_library/options.md | 99 -- .../standard_library/recursion.md | 96 -- .../standard_library/zeroed.md | 25 - .../version-v0.19.0/examples/merkle-proof.mdx | 48 - .../getting_started/00_nargo_installation.md | 249 ----- .../getting_started/01_hello_world.md | 147 --- .../getting_started/02_breakdown.md | 198 ---- .../versioned_docs/version-v0.19.0/index.md | 100 -- .../language_concepts/01_functions.md | 225 ----- .../language_concepts/02_control_flow.md | 44 - .../language_concepts/03_ops.md | 97 -- .../language_concepts/04_assert.md | 26 - .../language_concepts/05_unconstrained.md | 96 -- .../language_concepts/06_generics.md | 109 -- .../language_concepts/07_mutability.md | 92 -- .../language_concepts/08_lambdas.md | 80 -- .../language_concepts/09_comments.md | 32 - .../language_concepts/10_distinct.md | 63 -- .../language_concepts/11_shadowing.md | 43 - .../language_concepts/data_types.md | 96 -- .../language_concepts/data_types/00_fields.md | 165 --- .../data_types/01_integers.md | 112 --- .../data_types/02_booleans.md | 30 - .../data_types/03_strings.md | 63 -- .../language_concepts/data_types/04_arrays.md | 244 ----- .../data_types/05_slices.mdx | 146 --- .../data_types/06_vectors.mdx | 172 ---- .../language_concepts/data_types/07_tuples.md | 47 - .../data_types/08_structs.md | 73 -- .../data_types/09_references.md | 22 - .../data_types/10_function_types.md | 25 - .../version-v0.19.0/migration_notes.md | 91 -- .../crates_and_packages.md | 42 - .../modules_packages_crates/dependencies.md | 123 --- .../modules_packages_crates/modules.md | 104 -- .../modules_packages_crates/workspaces.md | 41 - .../version-v0.19.0/nargo/01_commands.md | 250 ----- .../version-v0.19.0/nargo/02_testing.md | 61 -- .../nargo/03_solidity_verifier.md | 129 --- .../nargo/04_language_server.md | 42 - .../getting_started/01_tiny_noir_app.md | 260 ----- .../version-v0.19.0/noir_js/noir_js.md | 36 - .../noir_js/reference/01_noirjs.md | 147 --- .../noir_js/reference/02_bb_backend.md | 272 ----- .../classes/BarretenbergBackend.md | 185 ---- .../reference/backend_barretenberg/index.md | 27 - .../interfaces/Backend.md | 132 --- .../type-aliases/BackendOptions.md | 19 - .../type-aliases/CompiledCircuit.md | 20 - .../type-aliases/ProofData.md | 20 - .../backend_barretenberg/typedoc-sidebar.cjs | 4 - .../noir_js/reference/noir_js/classes/Noir.md | 131 --- .../functions/ecdsa_secp256k1_verify.md | 29 - .../noir_js/reference/noir_js/index.md | 36 - .../noir_js/type-aliases/CompiledCircuit.md | 20 - .../noir_js/type-aliases/ProofData.md | 20 - .../reference/noir_js/typedoc-sidebar.cjs | 4 - .../standard_library/black_box_fns.md | 46 - .../cryptographic_primitives.md | 14 - .../cryptographic_primitives/00_hashes.mdx | 167 ---- .../cryptographic_primitives/01_scalar.mdx | 27 - .../cryptographic_primitives/02_schnorr.mdx | 37 - .../03_ecdsa_sig_verification.mdx | 45 - .../04_ec_primitives.md | 101 -- .../cryptographic_primitives/05_eddsa.mdx | 17 - .../standard_library/logging.md | 62 -- .../standard_library/merkle_trees.md | 58 -- .../standard_library/options.md | 99 -- .../standard_library/recursion.md | 96 -- .../standard_library/zeroed.md | 25 - .../version-v0.19.1/examples/merkle-proof.mdx | 48 - .../getting_started/00_nargo_installation.md | 249 ----- .../getting_started/01_hello_world.md | 147 --- .../getting_started/02_breakdown.md | 198 ---- .../versioned_docs/version-v0.19.1/index.md | 100 -- .../language_concepts/01_functions.md | 225 ----- .../language_concepts/02_control_flow.md | 44 - .../language_concepts/03_ops.md | 97 -- .../language_concepts/04_assert.md | 26 - .../language_concepts/05_unconstrained.md | 96 -- .../language_concepts/06_generics.md | 113 --- .../language_concepts/07_mutability.md | 92 -- .../language_concepts/08_lambdas.md | 80 -- .../language_concepts/09_comments.md | 32 - .../language_concepts/10_distinct.md | 63 -- .../language_concepts/11_shadowing.md | 43 - .../language_concepts/data_types.md | 96 -- .../language_concepts/data_types/00_fields.md | 165 --- .../data_types/01_integers.md | 112 --- .../data_types/02_booleans.md | 30 - .../data_types/03_strings.md | 63 -- .../language_concepts/data_types/04_arrays.md | 244 ----- .../data_types/05_slices.mdx | 146 --- .../data_types/06_vectors.mdx | 172 ---- .../language_concepts/data_types/07_tuples.md | 47 - .../data_types/08_structs.md | 69 -- .../data_types/09_references.md | 22 - .../data_types/10_function_types.md | 25 - .../version-v0.19.1/migration_notes.md | 91 -- .../crates_and_packages.md | 42 - .../modules_packages_crates/dependencies.md | 123 --- .../modules_packages_crates/modules.md | 104 -- .../modules_packages_crates/workspaces.md | 41 - .../version-v0.19.1/nargo/01_commands.md | 250 ----- .../version-v0.19.1/nargo/02_testing.md | 61 -- .../nargo/03_solidity_verifier.md | 129 --- .../nargo/04_language_server.md | 42 - .../getting_started/01_tiny_noir_app.md | 260 ----- .../version-v0.19.1/noir_js/noir_js.md | 36 - .../classes/BarretenbergBackend.md | 185 ---- .../reference/backend_barretenberg/index.md | 27 - .../interfaces/Backend.md | 132 --- .../type-aliases/BackendOptions.md | 19 - .../type-aliases/CompiledCircuit.md | 20 - .../type-aliases/ProofData.md | 20 - .../backend_barretenberg/typedoc-sidebar.cjs | 4 - .../noir_js/reference/noir_js/.nojekyll | 1 - .../noir_js/reference/noir_js/classes/Noir.md | 131 --- .../reference/noir_js/functions/and.md | 22 - .../reference/noir_js/functions/blake2s256.md | 21 - .../functions/ecdsa_secp256k1_verify.md | 29 - .../functions/ecdsa_secp256r1_verify.md | 28 - .../reference/noir_js/functions/keccak256.md | 21 - .../reference/noir_js/functions/sha256.md | 21 - .../reference/noir_js/functions/xor.md | 22 - .../noir_js/reference/noir_js/index.md | 36 - .../noir_js/type-aliases/CompiledCircuit.md | 20 - .../type-aliases/ForeignCallHandler.md | 24 - .../noir_js/type-aliases/ForeignCallInput.md | 9 - .../noir_js/type-aliases/ForeignCallOutput.md | 9 - .../noir_js/type-aliases/ProofData.md | 20 - .../noir_js/type-aliases/WitnessMap.md | 9 - .../reference/noir_js/typedoc-sidebar.cjs | 4 - .../standard_library/black_box_fns.md | 46 - .../cryptographic_primitives.md | 14 - .../cryptographic_primitives/00_hashes.mdx | 167 ---- .../cryptographic_primitives/01_scalar.mdx | 27 - .../cryptographic_primitives/02_schnorr.mdx | 37 - .../03_ecdsa_sig_verification.mdx | 45 - .../04_ec_primitives.md | 101 -- .../cryptographic_primitives/05_eddsa.mdx | 17 - .../standard_library/logging.md | 62 -- .../standard_library/merkle_trees.md | 58 -- .../standard_library/options.md | 99 -- .../standard_library/recursion.md | 96 -- .../standard_library/zeroed.md | 25 - .../version-v0.19.2/examples/merkle-proof.mdx | 48 - .../getting_started/00_nargo_installation.md | 249 ----- .../getting_started/01_hello_world.md | 147 --- .../getting_started/02_breakdown.md | 198 ---- .../versioned_docs/version-v0.19.2/index.md | 100 -- .../language_concepts/01_functions.md | 225 ----- .../language_concepts/02_control_flow.md | 44 - .../language_concepts/03_ops.md | 97 -- .../language_concepts/04_assert.md | 26 - .../language_concepts/05_unconstrained.md | 96 -- .../language_concepts/06_generics.md | 113 --- .../language_concepts/07_mutability.md | 92 -- .../language_concepts/08_lambdas.md | 80 -- .../language_concepts/09_comments.md | 32 - .../language_concepts/10_distinct.md | 63 -- .../language_concepts/11_shadowing.md | 43 - .../language_concepts/data_types.md | 96 -- .../language_concepts/data_types/00_fields.md | 165 --- .../data_types/01_integers.md | 112 --- .../data_types/02_booleans.md | 30 - .../data_types/03_strings.md | 63 -- .../language_concepts/data_types/04_arrays.md | 244 ----- .../data_types/05_slices.mdx | 146 --- .../data_types/06_vectors.mdx | 172 ---- .../language_concepts/data_types/07_tuples.md | 47 - .../data_types/08_structs.md | 69 -- .../data_types/09_references.md | 22 - .../data_types/10_function_types.md | 25 - .../version-v0.19.2/migration_notes.md | 91 -- .../crates_and_packages.md | 42 - .../modules_packages_crates/dependencies.md | 123 --- .../modules_packages_crates/modules.md | 104 -- .../modules_packages_crates/workspaces.md | 41 - .../version-v0.19.2/nargo/01_commands.md | 250 ----- .../version-v0.19.2/nargo/02_testing.md | 61 -- .../nargo/03_solidity_verifier.md | 129 --- .../nargo/04_language_server.md | 42 - .../getting_started/01_tiny_noir_app.md | 260 ----- .../version-v0.19.2/noir_js/noir_js.md | 36 - .../reference/backend_barretenberg/.nojekyll | 1 - .../classes/BarretenbergBackend.md | 185 ---- .../reference/backend_barretenberg/index.md | 27 - .../interfaces/Backend.md | 132 --- .../type-aliases/BackendOptions.md | 19 - .../type-aliases/CompiledCircuit.md | 20 - .../type-aliases/ProofData.md | 20 - .../backend_barretenberg/typedoc-sidebar.cjs | 4 - .../noir_js/reference/noir_js/.nojekyll | 1 - .../noir_js/reference/noir_js/classes/Noir.md | 131 --- .../reference/noir_js/functions/and.md | 22 - .../reference/noir_js/functions/blake2s256.md | 21 - .../functions/ecdsa_secp256k1_verify.md | 29 - .../functions/ecdsa_secp256r1_verify.md | 28 - .../reference/noir_js/functions/keccak256.md | 21 - .../reference/noir_js/functions/sha256.md | 21 - .../reference/noir_js/functions/xor.md | 22 - .../noir_js/reference/noir_js/index.md | 36 - .../noir_js/type-aliases/CompiledCircuit.md | 20 - .../type-aliases/ForeignCallHandler.md | 24 - .../noir_js/type-aliases/ForeignCallInput.md | 9 - .../noir_js/type-aliases/ForeignCallOutput.md | 9 - .../noir_js/type-aliases/ProofData.md | 20 - .../noir_js/type-aliases/WitnessMap.md | 9 - .../reference/noir_js/typedoc-sidebar.cjs | 4 - .../standard_library/black_box_fns.md | 46 - .../cryptographic_primitives.md | 14 - .../cryptographic_primitives/00_hashes.mdx | 167 ---- .../cryptographic_primitives/01_scalar.mdx | 27 - .../cryptographic_primitives/02_schnorr.mdx | 37 - .../03_ecdsa_sig_verification.mdx | 45 - .../04_ec_primitives.md | 101 -- .../cryptographic_primitives/05_eddsa.mdx | 17 - .../standard_library/logging.md | 62 -- .../standard_library/merkle_trees.md | 58 -- .../standard_library/options.md | 99 -- .../standard_library/recursion.md | 96 -- .../standard_library/zeroed.md | 25 - .../version-v0.19.3/examples/merkle-proof.mdx | 48 - .../getting_started/00_nargo_installation.md | 249 ----- .../getting_started/01_hello_world.md | 147 --- .../getting_started/02_breakdown.md | 198 ---- .../versioned_docs/version-v0.19.3/index.md | 100 -- .../language_concepts/01_functions.md | 225 ----- .../language_concepts/02_control_flow.md | 44 - .../language_concepts/03_ops.md | 97 -- .../language_concepts/04_assert.md | 26 - .../language_concepts/05_unconstrained.md | 96 -- .../language_concepts/06_generics.md | 113 --- .../language_concepts/07_mutability.md | 92 -- .../language_concepts/08_lambdas.md | 80 -- .../language_concepts/09_comments.md | 32 - .../language_concepts/10_distinct.md | 63 -- .../language_concepts/11_shadowing.md | 43 - .../language_concepts/data_types.md | 96 -- .../language_concepts/data_types/00_fields.md | 165 --- .../data_types/01_integers.md | 112 --- .../data_types/02_booleans.md | 30 - .../data_types/03_strings.md | 63 -- .../language_concepts/data_types/04_arrays.md | 244 ----- .../data_types/05_slices.mdx | 146 --- .../data_types/06_vectors.mdx | 172 ---- .../language_concepts/data_types/07_tuples.md | 47 - .../data_types/08_structs.md | 69 -- .../data_types/09_references.md | 22 - .../data_types/10_function_types.md | 25 - .../version-v0.19.3/migration_notes.md | 91 -- .../crates_and_packages.md | 42 - .../modules_packages_crates/dependencies.md | 123 --- .../modules_packages_crates/modules.md | 104 -- .../modules_packages_crates/workspaces.md | 41 - .../version-v0.19.3/nargo/01_commands.md | 250 ----- .../version-v0.19.3/nargo/02_testing.md | 61 -- .../nargo/03_solidity_verifier.md | 129 --- .../nargo/04_language_server.md | 42 - .../getting_started/01_tiny_noir_app.md | 260 ----- .../version-v0.19.3/noir_js/noir_js.md | 36 - .../reference/backend_barretenberg/.nojekyll | 1 - .../classes/BarretenbergBackend.md | 185 ---- .../reference/backend_barretenberg/index.md | 27 - .../interfaces/Backend.md | 132 --- .../type-aliases/BackendOptions.md | 19 - .../type-aliases/CompiledCircuit.md | 20 - .../type-aliases/ProofData.md | 20 - .../backend_barretenberg/typedoc-sidebar.cjs | 4 - .../noir_js/reference/noir_js/.nojekyll | 1 - .../noir_js/reference/noir_js/classes/Noir.md | 131 --- .../reference/noir_js/functions/and.md | 22 - .../reference/noir_js/functions/blake2s256.md | 21 - .../functions/ecdsa_secp256k1_verify.md | 29 - .../functions/ecdsa_secp256r1_verify.md | 28 - .../reference/noir_js/functions/keccak256.md | 21 - .../reference/noir_js/functions/sha256.md | 21 - .../reference/noir_js/functions/xor.md | 22 - .../noir_js/reference/noir_js/index.md | 36 - .../noir_js/type-aliases/CompiledCircuit.md | 20 - .../type-aliases/ForeignCallHandler.md | 24 - .../noir_js/type-aliases/ForeignCallInput.md | 9 - .../noir_js/type-aliases/ForeignCallOutput.md | 9 - .../noir_js/type-aliases/ProofData.md | 20 - .../noir_js/type-aliases/WitnessMap.md | 9 - .../reference/noir_js/typedoc-sidebar.cjs | 4 - .../standard_library/black_box_fns.md | 46 - .../cryptographic_primitives.md | 14 - .../cryptographic_primitives/00_hashes.mdx | 167 ---- .../cryptographic_primitives/01_scalar.mdx | 27 - .../cryptographic_primitives/02_schnorr.mdx | 37 - .../03_ecdsa_sig_verification.mdx | 45 - .../04_ec_primitives.md | 101 -- .../cryptographic_primitives/05_eddsa.mdx | 17 - .../standard_library/logging.md | 62 -- .../standard_library/merkle_trees.md | 58 -- .../standard_library/options.md | 99 -- .../standard_library/recursion.md | 96 -- .../standard_library/zeroed.md | 25 - .../version-v0.19.4/examples/merkle-proof.mdx | 48 - .../getting_started/00_nargo_installation.md | 249 ----- .../getting_started/01_hello_world.md | 147 --- .../getting_started/02_breakdown.md | 198 ---- .../versioned_docs/version-v0.19.4/index.md | 100 -- .../language_concepts/01_functions.md | 225 ----- .../language_concepts/02_control_flow.md | 44 - .../language_concepts/03_ops.md | 97 -- .../language_concepts/04_assert.md | 26 - .../language_concepts/05_unconstrained.md | 96 -- .../language_concepts/06_generics.md | 113 --- .../language_concepts/07_mutability.md | 92 -- .../language_concepts/08_lambdas.md | 80 -- .../language_concepts/09_comments.md | 32 - .../language_concepts/10_distinct.md | 63 -- .../language_concepts/11_shadowing.md | 43 - .../language_concepts/data_types.md | 96 -- .../language_concepts/data_types/00_fields.md | 165 --- .../data_types/01_integers.md | 112 --- .../data_types/02_booleans.md | 30 - .../data_types/03_strings.md | 88 -- .../language_concepts/data_types/04_arrays.md | 244 ----- .../data_types/05_slices.mdx | 146 --- .../data_types/06_vectors.mdx | 172 ---- .../language_concepts/data_types/07_tuples.md | 47 - .../data_types/08_structs.md | 69 -- .../data_types/09_references.md | 22 - .../data_types/10_function_types.md | 25 - .../version-v0.19.4/migration_notes.md | 91 -- .../crates_and_packages.md | 42 - .../modules_packages_crates/dependencies.md | 123 --- .../modules_packages_crates/modules.md | 104 -- .../modules_packages_crates/workspaces.md | 41 - .../version-v0.19.4/nargo/01_commands.md | 250 ----- .../version-v0.19.4/nargo/02_testing.md | 61 -- .../nargo/03_solidity_verifier.md | 129 --- .../nargo/04_language_server.md | 42 - .../getting_started/01_tiny_noir_app.md | 260 ----- .../version-v0.19.4/noir_js/noir_js.md | 36 - .../reference/backend_barretenberg/.nojekyll | 1 - .../classes/BarretenbergBackend.md | 185 ---- .../reference/backend_barretenberg/index.md | 45 - .../interfaces/Backend.md | 132 --- .../type-aliases/BackendOptions.md | 19 - .../type-aliases/CompiledCircuit.md | 20 - .../type-aliases/ProofData.md | 20 - .../backend_barretenberg/typedoc-sidebar.cjs | 4 - .../noir_js/reference/noir_js/.nojekyll | 1 - .../noir_js/reference/noir_js/classes/Noir.md | 131 --- .../reference/noir_js/functions/and.md | 22 - .../reference/noir_js/functions/blake2s256.md | 21 - .../functions/ecdsa_secp256k1_verify.md | 29 - .../functions/ecdsa_secp256r1_verify.md | 28 - .../reference/noir_js/functions/keccak256.md | 21 - .../reference/noir_js/functions/sha256.md | 21 - .../reference/noir_js/functions/xor.md | 22 - .../noir_js/reference/noir_js/index.md | 37 - .../noir_js/type-aliases/CompiledCircuit.md | 20 - .../type-aliases/ForeignCallHandler.md | 24 - .../noir_js/type-aliases/ForeignCallInput.md | 9 - .../noir_js/type-aliases/ForeignCallOutput.md | 9 - .../noir_js/type-aliases/InputMap.md | 13 - .../noir_js/type-aliases/ProofData.md | 20 - .../noir_js/type-aliases/WitnessMap.md | 9 - .../reference/noir_js/typedoc-sidebar.cjs | 4 - .../standard_library/black_box_fns.md | 46 - .../cryptographic_primitives.md | 14 - .../cryptographic_primitives/00_hashes.mdx | 167 ---- .../cryptographic_primitives/01_scalar.mdx | 27 - .../cryptographic_primitives/02_schnorr.mdx | 37 - .../03_ecdsa_sig_verification.mdx | 45 - .../04_ec_primitives.md | 101 -- .../cryptographic_primitives/05_eddsa.mdx | 17 - .../standard_library/logging.md | 62 -- .../standard_library/merkle_trees.md | 58 -- .../standard_library/options.md | 99 -- .../standard_library/recursion.md | 96 -- .../standard_library/zeroed.md | 25 - .../explainers/explainer-recursion.md | 175 ---- .../explanations/noir/traits.md | 348 ------- .../explanations/standard_library/traits.md | 140 --- .../getting_started/create_a_project.md | 142 --- .../getting_started/installation/index.md | 45 - .../installation/other_install_methods.md | 190 ---- .../getting_started/project_breakdown.md | 199 ---- .../getting_started/tooling/_category_.json | 6 - .../getting_started/tooling/index.md | 29 - .../how_to/how-to-recursion.md | 184 ---- .../version-v0.22.0/how_to/merkle-proof.mdx | 48 - .../how_to/solidity_verifier.md | 131 --- .../versioned_docs/version-v0.22.0/index.md | 84 -- .../version-v0.22.0/migration_notes.md | 105 -- .../modules_packages_crates/dependencies.md | 124 --- .../noir/standard_library/black_box_fns.md | 46 - .../cryptographic_primitives/ec_primitives.md | 102 -- .../ecdsa_sig_verification.mdx | 46 - .../cryptographic_primitives/eddsa.mdx | 18 - .../cryptographic_primitives/hashes.mdx | 168 ---- .../cryptographic_primitives/scalar.mdx | 28 - .../cryptographic_primitives/schnorr.mdx | 38 - .../noir/standard_library/logging.md | 77 -- .../noir/standard_library/merkle_trees.md | 58 -- .../noir/standard_library/options.md | 99 -- .../noir/standard_library/recursion.md | 90 -- .../noir/standard_library/zeroed.md | 25 - .../noir/syntax/_category_.json | 6 - .../version-v0.22.0/noir/syntax/assert.md | 27 - .../version-v0.22.0/noir/syntax/comments.md | 33 - .../noir/syntax/control_flow.md | 45 - .../version-v0.22.0/noir/syntax/data_bus.md | 21 - .../noir/syntax/data_types/arrays.md | 245 ----- .../noir/syntax/data_types/booleans.md | 31 - .../noir/syntax/data_types/fields.md | 166 ---- .../noir/syntax/data_types/index.md | 96 -- .../noir/syntax/data_types/integers.md | 113 --- .../noir/syntax/data_types/slices.mdx | 147 --- .../noir/syntax/data_types/strings.md | 80 -- .../noir/syntax/data_types/vectors.mdx | 173 ---- .../version-v0.22.0/noir/syntax/distinct.md | 64 -- .../version-v0.22.0/noir/syntax/functions.md | 226 ----- .../version-v0.22.0/noir/syntax/generics.md | 114 --- .../version-v0.22.0/noir/syntax/lambdas.md | 81 -- .../version-v0.22.0/noir/syntax/mutability.md | 93 -- .../version-v0.22.0/noir/syntax/ops.md | 98 -- .../version-v0.22.0/noir/syntax/shadowing.md | 44 - .../noir/syntax/unconstrained.md | 95 -- .../NoirJS/backend_barretenberg/.nojekyll | 1 - .../classes/BarretenbergBackend.md | 185 ---- .../NoirJS/backend_barretenberg/index.md | 45 - .../interfaces/Backend.md | 132 --- .../type-aliases/BackendOptions.md | 19 - .../type-aliases/CompiledCircuit.md | 20 - .../type-aliases/ProofData.md | 20 - .../backend_barretenberg/typedoc-sidebar.cjs | 4 - .../reference/NoirJS/noir_js/.nojekyll | 1 - .../reference/NoirJS/noir_js/classes/Noir.md | 132 --- .../reference/NoirJS/noir_js/functions/and.md | 22 - .../NoirJS/noir_js/functions/blake2s256.md | 21 - .../functions/ecdsa_secp256k1_verify.md | 29 - .../functions/ecdsa_secp256r1_verify.md | 28 - .../NoirJS/noir_js/functions/keccak256.md | 21 - .../NoirJS/noir_js/functions/sha256.md | 21 - .../reference/NoirJS/noir_js/functions/xor.md | 22 - .../reference/NoirJS/noir_js/index.md | 37 - .../noir_js/type-aliases/CompiledCircuit.md | 20 - .../type-aliases/ForeignCallHandler.md | 24 - .../noir_js/type-aliases/ForeignCallInput.md | 9 - .../noir_js/type-aliases/ForeignCallOutput.md | 9 - .../NoirJS/noir_js/type-aliases/InputMap.md | 13 - .../NoirJS/noir_js/type-aliases/ProofData.md | 20 - .../NoirJS/noir_js/type-aliases/WitnessMap.md | 9 - .../NoirJS/noir_js/typedoc-sidebar.cjs | 4 - .../reference/nargo_commands.md | 250 ----- .../version-v0.22.0/tutorials/noirjs_app.md | 261 ----- .../getting_started/_category_.json | 5 - .../hello_noir/_category_.json | 5 - .../getting_started/hello_noir/index.md | 142 --- .../hello_noir/project_breakdown.md | 199 ---- .../installation/_category_.json | 6 - .../getting_started/installation/index.md | 48 - .../installation/other_install_methods.md | 190 ---- .../getting_started/tooling/_category_.json | 6 - .../getting_started/tooling/index.mdx | 34 - .../tooling/language_server.md | 43 - .../getting_started/tooling/testing.md | 62 -- .../version-v0.23.0/how_to/_category_.json | 5 - .../version-v0.23.0/how_to/how-to-oracles.md | 280 ------ .../how_to/how-to-recursion.md | 179 ---- .../how_to/how-to-solidity-verifier.md | 231 ----- .../version-v0.23.0/how_to/merkle-proof.mdx | 48 - .../versioned_docs/version-v0.23.0/index.mdx | 67 -- .../version-v0.23.0/migration_notes.md | 107 -- .../version-v0.23.0/noir/concepts/assert.md | 27 - .../noir/concepts/control_flow.md | 45 - .../version-v0.23.0/noir/concepts/data_bus.md | 21 - .../noir/concepts/data_types/_category_.json | 5 - .../noir/concepts/data_types/arrays.md | 251 ----- .../noir/concepts/data_types/booleans.md | 31 - .../noir/concepts/data_types/fields.md | 192 ---- .../concepts/data_types/function_types.md | 26 - .../noir/concepts/data_types/index.md | 96 -- .../noir/concepts/data_types/integers.md | 162 --- .../noir/concepts/data_types/references.md | 23 - .../noir/concepts/data_types/slices.mdx | 147 --- .../noir/concepts/data_types/strings.md | 80 -- .../noir/concepts/data_types/structs.md | 70 -- .../noir/concepts/data_types/tuples.md | 48 - .../noir/concepts/data_types/vectors.mdx | 171 ---- .../version-v0.23.0/noir/concepts/distinct.md | 64 -- .../noir/concepts/functions.md | 226 ----- .../version-v0.23.0/noir/concepts/generics.md | 106 -- .../noir/concepts/mutability.md | 93 -- .../version-v0.23.0/noir/concepts/ops.md | 98 -- .../version-v0.23.0/noir/concepts/oracles.md | 23 - .../version-v0.23.0/noir/concepts/traits.md | 389 -------- .../noir/concepts/unconstrained.md | 95 -- .../modules_packages_crates/_category_.json | 6 - .../crates_and_packages.md | 43 - .../modules_packages_crates/dependencies.md | 124 --- .../noir/modules_packages_crates/modules.md | 105 -- .../modules_packages_crates/workspaces.md | 42 - .../noir/standard_library/_category_.json | 6 - .../noir/standard_library/black_box_fns.md | 31 - .../cryptographic_primitives/_category_.json | 5 - .../cryptographic_primitives/ec_primitives.md | 102 -- .../ecdsa_sig_verification.mdx | 60 -- .../cryptographic_primitives/eddsa.mdx | 18 - .../cryptographic_primitives/hashes.mdx | 234 ----- .../cryptographic_primitives/index.md | 14 - .../cryptographic_primitives/scalar.mdx | 33 - .../cryptographic_primitives/schnorr.mdx | 45 - .../noir/standard_library/merkle_trees.md | 58 -- .../noir/standard_library/options.md | 97 -- .../noir/standard_library/recursion.md | 68 -- .../noir/standard_library/traits.md | 284 ------ .../noir/standard_library/zeroed.md | 25 - .../reference/backend_barretenberg/.nojekyll | 1 - .../classes/BarretenbergBackend.md | 185 ---- .../reference/backend_barretenberg/index.md | 45 - .../interfaces/Backend.md | 132 --- .../type-aliases/BackendOptions.md | 19 - .../type-aliases/CompiledCircuit.md | 20 - .../type-aliases/ProofData.md | 20 - .../backend_barretenberg/typedoc-sidebar.cjs | 4 - .../noir_js/reference/noir_js/.nojekyll | 1 - .../noir_js/reference/noir_js/classes/Noir.md | 131 --- .../reference/noir_js/functions/and.md | 22 - .../reference/noir_js/functions/blake2s256.md | 21 - .../functions/ecdsa_secp256k1_verify.md | 29 - .../functions/ecdsa_secp256r1_verify.md | 28 - .../reference/noir_js/functions/keccak256.md | 21 - .../reference/noir_js/functions/sha256.md | 21 - .../reference/noir_js/functions/xor.md | 22 - .../noir_js/reference/noir_js/index.md | 37 - .../noir_js/type-aliases/CompiledCircuit.md | 20 - .../type-aliases/ForeignCallHandler.md | 24 - .../noir_js/type-aliases/ForeignCallInput.md | 9 - .../noir_js/type-aliases/ForeignCallOutput.md | 9 - .../noir_js/type-aliases/InputMap.md | 13 - .../noir_js/type-aliases/ProofData.md | 20 - .../noir_js/type-aliases/WitnessMap.md | 9 - .../reference/noir_js/typedoc-sidebar.cjs | 4 - .../NoirJS/backend_barretenberg/.nojekyll | 1 - .../classes/BarretenbergBackend.md | 185 ---- .../NoirJS/backend_barretenberg/index.md | 46 - .../interfaces/Backend.md | 132 --- .../type-aliases/BackendOptions.md | 19 - .../type-aliases/CompiledCircuit.md | 20 - .../type-aliases/ProofData.md | 20 - .../backend_barretenberg/typedoc-sidebar.cjs | 4 - .../reference/NoirJS/noir_js/.nojekyll | 1 - .../reference/NoirJS/noir_js/classes/Noir.md | 132 --- .../reference/NoirJS/noir_js/functions/and.md | 22 - .../NoirJS/noir_js/functions/blake2s256.md | 21 - .../functions/ecdsa_secp256r1_verify.md | 28 - .../NoirJS/noir_js/functions/keccak256.md | 21 - .../NoirJS/noir_js/functions/sha256.md | 21 - .../reference/NoirJS/noir_js/functions/xor.md | 22 - .../reference/NoirJS/noir_js/index.md | 37 - .../noir_js/type-aliases/CompiledCircuit.md | 20 - .../type-aliases/ForeignCallHandler.md | 24 - .../noir_js/type-aliases/ForeignCallInput.md | 9 - .../noir_js/type-aliases/ForeignCallOutput.md | 9 - .../NoirJS/noir_js/type-aliases/InputMap.md | 13 - .../NoirJS/noir_js/type-aliases/ProofData.md | 20 - .../NoirJS/noir_js/type-aliases/WitnessMap.md | 9 - .../NoirJS/noir_js/typedoc-sidebar.cjs | 4 - .../reference/NoirJS/noir_wasm/.nojekyll | 1 - .../NoirJS/noir_wasm/functions/compile.md | 51 - .../reference/NoirJS/noir_wasm/index.md | 21 - .../type-aliases/CompilationResult.md | 11 - .../NoirJS/noir_wasm/typedoc-sidebar.cjs | 4 - .../version-v0.23.0/reference/_category_.json | 5 - .../reference/nargo_commands.md | 253 ----- .../version-v0.23.0/tutorials/noirjs_app.md | 295 ------ .../explainers/explainer-oracle.md | 57 -- .../explainers/explainer-recursion.md | 176 ---- .../getting_started/_category_.json | 5 - .../hello_noir/_category_.json | 5 - .../getting_started/hello_noir/index.md | 142 --- .../hello_noir/project_breakdown.md | 199 ---- .../installation/_category_.json | 6 - .../getting_started/installation/index.md | 48 - .../installation/other_install_methods.md | 254 ----- .../getting_started/tooling/_category_.json | 6 - .../getting_started/tooling/index.mdx | 34 - .../tooling/language_server.md | 43 - .../getting_started/tooling/testing.md | 62 -- .../version-v0.24.0/how_to/_category_.json | 5 - .../version-v0.24.0/how_to/how-to-oracles.md | 280 ------ .../how_to/how-to-recursion.md | 179 ---- .../how_to/how-to-solidity-verifier.md | 231 ----- .../version-v0.24.0/how_to/merkle-proof.mdx | 48 - .../how_to/using-devcontainers.mdx | 110 -- .../versioned_docs/version-v0.24.0/index.mdx | 67 -- .../version-v0.24.0/migration_notes.md | 91 -- .../noir/concepts/_category_.json | 6 - .../version-v0.24.0/noir/concepts/comments.md | 33 - .../noir/concepts/control_flow.md | 45 - .../version-v0.24.0/noir/concepts/data_bus.md | 21 - .../noir/concepts/data_types/_category_.json | 5 - .../noir/concepts/data_types/arrays.md | 253 ----- .../noir/concepts/data_types/booleans.md | 31 - .../noir/concepts/data_types/fields.md | 192 ---- .../concepts/data_types/function_types.md | 26 - .../noir/concepts/data_types/index.md | 96 -- .../noir/concepts/data_types/integers.md | 162 --- .../noir/concepts/data_types/references.md | 23 - .../noir/concepts/data_types/slices.mdx | 147 --- .../noir/concepts/data_types/strings.md | 80 -- .../noir/concepts/data_types/structs.md | 70 -- .../noir/concepts/data_types/tuples.md | 48 - .../noir/concepts/data_types/vectors.mdx | 171 ---- .../version-v0.24.0/noir/concepts/distinct.md | 64 -- .../noir/concepts/functions.md | 226 ----- .../version-v0.24.0/noir/concepts/generics.md | 106 -- .../version-v0.24.0/noir/concepts/lambdas.md | 81 -- .../version-v0.24.0/noir/concepts/ops.md | 98 -- .../version-v0.24.0/noir/concepts/oracles.md | 23 - .../noir/concepts/shadowing.md | 44 - .../version-v0.24.0/noir/concepts/traits.md | 389 -------- .../noir/concepts/unconstrained.md | 95 -- .../modules_packages_crates/_category_.json | 6 - .../crates_and_packages.md | 43 - .../modules_packages_crates/dependencies.md | 124 --- .../noir/modules_packages_crates/modules.md | 105 -- .../modules_packages_crates/workspaces.md | 42 - .../noir/standard_library/_category_.json | 6 - .../noir/standard_library/black_box_fns.md | 31 - .../noir/standard_library/bn254.md | 46 - .../cryptographic_primitives/_category_.json | 5 - .../cryptographic_primitives/ec_primitives.md | 102 -- .../ecdsa_sig_verification.mdx | 60 -- .../cryptographic_primitives/eddsa.mdx | 18 - .../cryptographic_primitives/hashes.mdx | 234 ----- .../cryptographic_primitives/index.md | 14 - .../cryptographic_primitives/scalar.mdx | 33 - .../cryptographic_primitives/schnorr.mdx | 45 - .../noir/standard_library/logging.md | 78 -- .../noir/standard_library/merkle_trees.md | 58 -- .../noir/standard_library/recursion.md | 88 -- .../noir/standard_library/traits.md | 399 -------- .../noir/standard_library/zeroed.md | 25 - .../version-v0.24.0/reference/_category_.json | 5 - .../reference/nargo_commands.md | 380 ------- .../version-v0.24.0/tutorials/noirjs_app.md | 279 ------ .../explainers/explainer-oracle.md | 57 -- .../explainers/explainer-recursion.md | 176 ---- .../getting_started/_category_.json | 5 - .../hello_noir/_category_.json | 5 - .../getting_started/hello_noir/index.md | 142 --- .../hello_noir/project_breakdown.md | 199 ---- .../installation/_category_.json | 6 - .../getting_started/installation/index.md | 48 - .../installation/other_install_methods.md | 254 ----- .../getting_started/tooling/_category_.json | 6 - .../getting_started/tooling/index.mdx | 34 - .../tooling/language_server.md | 43 - .../getting_started/tooling/testing.md | 62 -- .../version-v0.25.0/how_to/_category_.json | 5 - .../version-v0.25.0/how_to/how-to-oracles.md | 280 ------ .../how_to/how-to-recursion.md | 179 ---- .../how_to/how-to-solidity-verifier.md | 231 ----- .../version-v0.25.0/how_to/merkle-proof.mdx | 48 - .../how_to/using-devcontainers.mdx | 110 -- .../versioned_docs/version-v0.25.0/index.mdx | 67 -- .../noir/concepts/_category_.json | 6 - .../version-v0.25.0/noir/concepts/assert.md | 45 - .../version-v0.25.0/noir/concepts/comments.md | 33 - .../noir/concepts/control_flow.md | 45 - .../version-v0.25.0/noir/concepts/data_bus.md | 21 - .../noir/concepts/data_types/_category_.json | 5 - .../noir/concepts/data_types/arrays.md | 253 ----- .../noir/concepts/data_types/booleans.md | 31 - .../noir/concepts/data_types/fields.md | 192 ---- .../concepts/data_types/function_types.md | 26 - .../noir/concepts/data_types/index.md | 110 -- .../noir/concepts/data_types/integers.md | 155 --- .../noir/concepts/data_types/references.md | 23 - .../noir/concepts/data_types/slices.mdx | 147 --- .../noir/concepts/data_types/strings.md | 80 -- .../noir/concepts/data_types/structs.md | 70 -- .../noir/concepts/data_types/tuples.md | 48 - .../version-v0.25.0/noir/concepts/distinct.md | 64 -- .../noir/concepts/functions.md | 226 ----- .../version-v0.25.0/noir/concepts/generics.md | 106 -- .../version-v0.25.0/noir/concepts/globals.md | 72 -- .../version-v0.25.0/noir/concepts/lambdas.md | 81 -- .../noir/concepts/mutability.md | 121 --- .../version-v0.25.0/noir/concepts/ops.md | 98 -- .../version-v0.25.0/noir/concepts/oracles.md | 23 - .../noir/concepts/shadowing.md | 44 - .../version-v0.25.0/noir/concepts/traits.md | 389 -------- .../noir/concepts/unconstrained.md | 95 -- .../modules_packages_crates/_category_.json | 6 - .../crates_and_packages.md | 43 - .../modules_packages_crates/dependencies.md | 124 --- .../noir/modules_packages_crates/modules.md | 105 -- .../modules_packages_crates/workspaces.md | 42 - .../noir/standard_library/_category_.json | 6 - .../noir/standard_library/black_box_fns.md | 31 - .../noir/standard_library/bn254.md | 46 - .../standard_library/containers/boundedvec.md | 326 ------ .../standard_library/containers/hashmap.md | 569 ----------- .../noir/standard_library/containers/vec.mdx | 151 --- .../cryptographic_primitives/_category_.json | 5 - .../cryptographic_primitives/ec_primitives.md | 102 -- .../ecdsa_sig_verification.mdx | 60 -- .../cryptographic_primitives/eddsa.mdx | 37 - .../cryptographic_primitives/hashes.mdx | 251 ----- .../cryptographic_primitives/index.md | 14 - .../cryptographic_primitives/scalar.mdx | 33 - .../cryptographic_primitives/schnorr.mdx | 45 - .../noir/standard_library/logging.md | 78 -- .../noir/standard_library/merkle_trees.md | 58 -- .../noir/standard_library/options.md | 101 -- .../noir/standard_library/recursion.md | 88 -- .../noir/standard_library/traits.md | 399 -------- .../noir/standard_library/zeroed.md | 25 - .../NoirJS/backend_barretenberg/.nojekyll | 1 - .../classes/BarretenbergBackend.md | 127 --- .../NoirJS/backend_barretenberg/index.md | 46 - .../interfaces/Backend.md | 132 --- .../type-aliases/CompiledCircuit.md | 20 - .../type-aliases/ProofData.md | 20 - .../backend_barretenberg/typedoc-sidebar.cjs | 4 - .../reference/NoirJS/noir_js/.nojekyll | 1 - .../reference/NoirJS/noir_js/classes/Noir.md | 132 --- .../reference/NoirJS/noir_js/functions/and.md | 22 - .../NoirJS/noir_js/functions/blake2s256.md | 21 - .../functions/ecdsa_secp256k1_verify.md | 28 - .../functions/ecdsa_secp256r1_verify.md | 28 - .../NoirJS/noir_js/functions/keccak256.md | 21 - .../NoirJS/noir_js/functions/sha256.md | 21 - .../reference/NoirJS/noir_js/functions/xor.md | 22 - .../reference/NoirJS/noir_js/index.md | 37 - .../noir_js/type-aliases/CompiledCircuit.md | 20 - .../type-aliases/ForeignCallHandler.md | 24 - .../noir_js/type-aliases/ForeignCallInput.md | 9 - .../noir_js/type-aliases/ForeignCallOutput.md | 9 - .../NoirJS/noir_js/type-aliases/InputMap.md | 13 - .../NoirJS/noir_js/type-aliases/ProofData.md | 20 - .../NoirJS/noir_js/type-aliases/WitnessMap.md | 9 - .../NoirJS/noir_js/typedoc-sidebar.cjs | 4 - .../reference/NoirJS/noir_wasm/.nojekyll | 1 - .../noir_wasm/functions/createFileManager.md | 21 - .../functions/inflateDebugSymbols.md | 21 - .../version-v0.25.0/reference/_category_.json | 5 - .../reference/nargo_commands.md | 380 ------- .../version-v0.25.0/tutorials/noirjs_app.md | 324 ------ .../explainers/explainer-oracle.md | 57 -- .../explainers/explainer-recursion.md | 176 ---- .../getting_started/_category_.json | 5 - .../hello_noir/_category_.json | 5 - .../getting_started/hello_noir/index.md | 142 --- .../hello_noir/project_breakdown.md | 199 ---- .../installation/_category_.json | 6 - .../getting_started/installation/index.md | 48 - .../getting_started/tooling/_category_.json | 6 - .../getting_started/tooling/index.mdx | 34 - .../tooling/language_server.md | 43 - .../getting_started/tooling/noir_codegen.md | 113 --- .../getting_started/tooling/testing.md | 62 -- .../version-v0.26.0/how_to/_category_.json | 5 - .../version-v0.26.0/how_to/how-to-oracles.md | 276 ----- .../how_to/how-to-recursion.md | 179 ---- .../how_to/how-to-solidity-verifier.md | 231 ----- .../version-v0.26.0/how_to/merkle-proof.mdx | 48 - .../how_to/using-devcontainers.mdx | 110 -- .../versioned_docs/version-v0.26.0/index.mdx | 67 -- .../version-v0.26.0/migration_notes.md | 105 -- .../noir/concepts/_category_.json | 6 - .../version-v0.26.0/noir/concepts/assert.md | 45 - .../version-v0.26.0/noir/concepts/comments.md | 33 - .../noir/concepts/data_types/_category_.json | 5 - .../noir/concepts/data_types/booleans.md | 31 - .../noir/concepts/data_types/fields.md | 192 ---- .../concepts/data_types/function_types.md | 26 - .../noir/concepts/data_types/integers.md | 155 --- .../noir/concepts/data_types/references.md | 23 - .../noir/concepts/data_types/slices.mdx | 170 ---- .../noir/concepts/data_types/strings.md | 80 -- .../noir/concepts/data_types/structs.md | 70 -- .../noir/concepts/data_types/tuples.md | 48 - .../version-v0.26.0/noir/concepts/distinct.md | 64 -- .../noir/concepts/functions.md | 226 ----- .../version-v0.26.0/noir/concepts/generics.md | 106 -- .../version-v0.26.0/noir/concepts/globals.md | 72 -- .../version-v0.26.0/noir/concepts/lambdas.md | 81 -- .../noir/concepts/mutability.md | 121 --- .../version-v0.26.0/noir/concepts/ops.md | 98 -- .../version-v0.26.0/noir/concepts/oracles.md | 23 - .../noir/concepts/shadowing.md | 44 - .../version-v0.26.0/noir/concepts/traits.md | 389 -------- .../modules_packages_crates/_category_.json | 6 - .../crates_and_packages.md | 43 - .../modules_packages_crates/dependencies.md | 124 --- .../noir/modules_packages_crates/modules.md | 105 -- .../modules_packages_crates/workspaces.md | 42 - .../noir/standard_library/_category_.json | 6 - .../noir/standard_library/bigint.md | 119 --- .../noir/standard_library/black_box_fns.md | 31 - .../noir/standard_library/bn254.md | 46 - .../standard_library/containers/boundedvec.md | 326 ------ .../standard_library/containers/hashmap.md | 569 ----------- .../noir/standard_library/containers/index.md | 5 - .../noir/standard_library/containers/vec.mdx | 151 --- .../cryptographic_primitives/_category_.json | 5 - .../cryptographic_primitives/ec_primitives.md | 102 -- .../ecdsa_sig_verification.mdx | 98 -- .../cryptographic_primitives/eddsa.mdx | 37 - .../cryptographic_primitives/hashes.mdx | 331 ------ .../cryptographic_primitives/index.md | 14 - .../cryptographic_primitives/scalar.mdx | 33 - .../noir/standard_library/logging.md | 78 -- .../noir/standard_library/options.md | 101 -- .../noir/standard_library/recursion.md | 88 -- .../noir/standard_library/traits.md | 408 -------- .../NoirJS/backend_barretenberg/.nojekyll | 1 - .../NoirJS/backend_barretenberg/index.md | 58 -- .../type-aliases/BackendOptions.md | 21 - .../backend_barretenberg/typedoc-sidebar.cjs | 4 - .../reference/NoirJS/noir_js/.nojekyll | 1 - .../reference/NoirJS/noir_js/classes/Noir.md | 132 --- .../reference/NoirJS/noir_js/functions/and.md | 22 - .../NoirJS/noir_js/functions/blake2s256.md | 21 - .../functions/ecdsa_secp256k1_verify.md | 28 - .../functions/ecdsa_secp256r1_verify.md | 28 - .../NoirJS/noir_js/functions/keccak256.md | 21 - .../NoirJS/noir_js/functions/sha256.md | 21 - .../reference/NoirJS/noir_js/functions/xor.md | 22 - .../reference/NoirJS/noir_js/index.md | 54 - .../type-aliases/ForeignCallHandler.md | 24 - .../noir_js/type-aliases/ForeignCallInput.md | 9 - .../noir_js/type-aliases/ForeignCallOutput.md | 9 - .../NoirJS/noir_js/type-aliases/WitnessMap.md | 9 - .../NoirJS/noir_js/typedoc-sidebar.cjs | 4 - .../reference/NoirJS/noir_wasm/.nojekyll | 1 - .../NoirJS/noir_wasm/functions/compile.md | 51 - .../noir_wasm/functions/compile_contract.md | 51 - .../noir_wasm/functions/createFileManager.md | 21 - .../functions/inflateDebugSymbols.md | 21 - .../reference/NoirJS/noir_wasm/index.md | 49 - .../NoirJS/noir_wasm/typedoc-sidebar.cjs | 4 - .../version-v0.26.0/reference/_category_.json | 5 - .../reference/nargo_commands.md | 381 ------- .../version-v0.26.0/tutorials/noirjs_app.md | 324 ------ .../explainers/explainer-oracle.md | 57 -- .../explainers/explainer-recursion.md | 176 ---- .../getting_started/_category_.json | 5 - .../hello_noir/_category_.json | 5 - .../getting_started/hello_noir/index.md | 142 --- .../hello_noir/project_breakdown.md | 199 ---- .../installation/_category_.json | 6 - .../getting_started/installation/index.md | 48 - .../installation/other_install_methods.md | 102 -- .../getting_started/tooling/_category_.json | 6 - .../getting_started/tooling/index.mdx | 34 - .../tooling/language_server.md | 43 - .../getting_started/tooling/noir_codegen.md | 113 --- .../getting_started/tooling/testing.md | 62 -- .../version-v0.27.0/how_to/_category_.json | 5 - .../version-v0.27.0/how_to/how-to-oracles.md | 276 ----- .../how_to/how-to-recursion.md | 179 ---- .../how_to/how-to-solidity-verifier.md | 231 ----- .../version-v0.27.0/how_to/merkle-proof.mdx | 48 - .../how_to/using-devcontainers.mdx | 110 -- .../versioned_docs/version-v0.27.0/index.mdx | 67 -- .../version-v0.27.0/migration_notes.md | 105 -- .../noir/concepts/_category_.json | 6 - .../version-v0.27.0/noir/concepts/assert.md | 45 - .../version-v0.27.0/noir/concepts/comments.md | 33 - .../noir/concepts/control_flow.md | 77 -- .../version-v0.27.0/noir/concepts/data_bus.md | 21 - .../noir/concepts/data_types/_category_.json | 5 - .../noir/concepts/data_types/arrays.md | 253 ----- .../noir/concepts/data_types/booleans.md | 31 - .../noir/concepts/data_types/fields.md | 192 ---- .../concepts/data_types/function_types.md | 26 - .../noir/concepts/data_types/index.md | 110 -- .../noir/concepts/data_types/integers.md | 155 --- .../noir/concepts/data_types/references.md | 23 - .../noir/concepts/data_types/slices.mdx | 170 ---- .../noir/concepts/data_types/strings.md | 80 -- .../noir/concepts/data_types/structs.md | 70 -- .../noir/concepts/data_types/tuples.md | 48 - .../version-v0.27.0/noir/concepts/distinct.md | 64 -- .../noir/concepts/functions.md | 226 ----- .../version-v0.27.0/noir/concepts/generics.md | 106 -- .../version-v0.27.0/noir/concepts/globals.md | 72 -- .../version-v0.27.0/noir/concepts/lambdas.md | 81 -- .../noir/concepts/mutability.md | 121 --- .../version-v0.27.0/noir/concepts/ops.md | 98 -- .../version-v0.27.0/noir/concepts/oracles.md | 23 - .../noir/concepts/shadowing.md | 44 - .../version-v0.27.0/noir/concepts/traits.md | 389 -------- .../noir/concepts/unconstrained.md | 99 -- .../modules_packages_crates/_category_.json | 6 - .../crates_and_packages.md | 43 - .../modules_packages_crates/dependencies.md | 124 --- .../noir/modules_packages_crates/modules.md | 105 -- .../modules_packages_crates/workspaces.md | 42 - .../noir/standard_library/_category_.json | 6 - .../noir/standard_library/bigint.md | 119 --- .../noir/standard_library/black_box_fns.md | 31 - .../noir/standard_library/bn254.md | 46 - .../standard_library/containers/boundedvec.md | 326 ------ .../standard_library/containers/hashmap.md | 569 ----------- .../noir/standard_library/containers/index.md | 5 - .../noir/standard_library/containers/vec.mdx | 151 --- .../cryptographic_primitives/_category_.json | 5 - .../cryptographic_primitives/ec_primitives.md | 102 -- .../cryptographic_primitives/eddsa.mdx | 37 - .../cryptographic_primitives/hashes.mdx | 331 ------ .../cryptographic_primitives/index.md | 14 - .../cryptographic_primitives/scalar.mdx | 33 - .../cryptographic_primitives/schnorr.mdx | 64 -- .../noir/standard_library/logging.md | 78 -- .../noir/standard_library/merkle_trees.md | 58 -- .../noir/standard_library/options.md | 101 -- .../noir/standard_library/recursion.md | 88 -- .../noir/standard_library/traits.md | 408 -------- .../noir/standard_library/zeroed.md | 26 - .../NoirJS/backend_barretenberg/.nojekyll | 1 - .../classes/BarretenbergBackend.md | 119 --- .../NoirJS/backend_barretenberg/index.md | 58 -- .../type-aliases/BackendOptions.md | 21 - .../backend_barretenberg/typedoc-sidebar.cjs | 4 - .../reference/NoirJS/noir_js/.nojekyll | 1 - .../reference/NoirJS/noir_js/classes/Noir.md | 132 --- .../reference/NoirJS/noir_js/functions/and.md | 22 - .../NoirJS/noir_js/functions/blake2s256.md | 21 - .../functions/ecdsa_secp256k1_verify.md | 28 - .../functions/ecdsa_secp256r1_verify.md | 28 - .../NoirJS/noir_js/functions/keccak256.md | 21 - .../NoirJS/noir_js/functions/sha256.md | 21 - .../reference/NoirJS/noir_js/functions/xor.md | 22 - .../reference/NoirJS/noir_js/index.md | 54 - .../type-aliases/ForeignCallHandler.md | 24 - .../noir_js/type-aliases/ForeignCallInput.md | 9 - .../noir_js/type-aliases/ForeignCallOutput.md | 9 - .../NoirJS/noir_js/type-aliases/WitnessMap.md | 9 - .../NoirJS/noir_js/typedoc-sidebar.cjs | 4 - .../reference/NoirJS/noir_wasm/.nojekyll | 1 - .../NoirJS/noir_wasm/functions/compile.md | 51 - .../noir_wasm/functions/compile_contract.md | 51 - .../noir_wasm/functions/createFileManager.md | 21 - .../functions/inflateDebugSymbols.md | 21 - .../reference/NoirJS/noir_wasm/index.md | 49 - .../NoirJS/noir_wasm/typedoc-sidebar.cjs | 4 - .../version-v0.27.0/reference/_category_.json | 5 - .../version-v0.27.0/tutorials/noirjs_app.md | 279 ------ .../explainers/explainer-oracle.md | 57 -- .../explainers/explainer-recursion.md | 176 ---- .../getting_started/_category_.json | 5 - .../hello_noir/_category_.json | 5 - .../getting_started/hello_noir/index.md | 142 --- .../hello_noir/project_breakdown.md | 199 ---- .../installation/_category_.json | 6 - .../getting_started/installation/index.md | 48 - .../installation/other_install_methods.md | 102 -- .../getting_started/tooling/noir_codegen.md | 113 --- .../version-v0.28.0/how_to/_category_.json | 5 - .../version-v0.28.0/how_to/how-to-oracles.md | 276 ----- .../how_to/how-to-recursion.md | 179 ---- .../how_to/how-to-solidity-verifier.md | 231 ----- .../version-v0.28.0/how_to/merkle-proof.mdx | 49 - .../how_to/using-devcontainers.mdx | 110 -- .../versioned_docs/version-v0.28.0/index.mdx | 67 -- .../version-v0.28.0/migration_notes.md | 105 -- .../noir/concepts/_category_.json | 6 - .../version-v0.28.0/noir/concepts/assert.md | 45 - .../version-v0.28.0/noir/concepts/comments.md | 33 - .../noir/concepts/control_flow.md | 77 -- .../version-v0.28.0/noir/concepts/data_bus.md | 21 - .../noir/concepts/data_types/_category_.json | 5 - .../noir/concepts/data_types/arrays.md | 253 ----- .../noir/concepts/data_types/booleans.md | 31 - .../noir/concepts/data_types/fields.md | 192 ---- .../concepts/data_types/function_types.md | 26 - .../noir/concepts/data_types/index.md | 110 -- .../noir/concepts/data_types/integers.md | 155 --- .../noir/concepts/data_types/references.md | 23 - .../noir/concepts/data_types/slices.mdx | 195 ---- .../noir/concepts/data_types/strings.md | 80 -- .../noir/concepts/data_types/structs.md | 70 -- .../noir/concepts/data_types/tuples.md | 48 - .../version-v0.28.0/noir/concepts/distinct.md | 64 -- .../version-v0.28.0/noir/concepts/generics.md | 106 -- .../version-v0.28.0/noir/concepts/globals.md | 72 -- .../version-v0.28.0/noir/concepts/lambdas.md | 81 -- .../noir/concepts/mutability.md | 121 --- .../version-v0.28.0/noir/concepts/ops.md | 98 -- .../noir/concepts/shadowing.md | 44 - .../version-v0.28.0/noir/concepts/traits.md | 389 -------- .../noir/concepts/unconstrained.md | 99 -- .../modules_packages_crates/_category_.json | 6 - .../crates_and_packages.md | 43 - .../modules_packages_crates/dependencies.md | 124 --- .../noir/modules_packages_crates/modules.md | 105 -- .../modules_packages_crates/workspaces.md | 42 - .../noir/standard_library/_category_.json | 6 - .../noir/standard_library/bigint.md | 122 --- .../noir/standard_library/black_box_fns.md | 31 - .../noir/standard_library/bn254.md | 46 - .../standard_library/containers/boundedvec.md | 326 ------ .../standard_library/containers/hashmap.md | 570 ----------- .../noir/standard_library/containers/index.md | 5 - .../noir/standard_library/containers/vec.mdx | 151 --- .../cryptographic_primitives/_category_.json | 5 - .../cryptographic_primitives/ec_primitives.md | 102 -- .../ecdsa_sig_verification.mdx | 98 -- .../cryptographic_primitives/eddsa.mdx | 37 - .../cryptographic_primitives/hashes.mdx | 250 ----- .../cryptographic_primitives/index.md | 14 - .../cryptographic_primitives/scalar.mdx | 33 - .../cryptographic_primitives/schnorr.mdx | 64 -- .../noir/standard_library/logging.md | 78 -- .../noir/standard_library/merkle_trees.md | 58 -- .../noir/standard_library/options.md | 101 -- .../noir/standard_library/recursion.md | 88 -- .../noir/standard_library/traits.md | 410 -------- .../noir/standard_library/zeroed.md | 26 - .../NoirJS/backend_barretenberg/.nojekyll | 1 - .../classes/BarretenbergBackend.md | 160 --- .../NoirJS/backend_barretenberg/index.md | 59 -- .../type-aliases/BackendOptions.md | 21 - .../backend_barretenberg/typedoc-sidebar.cjs | 4 - .../reference/NoirJS/noir_js/.nojekyll | 1 - .../reference/NoirJS/noir_js/classes/Noir.md | 132 --- .../reference/NoirJS/noir_js/functions/and.md | 22 - .../NoirJS/noir_js/functions/blake2s256.md | 21 - .../functions/ecdsa_secp256k1_verify.md | 28 - .../functions/ecdsa_secp256r1_verify.md | 28 - .../NoirJS/noir_js/functions/keccak256.md | 21 - .../NoirJS/noir_js/functions/sha256.md | 21 - .../reference/NoirJS/noir_js/functions/xor.md | 22 - .../reference/NoirJS/noir_js/index.md | 54 - .../type-aliases/ForeignCallHandler.md | 24 - .../noir_js/type-aliases/ForeignCallInput.md | 9 - .../noir_js/type-aliases/ForeignCallOutput.md | 9 - .../NoirJS/noir_js/type-aliases/WitnessMap.md | 9 - .../NoirJS/noir_js/typedoc-sidebar.cjs | 4 - .../reference/NoirJS/noir_wasm/.nojekyll | 1 - .../NoirJS/noir_wasm/functions/compile.md | 51 - .../noir_wasm/functions/compile_contract.md | 51 - .../noir_wasm/functions/createFileManager.md | 21 - .../functions/inflateDebugSymbols.md | 21 - .../reference/NoirJS/noir_wasm/index.md | 49 - .../NoirJS/noir_wasm/typedoc-sidebar.cjs | 4 - .../version-v0.28.0/reference/_category_.json | 5 - .../reference/nargo_commands.md | 381 ------- .../tooling/language_server.md | 43 - .../version-v0.28.0/tooling/testing.md | 62 -- .../version-v0.28.0/tutorials/noirjs_app.md | 326 ------ .../explainers/explainer-oracle.md | 57 -- .../explainers/explainer-recursion.md | 176 ---- .../getting_started/_category_.json | 5 - .../hello_noir/_category_.json | 5 - .../getting_started/hello_noir/index.md | 142 --- .../hello_noir/project_breakdown.md | 199 ---- .../installation/_category_.json | 6 - .../getting_started/installation/index.md | 48 - .../installation/other_install_methods.md | 102 -- .../getting_started/tooling/noir_codegen.md | 113 --- .../version-v0.29.0/how_to/_category_.json | 5 - .../how_to/debugger/_category_.json | 6 - .../debugger/debugging_with_the_repl.md | 164 --- .../how_to/debugger/debugging_with_vs_code.md | 68 -- .../version-v0.29.0/how_to/how-to-oracles.md | 276 ----- .../how_to/how-to-recursion.md | 179 ---- .../how_to/how-to-solidity-verifier.md | 232 ----- .../version-v0.29.0/how_to/merkle-proof.mdx | 49 - .../how_to/using-devcontainers.mdx | 110 -- .../versioned_docs/version-v0.29.0/index.mdx | 67 -- .../version-v0.29.0/migration_notes.md | 105 -- .../noir/concepts/_category_.json | 6 - .../version-v0.29.0/noir/concepts/assert.md | 45 - .../version-v0.29.0/noir/concepts/comments.md | 33 - .../noir/concepts/control_flow.md | 77 -- .../version-v0.29.0/noir/concepts/data_bus.md | 21 - .../noir/concepts/data_types/_category_.json | 5 - .../noir/concepts/data_types/arrays.md | 253 ----- .../noir/concepts/data_types/booleans.md | 31 - .../noir/concepts/data_types/fields.md | 192 ---- .../concepts/data_types/function_types.md | 26 - .../noir/concepts/data_types/index.md | 110 -- .../noir/concepts/data_types/integers.md | 155 --- .../noir/concepts/data_types/references.md | 23 - .../noir/concepts/data_types/slices.mdx | 195 ---- .../noir/concepts/data_types/strings.md | 80 -- .../noir/concepts/data_types/structs.md | 70 -- .../noir/concepts/data_types/tuples.md | 48 - .../noir/concepts/functions.md | 226 ----- .../version-v0.29.0/noir/concepts/generics.md | 106 -- .../version-v0.29.0/noir/concepts/globals.md | 72 -- .../version-v0.29.0/noir/concepts/lambdas.md | 81 -- .../noir/concepts/mutability.md | 121 --- .../version-v0.29.0/noir/concepts/oracles.md | 31 - .../noir/concepts/shadowing.md | 44 - .../version-v0.29.0/noir/concepts/traits.md | 389 -------- .../noir/concepts/unconstrained.md | 99 -- .../modules_packages_crates/_category_.json | 6 - .../crates_and_packages.md | 43 - .../modules_packages_crates/dependencies.md | 124 --- .../noir/modules_packages_crates/modules.md | 105 -- .../modules_packages_crates/workspaces.md | 42 - .../noir/standard_library/_category_.json | 6 - .../noir/standard_library/bigint.md | 122 --- .../noir/standard_library/black_box_fns.md | 31 - .../noir/standard_library/bn254.md | 46 - .../standard_library/containers/boundedvec.md | 326 ------ .../standard_library/containers/hashmap.md | 570 ----------- .../noir/standard_library/containers/index.md | 5 - .../noir/standard_library/containers/vec.mdx | 151 --- .../cryptographic_primitives/_category_.json | 5 - .../cryptographic_primitives/ec_primitives.md | 102 -- .../ecdsa_sig_verification.mdx | 98 -- .../cryptographic_primitives/eddsa.mdx | 37 - .../cryptographic_primitives/hashes.mdx | 257 ----- .../cryptographic_primitives/index.md | 14 - .../cryptographic_primitives/scalar.mdx | 33 - .../cryptographic_primitives/schnorr.mdx | 64 -- .../noir/standard_library/logging.md | 78 -- .../noir/standard_library/merkle_trees.md | 58 -- .../noir/standard_library/options.md | 101 -- .../noir/standard_library/recursion.md | 88 -- .../noir/standard_library/traits.md | 410 -------- .../noir/standard_library/zeroed.md | 26 - .../NoirJS/backend_barretenberg/.nojekyll | 1 - .../classes/BarretenbergBackend.md | 160 --- .../classes/BarretenbergVerifier.md | 58 -- .../NoirJS/backend_barretenberg/index.md | 59 -- .../type-aliases/BackendOptions.md | 21 - .../backend_barretenberg/typedoc-sidebar.cjs | 4 - .../reference/NoirJS/noir_js/.nojekyll | 1 - .../reference/NoirJS/noir_js/classes/Noir.md | 132 --- .../reference/NoirJS/noir_js/functions/and.md | 22 - .../NoirJS/noir_js/functions/blake2s256.md | 21 - .../functions/ecdsa_secp256k1_verify.md | 28 - .../functions/ecdsa_secp256r1_verify.md | 28 - .../NoirJS/noir_js/functions/keccak256.md | 21 - .../NoirJS/noir_js/functions/sha256.md | 21 - .../reference/NoirJS/noir_js/functions/xor.md | 22 - .../reference/NoirJS/noir_js/index.md | 54 - .../type-aliases/ForeignCallHandler.md | 24 - .../noir_js/type-aliases/ForeignCallInput.md | 9 - .../noir_js/type-aliases/ForeignCallOutput.md | 9 - .../NoirJS/noir_js/type-aliases/WitnessMap.md | 9 - .../NoirJS/noir_js/typedoc-sidebar.cjs | 4 - .../reference/NoirJS/noir_wasm/.nojekyll | 1 - .../NoirJS/noir_wasm/functions/compile.md | 51 - .../noir_wasm/functions/compile_contract.md | 51 - .../noir_wasm/functions/createFileManager.md | 21 - .../functions/inflateDebugSymbols.md | 21 - .../reference/NoirJS/noir_wasm/index.md | 49 - .../NoirJS/noir_wasm/typedoc-sidebar.cjs | 4 - .../version-v0.29.0/reference/_category_.json | 5 - .../reference/debugger/_category_.json | 6 - .../debugger/debugger_known_limitations.md | 59 -- .../reference/debugger/debugger_repl.md | 360 ------- .../reference/debugger/debugger_vscode.md | 82 -- .../reference/nargo_commands.md | 381 ------- .../version-v0.29.0/tooling/debugger.md | 26 - .../tooling/language_server.md | 43 - .../version-v0.29.0/tooling/testing.md | 62 -- .../version-v0.29.0/tutorials/noirjs_app.md | 326 ------ .../explainers/explainer-oracle.md | 57 -- .../explainers/explainer-recursion.md | 176 ---- .../getting_started/_category_.json | 5 - .../hello_noir/_category_.json | 5 - .../getting_started/hello_noir/index.md | 142 --- .../hello_noir/project_breakdown.md | 199 ---- .../installation/_category_.json | 6 - .../getting_started/installation/index.md | 48 - .../installation/other_install_methods.md | 102 -- .../getting_started/tooling/noir_codegen.md | 113 --- .../version-v0.30.0/how_to/_category_.json | 5 - .../how_to/debugger/_category_.json | 6 - .../debugger/debugging_with_the_repl.md | 164 --- .../how_to/debugger/debugging_with_vs_code.md | 68 -- .../version-v0.30.0/how_to/how-to-oracles.md | 276 ----- .../how_to/how-to-recursion.md | 179 ---- .../how_to/how-to-solidity-verifier.md | 231 ----- .../version-v0.30.0/how_to/merkle-proof.mdx | 49 - .../how_to/using-devcontainers.mdx | 110 -- .../versioned_docs/version-v0.30.0/index.mdx | 67 -- .../version-v0.30.0/migration_notes.md | 105 -- .../noir/concepts/_category_.json | 6 - .../version-v0.30.0/noir/concepts/assert.md | 45 - .../version-v0.30.0/noir/concepts/comments.md | 33 - .../noir/concepts/control_flow.md | 77 -- .../version-v0.30.0/noir/concepts/data_bus.md | 21 - .../noir/concepts/data_types/_category_.json | 5 - .../noir/concepts/data_types/arrays.md | 253 ----- .../noir/concepts/data_types/booleans.md | 31 - .../noir/concepts/data_types/fields.md | 192 ---- .../concepts/data_types/function_types.md | 26 - .../noir/concepts/data_types/index.md | 110 -- .../noir/concepts/data_types/integers.md | 157 --- .../noir/concepts/data_types/references.md | 23 - .../noir/concepts/data_types/slices.mdx | 195 ---- .../noir/concepts/data_types/strings.md | 80 -- .../noir/concepts/data_types/structs.md | 70 -- .../noir/concepts/data_types/tuples.md | 48 - .../noir/concepts/functions.md | 226 ----- .../version-v0.30.0/noir/concepts/generics.md | 106 -- .../version-v0.30.0/noir/concepts/globals.md | 72 -- .../version-v0.30.0/noir/concepts/lambdas.md | 81 -- .../noir/concepts/mutability.md | 121 --- .../version-v0.30.0/noir/concepts/ops.md | 98 -- .../version-v0.30.0/noir/concepts/oracles.md | 31 - .../noir/concepts/shadowing.md | 44 - .../version-v0.30.0/noir/concepts/traits.md | 389 -------- .../noir/concepts/unconstrained.md | 99 -- .../modules_packages_crates/_category_.json | 6 - .../crates_and_packages.md | 43 - .../modules_packages_crates/dependencies.md | 124 --- .../noir/modules_packages_crates/modules.md | 105 -- .../modules_packages_crates/workspaces.md | 42 - .../noir/standard_library/_category_.json | 6 - .../noir/standard_library/bn254.md | 46 - .../standard_library/containers/boundedvec.md | 340 ------- .../standard_library/containers/hashmap.md | 570 ----------- .../noir/standard_library/containers/index.md | 5 - .../noir/standard_library/containers/vec.mdx | 151 --- .../cryptographic_primitives/_category_.json | 5 - .../cryptographic_primitives/ec_primitives.md | 102 -- .../ecdsa_sig_verification.mdx | 98 -- .../cryptographic_primitives/eddsa.mdx | 37 - .../embedded_curve_ops.mdx | 98 -- .../cryptographic_primitives/hashes.mdx | 257 ----- .../cryptographic_primitives/index.md | 14 - .../cryptographic_primitives/schnorr.mdx | 64 -- .../noir/standard_library/logging.md | 78 -- .../noir/standard_library/merkle_trees.md | 58 -- .../noir/standard_library/options.md | 101 -- .../noir/standard_library/recursion.md | 88 -- .../noir/standard_library/zeroed.md | 26 - .../NoirJS/backend_barretenberg/.nojekyll | 1 - .../classes/BarretenbergBackend.md | 160 --- .../classes/BarretenbergVerifier.md | 58 -- .../NoirJS/backend_barretenberg/index.md | 59 -- .../type-aliases/BackendOptions.md | 21 - .../backend_barretenberg/typedoc-sidebar.cjs | 4 - .../reference/NoirJS/noir_js/.nojekyll | 1 - .../reference/NoirJS/noir_js/classes/Noir.md | 132 --- .../reference/NoirJS/noir_js/functions/and.md | 22 - .../NoirJS/noir_js/functions/blake2s256.md | 21 - .../functions/ecdsa_secp256k1_verify.md | 28 - .../functions/ecdsa_secp256r1_verify.md | 28 - .../NoirJS/noir_js/functions/keccak256.md | 21 - .../NoirJS/noir_js/functions/sha256.md | 21 - .../reference/NoirJS/noir_js/functions/xor.md | 22 - .../reference/NoirJS/noir_js/index.md | 55 - .../type-aliases/ForeignCallHandler.md | 24 - .../noir_js/type-aliases/ForeignCallInput.md | 9 - .../noir_js/type-aliases/ForeignCallOutput.md | 9 - .../NoirJS/noir_js/type-aliases/WitnessMap.md | 9 - .../reference/NoirJS/noir_wasm/.nojekyll | 1 - .../NoirJS/noir_wasm/functions/compile.md | 51 - .../noir_wasm/functions/compile_contract.md | 51 - .../noir_wasm/functions/createFileManager.md | 21 - .../functions/inflateDebugSymbols.md | 21 - .../reference/NoirJS/noir_wasm/index.md | 49 - .../NoirJS/noir_wasm/typedoc-sidebar.cjs | 4 - .../version-v0.30.0/reference/_category_.json | 5 - .../reference/debugger/_category_.json | 6 - .../debugger/debugger_known_limitations.md | 59 -- .../reference/debugger/debugger_repl.md | 360 ------- .../reference/debugger/debugger_vscode.md | 82 -- .../reference/nargo_commands.md | 397 -------- .../version-v0.30.0/tooling/debugger.md | 26 - .../tooling/language_server.md | 43 - .../version-v0.30.0/tooling/testing.md | 62 -- .../version-v0.30.0/tutorials/noirjs_app.md | 326 ------ .../explainers/explainer-oracle.md | 57 -- .../explainers/explainer-recursion.md | 176 ---- .../getting_started/_category_.json | 5 - .../installation/_category_.json | 6 - .../installation/other_install_methods.md | 102 -- .../version-v0.31.0/how_to/_category_.json | 5 - .../how_to/debugger/_category_.json | 6 - .../debugger/debugging_with_the_repl.md | 164 --- .../how_to/debugger/debugging_with_vs_code.md | 68 -- .../how_to/using-devcontainers.mdx | 110 -- .../version-v0.31.0/migration_notes.md | 105 -- .../noir/concepts/_category_.json | 6 - .../version-v0.31.0/noir/concepts/assert.md | 45 - .../version-v0.31.0/noir/concepts/comments.md | 33 - .../noir/concepts/control_flow.md | 77 -- .../version-v0.31.0/noir/concepts/data_bus.md | 21 - .../noir/concepts/data_types/_category_.json | 5 - .../noir/concepts/data_types/arrays.md | 253 ----- .../noir/concepts/data_types/fields.md | 192 ---- .../concepts/data_types/function_types.md | 26 - .../noir/concepts/data_types/index.md | 110 -- .../noir/concepts/data_types/references.md | 23 - .../noir/concepts/data_types/structs.md | 70 -- .../noir/concepts/data_types/tuples.md | 48 - .../noir/concepts/functions.md | 226 ----- .../version-v0.31.0/noir/concepts/generics.md | 106 -- .../version-v0.31.0/noir/concepts/globals.md | 72 -- .../version-v0.31.0/noir/concepts/lambdas.md | 81 -- .../noir/concepts/mutability.md | 121 --- .../version-v0.31.0/noir/concepts/ops.md | 98 -- .../version-v0.31.0/noir/concepts/oracles.md | 31 - .../noir/concepts/shadowing.md | 44 - .../noir/concepts/unconstrained.md | 99 -- .../modules_packages_crates/_category_.json | 6 - .../crates_and_packages.md | 43 - .../noir/modules_packages_crates/modules.md | 105 -- .../modules_packages_crates/workspaces.md | 42 - .../noir/standard_library/_category_.json | 6 - .../noir/standard_library/bigint.md | 122 --- .../noir/standard_library/black_box_fns.md | 32 - .../noir/standard_library/bn254.md | 46 - .../noir/standard_library/containers/index.md | 5 - .../cryptographic_primitives/_category_.json | 5 - .../cryptographic_primitives/ciphers.mdx | 32 - .../ecdsa_sig_verification.mdx | 98 -- .../cryptographic_primitives/index.md | 14 - .../cryptographic_primitives/schnorr.mdx | 64 -- .../noir/standard_library/logging.md | 78 -- .../noir/standard_library/merkle_trees.md | 58 -- .../noir/standard_library/options.md | 101 -- .../noir/standard_library/traits.md | 464 --------- .../noir/standard_library/zeroed.md | 26 - .../NoirJS/backend_barretenberg/.nojekyll | 1 - .../classes/BarretenbergBackend.md | 160 --- .../type-aliases/BackendOptions.md | 21 - .../backend_barretenberg/typedoc-sidebar.cjs | 4 - .../reference/NoirJS/noir_js/.nojekyll | 1 - .../reference/NoirJS/noir_js/functions/and.md | 22 - .../NoirJS/noir_js/functions/blake2s256.md | 21 - .../functions/ecdsa_secp256k1_verify.md | 28 - .../functions/ecdsa_secp256r1_verify.md | 28 - .../NoirJS/noir_js/functions/keccak256.md | 21 - .../NoirJS/noir_js/functions/sha256.md | 21 - .../reference/NoirJS/noir_js/functions/xor.md | 22 - .../noir_js/type-aliases/ErrorWithPayload.md | 15 - .../type-aliases/ForeignCallHandler.md | 24 - .../noir_js/type-aliases/ForeignCallInput.md | 9 - .../noir_js/type-aliases/ForeignCallOutput.md | 9 - .../NoirJS/noir_js/type-aliases/WitnessMap.md | 9 - .../NoirJS/noir_js/typedoc-sidebar.cjs | 4 - .../reference/NoirJS/noir_wasm/.nojekyll | 1 - .../NoirJS/noir_wasm/functions/compile.md | 51 - .../noir_wasm/functions/compile_contract.md | 51 - .../noir_wasm/functions/createFileManager.md | 21 - .../functions/inflateDebugSymbols.md | 21 - .../reference/NoirJS/noir_wasm/index.md | 49 - .../NoirJS/noir_wasm/typedoc-sidebar.cjs | 4 - .../version-v0.31.0/reference/_category_.json | 5 - .../reference/debugger/_category_.json | 6 - .../debugger/debugger_known_limitations.md | 59 -- .../reference/debugger/debugger_repl.md | 360 ------- .../reference/debugger/debugger_vscode.md | 82 -- .../reference/nargo_commands.md | 244 ----- .../version-v0.31.0/tooling/debugger.md | 26 - .../tooling/language_server.md | 43 - .../version-v0.31.0/tooling/testing.md | 62 -- .../version-v0.34.0/explainers/cspell.json | 5 + .../explainers/explainer-oracle.md | 4 +- .../explainers/explainer-recursion.md | 0 .../explainers/explainer-writing-noir.md | 177 ++++ .../getting_started/_category_.json | 0 .../getting_started/backend/_category_.json | 0 .../getting_started/backend/index.md | 0 .../hello_noir/_category_.json | 0 .../getting_started/hello_noir/index.md | 5 + .../hello_noir/project_breakdown.md | 0 .../installation/_category_.json | 0 .../getting_started/installation/index.md | 0 .../installation/other_install_methods.md | 0 .../how_to/_category_.json | 0 .../how_to/debugger/_category_.json | 0 .../debugger/debugging_with_the_repl.md | 0 .../how_to/debugger/debugging_with_vs_code.md | 0 .../how_to/how-to-oracles.md | 8 +- .../how_to/how-to-recursion.md | 2 +- .../how_to/how-to-solidity-verifier.md | 14 +- .../how_to/merkle-proof.mdx | 0 .../how_to/using-devcontainers.mdx | 0 .../index.mdx | 0 .../migration_notes.md | 0 .../noir/concepts/_category_.json | 0 .../noir/concepts/assert.md | 39 +- .../noir/concepts/comments.md | 0 .../version-v0.34.0/noir/concepts/comptime.md | 424 ++++++++ .../noir/concepts/control_flow.md | 0 .../noir/concepts/data_bus.mdx} | 4 +- .../noir/concepts/data_types}/_category_.json | 0 .../noir/concepts/data_types/arrays.md | 26 +- .../noir/concepts/data_types/booleans.md | 0 .../noir/concepts/data_types/fields.md | 240 +++++ .../concepts}/data_types/function_types.md | 0 .../noir/concepts/data_types/index.md | 8 + .../noir/concepts/data_types/integers.md | 0 .../noir/concepts}/data_types/references.md | 0 .../noir/concepts/data_types/slices.mdx | 167 +++- .../noir/concepts/data_types/strings.md | 0 .../noir/concepts}/data_types/structs.md | 0 .../noir/concepts}/data_types/tuples.md | 0 .../noir/concepts/functions.md | 0 .../version-v0.34.0/noir/concepts/generics.md | 258 +++++ .../noir/concepts/globals.md | 0 .../noir/concepts/lambdas.md | 0 .../noir/concepts/mutability.md | 0 .../noir/concepts/ops.md | 0 .../noir/concepts/oracles.mdx} | 6 +- .../noir/concepts/shadowing.md | 0 .../noir/concepts/traits.md | 78 +- .../noir/concepts/unconstrained.md | 9 +- .../modules_packages_crates/_category_.json | 0 .../crates_and_packages.md | 0 .../modules_packages_crates/dependencies.md | 0 .../noir/modules_packages_crates/modules.md | 106 ++ .../modules_packages_crates/workspaces.md | 0 .../noir/standard_library/_category_.json | 0 .../noir/standard_library/bigint.md | 7 +- .../noir/standard_library/black_box_fns.md | 0 .../noir/standard_library/bn254.md | 0 .../standard_library/containers/boundedvec.md | 10 +- .../standard_library/containers/hashmap.md | 144 +-- .../noir/standard_library/containers/index.md | 0 .../noir/standard_library/containers/vec.mdx | 0 .../cryptographic_primitives}/_category_.json | 0 .../cryptographic_primitives/ciphers.mdx | 2 +- .../cryptographic_primitives/ec_primitives.md | 4 +- .../ecdsa_sig_verification.mdx | 4 +- .../cryptographic_primitives/eddsa.mdx | 0 .../embedded_curve_ops.mdx | 15 +- .../cryptographic_primitives/hashes.mdx | 45 +- .../cryptographic_primitives/index.md | 0 .../cryptographic_primitives/schnorr.mdx | 2 +- .../noir/standard_library/fmtstr.md | 17 + .../noir/standard_library/is_unconstrained.md | 12 +- .../noir/standard_library/logging.md | 0 .../noir/standard_library/merkle_trees.md | 0 .../noir/standard_library/meta/expr.md | 323 ++++++ .../standard_library/meta/function_def.md | 166 ++++ .../noir/standard_library/meta/index.md | 210 ++++ .../noir/standard_library/meta/module.md | 82 ++ .../noir/standard_library/meta/op.md | 244 +++++ .../noir/standard_library/meta/quoted.md | 138 +++ .../noir/standard_library/meta/struct_def.md | 177 ++++ .../standard_library/meta/trait_constraint.md | 17 + .../noir/standard_library/meta/trait_def.md | 26 + .../noir/standard_library/meta/trait_impl.md | 60 ++ .../noir/standard_library/meta/typ.md | 239 +++++ .../noir/standard_library/meta/typed_expr.md | 27 + .../standard_library/meta/unresolved_type.md | 17 + .../noir/standard_library/options.md | 0 .../noir/standard_library/recursion.md | 12 +- .../noir/standard_library/traits.md | 265 ++++- .../noir/standard_library/zeroed.md | 0 .../NoirJS}/backend_barretenberg/.nojekyll | 0 .../classes/BarretenbergBackend.md | 22 + .../classes/BarretenbergVerifier.md | 0 .../classes/UltraHonkBackend.md | 116 +++ .../classes/UltraHonkVerifier.md} | 8 +- .../NoirJS/backend_barretenberg/index.md | 2 + .../type-aliases/BackendOptions.md | 0 .../backend_barretenberg/typedoc-sidebar.cjs | 4 + .../reference/NoirJS}/noir_js/.nojekyll | 0 .../reference/NoirJS/noir_js/classes/Noir.md | 0 .../NoirJS}/noir_js/functions/and.md | 0 .../NoirJS}/noir_js/functions/blake2s256.md | 0 .../functions/ecdsa_secp256k1_verify.md | 0 .../functions/ecdsa_secp256r1_verify.md | 0 .../NoirJS}/noir_js/functions/keccak256.md | 0 .../NoirJS}/noir_js/functions/sha256.md | 0 .../NoirJS}/noir_js/functions/xor.md | 0 .../reference/NoirJS/noir_js/index.md | 0 .../noir_js/type-aliases/ErrorWithPayload.md | 0 .../type-aliases/ForeignCallHandler.md | 0 .../noir_js/type-aliases/ForeignCallInput.md | 0 .../noir_js/type-aliases/ForeignCallOutput.md | 0 .../noir_js/type-aliases/WitnessMap.md | 0 .../NoirJS/noir_js/typedoc-sidebar.cjs | 0 .../reference/NoirJS/noir_wasm}/.nojekyll | 0 .../NoirJS/noir_wasm/functions/compile.md | 0 .../noir_wasm/functions/compile_contract.md | 0 .../noir_wasm/functions/createFileManager.md | 0 .../functions/inflateDebugSymbols.md | 0 .../reference/NoirJS/noir_wasm/index.md | 0 .../NoirJS/noir_wasm/typedoc-sidebar.cjs | 0 .../reference/_category_.json | 0 .../reference/debugger/_category_.json | 0 .../debugger/debugger_known_limitations.md | 0 .../reference/debugger/debugger_repl.md | 0 .../reference/debugger/debugger_vscode.md | 0 .../reference/nargo_commands.md | 182 +--- .../reference}/noir_codegen.md | 2 +- .../tooling/debugger.md | 0 .../tooling/language_server.md | 0 .../tooling/testing.md | 21 +- .../tutorials/noirjs_app.md | 14 + .../version-v0.17.0-sidebars.json | 141 --- .../version-v0.19.0-sidebars.json | 141 --- .../version-v0.19.1-sidebars.json | 288 ------ .../version-v0.19.2-sidebars.json | 288 ------ .../version-v0.19.3-sidebars.json | 288 ------ .../version-v0.19.4-sidebars.json | 293 ------ .../version-v0.22.0-sidebars.json | 83 -- .../version-v0.23.0-sidebars.json | 83 -- .../version-v0.24.0-sidebars.json | 83 -- .../version-v0.25.0-sidebars.json | 83 -- .../version-v0.26.0-sidebars.json | 83 -- .../version-v0.27.0-sidebars.json | 83 -- .../version-v0.29.0-sidebars.json | 93 -- .../version-v0.30.0-sidebars.json | 93 -- .../version-v0.31.0-sidebars.json | 93 -- ...ars.json => version-v0.34.0-sidebars.json} | 0 noir/noir-repo/noir_stdlib/src/append.nr | 2 +- noir/noir-repo/noir_stdlib/src/array/mod.nr | 143 ++- noir/noir-repo/noir_stdlib/src/bigint.nr | 16 +- noir/noir-repo/noir_stdlib/src/cmp.nr | 6 +- .../src/collections/bounded_vec.nr | 4 +- .../noir_stdlib/src/collections/map.nr | 2 +- .../noir_stdlib/src/collections/umap.nr | 2 +- .../noir_stdlib/src/collections/vec.nr | 2 +- noir/noir-repo/noir_stdlib/src/convert.nr | 4 +- noir/noir-repo/noir_stdlib/src/default.nr | 2 +- .../noir-repo/noir_stdlib/src/ec/consts/te.nr | 2 +- .../noir-repo/noir_stdlib/src/ec/montcurve.nr | 8 +- noir/noir-repo/noir_stdlib/src/ec/swcurve.nr | 8 +- noir/noir-repo/noir_stdlib/src/ec/tecurve.nr | 8 +- .../noir_stdlib/src/embedded_curve_ops.nr | 84 +- noir/noir-repo/noir_stdlib/src/hash/keccak.nr | 4 +- noir/noir-repo/noir_stdlib/src/hash/mimc.nr | 4 +- noir/noir-repo/noir_stdlib/src/hash/mod.nr | 8 +- .../noir_stdlib/src/hash/poseidon/mod.nr | 4 +- .../noir_stdlib/src/hash/poseidon2.nr | 4 +- .../noir_stdlib/src/meta/ctstring.nr | 98 ++ noir/noir-repo/noir_stdlib/src/meta/expr.nr | 398 ++++---- noir/noir-repo/noir_stdlib/src/meta/mod.nr | 20 +- noir/noir-repo/noir_stdlib/src/meta/op.nr | 4 +- noir/noir-repo/noir_stdlib/src/ops/arith.nr | 12 +- noir/noir-repo/noir_stdlib/src/ops/bit.nr | 12 +- noir/noir-repo/noir_stdlib/src/option.nr | 2 +- noir/noir-repo/noir_stdlib/src/schnorr.nr | 65 ++ noir/noir-repo/noir_stdlib/src/test.nr | 2 +- noir/noir-repo/noir_stdlib/src/uint128.nr | 2 +- noir/noir-repo/scripts/install_bb.sh | 2 +- .../comptime_parse_all_tokens/Nargo.toml | 7 + .../comptime_parse_all_tokens/src/main.nr | 9 + .../Nargo.toml | 7 + .../src/main.nr | 2 + .../macro_result_type/Nargo.toml | 7 + .../macro_result_type/src/main.nr | 13 + .../arithmetic_generics/src/main.nr | 7 +- .../closure_explicit_types/src/main.nr | 2 +- .../Nargo.toml | 7 + .../src/main.nr | 19 + .../Nargo.toml | 7 + .../src/main.nr | 27 + .../comptime_to_radix}/Nargo.toml | 2 +- .../comptime_to_radix/src/main.nr | 10 + .../compile_success_empty/ctstring/Nargo.toml | 7 + .../ctstring/src/main.nr | 18 + .../Nargo.toml | 7 + .../src/main.nr | 25 + .../macros_in_comptime/src/main.nr | 5 +- .../numeric_generics/src/main.nr | 6 +- .../numeric_generics_explicit/src/main.nr | 2 +- .../Nargo.toml | 7 + .../src/main.nr | 6 + .../references_aliasing/src/main.nr | 18 + .../regression_4635/src/main.nr | 2 +- .../regression_6077/Nargo.toml | 7 + .../regression_6077/Prover.toml | 1 + .../regression_6077/src/main.nr | 28 + .../serialize/src/main.nr | 6 +- .../trait_generics/src/main.nr | 4 +- .../type_path/Nargo.toml | 7 + .../type_path/src/main.nr | 15 + .../use_callers_scope/Nargo.toml | 7 + .../use_callers_scope/src/main.nr | 34 + .../databus_mapping_regression/Nargo.toml | 7 + .../databus_mapping_regression/src/main.nr | 42 + .../execution_success/7_function/src/main.nr | 2 +- .../aes128_encrypt/src/main.nr | 2 +- .../execution_success/array_len/src/main.nr | 6 +- .../array_to_slice/src/main.nr | 2 +- .../Nargo.toml | 6 + .../Prover.toml | 1 + .../src/main.nr | 16 + .../brillig_cow_regression/src/main.nr | 20 +- .../brillig_keccak/src/main.nr | 2 +- .../cast_and_shift_global/src/main.nr | 6 +- .../execution_success/debug_logs/src/main.nr | 4 +- .../fold_numeric_generic_poseidon/src/main.nr | 2 +- .../execution_success/generics/src/main.nr | 6 +- .../global_consts/src/foo.nr | 4 +- .../global_consts/src/foo/bar.nr | 2 +- .../global_consts/src/main.nr | 28 +- .../execution_success/hashmap/src/main.nr | 2 +- .../execution_success/hashmap/src/utils.nr | 2 +- .../src/main.nr | 4 +- .../reference_only_used_as_alias/Nargo.toml | 7 + .../reference_only_used_as_alias/Prover.toml | 3 + .../reference_only_used_as_alias/src/main.nr | 88 ++ .../execution_success/regression/src/main.nr | 4 +- .../regression_4088/src/main.nr | 2 +- .../regression_4124/src/main.nr | 2 +- .../Nargo.toml | 5 + .../Prover.toml | 2 + .../src/main.nr | 25 + .../execution_success/schnorr/src/main.nr | 96 +- .../verify_honk_proof/Prover.toml | 4 - .../verify_honk_proof/src/main.nr | 17 - .../noir_test_success/bounded_vec/src/main.nr | 2 +- .../comptime_expr/src/main.nr | 123 +++ .../tooling/debugger/ignored-tests.txt | 3 +- noir/noir-repo/tooling/lsp/src/lib.rs | 25 +- .../tooling/lsp/src/notifications/mod.rs | 23 +- .../code_action/fill_struct_fields.rs | 12 +- .../code_action/implement_missing_members.rs | 442 +-------- .../requests/code_action/import_or_qualify.rs | 8 +- .../lsp/src/requests/code_lens_request.rs | 2 +- .../tooling/lsp/src/requests/completion.rs | 410 +++++++- .../src/requests/completion/auto_import.rs | 105 +- .../lsp/src/requests/completion/builtins.rs | 2 + .../requests/completion/completion_items.rs | 102 +- .../lsp/src/requests/completion/tests.rs | 307 +++++- .../tooling/lsp/src/requests/hover.rs | 98 +- .../tooling/lsp/src/requests/inlay_hint.rs | 10 +- .../noir-repo/tooling/lsp/src/requests/mod.rs | 88 +- .../tooling/lsp/src/requests/references.rs | 2 +- .../tooling/lsp/src/requests/rename.rs | 2 +- .../lsp/src/requests/signature_help.rs | 35 +- .../tooling/lsp/src/requests/test_run.rs | 2 +- .../src/trait_impl_method_stub_generator.rs | 455 +++++++++ noir/noir-repo/tooling/nargo/src/errors.rs | 9 +- .../tooling/nargo_cli/src/cli/execute_cmd.rs | 10 +- .../tooling/nargo_fmt/src/rewrite/expr.rs | 26 +- .../tooling/nargo_fmt/src/visitor/stmt.rs | 38 +- .../tooling/noir_codegen/package.json | 2 +- .../noir_codegen/test/test_lib/src/lib.nr | 4 +- noir/noir-repo/tooling/noir_js/package.json | 2 +- .../noir_js/scripts/compile_test_programs.sh | 1 + .../tooling/noir_js/test/node/execute.test.ts | 85 +- .../noir_compiled_examples/databus/Nargo.toml | 5 + .../databus/src/main.nr | 12 + .../noir_js_backend_barretenberg/package.json | 4 +- .../tooling/noir_js_types/package.json | 2 +- noir/noir-repo/tooling/noirc_abi/src/lib.rs | 17 +- .../noir-repo/tooling/noirc_abi_wasm/build.sh | 2 +- .../tooling/noirc_abi_wasm/package.json | 2 +- noir/noir-repo/yarn.lock | 13 +- 1803 files changed, 11595 insertions(+), 119776 deletions(-) delete mode 100644 noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/bubble_up_constrains.rs create mode 100644 noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/display.rs delete mode 100644 noir/noir-repo/compiler/noirc_frontend/src/parser/parser.rs:28:9 create mode 100644 noir/noir-repo/docs/docs/noir/standard_library/meta/ctstring.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/examples/merkle-proof.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/getting_started/00_nargo_installation.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/getting_started/01_hello_world.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/getting_started/02_breakdown.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/01_functions.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/02_control_flow.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/03_ops.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/04_assert.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/05_unconstrained.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/06_generics.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/07_mutability.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/08_lambdas.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/09_comments.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/10_distinct.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/11_shadowing.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/00_fields.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/01_integers.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/02_booleans.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/03_strings.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/04_arrays.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/05_slices.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/06_vectors.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/07_tuples.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/08_structs.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/09_references.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/10_function_types.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/migration_notes.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/modules_packages_crates/crates_and_packages.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/modules_packages_crates/dependencies.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/modules_packages_crates/modules.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/modules_packages_crates/workspaces.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/nargo/01_commands.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/nargo/02_testing.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/nargo/03_solidity_verifier.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/nargo/04_language_server.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/noir_js/getting_started/01_tiny_noir_app.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/noir_js/noir_js.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/noir_js/reference/01_noirjs.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/noir_js/reference/02_bb_backend.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/black_box_fns.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives/00_hashes.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives/01_scalar.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives/02_schnorr.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives/04_ec_primitives.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives/05_eddsa.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/logging.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/merkle_trees.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/options.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/recursion.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/zeroed.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/examples/merkle-proof.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/getting_started/00_nargo_installation.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/getting_started/01_hello_world.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/getting_started/02_breakdown.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/01_functions.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/02_control_flow.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/03_ops.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/04_assert.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/05_unconstrained.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/06_generics.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/07_mutability.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/08_lambdas.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/09_comments.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/10_distinct.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/11_shadowing.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/00_fields.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/01_integers.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/02_booleans.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/03_strings.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/04_arrays.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/05_slices.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/06_vectors.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/07_tuples.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/08_structs.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/09_references.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/10_function_types.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/migration_notes.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/modules_packages_crates/crates_and_packages.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/modules_packages_crates/dependencies.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/modules_packages_crates/modules.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/modules_packages_crates/workspaces.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/nargo/01_commands.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/nargo/02_testing.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/nargo/03_solidity_verifier.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/nargo/04_language_server.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/getting_started/01_tiny_noir_app.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/noir_js.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/01_noirjs.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/02_bb_backend.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/classes/BarretenbergBackend.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/interfaces/Backend.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/type-aliases/BackendOptions.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/type-aliases/ProofData.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/classes/Noir.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/type-aliases/CompiledCircuit.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/type-aliases/ProofData.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/typedoc-sidebar.cjs delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/black_box_fns.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives/00_hashes.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives/01_scalar.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives/02_schnorr.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives/04_ec_primitives.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives/05_eddsa.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/logging.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/merkle_trees.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/options.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/recursion.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/zeroed.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/examples/merkle-proof.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/getting_started/00_nargo_installation.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/getting_started/01_hello_world.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/getting_started/02_breakdown.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/01_functions.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/02_control_flow.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/03_ops.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/04_assert.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/05_unconstrained.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/06_generics.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/07_mutability.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/08_lambdas.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/09_comments.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/10_distinct.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/11_shadowing.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/00_fields.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/01_integers.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/02_booleans.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/03_strings.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/04_arrays.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/05_slices.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/06_vectors.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/07_tuples.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/08_structs.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/09_references.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/10_function_types.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/migration_notes.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/modules_packages_crates/crates_and_packages.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/modules_packages_crates/dependencies.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/modules_packages_crates/modules.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/modules_packages_crates/workspaces.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/nargo/01_commands.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/nargo/02_testing.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/nargo/03_solidity_verifier.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/nargo/04_language_server.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/getting_started/01_tiny_noir_app.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/noir_js.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/classes/BarretenbergBackend.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/interfaces/Backend.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/type-aliases/BackendOptions.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/type-aliases/ProofData.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/.nojekyll delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/classes/Noir.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/functions/and.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/functions/blake2s256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/functions/keccak256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/functions/sha256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/functions/xor.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/type-aliases/CompiledCircuit.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/type-aliases/ForeignCallHandler.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/type-aliases/ForeignCallInput.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/type-aliases/ForeignCallOutput.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/type-aliases/ProofData.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/type-aliases/WitnessMap.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/typedoc-sidebar.cjs delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/black_box_fns.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives/00_hashes.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives/01_scalar.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives/02_schnorr.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives/04_ec_primitives.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives/05_eddsa.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/logging.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/merkle_trees.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/options.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/recursion.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/zeroed.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/examples/merkle-proof.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/getting_started/00_nargo_installation.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/getting_started/01_hello_world.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/getting_started/02_breakdown.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/01_functions.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/02_control_flow.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/03_ops.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/04_assert.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/05_unconstrained.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/06_generics.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/07_mutability.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/08_lambdas.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/09_comments.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/10_distinct.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/11_shadowing.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/00_fields.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/01_integers.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/02_booleans.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/03_strings.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/04_arrays.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/05_slices.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/06_vectors.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/07_tuples.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/08_structs.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/09_references.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/10_function_types.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/migration_notes.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/modules_packages_crates/crates_and_packages.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/modules_packages_crates/dependencies.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/modules_packages_crates/modules.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/modules_packages_crates/workspaces.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/nargo/01_commands.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/nargo/02_testing.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/nargo/03_solidity_verifier.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/nargo/04_language_server.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/getting_started/01_tiny_noir_app.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/noir_js.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/.nojekyll delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/classes/BarretenbergBackend.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/interfaces/Backend.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/type-aliases/BackendOptions.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/type-aliases/ProofData.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/.nojekyll delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/classes/Noir.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/functions/and.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/functions/blake2s256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/functions/keccak256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/functions/sha256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/functions/xor.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/type-aliases/CompiledCircuit.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/type-aliases/ForeignCallHandler.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/type-aliases/ForeignCallInput.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/type-aliases/ForeignCallOutput.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/type-aliases/ProofData.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/type-aliases/WitnessMap.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/typedoc-sidebar.cjs delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/black_box_fns.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives/00_hashes.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives/01_scalar.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives/02_schnorr.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives/04_ec_primitives.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives/05_eddsa.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/logging.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/merkle_trees.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/options.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/recursion.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/zeroed.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/examples/merkle-proof.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/getting_started/00_nargo_installation.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/getting_started/01_hello_world.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/getting_started/02_breakdown.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/01_functions.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/02_control_flow.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/03_ops.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/04_assert.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/05_unconstrained.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/06_generics.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/07_mutability.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/08_lambdas.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/09_comments.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/10_distinct.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/11_shadowing.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/00_fields.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/01_integers.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/02_booleans.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/03_strings.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/04_arrays.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/05_slices.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/06_vectors.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/07_tuples.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/08_structs.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/09_references.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/10_function_types.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/migration_notes.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/modules_packages_crates/crates_and_packages.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/modules_packages_crates/dependencies.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/modules_packages_crates/modules.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/modules_packages_crates/workspaces.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/nargo/01_commands.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/nargo/02_testing.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/nargo/03_solidity_verifier.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/nargo/04_language_server.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/getting_started/01_tiny_noir_app.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/noir_js.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/.nojekyll delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/classes/BarretenbergBackend.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/interfaces/Backend.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/type-aliases/BackendOptions.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/type-aliases/ProofData.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/.nojekyll delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/classes/Noir.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/and.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/blake2s256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/keccak256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/sha256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/xor.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/CompiledCircuit.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/ForeignCallHandler.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/ForeignCallInput.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/ForeignCallOutput.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/ProofData.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/WitnessMap.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/typedoc-sidebar.cjs delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/black_box_fns.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/00_hashes.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/01_scalar.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/02_schnorr.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/04_ec_primitives.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/05_eddsa.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/logging.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/merkle_trees.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/options.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/recursion.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/zeroed.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/examples/merkle-proof.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/getting_started/00_nargo_installation.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/getting_started/01_hello_world.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/getting_started/02_breakdown.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/01_functions.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/02_control_flow.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/03_ops.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/04_assert.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/05_unconstrained.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/06_generics.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/07_mutability.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/08_lambdas.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/09_comments.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/10_distinct.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/11_shadowing.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/00_fields.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/01_integers.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/02_booleans.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/03_strings.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/04_arrays.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/05_slices.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/06_vectors.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/07_tuples.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/08_structs.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/09_references.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/10_function_types.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/migration_notes.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/modules_packages_crates/crates_and_packages.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/modules_packages_crates/dependencies.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/modules_packages_crates/modules.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/modules_packages_crates/workspaces.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/nargo/01_commands.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/nargo/02_testing.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/nargo/03_solidity_verifier.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/nargo/04_language_server.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/getting_started/01_tiny_noir_app.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/noir_js.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/.nojekyll delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/classes/BarretenbergBackend.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/interfaces/Backend.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/type-aliases/BackendOptions.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/type-aliases/ProofData.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/.nojekyll delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/classes/Noir.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/and.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/blake2s256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/keccak256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/sha256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/xor.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/CompiledCircuit.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/ForeignCallHandler.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/ForeignCallInput.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/ForeignCallOutput.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/InputMap.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/ProofData.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/WitnessMap.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/typedoc-sidebar.cjs delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/black_box_fns.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/00_hashes.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/01_scalar.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/02_schnorr.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/04_ec_primitives.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/05_eddsa.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/logging.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/merkle_trees.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/options.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/recursion.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/zeroed.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/explainers/explainer-recursion.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/explanations/noir/traits.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/explanations/standard_library/traits.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/getting_started/create_a_project.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/getting_started/installation/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/getting_started/installation/other_install_methods.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/getting_started/project_breakdown.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/getting_started/tooling/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/getting_started/tooling/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/how_to/how-to-recursion.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/how_to/merkle-proof.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/how_to/solidity_verifier.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/migration_notes.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/dependencies.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/black_box_fns.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/ec_primitives.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/eddsa.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/hashes.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/scalar.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/schnorr.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/logging.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/merkle_trees.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/options.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/recursion.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/zeroed.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/assert.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/comments.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/control_flow.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_bus.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/arrays.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/booleans.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/fields.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/integers.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/slices.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/strings.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/vectors.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/distinct.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/functions.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/generics.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/lambdas.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/mutability.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/ops.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/shadowing.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/unconstrained.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/.nojekyll delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/interfaces/Backend.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/type-aliases/ProofData.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/.nojekyll delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/classes/Noir.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/and.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/blake2s256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/keccak256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/sha256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/xor.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/CompiledCircuit.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/InputMap.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/ProofData.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/nargo_commands.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.22.0/tutorials/noirjs_app.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/hello_noir/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/hello_noir/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/hello_noir/project_breakdown.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/installation/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/installation/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/installation/other_install_methods.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/tooling/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/tooling/index.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/tooling/language_server.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/tooling/testing.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/how_to/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/how_to/how-to-oracles.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/how_to/how-to-recursion.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/how_to/how-to-solidity-verifier.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/how_to/merkle-proof.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/index.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/migration_notes.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/assert.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/control_flow.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_bus.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/arrays.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/booleans.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/fields.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/function_types.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/integers.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/references.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/slices.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/strings.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/structs.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/tuples.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/vectors.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/distinct.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/functions.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/generics.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/mutability.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/ops.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/oracles.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/traits.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/unconstrained.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/crates_and_packages.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/dependencies.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/modules.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/workspaces.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/black_box_fns.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/cryptographic_primitives/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/cryptographic_primitives/ec_primitives.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/cryptographic_primitives/eddsa.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/cryptographic_primitives/hashes.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/cryptographic_primitives/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/cryptographic_primitives/scalar.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/cryptographic_primitives/schnorr.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/merkle_trees.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/options.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/recursion.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/traits.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/zeroed.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/backend_barretenberg/.nojekyll delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/backend_barretenberg/classes/BarretenbergBackend.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/backend_barretenberg/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/backend_barretenberg/interfaces/Backend.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/backend_barretenberg/type-aliases/BackendOptions.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/backend_barretenberg/type-aliases/ProofData.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/.nojekyll delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/classes/Noir.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/functions/and.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/functions/blake2s256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/functions/keccak256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/functions/sha256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/functions/xor.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/type-aliases/CompiledCircuit.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/type-aliases/ForeignCallHandler.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/type-aliases/ForeignCallInput.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/type-aliases/ForeignCallOutput.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/type-aliases/InputMap.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/type-aliases/ProofData.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/type-aliases/WitnessMap.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/typedoc-sidebar.cjs delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/backend_barretenberg/.nojekyll delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/backend_barretenberg/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/backend_barretenberg/interfaces/Backend.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/backend_barretenberg/type-aliases/ProofData.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/.nojekyll delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/classes/Noir.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/functions/and.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/functions/blake2s256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/functions/keccak256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/functions/sha256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/functions/xor.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/type-aliases/CompiledCircuit.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/type-aliases/InputMap.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/type-aliases/ProofData.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_wasm/.nojekyll delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_wasm/functions/compile.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_wasm/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_wasm/type-aliases/CompilationResult.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/nargo_commands.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.23.0/tutorials/noirjs_app.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/explainers/explainer-oracle.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/explainers/explainer-recursion.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/hello_noir/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/hello_noir/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/hello_noir/project_breakdown.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/installation/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/installation/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/installation/other_install_methods.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/tooling/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/tooling/index.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/tooling/language_server.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/tooling/testing.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/how_to/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/how_to/how-to-oracles.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/how_to/how-to-recursion.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/how_to/how-to-solidity-verifier.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/how_to/merkle-proof.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/how_to/using-devcontainers.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/index.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/migration_notes.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/comments.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/control_flow.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_bus.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/arrays.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/booleans.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/fields.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/function_types.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/integers.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/references.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/slices.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/strings.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/structs.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/tuples.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/vectors.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/distinct.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/functions.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/generics.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/lambdas.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/ops.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/oracles.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/shadowing.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/traits.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/unconstrained.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/crates_and_packages.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/dependencies.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/modules.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/workspaces.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/black_box_fns.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/bn254.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/cryptographic_primitives/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/cryptographic_primitives/ec_primitives.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/cryptographic_primitives/eddsa.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/cryptographic_primitives/hashes.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/cryptographic_primitives/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/cryptographic_primitives/scalar.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/cryptographic_primitives/schnorr.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/logging.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/merkle_trees.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/recursion.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/traits.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/zeroed.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/reference/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/reference/nargo_commands.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.24.0/tutorials/noirjs_app.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/explainers/explainer-oracle.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/explainers/explainer-recursion.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/hello_noir/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/hello_noir/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/hello_noir/project_breakdown.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/installation/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/installation/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/installation/other_install_methods.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/tooling/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/tooling/index.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/tooling/language_server.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/tooling/testing.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/how-to-oracles.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/how-to-recursion.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/how-to-solidity-verifier.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/merkle-proof.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/using-devcontainers.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/index.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/assert.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/comments.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/control_flow.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_bus.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/arrays.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/booleans.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/fields.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/function_types.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/integers.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/references.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/slices.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/strings.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/structs.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/tuples.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/distinct.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/functions.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/generics.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/globals.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/lambdas.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/mutability.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/ops.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/oracles.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/shadowing.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/traits.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/unconstrained.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/crates_and_packages.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/dependencies.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/modules.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/workspaces.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/black_box_fns.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/bn254.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/boundedvec.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/hashmap.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/vec.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/ec_primitives.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/eddsa.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/hashes.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/scalar.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/schnorr.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/logging.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/merkle_trees.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/options.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/recursion.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/traits.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/zeroed.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/.nojekyll delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/interfaces/Backend.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/type-aliases/ProofData.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/.nojekyll delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/classes/Noir.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/and.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/blake2s256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/keccak256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/sha256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/xor.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/type-aliases/CompiledCircuit.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/type-aliases/InputMap.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/type-aliases/ProofData.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_wasm/.nojekyll delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_wasm/functions/createFileManager.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/nargo_commands.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.25.0/tutorials/noirjs_app.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/explainers/explainer-oracle.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/explainers/explainer-recursion.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/hello_noir/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/hello_noir/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/hello_noir/project_breakdown.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/installation/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/installation/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/tooling/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/tooling/index.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/tooling/language_server.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/tooling/noir_codegen.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/tooling/testing.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/how_to/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/how_to/how-to-oracles.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/how_to/how-to-recursion.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/how_to/how-to-solidity-verifier.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/how_to/merkle-proof.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/how_to/using-devcontainers.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/index.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/migration_notes.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/assert.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/comments.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/booleans.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/fields.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/function_types.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/integers.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/references.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/slices.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/strings.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/structs.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/tuples.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/distinct.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/functions.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/generics.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/globals.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/lambdas.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/mutability.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/ops.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/oracles.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/shadowing.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/traits.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/crates_and_packages.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/dependencies.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/modules.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/workspaces.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/bigint.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/black_box_fns.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/bn254.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/containers/boundedvec.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/containers/hashmap.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/containers/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/containers/vec.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/ec_primitives.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/eddsa.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/hashes.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/scalar.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/logging.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/options.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/recursion.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/traits.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/backend_barretenberg/.nojekyll delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/backend_barretenberg/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/.nojekyll delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/classes/Noir.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/and.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/blake2s256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/keccak256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/sha256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/xor.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/.nojekyll delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/functions/compile.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/functions/compile_contract.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/functions/createFileManager.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/nargo_commands.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.26.0/tutorials/noirjs_app.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/explainers/explainer-oracle.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/explainers/explainer-recursion.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/hello_noir/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/hello_noir/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/hello_noir/project_breakdown.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/installation/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/installation/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/installation/other_install_methods.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/tooling/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/tooling/index.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/tooling/language_server.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/tooling/noir_codegen.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/tooling/testing.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/how_to/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/how_to/how-to-oracles.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/how_to/how-to-recursion.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/how_to/how-to-solidity-verifier.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/how_to/merkle-proof.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/how_to/using-devcontainers.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/index.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/migration_notes.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/assert.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/comments.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/control_flow.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_bus.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/arrays.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/booleans.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/fields.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/function_types.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/integers.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/references.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/slices.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/strings.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/structs.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/tuples.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/distinct.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/functions.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/generics.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/globals.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/lambdas.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/mutability.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/ops.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/oracles.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/shadowing.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/traits.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/unconstrained.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/crates_and_packages.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/dependencies.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/modules.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/workspaces.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/bigint.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/black_box_fns.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/bn254.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/containers/boundedvec.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/containers/hashmap.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/containers/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/containers/vec.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/ec_primitives.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/eddsa.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/hashes.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/scalar.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/schnorr.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/logging.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/merkle_trees.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/options.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/recursion.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/traits.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/zeroed.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/backend_barretenberg/.nojekyll delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/backend_barretenberg/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/.nojekyll delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/classes/Noir.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/and.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/blake2s256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/keccak256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/sha256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/xor.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/.nojekyll delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/functions/compile.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/functions/compile_contract.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/functions/createFileManager.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.27.0/tutorials/noirjs_app.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/explainers/explainer-oracle.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/explainers/explainer-recursion.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/getting_started/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/getting_started/hello_noir/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/getting_started/hello_noir/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/getting_started/hello_noir/project_breakdown.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/getting_started/installation/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/getting_started/installation/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/getting_started/installation/other_install_methods.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/getting_started/tooling/noir_codegen.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/how_to/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/how_to/how-to-oracles.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/how_to/how-to-recursion.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/how_to/how-to-solidity-verifier.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/how_to/merkle-proof.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/how_to/using-devcontainers.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/index.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/migration_notes.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/assert.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/comments.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/control_flow.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_bus.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/arrays.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/booleans.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/fields.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/function_types.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/integers.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/references.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/slices.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/strings.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/structs.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/tuples.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/distinct.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/generics.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/globals.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/lambdas.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/mutability.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/ops.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/shadowing.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/traits.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/unconstrained.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/crates_and_packages.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/dependencies.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/modules.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/workspaces.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/bigint.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/black_box_fns.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/bn254.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/containers/boundedvec.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/containers/hashmap.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/containers/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/containers/vec.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/ec_primitives.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/eddsa.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/hashes.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/scalar.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/schnorr.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/logging.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/merkle_trees.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/options.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/recursion.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/traits.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/zeroed.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/backend_barretenberg/.nojekyll delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/backend_barretenberg/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/.nojekyll delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/classes/Noir.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/and.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/blake2s256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/keccak256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/sha256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/xor.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/.nojekyll delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/functions/compile.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/functions/compile_contract.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/functions/createFileManager.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/nargo_commands.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/tooling/language_server.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/tooling/testing.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.28.0/tutorials/noirjs_app.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/explainers/explainer-oracle.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/explainers/explainer-recursion.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/getting_started/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/getting_started/hello_noir/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/getting_started/hello_noir/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/getting_started/hello_noir/project_breakdown.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/getting_started/installation/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/getting_started/installation/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/getting_started/installation/other_install_methods.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/getting_started/tooling/noir_codegen.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/how_to/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/how_to/debugger/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/how_to/debugger/debugging_with_the_repl.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/how_to/debugger/debugging_with_vs_code.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/how_to/how-to-oracles.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/how_to/how-to-recursion.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/how_to/how-to-solidity-verifier.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/how_to/merkle-proof.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/how_to/using-devcontainers.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/index.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/migration_notes.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/assert.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/comments.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/control_flow.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_bus.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/arrays.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/booleans.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/fields.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/function_types.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/integers.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/references.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/slices.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/strings.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/structs.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/tuples.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/functions.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/generics.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/globals.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/lambdas.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/mutability.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/oracles.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/shadowing.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/traits.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/unconstrained.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/crates_and_packages.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/dependencies.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/modules.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/workspaces.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/bigint.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/black_box_fns.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/bn254.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/containers/boundedvec.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/containers/hashmap.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/containers/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/containers/vec.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/ec_primitives.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/eddsa.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/hashes.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/scalar.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/schnorr.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/logging.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/merkle_trees.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/options.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/recursion.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/traits.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/zeroed.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/.nojekyll delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/.nojekyll delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/classes/Noir.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/and.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/blake2s256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/keccak256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/sha256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/xor.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/.nojekyll delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/functions/compile.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/functions/compile_contract.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/functions/createFileManager.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/debugger/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/debugger/debugger_known_limitations.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/debugger/debugger_repl.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/debugger/debugger_vscode.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/nargo_commands.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/tooling/debugger.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/tooling/language_server.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/tooling/testing.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.29.0/tutorials/noirjs_app.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/explainers/explainer-oracle.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/explainers/explainer-recursion.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/getting_started/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/getting_started/hello_noir/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/getting_started/hello_noir/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/getting_started/hello_noir/project_breakdown.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/getting_started/installation/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/getting_started/installation/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/getting_started/installation/other_install_methods.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/getting_started/tooling/noir_codegen.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/how_to/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/how_to/debugger/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/how_to/debugger/debugging_with_the_repl.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/how_to/debugger/debugging_with_vs_code.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/how_to/how-to-oracles.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/how_to/how-to-recursion.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/how_to/how-to-solidity-verifier.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/how_to/merkle-proof.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/how_to/using-devcontainers.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/index.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/migration_notes.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/assert.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/comments.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/control_flow.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_bus.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/arrays.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/booleans.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/fields.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/function_types.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/integers.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/references.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/slices.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/strings.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/structs.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/tuples.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/functions.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/generics.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/globals.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/lambdas.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/mutability.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/ops.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/oracles.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/shadowing.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/traits.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/unconstrained.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/crates_and_packages.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/dependencies.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/modules.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/workspaces.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/bn254.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/containers/boundedvec.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/containers/hashmap.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/containers/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/containers/vec.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/ec_primitives.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/eddsa.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/embedded_curve_ops.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/hashes.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/schnorr.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/logging.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/merkle_trees.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/options.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/recursion.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/zeroed.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/.nojekyll delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/.nojekyll delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/classes/Noir.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/and.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/blake2s256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/keccak256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/sha256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/xor.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/.nojekyll delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/functions/compile.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/functions/compile_contract.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/functions/createFileManager.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/debugger/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/debugger/debugger_known_limitations.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/debugger/debugger_repl.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/debugger/debugger_vscode.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/nargo_commands.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/tooling/debugger.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/tooling/language_server.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/tooling/testing.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.30.0/tutorials/noirjs_app.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/explainers/explainer-oracle.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/explainers/explainer-recursion.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/installation/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/installation/other_install_methods.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/debugger/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/debugger/debugging_with_the_repl.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/debugger/debugging_with_vs_code.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/using-devcontainers.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/migration_notes.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/assert.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/comments.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/control_flow.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_bus.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/arrays.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/fields.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/function_types.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/references.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/structs.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/tuples.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/functions.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/generics.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/globals.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/lambdas.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/mutability.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/ops.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/oracles.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/shadowing.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/unconstrained.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/crates_and_packages.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/modules.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/workspaces.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/bigint.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/black_box_fns.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/bn254.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/containers/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/ciphers.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/schnorr.mdx delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/logging.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/merkle_trees.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/options.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/traits.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/zeroed.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/.nojekyll delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/.nojekyll delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/and.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/blake2s256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/keccak256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/sha256.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/xor.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/ErrorWithPayload.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/.nojekyll delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/functions/compile.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/functions/compile_contract.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/functions/createFileManager.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/index.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/debugger/_category_.json delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/debugger/debugger_known_limitations.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/debugger/debugger_repl.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/debugger/debugger_vscode.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/nargo_commands.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/tooling/debugger.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/tooling/language_server.md delete mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/tooling/testing.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.34.0/explainers/cspell.json rename noir/noir-repo/docs/versioned_docs/{version-v0.23.0 => version-v0.34.0}/explainers/explainer-oracle.md (91%) rename noir/noir-repo/docs/versioned_docs/{version-v0.23.0 => version-v0.34.0}/explainers/explainer-recursion.md (100%) create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.34.0/explainers/explainer-writing-noir.md rename noir/noir-repo/docs/versioned_docs/{version-v0.22.0 => version-v0.34.0}/getting_started/_category_.json (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.31.0 => version-v0.34.0}/getting_started/backend/_category_.json (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.31.0 => version-v0.34.0}/getting_started/backend/index.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.31.0 => version-v0.34.0}/getting_started/hello_noir/_category_.json (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.31.0 => version-v0.34.0}/getting_started/hello_noir/index.md (93%) rename noir/noir-repo/docs/versioned_docs/{version-v0.31.0 => version-v0.34.0}/getting_started/hello_noir/project_breakdown.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.22.0 => version-v0.34.0}/getting_started/installation/_category_.json (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.31.0 => version-v0.34.0}/getting_started/installation/index.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.26.0 => version-v0.34.0}/getting_started/installation/other_install_methods.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.22.0 => version-v0.34.0}/how_to/_category_.json (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.28.0 => version-v0.34.0}/how_to/debugger/_category_.json (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.28.0 => version-v0.34.0}/how_to/debugger/debugging_with_the_repl.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.28.0 => version-v0.34.0}/how_to/debugger/debugging_with_vs_code.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.31.0 => version-v0.34.0}/how_to/how-to-oracles.md (95%) rename noir/noir-repo/docs/versioned_docs/{version-v0.31.0 => version-v0.34.0}/how_to/how-to-recursion.md (99%) rename noir/noir-repo/docs/versioned_docs/{version-v0.31.0 => version-v0.34.0}/how_to/how-to-solidity-verifier.md (95%) rename noir/noir-repo/docs/versioned_docs/{version-v0.31.0 => version-v0.34.0}/how_to/merkle-proof.mdx (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.23.0 => version-v0.34.0}/how_to/using-devcontainers.mdx (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.31.0 => version-v0.34.0}/index.mdx (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.25.0 => version-v0.34.0}/migration_notes.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.23.0 => version-v0.34.0}/noir/concepts/_category_.json (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.24.0 => version-v0.34.0}/noir/concepts/assert.md (51%) rename noir/noir-repo/docs/versioned_docs/{version-v0.23.0 => version-v0.34.0}/noir/concepts/comments.md (100%) create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/comptime.md rename noir/noir-repo/docs/versioned_docs/{version-v0.26.0 => version-v0.34.0}/noir/concepts/control_flow.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.26.0/noir/concepts/data_bus.md => version-v0.34.0/noir/concepts/data_bus.mdx} (88%) rename noir/noir-repo/docs/versioned_docs/{version-v0.22.0/noir/standard_library/cryptographic_primitives => version-v0.34.0/noir/concepts/data_types}/_category_.json (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.26.0 => version-v0.34.0}/noir/concepts/data_types/arrays.md (86%) rename noir/noir-repo/docs/versioned_docs/{version-v0.31.0 => version-v0.34.0}/noir/concepts/data_types/booleans.md (100%) create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/data_types/fields.md rename noir/noir-repo/docs/versioned_docs/{version-v0.22.0/noir/syntax => version-v0.34.0/noir/concepts}/data_types/function_types.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.26.0 => version-v0.34.0}/noir/concepts/data_types/index.md (86%) rename noir/noir-repo/docs/versioned_docs/{version-v0.31.0 => version-v0.34.0}/noir/concepts/data_types/integers.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.22.0/noir/syntax => version-v0.34.0/noir/concepts}/data_types/references.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.31.0 => version-v0.34.0}/noir/concepts/data_types/slices.mdx (55%) rename noir/noir-repo/docs/versioned_docs/{version-v0.31.0 => version-v0.34.0}/noir/concepts/data_types/strings.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.22.0/noir/syntax => version-v0.34.0/noir/concepts}/data_types/structs.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.22.0/noir/syntax => version-v0.34.0/noir/concepts}/data_types/tuples.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.28.0 => version-v0.34.0}/noir/concepts/functions.md (100%) create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/generics.md rename noir/noir-repo/docs/versioned_docs/{version-v0.24.0 => version-v0.34.0}/noir/concepts/globals.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.23.0 => version-v0.34.0}/noir/concepts/lambdas.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.24.0 => version-v0.34.0}/noir/concepts/mutability.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.29.0 => version-v0.34.0}/noir/concepts/ops.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.28.0/noir/concepts/oracles.md => version-v0.34.0/noir/concepts/oracles.mdx} (78%) rename noir/noir-repo/docs/versioned_docs/{version-v0.23.0 => version-v0.34.0}/noir/concepts/shadowing.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.31.0 => version-v0.34.0}/noir/concepts/traits.md (82%) rename noir/noir-repo/docs/versioned_docs/{version-v0.26.0 => version-v0.34.0}/noir/concepts/unconstrained.md (91%) rename noir/noir-repo/docs/versioned_docs/{version-v0.22.0 => version-v0.34.0}/noir/modules_packages_crates/_category_.json (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.22.0 => version-v0.34.0}/noir/modules_packages_crates/crates_and_packages.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.31.0 => version-v0.34.0}/noir/modules_packages_crates/dependencies.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.22.0 => version-v0.34.0}/noir/modules_packages_crates/modules.md (51%) rename noir/noir-repo/docs/versioned_docs/{version-v0.22.0 => version-v0.34.0}/noir/modules_packages_crates/workspaces.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.22.0 => version-v0.34.0}/noir/standard_library/_category_.json (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.30.0 => version-v0.34.0}/noir/standard_library/bigint.md (88%) rename noir/noir-repo/docs/versioned_docs/{version-v0.30.0 => version-v0.34.0}/noir/standard_library/black_box_fns.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.23.0 => version-v0.34.0}/noir/standard_library/bn254.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.31.0 => version-v0.34.0}/noir/standard_library/containers/boundedvec.md (97%) rename noir/noir-repo/docs/versioned_docs/{version-v0.31.0 => version-v0.34.0}/noir/standard_library/containers/hashmap.md (73%) rename noir/noir-repo/docs/versioned_docs/{version-v0.25.0 => version-v0.34.0}/noir/standard_library/containers/index.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.31.0 => version-v0.34.0}/noir/standard_library/containers/vec.mdx (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.22.0/noir/syntax/data_types => version-v0.34.0/noir/standard_library/cryptographic_primitives}/_category_.json (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.30.0 => version-v0.34.0}/noir/standard_library/cryptographic_primitives/ciphers.mdx (92%) rename noir/noir-repo/docs/versioned_docs/{version-v0.31.0 => version-v0.34.0}/noir/standard_library/cryptographic_primitives/ec_primitives.md (97%) rename noir/noir-repo/docs/versioned_docs/{version-v0.27.0 => version-v0.34.0}/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx (97%) rename noir/noir-repo/docs/versioned_docs/{version-v0.31.0 => version-v0.34.0}/noir/standard_library/cryptographic_primitives/eddsa.mdx (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.31.0 => version-v0.34.0}/noir/standard_library/cryptographic_primitives/embedded_curve_ops.mdx (83%) rename noir/noir-repo/docs/versioned_docs/{version-v0.31.0 => version-v0.34.0}/noir/standard_library/cryptographic_primitives/hashes.mdx (78%) rename noir/noir-repo/docs/versioned_docs/{version-v0.22.0 => version-v0.34.0}/noir/standard_library/cryptographic_primitives/index.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.26.0 => version-v0.34.0}/noir/standard_library/cryptographic_primitives/schnorr.mdx (98%) create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/fmtstr.md rename noir/noir-repo/docs/versioned_docs/{version-v0.31.0 => version-v0.34.0}/noir/standard_library/is_unconstrained.md (89%) rename noir/noir-repo/docs/versioned_docs/{version-v0.23.0 => version-v0.34.0}/noir/standard_library/logging.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.26.0 => version-v0.34.0}/noir/standard_library/merkle_trees.md (100%) create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/expr.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/function_def.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/index.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/module.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/op.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/quoted.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/struct_def.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/trait_constraint.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/trait_def.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/trait_impl.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/typ.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/typed_expr.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/unresolved_type.md rename noir/noir-repo/docs/versioned_docs/{version-v0.24.0 => version-v0.34.0}/noir/standard_library/options.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.31.0 => version-v0.34.0}/noir/standard_library/recursion.md (93%) rename noir/noir-repo/docs/versioned_docs/{version-v0.30.0 => version-v0.34.0}/noir/standard_library/traits.md (71%) rename noir/noir-repo/docs/versioned_docs/{version-v0.26.0 => version-v0.34.0}/noir/standard_library/zeroed.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.19.0/noir_js/reference => version-v0.34.0/reference/NoirJS}/backend_barretenberg/.nojekyll (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.26.0 => version-v0.34.0}/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md (83%) rename noir/noir-repo/docs/versioned_docs/{version-v0.28.0 => version-v0.34.0}/reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier.md (100%) create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/backend_barretenberg/classes/UltraHonkBackend.md rename noir/noir-repo/docs/versioned_docs/{version-v0.31.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier.md => version-v0.34.0/reference/NoirJS/backend_barretenberg/classes/UltraHonkVerifier.md} (80%) rename noir/noir-repo/docs/versioned_docs/{version-v0.31.0 => version-v0.34.0}/reference/NoirJS/backend_barretenberg/index.md (85%) rename noir/noir-repo/docs/versioned_docs/{version-v0.25.0 => version-v0.34.0}/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md (100%) create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs rename noir/noir-repo/docs/versioned_docs/{version-v0.19.0/noir_js/reference => version-v0.34.0/reference/NoirJS}/noir_js/.nojekyll (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.31.0 => version-v0.34.0}/reference/NoirJS/noir_js/classes/Noir.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.19.0/noir_js/reference => version-v0.34.0/reference/NoirJS}/noir_js/functions/and.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.19.0/noir_js/reference => version-v0.34.0/reference/NoirJS}/noir_js/functions/blake2s256.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.23.0 => version-v0.34.0}/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.19.0/noir_js/reference => version-v0.34.0/reference/NoirJS}/noir_js/functions/ecdsa_secp256r1_verify.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.19.0/noir_js/reference => version-v0.34.0/reference/NoirJS}/noir_js/functions/keccak256.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.19.0/noir_js/reference => version-v0.34.0/reference/NoirJS}/noir_js/functions/sha256.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.19.0/noir_js/reference => version-v0.34.0/reference/NoirJS}/noir_js/functions/xor.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.31.0 => version-v0.34.0}/reference/NoirJS/noir_js/index.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.30.0 => version-v0.34.0}/reference/NoirJS/noir_js/type-aliases/ErrorWithPayload.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.19.0/noir_js/reference => version-v0.34.0/reference/NoirJS}/noir_js/type-aliases/ForeignCallHandler.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.19.0/noir_js/reference => version-v0.34.0/reference/NoirJS}/noir_js/type-aliases/ForeignCallInput.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.19.0/noir_js/reference => version-v0.34.0/reference/NoirJS}/noir_js/type-aliases/ForeignCallOutput.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.19.0/noir_js/reference => version-v0.34.0/reference/NoirJS}/noir_js/type-aliases/WitnessMap.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.30.0 => version-v0.34.0}/reference/NoirJS/noir_js/typedoc-sidebar.cjs (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.19.1/noir_js/reference/backend_barretenberg => version-v0.34.0/reference/NoirJS/noir_wasm}/.nojekyll (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.25.0 => version-v0.34.0}/reference/NoirJS/noir_wasm/functions/compile.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.25.0 => version-v0.34.0}/reference/NoirJS/noir_wasm/functions/compile_contract.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.23.0 => version-v0.34.0}/reference/NoirJS/noir_wasm/functions/createFileManager.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.23.0 => version-v0.34.0}/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.25.0 => version-v0.34.0}/reference/NoirJS/noir_wasm/index.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.25.0 => version-v0.34.0}/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.22.0 => version-v0.34.0}/reference/_category_.json (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.28.0 => version-v0.34.0}/reference/debugger/_category_.json (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.28.0 => version-v0.34.0}/reference/debugger/debugger_known_limitations.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.28.0 => version-v0.34.0}/reference/debugger/debugger_repl.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.28.0 => version-v0.34.0}/reference/debugger/debugger_vscode.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.27.0 => version-v0.34.0}/reference/nargo_commands.md (54%) rename noir/noir-repo/docs/versioned_docs/{version-v0.31.0/getting_started/tooling => version-v0.34.0/reference}/noir_codegen.md (97%) rename noir/noir-repo/docs/versioned_docs/{version-v0.28.0 => version-v0.34.0}/tooling/debugger.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.22.0/getting_started => version-v0.34.0}/tooling/language_server.md (100%) rename noir/noir-repo/docs/versioned_docs/{version-v0.22.0/getting_started => version-v0.34.0}/tooling/testing.md (74%) rename noir/noir-repo/docs/versioned_docs/{version-v0.31.0 => version-v0.34.0}/tutorials/noirjs_app.md (94%) delete mode 100644 noir/noir-repo/docs/versioned_sidebars/version-v0.17.0-sidebars.json delete mode 100644 noir/noir-repo/docs/versioned_sidebars/version-v0.19.0-sidebars.json delete mode 100644 noir/noir-repo/docs/versioned_sidebars/version-v0.19.1-sidebars.json delete mode 100644 noir/noir-repo/docs/versioned_sidebars/version-v0.19.2-sidebars.json delete mode 100644 noir/noir-repo/docs/versioned_sidebars/version-v0.19.3-sidebars.json delete mode 100644 noir/noir-repo/docs/versioned_sidebars/version-v0.19.4-sidebars.json delete mode 100644 noir/noir-repo/docs/versioned_sidebars/version-v0.22.0-sidebars.json delete mode 100644 noir/noir-repo/docs/versioned_sidebars/version-v0.23.0-sidebars.json delete mode 100644 noir/noir-repo/docs/versioned_sidebars/version-v0.24.0-sidebars.json delete mode 100644 noir/noir-repo/docs/versioned_sidebars/version-v0.25.0-sidebars.json delete mode 100644 noir/noir-repo/docs/versioned_sidebars/version-v0.26.0-sidebars.json delete mode 100644 noir/noir-repo/docs/versioned_sidebars/version-v0.27.0-sidebars.json delete mode 100644 noir/noir-repo/docs/versioned_sidebars/version-v0.29.0-sidebars.json delete mode 100644 noir/noir-repo/docs/versioned_sidebars/version-v0.30.0-sidebars.json delete mode 100644 noir/noir-repo/docs/versioned_sidebars/version-v0.31.0-sidebars.json rename noir/noir-repo/docs/versioned_sidebars/{version-v0.28.0-sidebars.json => version-v0.34.0-sidebars.json} (100%) create mode 100644 noir/noir-repo/noir_stdlib/src/meta/ctstring.nr create mode 100644 noir/noir-repo/test_programs/compile_failure/comptime_parse_all_tokens/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_failure/comptime_parse_all_tokens/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_failure/global_without_a_type_used_as_array_length/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_failure/global_without_a_type_used_as_array_length/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_failure/macro_result_type/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_failure/macro_result_type/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_success_empty/comptime_change_type_each_iteration/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_success_empty/comptime_change_type_each_iteration/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_success_empty/comptime_parse_statement_as_expression/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_success_empty/comptime_parse_statement_as_expression/src/main.nr rename noir/noir-repo/test_programs/{execution_success/verify_honk_proof => compile_success_empty/comptime_to_radix}/Nargo.toml (66%) create mode 100644 noir/noir-repo/test_programs/compile_success_empty/comptime_to_radix/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_success_empty/ctstring/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_success_empty/ctstring/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_success_empty/field_or_integer_static_trait_method/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_success_empty/field_or_integer_static_trait_method/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_success_empty/parenthesized_expression_in_array_length/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_success_empty/parenthesized_expression_in_array_length/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_success_empty/regression_6077/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_success_empty/regression_6077/Prover.toml create mode 100644 noir/noir-repo/test_programs/compile_success_empty/regression_6077/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_success_empty/type_path/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_success_empty/type_path/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_success_empty/use_callers_scope/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_success_empty/use_callers_scope/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_success_no_bug/databus_mapping_regression/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_success_no_bug/databus_mapping_regression/src/main.nr create mode 100644 noir/noir-repo/test_programs/execution_success/brillig_constant_reference_regression/Nargo.toml create mode 100644 noir/noir-repo/test_programs/execution_success/brillig_constant_reference_regression/Prover.toml create mode 100644 noir/noir-repo/test_programs/execution_success/brillig_constant_reference_regression/src/main.nr create mode 100644 noir/noir-repo/test_programs/execution_success/reference_only_used_as_alias/Nargo.toml create mode 100644 noir/noir-repo/test_programs/execution_success/reference_only_used_as_alias/Prover.toml create mode 100644 noir/noir-repo/test_programs/execution_success/reference_only_used_as_alias/src/main.nr create mode 100644 noir/noir-repo/test_programs/execution_success/regression_unsafe_no_predicates/Nargo.toml create mode 100644 noir/noir-repo/test_programs/execution_success/regression_unsafe_no_predicates/Prover.toml create mode 100644 noir/noir-repo/test_programs/execution_success/regression_unsafe_no_predicates/src/main.nr delete mode 100644 noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml delete mode 100644 noir/noir-repo/test_programs/execution_success/verify_honk_proof/src/main.nr create mode 100644 noir/noir-repo/tooling/lsp/src/trait_impl_method_stub_generator.rs create mode 100644 noir/noir-repo/tooling/noir_js/test/noir_compiled_examples/databus/Nargo.toml create mode 100644 noir/noir-repo/tooling/noir_js/test/noir_compiled_examples/databus/src/main.nr diff --git a/.noir-sync-commit b/.noir-sync-commit index 28b35ff2f0d..50c04e84c16 100644 --- a/.noir-sync-commit +++ b/.noir-sync-commit @@ -1 +1 @@ -9bf2dcbf166f9ffd97c369c0de3d95329c850d47 \ No newline at end of file +9f0b3971ee41e78241cbea4e3f81bac4edd5897d diff --git a/noir/noir-repo/.release-please-manifest.json b/noir/noir-repo/.release-please-manifest.json index af171a74a63..8be8ad41ac0 100644 --- a/noir/noir-repo/.release-please-manifest.json +++ b/noir/noir-repo/.release-please-manifest.json @@ -1,4 +1,4 @@ { - ".": "0.33.0", - "acvm-repo": "0.49.0" + ".": "0.34.0", + "acvm-repo": "0.50.0" } diff --git a/noir/noir-repo/CHANGELOG.md b/noir/noir-repo/CHANGELOG.md index d9b71a82e4b..9779d7ab964 100644 --- a/noir/noir-repo/CHANGELOG.md +++ b/noir/noir-repo/CHANGELOG.md @@ -1,5 +1,212 @@ # Changelog +## [0.34.0](https://github.com/noir-lang/noir/compare/v0.33.0...v0.34.0) (2024-09-13) + + +### ⚠ BREAKING CHANGES + +* Add Not instruction in brillig (https://github.com/AztecProtocol/aztec-packages/pull/8488) +* **avm:** variants for SET opcode (https://github.com/AztecProtocol/aztec-packages/pull/8441) +* **avm/brillig:** take addresses in calldatacopy (https://github.com/AztecProtocol/aztec-packages/pull/8388) +* Do not encode assertion strings in the programs (https://github.com/AztecProtocol/aztec-packages/pull/8315) +* return arrays instead of slices from `to_be_radix` functions ([#5851](https://github.com/noir-lang/noir/issues/5851)) +* Check unused generics are bound ([#5840](https://github.com/noir-lang/noir/issues/5840)) + +### Features + +* (bb) 128-bit challenges (https://github.com/AztecProtocol/aztec-packages/pull/8406) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* (LSP) suggest names that match any part of the current prefix ([#5752](https://github.com/noir-lang/noir/issues/5752)) ([cb0d490](https://github.com/noir-lang/noir/commit/cb0d49017a3b592afc2002e592a61d33bf3ac3a4)) +* `Module::add_item` ([#5947](https://github.com/noir-lang/noir/issues/5947)) ([af50a7b](https://github.com/noir-lang/noir/commit/af50a7b3ad511de68c584e65ec4eec8b703bbc14)) +* Add `Expr::as_any_integer` and `Expr::as_member_access` ([#5742](https://github.com/noir-lang/noir/issues/5742)) ([6266755](https://github.com/noir-lang/noir/commit/626675567bb0bfff3c7984ed7f75c488e441ef98)) +* Add `Expr::as_array`, `Expr::as_repeated_element_array` and same for slice ([#5750](https://github.com/noir-lang/noir/issues/5750)) ([f44e0b3](https://github.com/noir-lang/noir/commit/f44e0b3ebfb30e9323ebf2d537830ea64d59488c)) +* Add `Expr::as_assert_eq` ([#5880](https://github.com/noir-lang/noir/issues/5880)) ([88f7858](https://github.com/noir-lang/noir/commit/88f785803ddb1a7d395a899b65e500e46bba1a5d)) +* Add `Expr::as_assert` ([#5857](https://github.com/noir-lang/noir/issues/5857)) ([4e4ad26](https://github.com/noir-lang/noir/commit/4e4ad26d56e6a487ca446ea4e1732c6af04e1410)) +* Add `Expr::as_binary_op` ([#5734](https://github.com/noir-lang/noir/issues/5734)) ([73a9f51](https://github.com/noir-lang/noir/commit/73a9f51e1fd1ba513ef721e07990abf510e8bf01)) +* Add `Expr::as_block` and `Expr::has_semicolon` ([#5784](https://github.com/noir-lang/noir/issues/5784)) ([19ffa20](https://github.com/noir-lang/noir/commit/19ffa2008fc9cbb5972b50d66d14908d5c82ed75)) +* Add `Expr::as_bool` ([#5729](https://github.com/noir-lang/noir/issues/5729)) ([ca75cc2](https://github.com/noir-lang/noir/commit/ca75cc2e35530c82cef3b86edf99a232f88b11e8)) +* Add `Expr::as_cast` and `UnresolvedType::is_field` ([#5801](https://github.com/noir-lang/noir/issues/5801)) ([c9aa50d](https://github.com/noir-lang/noir/commit/c9aa50dd25887a7e8b903515a0fd290335d1e572)) +* Add `Expr::as_let` ([#5964](https://github.com/noir-lang/noir/issues/5964)) ([65da598](https://github.com/noir-lang/noir/commit/65da5983ece16249fa939a493f197d13fbb1f9a4)) +* Add `Expr::as_unary` ([#5731](https://github.com/noir-lang/noir/issues/5731)) ([ae33811](https://github.com/noir-lang/noir/commit/ae33811f7ca770b54880d0095c1d5be0ee85c6e4)) +* Add `Expr::resolve` and `TypedExpr::as_function_definition` ([#5859](https://github.com/noir-lang/noir/issues/5859)) ([bceee55](https://github.com/noir-lang/noir/commit/bceee55cc3833978d120e194820cfae9132c8006)) +* Add `Expr` methods: `as_tuple`, `as_parenthesized`, `as_index`, `as_if` ([#5726](https://github.com/noir-lang/noir/issues/5726)) ([f57a7b2](https://github.com/noir-lang/noir/commit/f57a7b2bd4457cbbfd650c7467d1f96d65ea6c8b)) +* Add `Expr` methods: as_comptime, as_unsafe, is_break, is_continue ([#5799](https://github.com/noir-lang/noir/issues/5799)) ([619fa5c](https://github.com/noir-lang/noir/commit/619fa5c0ad115ac910abfc9995a4362271847d59)) +* Add `fmtstr::contents` ([#5928](https://github.com/noir-lang/noir/issues/5928)) ([f18e9ca](https://github.com/noir-lang/noir/commit/f18e9ca86c025f736af6e515f812e36fbb622930)) +* Add `FunctionDef::body` ([#5825](https://github.com/noir-lang/noir/issues/5825)) ([39b30ba](https://github.com/noir-lang/noir/commit/39b30ba2e9f13d8d99bfb1833e14e294f80773e5)) +* Add `FunctionDef::has_named_attribute` ([#5870](https://github.com/noir-lang/noir/issues/5870)) ([a950195](https://github.com/noir-lang/noir/commit/a950195baa9e6ed3880ad1d2f619e442b4c49473)) +* Add `FunctionDef::set_return_visibility` ([#5941](https://github.com/noir-lang/noir/issues/5941)) ([8beda6b](https://github.com/noir-lang/noir/commit/8beda6beb10a2e42da788bcc9bf2b375055675c6)) +* Add `FunctionDefinition::add_attribute` ([#5944](https://github.com/noir-lang/noir/issues/5944)) ([c7479c4](https://github.com/noir-lang/noir/commit/c7479c4e55f47f7c652f0e202636b9e590d11f5d)) +* Add `FunctionDefinition::module` and `StructDefinition::module` ([#5956](https://github.com/noir-lang/noir/issues/5956)) ([f19344c](https://github.com/noir-lang/noir/commit/f19344ca1a6d9ae78cd433864f71705f3381320f)) +* Add `FunctionDefinition` methods `is_unconstrained` and `set_unconstrained` ([#5962](https://github.com/noir-lang/noir/issues/5962)) ([b9a072d](https://github.com/noir-lang/noir/commit/b9a072d29c0f4abc4c6c683b9b2a872728d971fa)) +* Add `Module::structs` ([#6017](https://github.com/noir-lang/noir/issues/6017)) ([fc5bb02](https://github.com/noir-lang/noir/commit/fc5bb025d7df901050af1d8ad6ebb9283faf641f)) +* Add `Quoted::as_expr` and `Expr::as_function_call` ([#5708](https://github.com/noir-lang/noir/issues/5708)) ([3f79607](https://github.com/noir-lang/noir/commit/3f79607002a75880b6e21aadd15dd7e55f15dbfa)) +* Add `Quoted::tokens` ([#5942](https://github.com/noir-lang/noir/issues/5942)) ([a297ec6](https://github.com/noir-lang/noir/commit/a297ec643eb3b6c0e8bcf62abdc005414283c7c2)) +* Add `std::meta::typ::fresh_type_variable` ([#5948](https://github.com/noir-lang/noir/issues/5948)) ([3dab4dd](https://github.com/noir-lang/noir/commit/3dab4dd771b7d8b9242ce3a9aeff5770f4d85cf6)) +* Add `StructDefinition::add_attribute` and `has_named_attribute` ([#5945](https://github.com/noir-lang/noir/issues/5945)) ([344dd5e](https://github.com/noir-lang/noir/commit/344dd5ea7ed551dcc3fd414d1c5f49f44721c28c)) +* Add `StructDefinition::add_generic` ([#5961](https://github.com/noir-lang/noir/issues/5961)) ([6004067](https://github.com/noir-lang/noir/commit/6004067e42572c34dd6465e66d36410826e2fd90)) +* Add `StructDefinition::name` ([#5960](https://github.com/noir-lang/noir/issues/5960)) ([102ebe3](https://github.com/noir-lang/noir/commit/102ebe33694d65e1024fcba8260ada6f30c49578)) +* Add `StructDefinition::set_fields` ([#5931](https://github.com/noir-lang/noir/issues/5931)) ([9d2629d](https://github.com/noir-lang/noir/commit/9d2629dd1bb28a8c2ecb4c33d26119da75d626c2)) +* Add `TraitImpl::trait_generic_args` and `TraitImpl::methods` ([#5722](https://github.com/noir-lang/noir/issues/5722)) ([8c7e493](https://github.com/noir-lang/noir/commit/8c7e4937b24e6d782543dd42ac9fc293af550f7c)) +* Add `Type::as_string` ([#5871](https://github.com/noir-lang/noir/issues/5871)) ([e29d4b3](https://github.com/noir-lang/noir/commit/e29d4b3646f0527fc01bc4584ee33616db922c72)) +* Add `Type::get_trait_impl` ([#5716](https://github.com/noir-lang/noir/issues/5716)) ([eb33d1c](https://github.com/noir-lang/noir/commit/eb33d1cae626244a220e6ceea176be6f5fb1073d)) +* Add `Type::implements` ([#5701](https://github.com/noir-lang/noir/issues/5701)) ([2166c94](https://github.com/noir-lang/noir/commit/2166c9441c739ab6a3ee029ed051f1857bd27170)) +* Add `TypedExpr::get_type` ([#5992](https://github.com/noir-lang/noir/issues/5992)) ([31f50c4](https://github.com/noir-lang/noir/commit/31f50c442b59eac4de2c5c530278e345bd2f149f)) +* Add `UnresolvedType::is_field` and `Expr::as_assign` ([#5804](https://github.com/noir-lang/noir/issues/5804)) ([c45df4e](https://github.com/noir-lang/noir/commit/c45df4e83ab1ff5f6c35c4115aebf317110ee419)) +* Add `unsafe` blocks for calling unconstrained code from constrained functions ([#4429](https://github.com/noir-lang/noir/issues/4429)) ([79593b4](https://github.com/noir-lang/noir/commit/79593b4235efc031ed9b95c0b301cef66b4ab88c)) +* Add a `panic` method to the stdlib ([#5966](https://github.com/noir-lang/noir/issues/5966)) ([b86c2bc](https://github.com/noir-lang/noir/commit/b86c2bc0ec2712e9c24309a6f5e92afc3ef0a2dc)) +* Add array_to_str_lossy ([#5613](https://github.com/noir-lang/noir/issues/5613)) ([af5acf4](https://github.com/noir-lang/noir/commit/af5acf4eb4af38fd346b6365a45d8e7e83899542)) +* Add assertions for ACVM `FunctionInput` `bit_size` ([#5864](https://github.com/noir-lang/noir/issues/5864)) ([8712f4c](https://github.com/noir-lang/noir/commit/8712f4c20d23f3809bcfb03f2e3ba0e5ace20a1d)) +* Add Expr::as_method_call ([#5822](https://github.com/noir-lang/noir/issues/5822)) ([806af24](https://github.com/noir-lang/noir/commit/806af24e44b3abcc50e552fff0883f2497ba152f)) +* Add mutating FunctionDefinition functions ([#5685](https://github.com/noir-lang/noir/issues/5685)) ([2882eae](https://github.com/noir-lang/noir/commit/2882eaeb176988bb3d216d091c0e239f5b80f276)) +* Add Not instruction in brillig (https://github.com/AztecProtocol/aztec-packages/pull/8488) ([95e19ab](https://github.com/noir-lang/noir/commit/95e19ab9486ad054241b6e53e40e55bdba9dc7e5)) +* Add recursive aggregation object to proving/verification keys (https://github.com/AztecProtocol/aztec-packages/pull/6770) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Add reusable procedures to brillig generation (https://github.com/AztecProtocol/aztec-packages/pull/7981) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Add some `Module` comptime functions ([#5684](https://github.com/noir-lang/noir/issues/5684)) ([eefd69b](https://github.com/noir-lang/noir/commit/eefd69b1d72a9f5cb2e7bbd3e554925a7670a2f3)) +* Added indirect const instruction (https://github.com/AztecProtocol/aztec-packages/pull/8065) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Adding aggregation to honk and rollup (https://github.com/AztecProtocol/aztec-packages/pull/7466) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Allow inserting new structs and into programs from attributes ([#5927](https://github.com/noir-lang/noir/issues/5927)) ([94e661e](https://github.com/noir-lang/noir/commit/94e661e7520d80496bdc9da39b9736bafacb96dc)) +* Arithmetic Generics ([#5950](https://github.com/noir-lang/noir/issues/5950)) ([00a79ce](https://github.com/noir-lang/noir/commit/00a79ce6374bb09616ffb6f431cb6c011d786877)) +* Automate verify_honk_proof input generation (https://github.com/AztecProtocol/aztec-packages/pull/8092) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* **avm/brillig:** Take addresses in calldatacopy (https://github.com/AztecProtocol/aztec-packages/pull/8388) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* **avm:** Variants for SET opcode (https://github.com/AztecProtocol/aztec-packages/pull/8441) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* Better error message for misplaced doc comments ([#5990](https://github.com/noir-lang/noir/issues/5990)) ([28415ef](https://github.com/noir-lang/noir/commit/28415efd2fd8c7b836516b154ab54d65f15fbc23)) +* Better println for Quoted ([#5896](https://github.com/noir-lang/noir/issues/5896)) ([6f30e42](https://github.com/noir-lang/noir/commit/6f30e42f8a895c7813e770d6ee9ffbc9977c335b)) +* Calculate `FunctionSelector`s and `EventSelector`s during comptime (https://github.com/AztecProtocol/aztec-packages/pull/8354) ([33bd102](https://github.com/noir-lang/noir/commit/33bd102d6021912b56fe880efab65346c3ea9228)) +* Change the layout of arrays and vectors to be a single pointer (https://github.com/AztecProtocol/aztec-packages/pull/8448) ([d4832ec](https://github.com/noir-lang/noir/commit/d4832ece9d3ad16544afea49cc7caf40501a2cc3)) +* Check argument count and types on attribute function callback ([#5921](https://github.com/noir-lang/noir/issues/5921)) ([91f693d](https://github.com/noir-lang/noir/commit/91f693d81edb1913bf56d2c1038441cec5844646)) +* Do not encode assertion strings in the programs (https://github.com/AztecProtocol/aztec-packages/pull/8315) ([4144152](https://github.com/noir-lang/noir/commit/41441527700d7c0fe59769803048a3b285badd77)) +* Explicit Associated Types & Constants ([#5739](https://github.com/noir-lang/noir/issues/5739)) ([e050e93](https://github.com/noir-lang/noir/commit/e050e93a963b407dabedf7c236f59c387f787514)) +* Extract brillig slice ops to reusable procedures ([#6002](https://github.com/noir-lang/noir/issues/6002)) ([339c17b](https://github.com/noir-lang/noir/commit/339c17bb5253f0d290fa56644a49b2881c9de889)) +* Fault-tolerant parsing of `fn` and `impl` ([#5753](https://github.com/noir-lang/noir/issues/5753)) ([d4e2f0a](https://github.com/noir-lang/noir/commit/d4e2f0a30b07a98772fbc321a760641466cc01d1)) +* Format trait impl functions ([#6016](https://github.com/noir-lang/noir/issues/6016)) ([da32bd8](https://github.com/noir-lang/noir/commit/da32bd82d749a9c388e970883cc1ea756ce2db6b)) +* Hook up secondary calldata column in dsl (https://github.com/AztecProtocol/aztec-packages/pull/7759) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Impl Hash and Eq on more comptime types ([#6022](https://github.com/noir-lang/noir/issues/6022)) ([114903d](https://github.com/noir-lang/noir/commit/114903d6fbcb035b46478db36d696efa99e919d6)) +* Implement `str_as_bytes` in the `comptime` interpreter ([#5887](https://github.com/noir-lang/noir/issues/5887)) ([45344bf](https://github.com/noir-lang/noir/commit/45344bfe1148a2f592c2e432744d3fb3d46340cc)) +* Implement LSP code action "Implement missing members" ([#6020](https://github.com/noir-lang/noir/issues/6020)) ([9bf2dcb](https://github.com/noir-lang/noir/commit/9bf2dcbf166f9ffd97c369c0de3d95329c850d47)) +* Improve "type annotations needed" errors ([#5830](https://github.com/noir-lang/noir/issues/5830)) ([90f9ea0](https://github.com/noir-lang/noir/commit/90f9ea0df7055aa5881a77981c8be7862478c848)) +* Let `has_named_attribute` work for built-in attributes ([#6024](https://github.com/noir-lang/noir/issues/6024)) ([a09646b](https://github.com/noir-lang/noir/commit/a09646bde7ae27c1aa423ef56757d2fb8753658a)) +* Let `nargo` and LSP work well in the stdlib ([#5969](https://github.com/noir-lang/noir/issues/5969)) ([8e8e97c](https://github.com/noir-lang/noir/commit/8e8e97c68e48245a6c7de9b3a0fe9960a889c47a)) +* Liveness analysis for constants (https://github.com/AztecProtocol/aztec-packages/pull/8294) ([71e1556](https://github.com/noir-lang/noir/commit/71e1556717695e1ef80c53d273f7acbdf0d5b4e7)) +* LSP auto-import completion ([#5741](https://github.com/noir-lang/noir/issues/5741)) ([cdbb940](https://github.com/noir-lang/noir/commit/cdbb940a883ae32dd84c667ec06b0d155f2d7520)) +* LSP autocomplete constructor fields ([#5732](https://github.com/noir-lang/noir/issues/5732)) ([e71c75a](https://github.com/noir-lang/noir/commit/e71c75a0862dda26e5b08318bcec71d5b41ba9e9)) +* LSP autocompletion for attributes ([#5963](https://github.com/noir-lang/noir/issues/5963)) ([b7b9e3f](https://github.com/noir-lang/noir/commit/b7b9e3f2212db2b9c3412ddcfd1c40c6200a1740)) +* LSP autocompletion for use statement ([#5704](https://github.com/noir-lang/noir/issues/5704)) ([226aeb1](https://github.com/noir-lang/noir/commit/226aeb1400adc6d9028e9ad9f496783606fd9e11)) +* LSP code action "Fill struct fields" ([#5885](https://github.com/noir-lang/noir/issues/5885)) ([1e6e4f4](https://github.com/noir-lang/noir/commit/1e6e4f4f53c7d331c054dd84f3fe6064d2e844e3)) +* LSP code actions to import or qualify unresolved paths ([#5876](https://github.com/noir-lang/noir/issues/5876)) ([410c1f6](https://github.com/noir-lang/noir/commit/410c1f67ee93634bcfb22b236035d97eee33b0cf)) +* LSP completion function detail ([#5993](https://github.com/noir-lang/noir/issues/5993)) ([e84f7d2](https://github.com/noir-lang/noir/commit/e84f7d2e81c1f59e9af015f38c2d477607a9c558)) +* LSP completion now works better in the middle of idents ([#5795](https://github.com/noir-lang/noir/issues/5795)) ([1c84038](https://github.com/noir-lang/noir/commit/1c84038e4a1b2515f4f91aca4c833dd3b6c05d91)) +* LSP diagnostics for all package files ([#5895](https://github.com/noir-lang/noir/issues/5895)) ([4e616b3](https://github.com/noir-lang/noir/commit/4e616b340d144a615795e37ab87ced1d175188b3)) +* LSP diagnostics now have "unnecessary" and "deprecated" tags ([#5878](https://github.com/noir-lang/noir/issues/5878)) ([2f0d4e0](https://github.com/noir-lang/noir/commit/2f0d4e017b701b46b5c675e3b34af15ad6f28823)) +* LSP fields, functions and methods completion after "." and "::" ([#5714](https://github.com/noir-lang/noir/issues/5714)) ([13c1fe6](https://github.com/noir-lang/noir/commit/13c1fe686c51b762df71a138b1af474d67da7560)) +* LSP hover and go-to-definition for crates ([#5786](https://github.com/noir-lang/noir/issues/5786)) ([86d8840](https://github.com/noir-lang/noir/commit/86d884044ee5bac72af820d623e00e1375271845)) +* LSP now suggests self fields and methods ([#5955](https://github.com/noir-lang/noir/issues/5955)) ([f57ce85](https://github.com/noir-lang/noir/commit/f57ce850fdb42a33177638f2f4af1335023c5e62)) +* LSP path completion ([#5712](https://github.com/noir-lang/noir/issues/5712)) ([3c6b998](https://github.com/noir-lang/noir/commit/3c6b9982048e168fc86cb834b5e8e72b51d2498d)) +* LSP signature help ([#5725](https://github.com/noir-lang/noir/issues/5725)) ([5a3d241](https://github.com/noir-lang/noir/commit/5a3d24192d440c5bfe3749d4bcd8ebbc9cf4902b)) +* LSP signature help for assert and assert_eq ([#5862](https://github.com/noir-lang/noir/issues/5862)) ([663e00c](https://github.com/noir-lang/noir/commit/663e00cffcb2cd66ddc2b33c0453afca0e15f703)) +* LSP will now suggest private items if they are visible ([#5923](https://github.com/noir-lang/noir/issues/5923)) ([d2caa5b](https://github.com/noir-lang/noir/commit/d2caa5bb86f944d6d09182482bef6e35ca2213d6)) +* Make token transfer be recursive (https://github.com/AztecProtocol/aztec-packages/pull/7730) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* **meta:** Comptime keccak ([#5854](https://github.com/noir-lang/noir/issues/5854)) ([0e8becc](https://github.com/noir-lang/noir/commit/0e8becc7bccee2ae4e4e3ef373df08c3e9ef88c9)) +* Module attributes ([#5888](https://github.com/noir-lang/noir/issues/5888)) ([2ca2e5c](https://github.com/noir-lang/noir/commit/2ca2e5cf207a2a1f41ca86d877f0288bcbbfd212)) +* New test programs for wasm benchmarking (https://github.com/AztecProtocol/aztec-packages/pull/8389) ([95e19ab](https://github.com/noir-lang/noir/commit/95e19ab9486ad054241b6e53e40e55bdba9dc7e5)) +* Note hashes as points (https://github.com/AztecProtocol/aztec-packages/pull/7618) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Only check array bounds in brillig if index is unsafe ([#5938](https://github.com/noir-lang/noir/issues/5938)) ([8b60bbc](https://github.com/noir-lang/noir/commit/8b60bbc8082513e29f6573e5235e0a33fdd1517b)) +* **optimization:** Avoid merging identical (by ID) arrays ([#5853](https://github.com/noir-lang/noir/issues/5853)) ([062103e](https://github.com/noir-lang/noir/commit/062103ea039042e8e999b29dbb1fafc3cebd513c)) +* **optimization:** Follow past `array_set`s when optimizing `array_get`s ([#5772](https://github.com/noir-lang/noir/issues/5772)) ([090501d](https://github.com/noir-lang/noir/commit/090501dfaf7c569b1aa944856bf68ad663572ae4)) +* Optimize constant array handling in brillig_gen (https://github.com/AztecProtocol/aztec-packages/pull/7661) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Optimize to_radix (https://github.com/AztecProtocol/aztec-packages/pull/8073) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Pass calldata ids to the backend (https://github.com/AztecProtocol/aztec-packages/pull/7875) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* **perf:** Mem2reg function state for value loads to optimize across blocks ([#5757](https://github.com/noir-lang/noir/issues/5757)) ([0b297b3](https://github.com/noir-lang/noir/commit/0b297b3830ac26551bfb39fad01d74cd8ab341c3)) +* **perf:** Remove known store values that equal the store address in mem2reg ([#5935](https://github.com/noir-lang/noir/issues/5935)) ([b84009c](https://github.com/noir-lang/noir/commit/b84009ca428a5790acf53a6c027146b706170574)) +* **perf:** Remove last store in return block if last load is before that store ([#5910](https://github.com/noir-lang/noir/issues/5910)) ([1737b65](https://github.com/noir-lang/noir/commit/1737b656c861706c38b59bd5ef6cd095687a2898)) +* **perf:** Simplify poseidon2 cache zero-pad ([#5869](https://github.com/noir-lang/noir/issues/5869)) ([31e9be6](https://github.com/noir-lang/noir/commit/31e9be6b83b448eb6834645dc124589dc724a7b2)) +* Poseidon2 gates for Ultra arithmetisation (https://github.com/AztecProtocol/aztec-packages/pull/7494) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* **profiler:** Add support for brillig functions in opcodes-flamegraph (https://github.com/AztecProtocol/aztec-packages/pull/7698) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Remove blocks which consist of only a jump to another block ([#5889](https://github.com/noir-lang/noir/issues/5889)) ([f391af2](https://github.com/noir-lang/noir/commit/f391af2d61f4a38e02cb92c76fa4c2c148af3833)) +* Remove unnecessary copying of vector size during reversal ([#5852](https://github.com/noir-lang/noir/issues/5852)) ([5739904](https://github.com/noir-lang/noir/commit/5739904f8d9e6c00d9e140cd4926b4d149412476)) +* Removing superfluous call to MSM (https://github.com/AztecProtocol/aztec-packages/pull/7708) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Report gates and VKs of private protocol circuits with megahonk (https://github.com/AztecProtocol/aztec-packages/pull/7722) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Return arrays instead of slices from `to_be_radix` functions ([#5851](https://github.com/noir-lang/noir/issues/5851)) ([d59c708](https://github.com/noir-lang/noir/commit/d59c7087495f8af0dfb387dc587ecc422888096b)) +* Show backtrace on comptime assertion failures ([#5842](https://github.com/noir-lang/noir/issues/5842)) ([cfd68d4](https://github.com/noir-lang/noir/commit/cfd68d4c1bd1a2319698fca99d200a5d86ffa771)) +* Show doc comments in LSP ([#5968](https://github.com/noir-lang/noir/issues/5968)) ([45f4ae0](https://github.com/noir-lang/noir/commit/45f4ae09ca5fa5516e13c34c2ae9379077461cc9)) +* Simplify constant calls to `poseidon2_permutation`, `schnorr_verify` and `embedded_curve_add` ([#5140](https://github.com/noir-lang/noir/issues/5140)) ([2823ba7](https://github.com/noir-lang/noir/commit/2823ba7242db788ca1d7f6e7a48be2f1de62f278)) +* Small optimization in toradix (https://github.com/AztecProtocol/aztec-packages/pull/8040) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Suggest trait methods in LSP completion ([#5735](https://github.com/noir-lang/noir/issues/5735)) ([e2f7e95](https://github.com/noir-lang/noir/commit/e2f7e950c44883228d5e1230b04c83e479de7ed0)) +* Suggest tuple fields in LSP completion ([#5730](https://github.com/noir-lang/noir/issues/5730)) ([64d7d78](https://github.com/noir-lang/noir/commit/64d7d786ad2ddf0942690912cf05ca3b438c43be)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7743) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7862) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7945) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7958) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8008) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8093) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8125) ([f0c2686](https://github.com/noir-lang/noir/commit/f0c268606a71381ab4504396695a0adb9b3258b6)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8237) ([f0c2686](https://github.com/noir-lang/noir/commit/f0c268606a71381ab4504396695a0adb9b3258b6)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8314) ([4144152](https://github.com/noir-lang/noir/commit/41441527700d7c0fe59769803048a3b285badd77)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8333) ([33bd102](https://github.com/noir-lang/noir/commit/33bd102d6021912b56fe880efab65346c3ea9228)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8423) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8435) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8466) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8482) ([d4832ec](https://github.com/noir-lang/noir/commit/d4832ece9d3ad16544afea49cc7caf40501a2cc3)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8512) ([95e19ab](https://github.com/noir-lang/noir/commit/95e19ab9486ad054241b6e53e40e55bdba9dc7e5)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8526) ([95e19ab](https://github.com/noir-lang/noir/commit/95e19ab9486ad054241b6e53e40e55bdba9dc7e5)) +* TXE nr deployments, dependency cleanup for CLI (https://github.com/AztecProtocol/aztec-packages/pull/7548) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Unify all acir recursion constraints based on RecursionConstraint and proof_type (https://github.com/AztecProtocol/aztec-packages/pull/7993) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Unquote some value as tokens, not as unquote markers ([#5924](https://github.com/noir-lang/noir/issues/5924)) ([70ebb90](https://github.com/noir-lang/noir/commit/70ebb905da23a0541915a8f6883d6f530934be4e)) +* Use visibility ([#5856](https://github.com/noir-lang/noir/issues/5856)) ([e349f30](https://github.com/noir-lang/noir/commit/e349f30b60a473e2068afafb6fae4a4ea50d185b)) +* Use Zac's quicksort algorithm in stdlib sorting ([#5940](https://github.com/noir-lang/noir/issues/5940)) ([19f5757](https://github.com/noir-lang/noir/commit/19f5757a64c15a6b5a9478eceedb17c02d2351d7)) +* User `super::` in LSP autocompletion if possible ([#5751](https://github.com/noir-lang/noir/issues/5751)) ([5192e53](https://github.com/noir-lang/noir/commit/5192e537708fc9ec51f53bb6a6629c9d682532d5)) +* Warn on unused functions ([#5892](https://github.com/noir-lang/noir/issues/5892)) ([af3db4b](https://github.com/noir-lang/noir/commit/af3db4bf2e8f7feba6d06c3095d7cdf17c8dde75)) +* Warn on unused imports ([#5847](https://github.com/noir-lang/noir/issues/5847)) ([58f855e](https://github.com/noir-lang/noir/commit/58f855ec2124db39e5b2b08630d514d852d0e7df)) + + +### Bug Fixes + +* (LSP) only add cached files relevant to workspace ([#5775](https://github.com/noir-lang/noir/issues/5775)) ([1958a79](https://github.com/noir-lang/noir/commit/1958a7932642e2fa556a903a3186b142a70e3e48)) +* **acir_gen:** Nested dynamic array initialization ([#5810](https://github.com/noir-lang/noir/issues/5810)) ([4df53ad](https://github.com/noir-lang/noir/commit/4df53adfd0c5e2da70462b29fbf8d08e32203fc4)) +* **acvm:** Clear ACIR call stack after successful circuit execution ([#5783](https://github.com/noir-lang/noir/issues/5783)) ([656a7d6](https://github.com/noir-lang/noir/commit/656a7d6c1e0c3597a61c3606e3155a70032c1599)) +* Add locations to most SSA instructions ([#5697](https://github.com/noir-lang/noir/issues/5697)) ([85d5c85](https://github.com/noir-lang/noir/commit/85d5c8532acb21c39f3db466982039d1415d9300)) +* Add missing trait impls for integer types to stdlib ([#5738](https://github.com/noir-lang/noir/issues/5738)) ([d3f20c6](https://github.com/noir-lang/noir/commit/d3f20c6f830a84fce9d75ce3fe28e31b391b47ab)) +* Allow comptime code to use break without also being `unconstrained` ([#5744](https://github.com/noir-lang/noir/issues/5744)) ([c2a1a87](https://github.com/noir-lang/noir/commit/c2a1a87a6bcfc161ef5f550a17b603b0bccbab8e)) +* Always place module attribute generated items inside module ([#5943](https://github.com/noir-lang/noir/issues/5943)) ([89ac6e0](https://github.com/noir-lang/noir/commit/89ac6e087debc37dcc729db0b68062418cd64d2e)) +* Bit shifting type checking ([#5824](https://github.com/noir-lang/noir/issues/5824)) ([fb5136e](https://github.com/noir-lang/noir/commit/fb5136edda4b5b8ac6bba998939c94f11a27a59a)) +* Check unused generics are bound ([#5840](https://github.com/noir-lang/noir/issues/5840)) ([82eb158](https://github.com/noir-lang/noir/commit/82eb1581251faa9716d762a673fa1b871b3e7be2)) +* Collect functions generated by attributes ([#5930](https://github.com/noir-lang/noir/issues/5930)) ([2c22fe5](https://github.com/noir-lang/noir/commit/2c22fe555dc41fffc623026b4b8c57d44b869cd2)) +* Correctly print string tokens ([#6021](https://github.com/noir-lang/noir/issues/6021)) ([b8a3a9b](https://github.com/noir-lang/noir/commit/b8a3a9b03f83bba486d2623640f97f1a080f2d73)) +* **debugger:** Update the debugger to handle the new Brillig debug metadata format ([#5706](https://github.com/noir-lang/noir/issues/5706)) ([a31f82e](https://github.com/noir-lang/noir/commit/a31f82e598def60d00c65b79b8c5411f8aa832aa)) +* Deflatten databus visibilities (https://github.com/AztecProtocol/aztec-packages/pull/7761) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Do not duplicate redundant Brillig debug metadata ([#5696](https://github.com/noir-lang/noir/issues/5696)) ([e4f7dbe](https://github.com/noir-lang/noir/commit/e4f7dbe63b55807b3ff0b4d6f47a8b7f847299fb)) +* Do not use predicate for index in array operation, when the index is safe ([#5779](https://github.com/noir-lang/noir/issues/5779)) ([9d8f2bd](https://github.com/noir-lang/noir/commit/9d8f2bd759837d7f1f78c1b56b8e30de35c80867)) +* **docs:** Fix file paths for metaprogramming docs ([#5826](https://github.com/noir-lang/noir/issues/5826)) ([a764c5b](https://github.com/noir-lang/noir/commit/a764c5be9b15e499e0720f28a1a177bfecbef352)) +* Error when `quote` is used in runtime code ([#5978](https://github.com/noir-lang/noir/issues/5978)) ([cc30d88](https://github.com/noir-lang/noir/commit/cc30d88d85bb70248e452d9ec549d6dfe6be62ff)) +* Error when comptime functions are used in runtime code ([#5976](https://github.com/noir-lang/noir/issues/5976)) ([ec24917](https://github.com/noir-lang/noir/commit/ec24917bfda55746c7509dd28f8d808f97c948b8)) +* Error when comptime types are used in runtime code ([#5987](https://github.com/noir-lang/noir/issues/5987)) ([3d39196](https://github.com/noir-lang/noir/commit/3d39196040aa01e64c8a7fe989e2979a5de80023)) +* Error when mutating comptime variables in non-comptime code ([#6003](https://github.com/noir-lang/noir/issues/6003)) ([e20c44d](https://github.com/noir-lang/noir/commit/e20c44dcb21edd3ec2bbc015d85754872e86740e)) +* Export brillig names in contract functions (https://github.com/AztecProtocol/aztec-packages/pull/8212) ([f0c2686](https://github.com/noir-lang/noir/commit/f0c268606a71381ab4504396695a0adb9b3258b6)) +* Fix some mistakes in arithmetic generics docs ([#5999](https://github.com/noir-lang/noir/issues/5999)) ([29550d1](https://github.com/noir-lang/noir/commit/29550d1d7698a1af65b867171ff80e817f3ed2f6)) +* Fix using lazily elaborated comptime globals ([#5995](https://github.com/noir-lang/noir/issues/5995)) ([f6f493c](https://github.com/noir-lang/noir/commit/f6f493cb73e24337a7f11507b2b492d98cac2ada)) +* **frontend:** Ban type vars bound to a reference from passing the unconstrained boundary ([#5949](https://github.com/noir-lang/noir/issues/5949)) ([ce34fbd](https://github.com/noir-lang/noir/commit/ce34fbd19702b71426563a589235a2c5a1efb265)) +* **frontend:** Continue type check if we are missing an unsafe block ([#5720](https://github.com/noir-lang/noir/issues/5720)) ([86de991](https://github.com/noir-lang/noir/commit/86de991051a34567077076aa09a85b26eeff2ab2)) +* Handle multiple entry points for Brillig call stack resolution after metadata deduplication ([#5788](https://github.com/noir-lang/noir/issues/5788)) ([38fe9dd](https://github.com/noir-lang/noir/commit/38fe9dda111952fdb894df90a319c087382edfc9)) +* Help link was outdated ([#6004](https://github.com/noir-lang/noir/issues/6004)) ([d1e52f3](https://github.com/noir-lang/noir/commit/d1e52f3f3824ead1fd617fc21fcbe1051911986d)) +* Honor function visibility in LSP completion ([#5809](https://github.com/noir-lang/noir/issues/5809)) ([335de05](https://github.com/noir-lang/noir/commit/335de054dfcda366df50cc215900910ebdc8be63)) +* Let `derive(Eq)` work for empty structs ([#5965](https://github.com/noir-lang/noir/issues/5965)) ([ff8e8b5](https://github.com/noir-lang/noir/commit/ff8e8b5fae4db57bd7f819d0e23c68262057b790)) +* Let LSP autocompletion work in more contexts ([#5719](https://github.com/noir-lang/noir/issues/5719)) ([03ba6dd](https://github.com/noir-lang/noir/commit/03ba6dd328d56bf71c9e2b501c59eb9a6cdb95db)) +* LSP document symbol didn't work for primitive impls ([#5970](https://github.com/noir-lang/noir/issues/5970)) ([e1f81da](https://github.com/noir-lang/noir/commit/e1f81da1d8cfcc9cfe3d1bd2ed6f762580800ad9)) +* **mem2reg:** Handle aliases better when setting a known value for a load ([#5959](https://github.com/noir-lang/noir/issues/5959)) ([1b72a17](https://github.com/noir-lang/noir/commit/1b72a17e621465ac1dfaaf8948edcebd4f1b0b15)) +* **mem2reg:** Handle aliases in function last store cleanup and additional alias unit test ([#5967](https://github.com/noir-lang/noir/issues/5967)) ([36756e8](https://github.com/noir-lang/noir/commit/36756e8757ad40e2b231747ed754273f50e5dc2f)) +* **nargo:** Resolve Brillig assertion payloads ([#5872](https://github.com/noir-lang/noir/issues/5872)) ([f53a28b](https://github.com/noir-lang/noir/commit/f53a28bd3e70e9331e01f1fec4984e747723df74)) +* Prevent comptime println from crashing LSP ([#5918](https://github.com/noir-lang/noir/issues/5918)) ([44cf9a2](https://github.com/noir-lang/noir/commit/44cf9a2140bc06b550d4b46966f1637598ac11a7)) +* Replace unused ArrayGet/Set with constrain if possibly out of bounds ([#5691](https://github.com/noir-lang/noir/issues/5691)) ([a87d926](https://github.com/noir-lang/noir/commit/a87d92629c49c91d47685dba9a2a6dce4440756d)) +* Restrict keccak256_injective test input to 8 bits ([#5977](https://github.com/noir-lang/noir/issues/5977)) ([a1b1346](https://github.com/noir-lang/noir/commit/a1b1346bf7525c508fd390393c307475cc2345d7)) +* **sha256:** Add extra checks against message size when constructing msg blocks ([#5861](https://github.com/noir-lang/noir/issues/5861)) ([46e266a](https://github.com/noir-lang/noir/commit/46e266a5229dada42ee397beb0d39322451b1458)) +* **sha256:** Fix upper bound when building msg block and delay final block compression under certain cases ([#5838](https://github.com/noir-lang/noir/issues/5838)) ([130b7b6](https://github.com/noir-lang/noir/commit/130b7b6871ad165a75df5fa5760c94a7402521f4)) +* **sha256:** Perform compression per block and utilize ROM instead of RAM when setting up the message block ([#5760](https://github.com/noir-lang/noir/issues/5760)) ([c52dc1c](https://github.com/noir-lang/noir/commit/c52dc1c77aedf5a876a858cc5a942c29e868e9e6)) +* Suggest trait attributes in LSP ([#5972](https://github.com/noir-lang/noir/issues/5972)) ([d6f60d7](https://github.com/noir-lang/noir/commit/d6f60d70dc41640ad84f7a968927b20818bcaf2a)) +* Support debug comptime flag for attributes ([#5929](https://github.com/noir-lang/noir/issues/5929)) ([34f21c0](https://github.com/noir-lang/noir/commit/34f21c0eadfc8a03f5177d72de7958903de8ac98)) +* Temporary register leaks in brillig gen (https://github.com/AztecProtocol/aztec-packages/pull/8350) ([33bd102](https://github.com/noir-lang/noir/commit/33bd102d6021912b56fe880efab65346c3ea9228)) +* Try to move constant terms to one side for arithmetic generics ([#6008](https://github.com/noir-lang/noir/issues/6008)) ([4d8fe28](https://github.com/noir-lang/noir/commit/4d8fe28f6d0930b6e9cfe0d39dd003466b20b8b6)) +* Unconstrained fn mismatch is now a warning ([#5764](https://github.com/noir-lang/noir/issues/5764)) ([37af966](https://github.com/noir-lang/noir/commit/37af966024d5eb38eae5092a7976445e4bbe8adb)) +* Use element_size() instead of computing it with division ([#5939](https://github.com/noir-lang/noir/issues/5939)) ([6a45007](https://github.com/noir-lang/noir/commit/6a450076be2889c05428ea1285c5c149cfaf4456)) +* Use module name as line after which we'll insert auto-import ([#6025](https://github.com/noir-lang/noir/issues/6025)) ([c2e4a9a](https://github.com/noir-lang/noir/commit/c2e4a9a02c0138f6a8878f51291320ba7e57c79c)) + ## [0.33.0](https://github.com/noir-lang/noir/compare/v0.32.0...v0.33.0) (2024-08-06) diff --git a/noir/noir-repo/Cargo.lock b/noir/noir-repo/Cargo.lock index 796ac50ca9f..9a657dcf9d0 100644 --- a/noir/noir-repo/Cargo.lock +++ b/noir/noir-repo/Cargo.lock @@ -4,7 +4,7 @@ version = 3 [[package]] name = "acir" -version = "0.49.0" +version = "0.50.0" dependencies = [ "acir_field", "base64 0.21.7", @@ -26,7 +26,7 @@ dependencies = [ [[package]] name = "acir_field" -version = "0.49.0" +version = "0.50.0" dependencies = [ "ark-bls12-381", "ark-bn254", @@ -40,7 +40,7 @@ dependencies = [ [[package]] name = "acvm" -version = "0.49.0" +version = "0.50.0" dependencies = [ "acir", "acvm_blackbox_solver", @@ -59,7 +59,7 @@ dependencies = [ [[package]] name = "acvm_blackbox_solver" -version = "0.49.0" +version = "0.50.0" dependencies = [ "acir", "blake2", @@ -97,7 +97,7 @@ dependencies = [ [[package]] name = "acvm_js" -version = "0.49.0" +version = "0.50.0" dependencies = [ "acvm", "bn254_blackbox_solver", @@ -438,7 +438,7 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "aztec_macros" -version = "0.33.0" +version = "0.34.0" dependencies = [ "acvm", "convert_case 0.6.0", @@ -603,7 +603,7 @@ dependencies = [ [[package]] name = "bn254_blackbox_solver" -version = "0.49.0" +version = "0.50.0" dependencies = [ "acir", "acvm_blackbox_solver", @@ -621,7 +621,7 @@ dependencies = [ [[package]] name = "brillig" -version = "0.49.0" +version = "0.50.0" dependencies = [ "acir_field", "serde", @@ -629,7 +629,7 @@ dependencies = [ [[package]] name = "brillig_vm" -version = "0.49.0" +version = "0.50.0" dependencies = [ "acir", "acvm_blackbox_solver", @@ -1572,7 +1572,7 @@ dependencies = [ [[package]] name = "fm" -version = "0.33.0" +version = "0.34.0" dependencies = [ "codespan-reporting", "iter-extended", @@ -2178,7 +2178,7 @@ dependencies = [ [[package]] name = "iter-extended" -version = "0.33.0" +version = "0.34.0" [[package]] name = "itertools" @@ -2556,7 +2556,7 @@ dependencies = [ [[package]] name = "nargo" -version = "0.33.0" +version = "0.34.0" dependencies = [ "acvm", "fm", @@ -2583,7 +2583,7 @@ dependencies = [ [[package]] name = "nargo_cli" -version = "0.33.0" +version = "0.34.0" dependencies = [ "acvm", "assert_cmd", @@ -2636,7 +2636,7 @@ dependencies = [ [[package]] name = "nargo_fmt" -version = "0.33.0" +version = "0.34.0" dependencies = [ "bytecount", "noirc_frontend", @@ -2648,7 +2648,7 @@ dependencies = [ [[package]] name = "nargo_toml" -version = "0.33.0" +version = "0.34.0" dependencies = [ "dirs", "fm", @@ -2722,7 +2722,7 @@ dependencies = [ [[package]] name = "noir_debugger" -version = "0.33.0" +version = "0.34.0" dependencies = [ "acvm", "assert_cmd", @@ -2746,7 +2746,7 @@ dependencies = [ [[package]] name = "noir_fuzzer" -version = "0.33.0" +version = "0.34.0" dependencies = [ "acvm", "noirc_abi", @@ -2769,7 +2769,7 @@ dependencies = [ [[package]] name = "noir_lsp" -version = "0.33.0" +version = "0.34.0" dependencies = [ "acvm", "async-lsp", @@ -2798,7 +2798,7 @@ dependencies = [ [[package]] name = "noir_profiler" -version = "0.33.0" +version = "0.34.0" dependencies = [ "acir", "clap", @@ -2820,7 +2820,7 @@ dependencies = [ [[package]] name = "noir_wasm" -version = "0.33.0" +version = "0.34.0" dependencies = [ "acvm", "build-data", @@ -2844,7 +2844,7 @@ dependencies = [ [[package]] name = "noirc_abi" -version = "0.33.0" +version = "0.34.0" dependencies = [ "acvm", "iter-extended", @@ -2863,7 +2863,7 @@ dependencies = [ [[package]] name = "noirc_abi_wasm" -version = "0.33.0" +version = "0.34.0" dependencies = [ "acvm", "build-data", @@ -2880,11 +2880,11 @@ dependencies = [ [[package]] name = "noirc_arena" -version = "0.33.0" +version = "0.34.0" [[package]] name = "noirc_artifacts" -version = "0.33.0" +version = "0.34.0" dependencies = [ "acvm", "codespan-reporting", @@ -2899,7 +2899,7 @@ dependencies = [ [[package]] name = "noirc_driver" -version = "0.33.0" +version = "0.34.0" dependencies = [ "acvm", "aztec_macros", @@ -2919,7 +2919,7 @@ dependencies = [ [[package]] name = "noirc_errors" -version = "0.33.0" +version = "0.34.0" dependencies = [ "acvm", "base64 0.21.7", @@ -2937,7 +2937,7 @@ dependencies = [ [[package]] name = "noirc_evaluator" -version = "0.33.0" +version = "0.34.0" dependencies = [ "acvm", "bn254_blackbox_solver", @@ -2960,7 +2960,7 @@ dependencies = [ [[package]] name = "noirc_frontend" -version = "0.33.0" +version = "0.34.0" dependencies = [ "acvm", "base64 0.21.7", @@ -2991,7 +2991,7 @@ dependencies = [ [[package]] name = "noirc_printable_type" -version = "0.33.0" +version = "0.34.0" dependencies = [ "acvm", "iter-extended", diff --git a/noir/noir-repo/Cargo.toml b/noir/noir-repo/Cargo.toml index a903ef6fec9..6ef8829252a 100644 --- a/noir/noir-repo/Cargo.toml +++ b/noir/noir-repo/Cargo.toml @@ -42,7 +42,7 @@ resolver = "2" [workspace.package] # x-release-please-start-version -version = "0.33.0" +version = "0.34.0" # x-release-please-end authors = ["The Noir Team "] edition = "2021" @@ -59,13 +59,13 @@ unused_qualifications = "warn" [workspace.dependencies] # ACVM workspace dependencies -acir_field = { version = "0.49.0", path = "acvm-repo/acir_field", default-features = false } -acir = { version = "0.49.0", path = "acvm-repo/acir", default-features = false } -acvm = { version = "0.49.0", path = "acvm-repo/acvm" } -brillig = { version = "0.49.0", path = "acvm-repo/brillig", default-features = false } -brillig_vm = { version = "0.49.0", path = "acvm-repo/brillig_vm", default-features = false } -acvm_blackbox_solver = { version = "0.49.0", path = "acvm-repo/blackbox_solver", default-features = false } -bn254_blackbox_solver = { version = "0.49.0", path = "acvm-repo/bn254_blackbox_solver", default-features = false } +acir_field = { version = "0.50.0", path = "acvm-repo/acir_field", default-features = false } +acir = { version = "0.50.0", path = "acvm-repo/acir", default-features = false } +acvm = { version = "0.50.0", path = "acvm-repo/acvm" } +brillig = { version = "0.50.0", path = "acvm-repo/brillig", default-features = false } +brillig_vm = { version = "0.50.0", path = "acvm-repo/brillig_vm", default-features = false } +acvm_blackbox_solver = { version = "0.50.0", path = "acvm-repo/blackbox_solver", default-features = false } +bn254_blackbox_solver = { version = "0.50.0", path = "acvm-repo/bn254_blackbox_solver", default-features = false } # Noir compiler workspace dependencies fm = { path = "compiler/fm" } diff --git a/noir/noir-repo/acvm-repo/CHANGELOG.md b/noir/noir-repo/acvm-repo/CHANGELOG.md index 4b262d6b00f..8d47e10c45a 100644 --- a/noir/noir-repo/acvm-repo/CHANGELOG.md +++ b/noir/noir-repo/acvm-repo/CHANGELOG.md @@ -5,6 +5,96 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.50.0](https://github.com/noir-lang/noir/compare/v0.49.0...v0.50.0) (2024-09-13) + + +### ⚠ BREAKING CHANGES + +* Add Not instruction in brillig (https://github.com/AztecProtocol/aztec-packages/pull/8488) +* **avm:** variants for SET opcode (https://github.com/AztecProtocol/aztec-packages/pull/8441) +* **avm/brillig:** take addresses in calldatacopy (https://github.com/AztecProtocol/aztec-packages/pull/8388) +* constant inputs for blackbox (https://github.com/AztecProtocol/aztec-packages/pull/7222) +* add session id to foreign call RPC requests ([#5205](https://github.com/noir-lang/noir/issues/5205)) +* restrict noir word size to u32 ([#5180](https://github.com/noir-lang/noir/issues/5180)) + +### Features + +* (bb) 128-bit challenges (https://github.com/AztecProtocol/aztec-packages/pull/8406) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* **acir_gen:** Width aware ACIR gen addition ([#5493](https://github.com/noir-lang/noir/issues/5493)) ([85fa592](https://github.com/noir-lang/noir/commit/85fa592fdef3b8589ce03b232e1b51565837b540)) +* Add assertions for ACVM `FunctionInput` `bit_size` ([#5864](https://github.com/noir-lang/noir/issues/5864)) ([8712f4c](https://github.com/noir-lang/noir/commit/8712f4c20d23f3809bcfb03f2e3ba0e5ace20a1d)) +* Add Not instruction in brillig (https://github.com/AztecProtocol/aztec-packages/pull/8488) ([95e19ab](https://github.com/noir-lang/noir/commit/95e19ab9486ad054241b6e53e40e55bdba9dc7e5)) +* Add recursive aggregation object to proving/verification keys (https://github.com/AztecProtocol/aztec-packages/pull/6770) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Add reusable procedures to brillig generation (https://github.com/AztecProtocol/aztec-packages/pull/7981) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Add session id to foreign call RPC requests ([#5205](https://github.com/noir-lang/noir/issues/5205)) ([14adafc](https://github.com/noir-lang/noir/commit/14adafc965fa9c833e096ec037e086aae67703ad)) +* Added indirect const instruction (https://github.com/AztecProtocol/aztec-packages/pull/8065) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Adding aggregation to honk and rollup (https://github.com/AztecProtocol/aztec-packages/pull/7466) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Automate verify_honk_proof input generation (https://github.com/AztecProtocol/aztec-packages/pull/8092) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* **avm/brillig:** Take addresses in calldatacopy (https://github.com/AztecProtocol/aztec-packages/pull/8388) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* **avm:** Variants for SET opcode (https://github.com/AztecProtocol/aztec-packages/pull/8441) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* Avoid heap allocs when going to/from field (https://github.com/AztecProtocol/aztec-packages/pull/7547) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Change the layout of arrays and vectors to be a single pointer (https://github.com/AztecProtocol/aztec-packages/pull/8448) ([d4832ec](https://github.com/noir-lang/noir/commit/d4832ece9d3ad16544afea49cc7caf40501a2cc3)) +* Constant inputs for blackbox (https://github.com/AztecProtocol/aztec-packages/pull/7222) ([fb97bb9](https://github.com/noir-lang/noir/commit/fb97bb9b795c9d7af395b82fd6f0ea8111d59c11)) +* Hook up secondary calldata column in dsl (https://github.com/AztecProtocol/aztec-packages/pull/7759) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Integrate new proving systems in e2e (https://github.com/AztecProtocol/aztec-packages/pull/6971) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Make Brillig do integer arithmetic operations using u128 instead of Bigint (https://github.com/AztecProtocol/aztec-packages/pull/7518) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Make token transfer be recursive (https://github.com/AztecProtocol/aztec-packages/pull/7730) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* **nargo:** Hidden option to show contract artifact paths written by `nargo compile` (https://github.com/AztecProtocol/aztec-packages/pull/6131) ([ff67e14](https://github.com/noir-lang/noir/commit/ff67e145d086bf6fdf58fb5e57927033e52e03d3)) +* New test programs for wasm benchmarking (https://github.com/AztecProtocol/aztec-packages/pull/8389) ([95e19ab](https://github.com/noir-lang/noir/commit/95e19ab9486ad054241b6e53e40e55bdba9dc7e5)) +* Note hashes as points (https://github.com/AztecProtocol/aztec-packages/pull/7618) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Optimize constant array handling in brillig_gen (https://github.com/AztecProtocol/aztec-packages/pull/7661) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Optimize to_radix (https://github.com/AztecProtocol/aztec-packages/pull/8073) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Pass calldata ids to the backend (https://github.com/AztecProtocol/aztec-packages/pull/7875) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Poseidon2 gates for Ultra arithmetisation (https://github.com/AztecProtocol/aztec-packages/pull/7494) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* **profiler:** Add support for brillig functions in opcodes-flamegraph (https://github.com/AztecProtocol/aztec-packages/pull/7698) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Removing superfluous call to MSM (https://github.com/AztecProtocol/aztec-packages/pull/7708) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Report gates and VKs of private protocol circuits with megahonk (https://github.com/AztecProtocol/aztec-packages/pull/7722) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Restrict noir word size to u32 ([#5180](https://github.com/noir-lang/noir/issues/5180)) ([bdb2bc6](https://github.com/noir-lang/noir/commit/bdb2bc608ea8fd52d46545a38b68dd2558b28110)) +* Separate runtimes of SSA functions before inlining ([#5121](https://github.com/noir-lang/noir/issues/5121)) ([69eca9b](https://github.com/noir-lang/noir/commit/69eca9b8671fa54192bef814dd584fdb5387a5f7)) +* Simplify constant calls to `poseidon2_permutation`, `schnorr_verify` and `embedded_curve_add` ([#5140](https://github.com/noir-lang/noir/issues/5140)) ([2823ba7](https://github.com/noir-lang/noir/commit/2823ba7242db788ca1d7f6e7a48be2f1de62f278)) +* Small optimization in toradix (https://github.com/AztecProtocol/aztec-packages/pull/8040) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7392) ([fb97bb9](https://github.com/noir-lang/noir/commit/fb97bb9b795c9d7af395b82fd6f0ea8111d59c11)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7400) ([fb97bb9](https://github.com/noir-lang/noir/commit/fb97bb9b795c9d7af395b82fd6f0ea8111d59c11)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7432) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7444) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7454) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7512) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7577) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7583) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7743) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7862) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7945) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7958) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8008) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8093) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8125) ([f0c2686](https://github.com/noir-lang/noir/commit/f0c268606a71381ab4504396695a0adb9b3258b6)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8237) ([f0c2686](https://github.com/noir-lang/noir/commit/f0c268606a71381ab4504396695a0adb9b3258b6)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8423) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8435) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8466) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8482) ([d4832ec](https://github.com/noir-lang/noir/commit/d4832ece9d3ad16544afea49cc7caf40501a2cc3)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8512) ([95e19ab](https://github.com/noir-lang/noir/commit/95e19ab9486ad054241b6e53e40e55bdba9dc7e5)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8526) ([95e19ab](https://github.com/noir-lang/noir/commit/95e19ab9486ad054241b6e53e40e55bdba9dc7e5)) +* TXE nr deployments, dependency cleanup for CLI (https://github.com/AztecProtocol/aztec-packages/pull/7548) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Typing return values of embedded_curve_ops (https://github.com/AztecProtocol/aztec-packages/pull/7413) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Unify all acir recursion constraints based on RecursionConstraint and proof_type (https://github.com/AztecProtocol/aztec-packages/pull/7993) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) + + +### Bug Fixes + +* Add support for nested arrays returned by oracles ([#5132](https://github.com/noir-lang/noir/issues/5132)) ([f846879](https://github.com/noir-lang/noir/commit/f846879dd038328bd0a1d39a72b448ef52a1002b)) +* Add trailing extra arguments for backend in gates_flamegraph (https://github.com/AztecProtocol/aztec-packages/pull/7472) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Avoid unnecessarily splitting expressions with multiplication terms with a shared term ([#5291](https://github.com/noir-lang/noir/issues/5291)) ([19884f1](https://github.com/noir-lang/noir/commit/19884f161dfc7d7ce75dd2c404b8ef39cdad2240)) +* **debugger:** Update the debugger to handle the new Brillig debug metadata format ([#5706](https://github.com/noir-lang/noir/issues/5706)) ([a31f82e](https://github.com/noir-lang/noir/commit/a31f82e598def60d00c65b79b8c5411f8aa832aa)) +* Deflatten databus visibilities (https://github.com/AztecProtocol/aztec-packages/pull/7761) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Do not duplicate redundant Brillig debug metadata ([#5696](https://github.com/noir-lang/noir/issues/5696)) ([e4f7dbe](https://github.com/noir-lang/noir/commit/e4f7dbe63b55807b3ff0b4d6f47a8b7f847299fb)) +* Export brillig names in contract functions (https://github.com/AztecProtocol/aztec-packages/pull/8212) ([f0c2686](https://github.com/noir-lang/noir/commit/f0c268606a71381ab4504396695a0adb9b3258b6)) +* Handle multiple entry points for Brillig call stack resolution after metadata deduplication ([#5788](https://github.com/noir-lang/noir/issues/5788)) ([38fe9dd](https://github.com/noir-lang/noir/commit/38fe9dda111952fdb894df90a319c087382edfc9)) +* Handle struct with nested arrays in oracle return values ([#5244](https://github.com/noir-lang/noir/issues/5244)) ([a30814f](https://github.com/noir-lang/noir/commit/a30814f1f767bf874cd7e2969f5061c68f16b9a7)) +* Move BigInt modulus checks to runtime in brillig ([#5374](https://github.com/noir-lang/noir/issues/5374)) ([741d339](https://github.com/noir-lang/noir/commit/741d33991f8e2918bf092c354ca56047e0274533)) +* Restrict keccak256_injective test input to 8 bits ([#5977](https://github.com/noir-lang/noir/issues/5977)) ([a1b1346](https://github.com/noir-lang/noir/commit/a1b1346bf7525c508fd390393c307475cc2345d7)) +* Revert "feat: Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7512)" (https://github.com/AztecProtocol/aztec-packages/pull/7558) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Runtime brillig bigint id assignment ([#5369](https://github.com/noir-lang/noir/issues/5369)) ([a8928dd](https://github.com/noir-lang/noir/commit/a8928ddcffcae15babf7aa5aff0e462e4549552e)) + ## [0.49.0](https://github.com/noir-lang/noir/compare/v0.48.0...v0.49.0) (2024-08-06) diff --git a/noir/noir-repo/acvm-repo/acir/Cargo.toml b/noir/noir-repo/acvm-repo/acir/Cargo.toml index 860b565544b..b707ae9ad79 100644 --- a/noir/noir-repo/acvm-repo/acir/Cargo.toml +++ b/noir/noir-repo/acvm-repo/acir/Cargo.toml @@ -2,7 +2,7 @@ name = "acir" description = "ACIR is the IR that the VM processes, it is analogous to LLVM IR" # x-release-please-start-version -version = "0.49.0" +version = "0.50.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/noir/noir-repo/acvm-repo/acir/src/circuit/black_box_functions.rs b/noir/noir-repo/acvm-repo/acir/src/circuit/black_box_functions.rs index fb7d9eb584c..6639f1fbe71 100644 --- a/noir/noir-repo/acvm-repo/acir/src/circuit/black_box_functions.rs +++ b/noir/noir-repo/acvm-repo/acir/src/circuit/black_box_functions.rs @@ -164,7 +164,15 @@ pub enum BlackBoxFunc { /// ultimately fail. RecursiveAggregation, - /// Addition over the embedded curve on which the witness is defined. + /// Addition over the embedded curve on which the witness is defined + /// The opcode makes the following assumptions but does not enforce them because + /// it is more efficient to do it only when required. For instance, adding two + /// points that are on the curve it guarantee to give a point on the curve. + /// + /// It assumes that the points are on the curve. + /// If the inputs are the same witnesses index, it will perform a doubling, + /// If not, it assumes that the points' x-coordinates are not equal. + /// It also assumes neither point is the infinity point. EmbeddedCurveAdd, /// BigInt addition diff --git a/noir/noir-repo/acvm-repo/acir_field/Cargo.toml b/noir/noir-repo/acvm-repo/acir_field/Cargo.toml index acc34457bc9..168628b0d4a 100644 --- a/noir/noir-repo/acvm-repo/acir_field/Cargo.toml +++ b/noir/noir-repo/acvm-repo/acir_field/Cargo.toml @@ -2,7 +2,7 @@ name = "acir_field" description = "The field implementation being used by ACIR." # x-release-please-start-version -version = "0.49.0" +version = "0.50.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/noir/noir-repo/acvm-repo/acvm/Cargo.toml b/noir/noir-repo/acvm-repo/acvm/Cargo.toml index ea80dbeedbb..29375a57a6e 100644 --- a/noir/noir-repo/acvm-repo/acvm/Cargo.toml +++ b/noir/noir-repo/acvm-repo/acvm/Cargo.toml @@ -2,7 +2,7 @@ name = "acvm" description = "The virtual machine that processes ACIR given a backend/proof system." # x-release-please-start-version -version = "0.49.0" +version = "0.50.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/noir/noir-repo/acvm-repo/acvm_js/Cargo.toml b/noir/noir-repo/acvm-repo/acvm_js/Cargo.toml index 6b457a8f5f8..b5b55dbb91a 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/Cargo.toml +++ b/noir/noir-repo/acvm-repo/acvm_js/Cargo.toml @@ -2,7 +2,7 @@ name = "acvm_js" description = "Typescript wrapper around the ACVM allowing execution of ACIR code" # x-release-please-start-version -version = "0.49.0" +version = "0.50.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/noir/noir-repo/acvm-repo/acvm_js/build.sh b/noir/noir-repo/acvm-repo/acvm_js/build.sh index c07d2d8a4c1..16fb26e55db 100755 --- a/noir/noir-repo/acvm-repo/acvm_js/build.sh +++ b/noir/noir-repo/acvm-repo/acvm_js/build.sh @@ -25,7 +25,7 @@ function run_if_available { require_command jq require_command cargo require_command wasm-bindgen -#require_command wasm-opt +require_command wasm-opt self_path=$(dirname "$(readlink -f "$0")") pname=$(cargo read-manifest | jq -r '.name') diff --git a/noir/noir-repo/acvm-repo/acvm_js/package.json b/noir/noir-repo/acvm-repo/acvm_js/package.json index f1e9cf5eef0..54261a78dbc 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/package.json +++ b/noir/noir-repo/acvm-repo/acvm_js/package.json @@ -1,6 +1,6 @@ { "name": "@noir-lang/acvm_js", - "version": "0.49.0", + "version": "0.50.0", "publishConfig": { "access": "public" }, diff --git a/noir/noir-repo/acvm-repo/blackbox_solver/Cargo.toml b/noir/noir-repo/acvm-repo/blackbox_solver/Cargo.toml index d0473857e1c..b8b17db433c 100644 --- a/noir/noir-repo/acvm-repo/blackbox_solver/Cargo.toml +++ b/noir/noir-repo/acvm-repo/blackbox_solver/Cargo.toml @@ -2,7 +2,7 @@ name = "acvm_blackbox_solver" description = "A solver for the blackbox functions found in ACIR and Brillig" # x-release-please-start-version -version = "0.49.0" +version = "0.50.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/noir/noir-repo/acvm-repo/bn254_blackbox_solver/Cargo.toml b/noir/noir-repo/acvm-repo/bn254_blackbox_solver/Cargo.toml index 9a23f503a06..c892dc45fdd 100644 --- a/noir/noir-repo/acvm-repo/bn254_blackbox_solver/Cargo.toml +++ b/noir/noir-repo/acvm-repo/bn254_blackbox_solver/Cargo.toml @@ -2,7 +2,7 @@ name = "bn254_blackbox_solver" description = "Solvers for black box functions which are specific for the bn254 curve" # x-release-please-start-version -version = "0.49.0" +version = "0.50.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/noir/noir-repo/acvm-repo/brillig/Cargo.toml b/noir/noir-repo/acvm-repo/brillig/Cargo.toml index 9f5a5ce0ee2..0dec8fa2147 100644 --- a/noir/noir-repo/acvm-repo/brillig/Cargo.toml +++ b/noir/noir-repo/acvm-repo/brillig/Cargo.toml @@ -2,7 +2,7 @@ name = "brillig" description = "Brillig is the bytecode ACIR uses for non-determinism." # x-release-please-start-version -version = "0.49.0" +version = "0.50.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/noir/noir-repo/acvm-repo/brillig_vm/Cargo.toml b/noir/noir-repo/acvm-repo/brillig_vm/Cargo.toml index cd9f754ebc0..a5e1f7182b1 100644 --- a/noir/noir-repo/acvm-repo/brillig_vm/Cargo.toml +++ b/noir/noir-repo/acvm-repo/brillig_vm/Cargo.toml @@ -2,7 +2,7 @@ name = "brillig_vm" description = "The virtual machine that processes Brillig bytecode, used to introduce non-determinism to the ACVM" # x-release-please-start-version -version = "0.49.0" +version = "0.50.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/noir/noir-repo/aztec_macros/src/transforms/functions.rs b/noir/noir-repo/aztec_macros/src/transforms/functions.rs index 39c0ca344e6..6c8af308a52 100644 --- a/noir/noir-repo/aztec_macros/src/transforms/functions.rs +++ b/noir/noir-repo/aztec_macros/src/transforms/functions.rs @@ -316,14 +316,17 @@ fn create_static_check(fname: &str, is_private: bool) -> Statement { .iter() .fold(variable("context"), |acc, member| member_access(acc, member)) }; - make_statement(StatementKind::Constrain(ConstrainStatement( - make_eq(is_static_call_expr, expression(ExpressionKind::Literal(Literal::Bool(true)))), - Some(expression(ExpressionKind::Literal(Literal::Str(format!( - "Function {} can only be called statically", - fname - ))))), - ConstrainKind::Assert, - ))) + make_statement(StatementKind::Constrain(ConstrainStatement { + kind: ConstrainKind::Assert, + arguments: vec![ + make_eq(is_static_call_expr, expression(ExpressionKind::Literal(Literal::Bool(true)))), + expression(ExpressionKind::Literal(Literal::Str(format!( + "Function {} can only be called statically", + fname + )))), + ], + span: Default::default(), + })) } /// Creates a check for internal functions ensuring that the caller is self. @@ -332,17 +335,20 @@ fn create_static_check(fname: &str, is_private: bool) -> Statement { /// assert(context.msg_sender() == context.this_address(), "Function can only be called internally"); /// ``` fn create_internal_check(fname: &str) -> Statement { - make_statement(StatementKind::Constrain(ConstrainStatement( - make_eq( - method_call(variable("context"), "msg_sender", vec![]), - method_call(variable("context"), "this_address", vec![]), - ), - Some(expression(ExpressionKind::Literal(Literal::Str(format!( - "Function {} can only be called internally", - fname - ))))), - ConstrainKind::Assert, - ))) + make_statement(StatementKind::Constrain(ConstrainStatement { + kind: ConstrainKind::Assert, + arguments: vec![ + make_eq( + method_call(variable("context"), "msg_sender", vec![]), + method_call(variable("context"), "this_address", vec![]), + ), + expression(ExpressionKind::Literal(Literal::Str(format!( + "Function {} can only be called internally", + fname + )))), + ], + span: Default::default(), + })) } /// Creates a call to assert_initialization_matches_address_preimage to be inserted diff --git a/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs b/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs index d9c4a594fc6..8587e08892b 100644 --- a/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs +++ b/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs @@ -776,6 +776,7 @@ pub fn inject_note_exports( note.borrow().id, "get_note_type_id", false, + true, ) .ok_or(( AztecMacroError::CouldNotExportStorageLayout { diff --git a/noir/noir-repo/aztec_macros/src/transforms/storage.rs b/noir/noir-repo/aztec_macros/src/transforms/storage.rs index a6bf2e14fb3..e8ee1675546 100644 --- a/noir/noir-repo/aztec_macros/src/transforms/storage.rs +++ b/noir/noir-repo/aztec_macros/src/transforms/storage.rs @@ -222,9 +222,11 @@ pub fn generate_storage_implementation( }) .collect(); - let storage_constructor_statement = make_statement(StatementKind::Expression(expression( - ExpressionKind::constructor((chained_path!(storage_struct_name), field_constructors)), - ))); + let storage_constructor_statement = + make_statement(StatementKind::Expression(expression(ExpressionKind::constructor(( + UnresolvedType::from_path(chained_path!(storage_struct_name)), + field_constructors, + ))))); // This is the type over which the impl is generic. let generic_context_ident = ident("Context"); @@ -358,6 +360,7 @@ pub fn assign_storage_slots( storage_struct.borrow().id, "init", false, + true, ) .ok_or(( AztecMacroError::CouldNotAssignStorageSlots { diff --git a/noir/noir-repo/aztec_macros/src/utils/hir_utils.rs b/noir/noir-repo/aztec_macros/src/utils/hir_utils.rs index 200ce3099cb..4f1ef78b474 100644 --- a/noir/noir-repo/aztec_macros/src/utils/hir_utils.rs +++ b/noir/noir-repo/aztec_macros/src/utils/hir_utils.rs @@ -74,7 +74,7 @@ pub fn signature_of_type(typ: &Type) -> String { Type::FieldElement => "Field".to_owned(), Type::Bool => "bool".to_owned(), Type::Array(len, typ) => { - if let Type::Constant(len) = **len { + if let Type::Constant(len, _) = **len { format!("[{};{len}]", signature_of_type(typ)) } else { unimplemented!("Cannot generate signature for array with length type {:?}", typ) @@ -90,7 +90,7 @@ pub fn signature_of_type(typ: &Type) -> String { format!("({})", fields.join(",")) } Type::String(len_typ) => { - if let Type::Constant(len) = **len_typ { + if let Type::Constant(len, _) = **len_typ { format!("str<{len}>") } else { unimplemented!( @@ -326,7 +326,7 @@ pub fn get_serialized_length( let serialized_trait_impl = serialized_trait_impl_shared.borrow(); match serialized_trait_impl.trait_generics.first().unwrap() { - Type::Constant(value) => Ok(*value), + Type::Constant(value, _) => Ok(*value), _ => Err(MacroError { primary_message: format!("{} length for {} must be a constant", trait_name, typ), secondary_message: None, diff --git a/noir/noir-repo/aztec_macros/src/utils/parse_utils.rs b/noir/noir-repo/aztec_macros/src/utils/parse_utils.rs index 712afbc248b..61f54377284 100644 --- a/noir/noir-repo/aztec_macros/src/utils/parse_utils.rs +++ b/noir/noir-repo/aztec_macros/src/utils/parse_utils.rs @@ -108,7 +108,17 @@ fn empty_noir_function(noir_function: &mut NoirFunction) { fn empty_trait_item(trait_item: &mut TraitItem) { match trait_item { - TraitItem::Function { name, generics, parameters, return_type, where_clause, body } => { + TraitItem::Function { + name, + generics, + parameters, + return_type, + where_clause, + body, + is_unconstrained: _, + visibility: _, + is_comptime: _, + } => { empty_ident(name); empty_unresolved_generics(generics); for (name, typ) in parameters.iter_mut() { @@ -233,10 +243,7 @@ fn empty_statement(statement: &mut Statement) { } fn empty_constrain_statement(constrain_statement: &mut ConstrainStatement) { - empty_expression(&mut constrain_statement.0); - if let Some(expression) = &mut constrain_statement.1 { - empty_expression(expression); - } + empty_expressions(&mut constrain_statement.arguments); } fn empty_expressions(expressions: &mut [Expression]) { @@ -285,10 +292,17 @@ fn empty_expression(expression: &mut Expression) { empty_unresolved_type(&mut path.typ); empty_path(&mut path.trait_path); empty_ident(&mut path.impl_item); + empty_type_args(&mut path.trait_generics); + } + ExpressionKind::TypePath(path) => { + empty_unresolved_type(&mut path.typ); + empty_ident(&mut path.item); + empty_type_args(&mut path.turbofish); } ExpressionKind::Quote(..) | ExpressionKind::Resolved(_) | ExpressionKind::Interned(_) + | ExpressionKind::InternedStatement(_) | ExpressionKind::Error => (), } } @@ -495,7 +509,7 @@ fn empty_method_call_expression(method_call_expression: &mut MethodCallExpressio } fn empty_constructor_expression(constructor_expression: &mut ConstructorExpression) { - empty_path(&mut constructor_expression.type_name); + empty_unresolved_type(&mut constructor_expression.typ); for (name, expression) in constructor_expression.fields.iter_mut() { empty_ident(name); empty_expression(expression); diff --git a/noir/noir-repo/compiler/noirc_driver/src/abi_gen.rs b/noir/noir-repo/compiler/noirc_driver/src/abi_gen.rs index e2692349baa..be89b24fee5 100644 --- a/noir/noir-repo/compiler/noirc_driver/src/abi_gen.rs +++ b/noir/noir-repo/compiler/noirc_driver/src/abi_gen.rs @@ -99,7 +99,7 @@ pub(super) fn abi_type_from_hir_type(context: &Context, typ: &Type) -> AbiType { } Type::Error | Type::Unit - | Type::Constant(_) + | Type::Constant(..) | Type::InfixExpr(..) | Type::TraitAsType(..) | Type::TypeVariable(_, _) diff --git a/noir/noir-repo/compiler/noirc_errors/src/lib.rs b/noir/noir-repo/compiler/noirc_errors/src/lib.rs index 6eaa96e0cb1..bcdc0684099 100644 --- a/noir/noir-repo/compiler/noirc_errors/src/lib.rs +++ b/noir/noir-repo/compiler/noirc_errors/src/lib.rs @@ -13,20 +13,11 @@ pub use reporter::{CustomDiagnostic, DiagnosticKind}; pub struct FileDiagnostic { pub file_id: fm::FileId, pub diagnostic: CustomDiagnostic, - - /// An optional call stack to display the full runtime call stack - /// leading up to a runtime error. If this is empty it will not be displayed. - pub call_stack: Vec, } impl FileDiagnostic { pub fn new(file_id: fm::FileId, diagnostic: CustomDiagnostic) -> FileDiagnostic { - FileDiagnostic { file_id, diagnostic, call_stack: Vec::new() } - } - - pub fn with_call_stack(mut self, call_stack: Vec) -> Self { - self.call_stack = call_stack; - self + FileDiagnostic { file_id, diagnostic } } } diff --git a/noir/noir-repo/compiler/noirc_errors/src/reporter.rs b/noir/noir-repo/compiler/noirc_errors/src/reporter.rs index 0886f83af9d..76e308969b4 100644 --- a/noir/noir-repo/compiler/noirc_errors/src/reporter.rs +++ b/noir/noir-repo/compiler/noirc_errors/src/reporter.rs @@ -14,6 +14,10 @@ pub struct CustomDiagnostic { pub kind: DiagnosticKind, pub deprecated: bool, pub unnecessary: bool, + + /// An optional call stack to display the full runtime call stack + /// leading up to a runtime error. If this is empty it will not be displayed. + pub call_stack: Vec, } #[derive(Debug, Copy, Clone, PartialEq, Eq)] @@ -39,6 +43,7 @@ impl CustomDiagnostic { kind: DiagnosticKind::Error, deprecated: false, unnecessary: false, + call_stack: Default::default(), } } @@ -55,6 +60,7 @@ impl CustomDiagnostic { kind, deprecated: false, unnecessary: false, + call_stack: Default::default(), } } @@ -109,6 +115,7 @@ impl CustomDiagnostic { kind: DiagnosticKind::Bug, deprecated: false, unnecessary: false, + call_stack: Default::default(), } } @@ -116,6 +123,11 @@ impl CustomDiagnostic { FileDiagnostic::new(file_id, self) } + pub fn with_call_stack(mut self, call_stack: Vec) -> Self { + self.call_stack = call_stack; + self + } + pub fn add_note(&mut self, message: String) { self.notes.push(message); } @@ -204,7 +216,7 @@ impl FileDiagnostic { files: &'files impl Files<'files, FileId = fm::FileId>, deny_warnings: bool, ) -> bool { - report(files, &self.diagnostic, Some(self.file_id), &self.call_stack, deny_warnings) + report(files, &self.diagnostic, Some(self.file_id), deny_warnings) } } @@ -213,7 +225,6 @@ pub fn report<'files>( files: &'files impl Files<'files, FileId = fm::FileId>, custom_diagnostic: &CustomDiagnostic, file: Option, - call_stack: &[Location], deny_warnings: bool, ) -> bool { let color_choice = @@ -221,7 +232,7 @@ pub fn report<'files>( let writer = StandardStream::stderr(color_choice); let config = codespan_reporting::term::Config::default(); - let stack_trace = stack_trace(files, call_stack); + let stack_trace = stack_trace(files, &custom_diagnostic.call_stack); let diagnostic = convert_diagnostic(custom_diagnostic, file, stack_trace, deny_warnings); term::emit(&mut writer.lock(), &config, files, &diagnostic).unwrap(); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs index c4f0e944099..8929122f515 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs @@ -666,7 +666,7 @@ impl<'block> BrilligBlock<'block> { self.brillig_context.deallocate_register(items_pointer); } - Instruction::ArraySet { array, index, value, mutable: _ } => { + Instruction::ArraySet { array, index, value, mutable } => { let source_variable = self.convert_ssa_value(*array, dfg); let index_register = self.convert_ssa_single_addr_value(*index, dfg); let value_variable = self.convert_ssa_value(*value, dfg); @@ -688,6 +688,7 @@ impl<'block> BrilligBlock<'block> { destination_variable, index_register, value_variable, + *mutable, ); } Instruction::RangeCheck { value, max_bit_size, assert_message } => { @@ -868,6 +869,7 @@ impl<'block> BrilligBlock<'block> { destination_variable: BrilligVariable, index_register: SingleAddrVariable, value_variable: BrilligVariable, + mutable: bool, ) { assert!(index_register.bit_size == BRILLIG_MEMORY_ADDRESSING_BIT_SIZE); match (source_variable, destination_variable) { @@ -875,20 +877,26 @@ impl<'block> BrilligBlock<'block> { BrilligVariable::BrilligArray(source_array), BrilligVariable::BrilligArray(destination_array), ) => { - self.brillig_context.call_array_copy_procedure(source_array, destination_array); + if !mutable { + self.brillig_context.call_array_copy_procedure(source_array, destination_array); + } } ( BrilligVariable::BrilligVector(source_vector), BrilligVariable::BrilligVector(destination_vector), ) => { - self.brillig_context.call_vector_copy_procedure(source_vector, destination_vector); + if !mutable { + self.brillig_context + .call_vector_copy_procedure(source_vector, destination_vector); + } } _ => unreachable!("ICE: array set on non-array"), } + let destination_for_store = if mutable { source_variable } else { destination_variable }; // Then set the value in the newly created array let items_pointer = - self.brillig_context.codegen_make_array_or_vector_items_pointer(destination_variable); + self.brillig_context.codegen_make_array_or_vector_items_pointer(destination_for_store); self.brillig_context.codegen_store_with_offset( items_pointer, @@ -896,6 +904,14 @@ impl<'block> BrilligBlock<'block> { value_variable.extract_register(), ); + // If we mutated the source array we want instructions that use the destination array to point to the source array + if mutable { + self.brillig_context.mov_instruction( + destination_variable.extract_register(), + source_variable.extract_register(), + ); + } + self.brillig_context.deallocate_register(items_pointer); } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_stack.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_stack.rs index 945b768efcf..b7b25c6db49 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_stack.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_stack.rs @@ -1,26 +1,290 @@ use acvm::{acir::brillig::MemoryAddress, AcirField}; +use fxhash::{FxHashMap as HashMap, FxHashSet as HashSet}; use super::{debug_show::DebugToString, registers::RegisterAllocator, BrilligContext}; impl BrilligContext { /// This function moves values from a set of registers to another set of registers. - /// It first moves all sources to new allocated registers to avoid overwriting. + /// The only requirement is that every destination needs to be written at most once. pub(crate) fn codegen_mov_registers_to_registers( &mut self, sources: Vec, destinations: Vec, ) { - let new_sources: Vec<_> = sources - .iter() - .map(|source| { - let new_source = self.allocate_register(); - self.mov_instruction(new_source, *source); - new_source - }) + assert_eq!(sources.len(), destinations.len()); + // Remove all no-ops + let movements: Vec<_> = sources + .into_iter() + .zip(destinations) + .filter(|(source, destination)| source != destination) .collect(); - for (new_source, destination) in new_sources.iter().zip(destinations.iter()) { - self.mov_instruction(*destination, *new_source); - self.deallocate_register(*new_source); + + // Now we need to detect all cycles. + // First build a map of the movements. Note that a source could have multiple destinations + let mut movements_map: HashMap> = + movements.into_iter().fold(HashMap::default(), |mut map, (source, destination)| { + map.entry(source).or_default().insert(destination); + map + }); + + let destinations_set: HashSet<_> = movements_map.values().flatten().copied().collect(); + assert_eq!( + destinations_set.len(), + movements_map.values().flatten().count(), + "Multiple moves to the same register found" + ); + + let mut loop_detector = LoopDetector::default(); + loop_detector.collect_loops(&movements_map); + let loops = loop_detector.loops; + // In order to break the loops we need to store one register from each in a temporary and then use that temporary as source. + let mut temporaries = Vec::with_capacity(loops.len()); + for loop_found in loops { + let temp_register = self.allocate_register(); + temporaries.push(temp_register); + let first_source = loop_found.iter().next().unwrap(); + self.mov_instruction(temp_register, *first_source); + let destinations_of_temp = movements_map.remove(first_source).unwrap(); + movements_map.insert(temp_register, destinations_of_temp); + } + // After removing loops we should have an DAG with each node having only one ancestor (but could have multiple successors) + // Now we should be able to move the registers just by performing a DFS on the movements map + let heads: Vec<_> = movements_map + .keys() + .filter(|source| !destinations_set.contains(source)) + .copied() + .collect(); + for head in heads { + self.perform_movements(&movements_map, head); + } + + // Deallocate all temporaries + for temp in temporaries { + self.deallocate_register(temp); } } + + fn perform_movements( + &mut self, + movements: &HashMap>, + current_source: MemoryAddress, + ) { + if let Some(destinations) = movements.get(¤t_source) { + for destination in destinations { + self.perform_movements(movements, *destination); + } + for destination in destinations { + self.mov_instruction(*destination, current_source); + } + } + } +} + +#[derive(Default)] +struct LoopDetector { + visited_sources: HashSet, + loops: Vec>, +} + +impl LoopDetector { + fn collect_loops(&mut self, movements: &HashMap>) { + for source in movements.keys() { + self.find_loop_recursive(*source, movements, im::OrdSet::default()); + } + } + + fn find_loop_recursive( + &mut self, + source: MemoryAddress, + movements: &HashMap>, + mut previous_sources: im::OrdSet, + ) { + if self.visited_sources.contains(&source) { + return; + } + // Mark as visited + self.visited_sources.insert(source); + + previous_sources.insert(source); + // Get all destinations + if let Some(destinations) = movements.get(&source) { + for destination in destinations { + if previous_sources.contains(destination) { + // Found a loop + let loop_sources = previous_sources.clone(); + self.loops.push(loop_sources); + } else { + self.find_loop_recursive(*destination, movements, previous_sources.clone()); + } + } + } + } +} + +#[cfg(test)] +mod tests { + use acvm::{ + acir::brillig::{MemoryAddress, Opcode}, + FieldElement, + }; + use fxhash::{FxHashMap as HashMap, FxHashSet as HashSet}; + + use crate::{ + brillig::brillig_ir::{artifact::Label, registers::Stack, BrilligContext}, + ssa::ir::function::FunctionId, + }; + + // Tests for the loop finder + + fn generate_movements_map( + movements: Vec<(usize, usize)>, + ) -> HashMap> { + movements.into_iter().fold(HashMap::default(), |mut map, (source, destination)| { + map.entry(MemoryAddress(source)).or_default().insert(MemoryAddress(destination)); + map + }) + } + + #[test] + fn test_loop_detector_basic_loop() { + let movements = vec![(0, 1), (1, 2), (2, 3), (3, 0)]; + let movements_map = generate_movements_map(movements); + let mut loop_detector = super::LoopDetector::default(); + loop_detector.collect_loops(&movements_map); + assert_eq!(loop_detector.loops.len(), 1); + assert_eq!(loop_detector.loops[0].len(), 4); + } + + #[test] + fn test_loop_detector_no_loop() { + let movements = vec![(0, 1), (1, 2), (2, 3), (3, 4)]; + let movements_map = generate_movements_map(movements); + let mut loop_detector = super::LoopDetector::default(); + loop_detector.collect_loops(&movements_map); + assert_eq!(loop_detector.loops.len(), 0); + } + + #[test] + fn test_loop_detector_loop_with_branch() { + let movements = vec![(0, 1), (1, 2), (2, 0), (0, 3), (3, 4)]; + let movements_map = generate_movements_map(movements); + let mut loop_detector = super::LoopDetector::default(); + loop_detector.collect_loops(&movements_map); + assert_eq!(loop_detector.loops.len(), 1); + assert_eq!(loop_detector.loops[0].len(), 3); + } + + #[test] + fn test_loop_detector_two_loops() { + let movements = vec![(0, 1), (1, 2), (2, 0), (3, 4), (4, 5), (5, 3)]; + let movements_map = generate_movements_map(movements); + let mut loop_detector = super::LoopDetector::default(); + loop_detector.collect_loops(&movements_map); + assert_eq!(loop_detector.loops.len(), 2); + assert_eq!(loop_detector.loops[0].len(), 3); + assert_eq!(loop_detector.loops[1].len(), 3); + } + + // Tests for mov_registers_to_registers + + fn movements_to_source_and_destinations( + movements: Vec<(usize, usize)>, + ) -> (Vec, Vec) { + let sources = movements.iter().map(|(source, _)| MemoryAddress::from(*source)).collect(); + let destinations = + movements.iter().map(|(_, destination)| MemoryAddress::from(*destination)).collect(); + (sources, destinations) + } + + pub(crate) fn create_context() -> BrilligContext { + let mut context = BrilligContext::new(true); + context.enter_context(Label::function(FunctionId::test_new(0))); + context + } + + #[test] + #[should_panic(expected = "Multiple moves to the same register found")] + fn test_mov_registers_to_registers_overwrite() { + let movements = vec![(10, 11), (12, 11), (10, 13)]; + let (sources, destinations) = movements_to_source_and_destinations(movements); + let mut context = create_context(); + + context.codegen_mov_registers_to_registers(sources, destinations); + } + + #[test] + fn test_mov_registers_to_registers_no_loop() { + let movements = vec![(10, 11), (11, 12), (12, 13), (13, 14)]; + let (sources, destinations) = movements_to_source_and_destinations(movements); + let mut context = create_context(); + + context.codegen_mov_registers_to_registers(sources, destinations); + let opcodes = context.artifact().byte_code; + assert_eq!( + opcodes, + vec![ + Opcode::Mov { destination: MemoryAddress(14), source: MemoryAddress(13) }, + Opcode::Mov { destination: MemoryAddress(13), source: MemoryAddress(12) }, + Opcode::Mov { destination: MemoryAddress(12), source: MemoryAddress(11) }, + Opcode::Mov { destination: MemoryAddress(11), source: MemoryAddress(10) }, + ] + ); + } + #[test] + fn test_mov_registers_to_registers_no_op_filter() { + let movements = vec![(10, 11), (11, 11), (11, 12)]; + let (sources, destinations) = movements_to_source_and_destinations(movements); + let mut context = create_context(); + + context.codegen_mov_registers_to_registers(sources, destinations); + let opcodes = context.artifact().byte_code; + assert_eq!( + opcodes, + vec![ + Opcode::Mov { destination: MemoryAddress(12), source: MemoryAddress(11) }, + Opcode::Mov { destination: MemoryAddress(11), source: MemoryAddress(10) }, + ] + ); + } + + #[test] + fn test_mov_registers_to_registers_loop() { + let movements = vec![(10, 11), (11, 12), (12, 13), (13, 10)]; + let (sources, destinations) = movements_to_source_and_destinations(movements); + let mut context = create_context(); + + context.codegen_mov_registers_to_registers(sources, destinations); + let opcodes = context.artifact().byte_code; + assert_eq!( + opcodes, + vec![ + Opcode::Mov { destination: MemoryAddress(3), source: MemoryAddress(10) }, + Opcode::Mov { destination: MemoryAddress(10), source: MemoryAddress(13) }, + Opcode::Mov { destination: MemoryAddress(13), source: MemoryAddress(12) }, + Opcode::Mov { destination: MemoryAddress(12), source: MemoryAddress(11) }, + Opcode::Mov { destination: MemoryAddress(11), source: MemoryAddress(3) } + ] + ); + } + + #[test] + fn test_mov_registers_to_registers_loop_and_branch() { + let movements = vec![(10, 11), (11, 12), (12, 10), (10, 13), (13, 14)]; + let (sources, destinations) = movements_to_source_and_destinations(movements); + let mut context = create_context(); + + context.codegen_mov_registers_to_registers(sources, destinations); + let opcodes = context.artifact().byte_code; + assert_eq!( + opcodes, + vec![ + Opcode::Mov { destination: MemoryAddress(3), source: MemoryAddress(10) }, // Temporary + Opcode::Mov { destination: MemoryAddress(14), source: MemoryAddress(13) }, // Branch + Opcode::Mov { destination: MemoryAddress(10), source: MemoryAddress(12) }, // Loop + Opcode::Mov { destination: MemoryAddress(12), source: MemoryAddress(11) }, // Loop + Opcode::Mov { destination: MemoryAddress(13), source: MemoryAddress(3) }, // Finish branch + Opcode::Mov { destination: MemoryAddress(11), source: MemoryAddress(3) } // Finish loop + ] + ); + } } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/errors.rs b/noir/noir-repo/compiler/noirc_evaluator/src/errors.rs index c4ba08f9acd..994e97eabb8 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/errors.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/errors.rs @@ -87,7 +87,7 @@ impl From for FileDiagnostic { let location = call_stack.last().expect("Expected RuntimeError to have a location"); let diagnostic = Diagnostic::simple_warning(message, secondary_message, location.span); - diagnostic.in_file(file_id).with_call_stack(call_stack) + diagnostic.with_call_stack(call_stack).in_file(file_id) } SsaReport::Bug(bug) => { let message = bug.to_string(); @@ -101,7 +101,7 @@ impl From for FileDiagnostic { let file_id = call_stack.last().map(|location| location.file).unwrap_or_default(); let location = call_stack.last().expect("Expected RuntimeError to have a location"); let diagnostic = Diagnostic::simple_bug(message, secondary_message, location.span); - diagnostic.in_file(file_id).with_call_stack(call_stack) + diagnostic.with_call_stack(call_stack).in_file(file_id) } } } @@ -178,7 +178,7 @@ impl From for FileDiagnostic { let call_stack = vecmap(error.call_stack(), |location| *location); let file_id = call_stack.last().map(|location| location.file).unwrap_or_default(); let diagnostic = error.into_diagnostic(); - diagnostic.in_file(file_id).with_call_stack(call_stack) + diagnostic.with_call_stack(call_stack).in_file(file_id) } } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index 9586d08e10c..b0f283eeaeb 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -1471,6 +1471,7 @@ impl AcirContext { | BlackBoxFunc::AND | BlackBoxFunc::XOR | BlackBoxFunc::AES128Encrypt + | BlackBoxFunc::EmbeddedCurveAdd ); // Convert `AcirVar` to `FunctionInput` let inputs = self.prepare_inputs_for_black_box_func_call(inputs, allow_constant_inputs)?; @@ -1944,6 +1945,15 @@ impl AcirContext { Ok(()) } + /// Insert the MemoryInit for the Return Data array, using the provided witnesses + pub(crate) fn initialize_return_data(&mut self, block_id: BlockId, init: Vec) { + self.acir_ir.push_opcode(Opcode::MemoryInit { + block_id, + init, + block_type: BlockType::ReturnData, + }); + } + /// Initializes an array in memory with the given values `optional_values`. /// If `optional_values` is empty, then the array is initialized with zeros. pub(crate) fn initialize_array( diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index 15b44fde65d..15d72c2ae74 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -434,16 +434,9 @@ impl<'a> Context<'a> { for instruction_id in entry_block.instructions() { warnings.extend(self.convert_ssa_instruction(*instruction_id, dfg, ssa, brillig)?); } - let (return_vars, return_warnings) = self.convert_ssa_return(entry_block.unwrap_terminator(), dfg)?; - let call_data_arrays: Vec = - self.data_bus.call_data.iter().map(|cd| cd.array_id).collect(); - for call_data_array in call_data_arrays { - self.ensure_array_is_initialized(call_data_array, dfg)?; - } - // TODO: This is a naive method of assigning the return values to their witnesses as // we're likely to get a number of constraints which are asserting one witness to be equal to another. // @@ -452,11 +445,45 @@ impl<'a> Context<'a> { self.acir_context.assert_eq_var(*witness_var, return_var, None)?; } + self.initialize_databus(&return_witnesses, dfg)?; warnings.extend(return_warnings); warnings.extend(self.acir_context.warnings.clone()); // Add the warnings from the alter Ssa passes - Ok(self.acir_context.finish(input_witness, return_witnesses, warnings)) + Ok(self.acir_context.finish( + input_witness, + // Don't embed databus return witnesses into the circuit. + if self.data_bus.return_data.is_some() { Vec::new() } else { return_witnesses }, + warnings, + )) + } + + fn initialize_databus( + &mut self, + witnesses: &Vec, + dfg: &DataFlowGraph, + ) -> Result<(), RuntimeError> { + // Initialize return_data using provided witnesses + if let Some(return_data) = self.data_bus.return_data { + let block_id = self.block_id(&return_data); + let already_initialized = self.initialized_arrays.contains(&block_id); + if !already_initialized { + // We hijack ensure_array_is_initialized() because we want the return data to use the return value witnesses, + // but the databus contains the computed values instead, that have just been asserted to be equal to the return values. + // We do not use initialize_array either for the case where a constant value is returned. + // In that case, the constant value has already been assigned a witness and the returned acir vars will be + // converted to it, instead of the corresponding return value witness. + self.acir_context.initialize_return_data(block_id, witnesses.to_owned()); + } + } + + // Initialize call_data + let call_data_arrays: Vec = + self.data_bus.call_data.iter().map(|cd| cd.array_id).collect(); + for call_data_array in call_data_arrays { + self.ensure_array_is_initialized(call_data_array, dfg)?; + } + Ok(()) } fn convert_brillig_main( @@ -1792,19 +1819,9 @@ impl<'a> Context<'a> { _ => unreachable!("ICE: Program must have a singular return"), }; - return_values.iter().fold(0, |acc, value_id| { - let is_databus = self - .data_bus - .return_data - .map_or(false, |return_databus| dfg[*value_id] == dfg[return_databus]); - - if is_databus { - // We do not return value for the data bus. - acc - } else { - acc + dfg.type_of_value(*value_id).flattened_size() - } - }) + return_values + .iter() + .fold(0, |acc, value_id| acc + dfg.type_of_value(*value_id).flattened_size()) } /// Converts an SSA terminator's return values into their ACIR representations @@ -1824,27 +1841,13 @@ impl<'a> Context<'a> { let mut has_constant_return = false; let mut return_vars: Vec = Vec::new(); for value_id in return_values { - let is_databus = self - .data_bus - .return_data - .map_or(false, |return_databus| dfg[*value_id] == dfg[return_databus]); let value = self.convert_value(*value_id, dfg); // `value` may or may not be an array reference. Calling `flatten` will expand the array if there is one. let acir_vars = self.acir_context.flatten(value)?; for (acir_var, _) in acir_vars { has_constant_return |= self.acir_context.is_constant(&acir_var); - if is_databus { - // We do not return value for the data bus. - self.ensure_array_is_initialized( - self.data_bus.return_data.expect( - "`is_databus == true` implies `data_bus.return_data` is `Some`", - ), - dfg, - )?; - } else { - return_vars.push(acir_var); - } + return_vars.push(acir_var); } } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function.rs index 65a616ef612..1466f2e5d44 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function.rs @@ -160,6 +160,17 @@ impl Function { let returns = vecmap(self.returns(), |ret| self.dfg.type_of_value(*ret)); Signature { params, returns } } + + /// Finds the block of the function with the Return instruction + pub(crate) fn find_last_block(&self) -> BasicBlockId { + for block in self.reachable_blocks() { + if matches!(self.dfg[block].terminator(), Some(TerminatorInstruction::Return { .. })) { + return block; + } + } + + unreachable!("SSA Function {} has no reachable return instruction!", self.id()) + } } impl std::fmt::Display for RuntimeType { diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function_inserter.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function_inserter.rs index 06325b31dd0..9221a925aa8 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function_inserter.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function_inserter.rs @@ -102,6 +102,14 @@ impl<'f> FunctionInserter<'f> { self.function.dfg[block].set_terminator(terminator); } + /// Maps the data bus in place, replacing any ValueId in the data bus with the + /// resolved version of that value id from this FunctionInserter's internal value mapping. + pub(crate) fn map_data_bus_in_place(&mut self) { + let data_bus = self.function.dfg.data_bus.clone(); + let data_bus = data_bus.map_values(|value| self.resolve(value)); + self.function.dfg.data_bus = data_bus; + } + /// Push a new instruction to the given block and return its new InstructionId. /// If the instruction was simplified out of the program, None is returned. pub(crate) fn push_instruction( diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/array_set.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/array_set.rs index cf61d7fd73f..491a17adb66 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/array_set.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/array_set.rs @@ -16,14 +16,17 @@ impl Ssa { #[tracing::instrument(level = "trace", skip(self))] pub(crate) fn array_set_optimization(mut self) -> Self { for func in self.functions.values_mut() { - if !func.runtime().is_entry_point() { - let mut reachable_blocks = func.reachable_blocks(); + let mut reachable_blocks = func.reachable_blocks(); + let block = 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 block = reachable_blocks.pop_first().unwrap(); - let instructions_to_update = analyze_last_uses(&func.dfg, block); - make_mutable(&mut func.dfg, block, instructions_to_update); - } + let instructions_to_update = analyze_last_uses(&func.dfg, block); + make_mutable(&mut func.dfg, block, instructions_to_update); } self } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/bubble_up_constrains.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/bubble_up_constrains.rs deleted file mode 100644 index 0409f0e6a49..00000000000 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/bubble_up_constrains.rs +++ /dev/null @@ -1,152 +0,0 @@ -use std::collections::HashMap; - -use crate::ssa::{ - ir::instruction::{Instruction, InstructionId}, - ssa_gen::Ssa, -}; - -impl Ssa { - /// A simple SSA pass to go through each instruction and move every `Instruction::Constrain` to immediately - /// after when all of its inputs are available. - #[tracing::instrument(level = "trace", skip(self))] - pub(crate) fn bubble_up_constrains(mut self) -> Ssa { - for function in self.functions.values_mut() { - for block in function.reachable_blocks() { - let instructions = function.dfg[block].take_instructions(); - let mut filtered_instructions = Vec::with_capacity(instructions.len()); - - // Multiple constrains can bubble up to sit under a single instruction. We want to maintain the ordering of these constraints, - // so we need to keep track of how many constraints are attached to a given instruction. - // Some assertions don't operate on instruction results, so we use Option so we also track the None case - let mut inserted_at_instruction: HashMap, usize> = - HashMap::with_capacity(instructions.len()); - - let dfg = &function.dfg; - for instruction in instructions { - let (lhs, rhs) = match dfg[instruction] { - Instruction::Constrain(lhs, rhs, ..) => (lhs, rhs), - _ => { - filtered_instructions.push(instruction); - continue; - } - }; - - let last_instruction_that_creates_inputs = filtered_instructions - .iter() - .rev() - .position(|&instruction_id| { - let results = dfg.instruction_results(instruction_id).to_vec(); - results.contains(&lhs) || results.contains(&rhs) - }) - // We iterate through the previous instructions in reverse order so the index is from the - // back of the vector - .map(|reversed_index| filtered_instructions.len() - reversed_index - 1); - - let insertion_index = last_instruction_that_creates_inputs - .map(|index| { - // We want to insert just after the last instruction that creates the inputs - index + 1 - }) - // If it doesn't depend from the previous instructions, then we insert at the start - .unwrap_or_default(); - - let already_inserted_for_this_instruction = inserted_at_instruction - .entry( - last_instruction_that_creates_inputs - .map(|index| filtered_instructions[index]), - ) - .or_default(); - - filtered_instructions.insert( - insertion_index + *already_inserted_for_this_instruction, - instruction, - ); - - *already_inserted_for_this_instruction += 1; - } - - *function.dfg[block].instructions_mut() = filtered_instructions; - } - } - self - } -} - -#[cfg(test)] -mod test { - use crate::ssa::{ - function_builder::FunctionBuilder, - ir::{ - instruction::{Binary, BinaryOp, Instruction}, - map::Id, - types::Type, - }, - }; - - #[test] - fn check_bubble_up_constrains() { - // fn main f0 { - // b0(v0: Field): - // v1 = add v0, Field 1 - // v2 = add v1, Field 1 - // constrain v0 == Field 1 'With message' - // constrain v2 == Field 3 - // constrain v0 == Field 1 - // constrain v1 == Field 2 - // constrain v1 == Field 2 'With message' - // } - // - let main_id = Id::test_new(0); - - // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id); - let v0 = builder.add_parameter(Type::field()); - - let one = builder.field_constant(1u128); - let two = builder.field_constant(2u128); - let three = builder.field_constant(3u128); - - let v1 = builder.insert_binary(v0, BinaryOp::Add, one); - let v2 = builder.insert_binary(v1, BinaryOp::Add, one); - builder.insert_constrain(v0, one, Some("With message".to_string().into())); - builder.insert_constrain(v2, three, None); - builder.insert_constrain(v0, one, None); - builder.insert_constrain(v1, two, None); - builder.insert_constrain(v1, two, Some("With message".to_string().into())); - builder.terminate_with_return(vec![]); - - let ssa = builder.finish(); - - // Expected output: - // - // fn main f0 { - // b0(v0: Field): - // constrain v0 == Field 1 'With message' - // constrain v0 == Field 1 - // v1 = add v0, Field 1 - // constrain v1 == Field 2 - // constrain v1 == Field 2 'With message' - // v2 = add v1, Field 1 - // constrain v2 == Field 3 - // } - // - let ssa = ssa.bubble_up_constrains(); - let main = ssa.main(); - let block = &main.dfg[main.entry_block()]; - assert_eq!(block.instructions().len(), 7); - - let expected_instructions = vec![ - Instruction::Constrain(v0, one, Some("With message".to_string().into())), - Instruction::Constrain(v0, one, None), - Instruction::Binary(Binary { lhs: v0, rhs: one, operator: BinaryOp::Add }), - Instruction::Constrain(v1, two, None), - Instruction::Constrain(v1, two, Some("With message".to_string().into())), - Instruction::Binary(Binary { lhs: v1, rhs: one, operator: BinaryOp::Add }), - Instruction::Constrain(v2, three, None), - ]; - - for (index, instruction) in block.instructions().iter().enumerate() { - assert_eq!(&main.dfg[*instruction], &expected_instructions[index]); - } - } -} diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/die.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/die.rs index 095413d7b9a..7356998ceb8 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/die.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/die.rs @@ -191,6 +191,7 @@ impl Context { self.used_values.insert(value_id); } Value::Array { array, .. } => { + self.used_values.insert(value_id); for elem in array { self.mark_used_instruction_results(dfg, *elem); } @@ -198,6 +199,9 @@ impl Context { Value::Param { .. } => { self.used_values.insert(value_id); } + Value::NumericConstant { .. } => { + self.used_values.insert(value_id); + } _ => { // Does not comprise of any instruction results } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs index d5fb98c7adc..467514114e4 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs @@ -142,7 +142,7 @@ use crate::ssa::{ basic_block::BasicBlockId, cfg::ControlFlowGraph, dfg::{CallStack, InsertInstructionResult}, - function::Function, + function::{Function, FunctionId}, function_inserter::FunctionInserter, instruction::{BinaryOp, Instruction, InstructionId, Intrinsic, TerminatorInstruction}, types::Type, @@ -164,8 +164,14 @@ impl Ssa { /// For more information, see the module-level comment at the top of this file. #[tracing::instrument(level = "trace", skip(self))] pub(crate) fn flatten_cfg(mut self) -> Ssa { + // Retrieve the 'no_predicates' attribute of the functions in a map, to avoid problems with borrowing + let mut no_predicates = HashMap::default(); + for function in self.functions.values() { + no_predicates.insert(function.id(), function.is_no_predicates()); + } + for function in self.functions.values_mut() { - flatten_function_cfg(function); + flatten_function_cfg(function, &no_predicates); } self } @@ -244,7 +250,7 @@ struct ConditionalContext { call_stack: CallStack, } -fn flatten_function_cfg(function: &mut Function) { +fn flatten_function_cfg(function: &mut Function, no_predicates: &HashMap) { // This pass may run forever on a brillig function. // Analyze will check if the predecessors have been processed and push the block to the back of // the queue. This loops forever if there are still any loops present in the program. @@ -264,18 +270,18 @@ fn flatten_function_cfg(function: &mut Function) { condition_stack: Vec::new(), arguments_stack: Vec::new(), }; - context.flatten(); + context.flatten(no_predicates); } impl<'f> Context<'f> { - fn flatten(&mut self) { + fn flatten(&mut self, no_predicates: &HashMap) { // Flatten the CFG by inlining all instructions from the queued blocks // until all blocks have been flattened. // We follow the terminator of each block to determine which blocks to // process next let mut queue = vec![self.inserter.function.entry_block()]; while let Some(block) = queue.pop() { - self.inline_block(block); + self.inline_block(block, no_predicates); let to_process = self.handle_terminator(block, &queue); for incoming_block in to_process { if !queue.contains(&incoming_block) { @@ -283,6 +289,7 @@ impl<'f> Context<'f> { } } } + self.inserter.map_data_bus_in_place(); } /// Returns the updated condition so that @@ -307,8 +314,23 @@ impl<'f> Context<'f> { }) } + /// Use the provided map to say if the instruction is a call to a no_predicates function + fn is_no_predicate( + &self, + no_predicates: &HashMap, + instruction: &InstructionId, + ) -> bool { + let mut result = false; + if let Instruction::Call { func, .. } = self.inserter.function.dfg[*instruction] { + if let Value::Function(fid) = self.inserter.function.dfg[func] { + result = *no_predicates.get(&fid).unwrap_or(&false); + } + } + result + } + // Inline all instructions from the given block into the entry block, and track slice capacities - fn inline_block(&mut self, block: BasicBlockId) { + fn inline_block(&mut self, block: BasicBlockId, no_predicates: &HashMap) { if self.inserter.function.entry_block() == block { // we do not inline the entry block into itself // for the outer block before we start inlining @@ -322,7 +344,23 @@ impl<'f> Context<'f> { // unnecessary, when removing it actually causes an aliasing/mutability error. let instructions = self.inserter.function.dfg[block].instructions().to_vec(); for instruction in instructions.iter() { - self.push_instruction(*instruction); + if self.is_no_predicate(no_predicates, instruction) { + // disable side effect for no_predicate functions + let one = self + .inserter + .function + .dfg + .make_constant(FieldElement::one(), Type::unsigned(1)); + self.insert_instruction_with_typevars( + Instruction::EnableSideEffectsIf { condition: one }, + None, + im::Vector::new(), + ); + self.push_instruction(*instruction); + self.insert_current_side_effects_enabled(); + } else { + self.push_instruction(*instruction); + } } } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/mem2reg.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/mem2reg.rs index 13e1e181dec..d14f50891ea 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/mem2reg.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/mem2reg.rs @@ -61,12 +61,44 @@ //! SSA optimization pipeline, although it will be more successful the simpler the program's CFG is. //! This pass is currently performed several times to enable other passes - most notably being //! performed before loop unrolling to try to allow for mutable variables used for loop indices. +//! +//! As stated above, the algorithm above can sometimes miss known references. +//! This most commonly occurs in the case of loops, where we may have allocations preceding a loop that are known, +//! but the loop body's blocks are predecessors to the loop header block, causing those known allocations to be marked unknown. +//! In certain cases we may be able to remove these allocations that precede a loop. +//! For example, if a reference is not stored to again in the loop we should be able to remove that store which precedes the loop. +//! +//! To handle cases such as the one laid out above, we maintain some extra state per function, +//! that we will analyze after the initial run through all of the blocks. +//! We refer to this as the "function cleanup" and it requires having already iterated through all blocks. +//! +//! The state contains the following: +//! - For each load address we store the number of loads from a given address, +//! the last load instruction from a given address across all blocks, and the respective block id of that instruction. +//! - A mapping of each load result to its number of uses, the load instruction that produced the given result, and the respective block id of that instruction. +//! - A set of the references and their aliases passed as an argument to a call. +//! - Maps the references which have been aliased to the instructions that aliased that reference. +//! - As we go through each instruction, if a load result has been used we increment its usage counter. +//! Upon removing an instruction, we decrement the load result counter. +//! After analyzing all of a function's blocks we can analyze the per function state: +//! - If we find that a load result's usage counter equals zero, we can remove that load. +//! - We can then remove a store if the following conditions are met: +//! - All loads to a given address have been removed +//! - None of the aliases of a reference are used in any of the following: +//! - Block parameters, function parameters, call arguments, terminator arguments +//! - The store address is not aliased. +//! - If a store is in a return block, we can have special handling that only checks if there is a load after +//! that store in the return block. In the case of a return block, even if there are other loads +//! in preceding blocks we can safely remove those stores. +//! - To further catch any stores to references which are never loaded, we can count the number of stores +//! that were removed in the previous step. If there is only a single store leftover, we can safely map +//! the value of this final store to any loads of that store. mod alias_set; mod block; use std::collections::{BTreeMap, BTreeSet}; -use fxhash::FxHashMap as HashMap; +use fxhash::{FxHashMap as HashMap, FxHashSet as HashSet}; use crate::ssa::{ ir::{ @@ -96,6 +128,7 @@ impl Ssa { context.remove_instructions(); context.update_data_bus(); } + self } } @@ -112,11 +145,58 @@ struct PerFunctionContext<'f> { /// /// We avoid removing individual instructions as we go since removing elements /// from the middle of Vecs many times will be slower than a single call to `retain`. - instructions_to_remove: BTreeSet, + instructions_to_remove: HashSet, /// Track a value's last load across all blocks. /// If a value is not used in anymore loads we can remove the last store to that value. - last_loads: HashMap, + last_loads: HashMap, + + /// Track whether a load result was used across all blocks. + load_results: HashMap, + + /// Track whether a reference was passed into another entry point + /// This is needed to determine whether we can remove a store. + calls_reference_input: HashSet, + + /// Track whether a reference has been aliased, and store the respective + /// instruction that aliased that reference. + /// If that store has been set for removal, we can also remove this instruction. + aliased_references: HashMap>, + + // The index of the last load instruction in a given block + return_block_load_locations: HashMap<(ValueId, BasicBlockId), usize>, +} + +#[derive(Debug, Clone)] +struct PerFuncLastLoadContext { + /// Reference counter that keeps track of how many times we loaded from a given address + num_loads: u32, + /// Last load instruction from a given address + load_instruction: InstructionId, + /// Block of the last load instruction + block_id: BasicBlockId, +} + +impl PerFuncLastLoadContext { + fn new(load_instruction: InstructionId, block_id: BasicBlockId, num_loads: u32) -> Self { + Self { num_loads, load_instruction, block_id } + } +} + +#[derive(Debug, Clone)] +struct PerFuncLoadResultContext { + /// Reference counter that keeps track of how many times a load was used in other instructions + uses: u32, + /// Load instruction that produced a given load result + load_instruction: InstructionId, + /// Block of the load instruction that produced a given result + block_id: BasicBlockId, +} + +impl PerFuncLoadResultContext { + fn new(load_instruction: InstructionId, block_id: BasicBlockId) -> Self { + Self { uses: 0, load_instruction, block_id } + } } impl<'f> PerFunctionContext<'f> { @@ -129,8 +209,12 @@ impl<'f> PerFunctionContext<'f> { post_order, inserter: FunctionInserter::new(function), blocks: BTreeMap::new(), - instructions_to_remove: BTreeSet::new(), + instructions_to_remove: HashSet::default(), last_loads: HashMap::default(), + load_results: HashMap::default(), + calls_reference_input: HashSet::default(), + aliased_references: HashMap::default(), + return_block_load_locations: HashMap::default(), } } @@ -148,44 +232,7 @@ impl<'f> PerFunctionContext<'f> { self.analyze_block(block, references); } - // If we never load from an address within a function we can remove all stores to that address. - // This rule does not apply to reference parameters, which we must also check for before removing these stores. - for (block_id, block) in self.blocks.iter() { - let block_params = self.inserter.function.dfg.block_parameters(*block_id); - for (store_address, store_instruction) in block.last_stores.iter() { - let is_reference_param = block_params.contains(store_address); - let terminator = self.inserter.function.dfg[*block_id].unwrap_terminator(); - - let is_return = matches!(terminator, TerminatorInstruction::Return { .. }); - let remove_load = if is_return { - // Determine whether the last store is used in the return value - let mut is_return_value = false; - terminator.for_each_value(|return_value| { - is_return_value = return_value == *store_address || is_return_value; - }); - - // If the last load of a store is not part of the block with a return terminator, - // we can safely remove this store. - let last_load_not_in_return = self - .last_loads - .get(store_address) - .map(|(_, last_load_block)| *last_load_block != *block_id) - .unwrap_or(true); - !is_return_value && last_load_not_in_return - } else { - self.last_loads.get(store_address).is_none() - }; - - let is_reference_alias = block - .expressions - .get(store_address) - .map_or(false, |expression| matches!(expression, Expression::Dereference(_))); - - if remove_load && !is_reference_param && !is_reference_alias { - self.instructions_to_remove.insert(*store_instruction); - } - } - } + self.cleanup_function(); } /// The value of each reference at the start of the given block is the unification @@ -241,6 +288,8 @@ impl<'f> PerFunctionContext<'f> { .filter(|param| self.inserter.function.dfg.value_is_reference(**param)) .collect::>(); + // Must collect here as we are immutably borrowing `self` to fetch the reference parameters + let mut values_to_reduce_counts = Vec::new(); for (allocation, instruction) in &references.last_stores { if let Some(expression) = references.expressions.get(allocation) { if let Some(aliases) = references.aliases.get(expression) { @@ -250,10 +299,27 @@ impl<'f> PerFunctionContext<'f> { // If `allocation_aliases_parameter` is known to be false if allocation_aliases_parameter == Some(false) { self.instructions_to_remove.insert(*instruction); + values_to_reduce_counts.push(*allocation); } } } } + + for value in values_to_reduce_counts { + self.reduce_load_result_count(value); + } + } + + fn increase_load_ref_counts(&mut self, value: ValueId) { + if let Some(context) = self.load_results.get_mut(&value) { + context.uses += 1; + } + let array_const = self.inserter.function.dfg.get_array_constant(value); + if let Some((values, _)) = array_const { + for array_value in values { + self.increase_load_ref_counts(array_value); + } + } } fn analyze_instruction( @@ -271,6 +337,16 @@ impl<'f> PerFunctionContext<'f> { return; } + let mut collect_values = Vec::new(); + // Track whether any load results were used in the instruction + self.inserter.function.dfg[instruction].for_each_value(|value| { + collect_values.push(value); + }); + + for value in collect_values { + self.increase_load_ref_counts(value); + } + match &self.inserter.function.dfg[instruction] { Instruction::Load { address } => { let address = self.inserter.function.dfg.resolve(*address); @@ -280,7 +356,6 @@ impl<'f> PerFunctionContext<'f> { // If the load is known, replace it with the known value and remove the load if let Some(value) = references.get_known_value(address) { - let result = self.inserter.function.dfg.instruction_results(instruction)[0]; self.inserter.map_value(result, value); self.instructions_to_remove.insert(instruction); } else { @@ -301,7 +376,23 @@ impl<'f> PerFunctionContext<'f> { // Mark that we know a load result is equivalent to the address of a load. references.set_known_value(result, address); - self.last_loads.insert(address, (instruction, block_id)); + self.load_results + .insert(result, PerFuncLoadResultContext::new(instruction, block_id)); + + let num_loads = + self.last_loads.get(&address).map_or(1, |context| context.num_loads + 1); + let last_load = PerFuncLastLoadContext::new(instruction, block_id, num_loads); + self.last_loads.insert(address, last_load); + + // If we are in a return block we want to save the last location of a load + let terminator = self.inserter.function.dfg[block_id].unwrap_terminator(); + let is_return = matches!(terminator, TerminatorInstruction::Return { .. }); + if is_return { + let instruction_index = + self.inserter.function.dfg[block_id].instructions().len(); + self.return_block_load_locations + .insert((address, block_id), instruction_index); + } } } Instruction::Store { address, value } => { @@ -310,10 +401,17 @@ impl<'f> PerFunctionContext<'f> { self.check_array_aliasing(references, value); - // If there was another store to this instruction without any (unremoved) loads or + // If there was another store to this address without any (unremoved) loads or // function calls in-between, we can remove the previous store. if let Some(last_store) = references.last_stores.get(&address) { self.instructions_to_remove.insert(*last_store); + let Instruction::Store { address, value } = + self.inserter.function.dfg[*last_store] + else { + panic!("Should have a store instruction here"); + }; + self.reduce_load_result_count(address); + self.reduce_load_result_count(value); } let known_value = references.get_known_value(value); @@ -321,11 +419,29 @@ impl<'f> PerFunctionContext<'f> { let known_value_is_address = known_value == address; if known_value_is_address { self.instructions_to_remove.insert(instruction); + self.reduce_load_result_count(address); + self.reduce_load_result_count(value); + } else { + references.last_stores.insert(address, instruction); + } + } else { + references.last_stores.insert(address, instruction); + } + + if self.inserter.function.dfg.value_is_reference(value) { + if let Some(expression) = references.expressions.get(&value) { + if let Some(aliases) = references.aliases.get(expression) { + aliases.for_each(|alias| { + self.aliased_references + .entry(alias) + .or_default() + .insert(instruction); + }); + } } } references.set_known_value(address, value); - references.last_stores.insert(address, instruction); } Instruction::Allocate => { // Register the new reference @@ -375,7 +491,20 @@ impl<'f> PerFunctionContext<'f> { references.aliases.insert(expression, aliases); } } - Instruction::Call { arguments, .. } => self.mark_all_unknown(arguments, references), + Instruction::Call { arguments, .. } => { + for arg in arguments { + if self.inserter.function.dfg.value_is_reference(*arg) { + if let Some(expression) = references.expressions.get(arg) { + if let Some(aliases) = references.aliases.get(expression) { + aliases.for_each(|alias| { + self.calls_reference_input.insert(alias); + }); + } + } + } + } + self.mark_all_unknown(arguments, references); + } _ => (), } } @@ -436,14 +565,26 @@ impl<'f> PerFunctionContext<'f> { } fn update_data_bus(&mut self) { - let databus = self.inserter.function.dfg.data_bus.clone(); - self.inserter.function.dfg.data_bus = databus.map_values(|t| self.inserter.resolve(t)); + self.inserter.map_data_bus_in_place(); } fn handle_terminator(&mut self, block: BasicBlockId, references: &mut Block) { self.inserter.map_terminator_in_place(block); - match self.inserter.function.dfg[block].unwrap_terminator() { + let terminator: &TerminatorInstruction = + self.inserter.function.dfg[block].unwrap_terminator(); + + let mut collect_values = Vec::new(); + terminator.for_each_value(|value| { + collect_values.push(value); + }); + + let terminator = terminator.clone(); + for value in collect_values.iter() { + self.increase_load_ref_counts(*value); + } + + match &terminator { TerminatorInstruction::JmpIf { .. } => (), // Nothing to do TerminatorInstruction::Jmp { destination, arguments, .. } => { let destination_parameters = self.inserter.function.dfg[*destination].parameters(); @@ -471,6 +612,309 @@ impl<'f> PerFunctionContext<'f> { } } } + + fn reduce_load_result_count(&mut self, value: ValueId) { + if let Some(context) = self.load_results.get_mut(&value) { + context.uses = context.uses.saturating_sub(1); + } + } + + fn recursively_add_values(&self, value: ValueId, set: &mut HashSet) { + set.insert(value); + if let Some((elements, _)) = self.inserter.function.dfg.get_array_constant(value) { + for array_element in elements { + self.recursively_add_values(array_element, set); + } + } + } + + /// The mem2reg pass is sometimes unable to determine certain known values + /// when iterating over a function's block in reverse post order. + /// We collect state about any final loads and stores to a given address during the initial mem2reg pass. + /// We can then utilize this state to clean up any loads and stores that may have been missed. + fn cleanup_function(&mut self) { + // Removing remaining unused loads during mem2reg can help expose removable stores that the initial + // mem2reg pass deemed we could not remove due to the existence of those unused loads. + let removed_loads = self.remove_unused_loads(); + let remaining_last_stores = self.remove_unloaded_last_stores(&removed_loads); + let stores_were_removed = + self.remove_remaining_last_stores(&removed_loads, &remaining_last_stores); + + // When removing some last loads with the last stores we will map the load result to the store value. + // We need to then map all the instructions again as we do not know which instructions are reliant on the load result. + if stores_were_removed { + let mut block_order = PostOrder::with_function(self.inserter.function).into_vec(); + block_order.reverse(); + for block in block_order { + let instructions = self.inserter.function.dfg[block].take_instructions(); + for instruction in instructions { + if !self.instructions_to_remove.contains(&instruction) { + self.inserter.push_instruction(instruction, block); + } + } + self.inserter.map_terminator_in_place(block); + } + } + } + + /// Cleanup remaining loads across the entire function + /// Remove any loads whose reference counter is zero. + /// Returns a map of the removed load address to the number of load instructions removed for that address + fn remove_unused_loads(&mut self) -> HashMap { + let mut removed_loads = HashMap::default(); + for (_, PerFuncLoadResultContext { uses, load_instruction, block_id, .. }) in + self.load_results.iter() + { + let Instruction::Load { address } = self.inserter.function.dfg[*load_instruction] + else { + unreachable!("Should only have a load instruction here"); + }; + // If the load result's counter is equal to zero we can safely remove that load instruction. + if *uses == 0 { + self.return_block_load_locations.remove(&(address, *block_id)); + + removed_loads.entry(address).and_modify(|counter| *counter += 1).or_insert(1); + self.instructions_to_remove.insert(*load_instruction); + } + } + removed_loads + } + + fn recursively_check_address_in_terminator( + &self, + return_value: ValueId, + store_address: ValueId, + is_return_value: &mut bool, + ) { + *is_return_value = return_value == store_address || *is_return_value; + let array_const = self.inserter.function.dfg.get_array_constant(return_value); + if let Some((values, _)) = array_const { + for array_value in values { + self.recursively_check_address_in_terminator( + array_value, + store_address, + is_return_value, + ); + } + } + } + + /// Cleanup remaining stores across the entire function. + /// If we never load from an address within a function we can remove all stores to that address. + /// This rule does not apply to reference parameters, which we must also check for before removing these stores. + /// Returns a map of any remaining stores which may still have loads in use. + fn remove_unloaded_last_stores( + &mut self, + removed_loads: &HashMap, + ) -> HashMap { + let mut all_terminator_values = HashSet::default(); + let mut per_func_block_params: HashSet = HashSet::default(); + for (block_id, _) in self.blocks.iter() { + let block_params = self.inserter.function.dfg.block_parameters(*block_id); + per_func_block_params.extend(block_params.iter()); + + let terminator = self.inserter.function.dfg[*block_id].unwrap_terminator(); + terminator.for_each_value(|value| { + self.recursively_add_values(value, &mut all_terminator_values); + }); + } + + let mut remaining_last_stores: HashMap = HashMap::default(); + for (block_id, block) in self.blocks.iter() { + for (store_address, store_instruction) in block.last_stores.iter() { + if self.instructions_to_remove.contains(store_instruction) { + continue; + } + + let all_loads_removed = self.all_loads_removed_for_address( + store_address, + *store_instruction, + *block_id, + removed_loads, + ); + + let store_alias_used = self.is_store_alias_used( + store_address, + block, + &all_terminator_values, + &per_func_block_params, + ); + + if all_loads_removed && !store_alias_used { + self.instructions_to_remove.insert(*store_instruction); + if let Some((_, counter)) = remaining_last_stores.get_mut(store_address) { + *counter = counter.saturating_sub(1); + } + } else if let Some((_, counter)) = remaining_last_stores.get_mut(store_address) { + *counter += 1; + } else { + remaining_last_stores.insert(*store_address, (*store_instruction, 1)); + } + } + } + remaining_last_stores + } + + fn all_loads_removed_for_address( + &self, + store_address: &ValueId, + store_instruction: InstructionId, + block_id: BasicBlockId, + removed_loads: &HashMap, + ) -> bool { + let terminator = self.inserter.function.dfg[block_id].unwrap_terminator(); + let is_return = matches!(terminator, TerminatorInstruction::Return { .. }); + // Determine whether any loads that reference this store address + // have been removed while cleaning up unused loads. + if is_return { + // If we are in a return terminator, and the last loads of a reference + // come before a store to that reference, we can safely remove that store. + let store_after_load = if let Some(max_load_index) = + self.return_block_load_locations.get(&(*store_address, block_id)) + { + let store_index = self.inserter.function.dfg[block_id] + .instructions() + .iter() + .position(|id| *id == store_instruction) + .expect("Store instruction should exist in the return block"); + store_index > *max_load_index + } else { + // Otherwise there is no load in this block + true + }; + store_after_load + } else if let (Some(context), Some(loads_removed_counter)) = + (self.last_loads.get(store_address), removed_loads.get(store_address)) + { + // `last_loads` contains the total number of loads for a given load address + // If the number of removed loads for a given address is equal to the total number of loads for that address, + // we know we can safely remove any stores to that load address. + context.num_loads == *loads_removed_counter + } else { + self.last_loads.get(store_address).is_none() + } + } + + // Extra checks on where a reference can be used aside a load instruction. + // Even if all loads to a reference have been removed we need to make sure that + // an allocation did not come from an entry point or was passed to an entry point. + fn is_store_alias_used( + &self, + store_address: &ValueId, + block: &Block, + all_terminator_values: &HashSet, + per_func_block_params: &HashSet, + ) -> bool { + let func_params = self.inserter.function.parameters(); + let reference_parameters = func_params + .iter() + .filter(|param| self.inserter.function.dfg.value_is_reference(**param)) + .collect::>(); + + let mut store_alias_used = false; + if let Some(expression) = block.expressions.get(store_address) { + if let Some(aliases) = block.aliases.get(expression) { + let allocation_aliases_parameter = + aliases.any(|alias| reference_parameters.contains(&alias)); + if allocation_aliases_parameter == Some(true) { + store_alias_used = true; + } + + let allocation_aliases_parameter = + aliases.any(|alias| per_func_block_params.contains(&alias)); + if allocation_aliases_parameter == Some(true) { + store_alias_used = true; + } + + let allocation_aliases_parameter = + aliases.any(|alias| self.calls_reference_input.contains(&alias)); + if allocation_aliases_parameter == Some(true) { + store_alias_used = true; + } + + let allocation_aliases_parameter = + aliases.any(|alias| all_terminator_values.contains(&alias)); + if allocation_aliases_parameter == Some(true) { + store_alias_used = true; + } + + let allocation_aliases_parameter = aliases.any(|alias| { + if let Some(alias_instructions) = self.aliased_references.get(&alias) { + self.instructions_to_remove.is_disjoint(alias_instructions) + } else { + false + } + }); + if allocation_aliases_parameter == Some(true) { + store_alias_used = true; + } + } + } + + store_alias_used + } + + /// Check if any remaining last stores are only used in a single load + /// Returns true if any stores were removed. + fn remove_remaining_last_stores( + &mut self, + removed_loads: &HashMap, + remaining_last_stores: &HashMap, + ) -> bool { + let mut stores_were_removed = false; + // Filter out any still in use load results and any load results that do not contain addresses from the remaining last stores + self.load_results.retain(|_, PerFuncLoadResultContext { load_instruction, uses, .. }| { + let Instruction::Load { address } = self.inserter.function.dfg[*load_instruction] + else { + unreachable!("Should only have a load instruction here"); + }; + remaining_last_stores.contains_key(&address) && *uses > 0 + }); + + for (store_address, (store_instruction, store_counter)) in remaining_last_stores { + let Instruction::Store { value, .. } = self.inserter.function.dfg[*store_instruction] + else { + unreachable!("Should only have a store instruction"); + }; + + if let (Some(context), Some(loads_removed_counter)) = + (self.last_loads.get(store_address), removed_loads.get(store_address)) + { + assert!( + context.num_loads >= *loads_removed_counter, + "The number of loads removed should not be more than all loads" + ); + } + + // We only want to remove last stores referencing a single address. + if *store_counter != 0 { + continue; + } + + self.instructions_to_remove.insert(*store_instruction); + + // Map any remaining load results to the value from the removed store + for (result, context) in self.load_results.iter() { + let Instruction::Load { address } = + self.inserter.function.dfg[context.load_instruction] + else { + unreachable!("Should only have a load instruction here"); + }; + if address != *store_address { + continue; + } + + // Map the load result to its respective store value + // We will have to map all instructions following this method + // as we do not know what instructions depend upon this result + self.inserter.map_value(*result, value); + self.instructions_to_remove.insert(context.load_instruction); + + stores_were_removed = true; + } + } + stores_were_removed + } } #[cfg(test)] @@ -756,7 +1200,7 @@ mod tests { // return // } let ssa = ssa.mem2reg(); - + println!("{}", ssa); let main = ssa.main(); assert_eq!(main.reachable_blocks().len(), 2); @@ -778,6 +1222,163 @@ mod tests { assert_eq!(b1_instructions.len(), 0); } + #[test] + fn remove_unused_loads_and_stores() { + // acir(inline) fn main f0 { + // b0(): + // v0 = allocate + // store Field 1 at v0 + // v2 = allocate + // store Field 1 at v2 + // v4 = allocate + // store u1 0 at v4 + // v5 = allocate + // store u1 0 at v5 + // v6 = allocate + // store u1 0 at v6 + // jmp b1(u1 0) + // b1(v7: u32): + // v9 = eq v7, u32 0 + // jmpif v9 then: b3, else: b2 + // b3(): + // v20 = load v0 + // v21 = load v2 + // v22 = load v4 + // v23 = load v5 + // v24 = load v6 + // constrain v20 == Field 1 + // v25 = eq v21, Field 1 + // constrain v21 == Field 1 + // v26 = eq v7, u32 0 + // jmp b1(v26) + // b2(): + // v10 = load v0 + // v11 = load v2 + // v12 = load v4 + // v13 = load v5 + // v14 = load v6 + // store Field 1 at v0 + // store Field 1 at v2 + // store v12 at v4 + // store v13 at v5 + // store v14 at v6 + // v15 = load v0 + // v16 = load v2 + // v17 = load v4 + // v18 = load v5 + // v19 = load v6 + // constrain v15 == Field 1 + // return v16 + // } + let main_id = Id::test_new(0); + let mut builder = FunctionBuilder::new("main".into(), main_id); + + let v0 = builder.insert_allocate(Type::field()); + let one = builder.numeric_constant(1u128, Type::field()); + builder.insert_store(v0, one); + + let v2 = builder.insert_allocate(Type::field()); + builder.insert_store(v2, one); + + let zero_bool = builder.numeric_constant(0u128, Type::bool()); + let v4 = builder.insert_allocate(Type::bool()); + builder.insert_store(v4, zero_bool); + + let v6 = builder.insert_allocate(Type::bool()); + builder.insert_store(v6, zero_bool); + + let v8 = builder.insert_allocate(Type::bool()); + builder.insert_store(v8, zero_bool); + + let b1 = builder.insert_block(); + builder.terminate_with_jmp(b1, vec![zero_bool]); + + builder.switch_to_block(b1); + + let v7 = builder.add_block_parameter(b1, Type::unsigned(32)); + let zero_u32 = builder.numeric_constant(0u128, Type::unsigned(32)); + let is_zero = builder.insert_binary(v7, BinaryOp::Eq, zero_u32); + + let b2 = builder.insert_block(); + let b3 = builder.insert_block(); + builder.terminate_with_jmpif(is_zero, b3, b2); + + builder.switch_to_block(b2); + + let _ = builder.insert_load(v0, Type::field()); + let _ = builder.insert_load(v2, Type::field()); + let v12 = builder.insert_load(v4, Type::bool()); + let v13 = builder.insert_load(v6, Type::bool()); + let v14 = builder.insert_load(v8, Type::bool()); + + builder.insert_store(v0, one); + builder.insert_store(v2, one); + builder.insert_store(v4, v12); + builder.insert_store(v6, v13); + builder.insert_store(v8, v14); + + let v15 = builder.insert_load(v0, Type::field()); + // Insert unused loads + let v16 = builder.insert_load(v2, Type::field()); + let _ = builder.insert_load(v4, Type::bool()); + let _ = builder.insert_load(v6, Type::bool()); + let _ = builder.insert_load(v8, Type::bool()); + + builder.insert_constrain(v15, one, None); + builder.terminate_with_return(vec![v16]); + + builder.switch_to_block(b3); + + let v26 = builder.insert_load(v0, Type::field()); + // Insert unused loads + let v27 = builder.insert_load(v2, Type::field()); + let _ = builder.insert_load(v4, Type::bool()); + let _ = builder.insert_load(v6, Type::bool()); + let _ = builder.insert_load(v8, Type::bool()); + + builder.insert_constrain(v26, one, None); + let _ = builder.insert_binary(v27, BinaryOp::Eq, one); + builder.insert_constrain(v27, one, None); + let one_u32 = builder.numeric_constant(0u128, Type::unsigned(32)); + let plus_one = builder.insert_binary(v7, BinaryOp::Eq, one_u32); + builder.terminate_with_jmp(b1, vec![plus_one]); + + let ssa = builder.finish(); + + // Expected result: + // acir(inline) fn main f0 { + // b0(): + // v27 = allocate + // v28 = allocate + // v29 = allocate + // v30 = allocate + // v31 = allocate + // jmp b1(u1 0) + // b1(v7: u32): + // v32 = eq v7, u32 0 + // jmpif v32 then: b3, else: b2 + // b3(): + // v49 = eq v7, u32 0 + // jmp b1(v49) + // b2(): + // return Field 1 + // } + let ssa = ssa.mem2reg(); + + let main = ssa.main(); + assert_eq!(main.reachable_blocks().len(), 4); + + // All loads should be removed + assert_eq!(count_loads(b2, &main.dfg), 0); + assert_eq!(count_loads(b3, &main.dfg), 0); + + // All stores should be removed + assert_eq!(count_stores(main.entry_block(), &main.dfg), 0); + assert_eq!(count_stores(b2, &main.dfg), 0); + // Should only have one instruction in b3 + assert_eq!(main.dfg[b3].instructions().len(), 1); + } + #[test] fn keep_store_to_alias_in_loop_block() { // This test makes sure the instruction `store Field 2 at v5` in b2 remains after mem2reg. @@ -871,4 +1472,240 @@ mod tests { assert_eq!(count_loads(b2, &main.dfg), 1); assert_eq!(count_loads(b3, &main.dfg), 3); } + + #[test] + fn accurate_tracking_of_load_results() { + // acir(inline) fn main f0 { + // b0(): + // v0 = allocate + // store Field 5 at v0 + // v2 = allocate + // store u32 10 at v2 + // v4 = load v0 + // v5 = load v2 + // v6 = allocate + // store v4 at v6 + // v7 = allocate + // store v5 at v7 + // v8 = load v6 + // v9 = load v7 + // v10 = load v6 + // v11 = load v7 + // v12 = allocate + // store Field 0 at v12 + // v15 = eq v11, u32 0 + // jmpif v15 then: b1, else: b2 + // b1(): + // v16 = load v12 + // v17 = add v16, v8 + // store v17 at v12 + // jmp b2() + // b2(): + // v18 = load v12 + // return [v18] + // } + let main_id = Id::test_new(0); + let mut builder = FunctionBuilder::new("main".into(), main_id); + + let v0 = builder.insert_allocate(Type::field()); + let five = builder.numeric_constant(5u128, Type::field()); + builder.insert_store(v0, five); + + let v2 = builder.insert_allocate(Type::unsigned(32)); + let ten = builder.numeric_constant(10u128, Type::unsigned(32)); + builder.insert_store(v2, ten); + + let v4 = builder.insert_load(v0, Type::field()); + let v5 = builder.insert_load(v2, Type::unsigned(32)); + let v4_type = builder.current_function.dfg.type_of_value(v4); + let v5_type = builder.current_function.dfg.type_of_value(v5); + + let v6 = builder.insert_allocate(Type::field()); + builder.insert_store(v6, v4); + let v7 = builder.insert_allocate(Type::unsigned(32)); + builder.insert_store(v7, v5); + + let v8 = builder.insert_load(v6, v4_type.clone()); + let _v9 = builder.insert_load(v7, v5_type.clone()); + + let _v10 = builder.insert_load(v6, v4_type); + let v11 = builder.insert_load(v7, v5_type); + + let v12 = builder.insert_allocate(Type::field()); + let zero = builder.numeric_constant(0u128, Type::field()); + builder.insert_store(v12, zero); + + let zero_u32 = builder.numeric_constant(0u128, Type::unsigned(32)); + let v15 = builder.insert_binary(v11, BinaryOp::Eq, zero_u32); + + let b1 = builder.insert_block(); + let b2 = builder.insert_block(); + builder.terminate_with_jmpif(v15, b1, b2); + + builder.switch_to_block(b1); + + let v16 = builder.insert_load(v12, Type::field()); + let v17 = builder.insert_binary(v16, BinaryOp::Add, v8); + builder.insert_store(v12, v17); + + builder.terminate_with_jmp(b2, vec![]); + + builder.switch_to_block(b2); + let v18 = builder.insert_load(v12, Type::field()); + + // Include the load result as part of an array constant to check that we are accounting for arrays + // when updating the reference counts of load results. + // + // If we were not accounting for arrays appropriately, the load of v18 would be removed. + // If v18 is the last load of a reference and is inadvertently removed, + // any stores to v12 will then be potentially removed as well and the program will be broken. + let return_array = + builder.array_constant(vector![v18], Type::Array(Arc::new(vec![Type::field()]), 1)); + builder.terminate_with_return(vec![return_array]); + + let ssa = builder.finish(); + + // Expected result: + // acir(inline) fn main f0 { + // b0(): + // v20 = allocate + // v21 = allocate + // v24 = allocate + // v25 = allocate + // v30 = allocate + // store Field 0 at v30 + // jmpif u1 0 then: b1, else: b2 + // b1(): + // store Field 5 at v30 + // jmp b2() + // b2(): + // v33 = load v30 + // return [v33] + // } + let ssa = ssa.mem2reg(); + + let main = ssa.main(); + assert_eq!(main.reachable_blocks().len(), 3); + + // A single store from the entry block should remain. + // If we are not appropriately handling unused stores across a function, + // we would expect all five stores from the original SSA to remain. + assert_eq!(count_stores(main.entry_block(), &main.dfg), 1); + // The store from the conditional block should remain, + // as it is loaded from in a successor block and used in the return terminator. + assert_eq!(count_stores(b1, &main.dfg), 1); + + assert_eq!(count_loads(main.entry_block(), &main.dfg), 0); + assert_eq!(count_loads(b1, &main.dfg), 0); + assert_eq!(count_loads(b2, &main.dfg), 1); + } + + #[test] + fn keep_unused_store_only_used_as_an_alias_across_blocks() { + // acir(inline) fn main f0 { + // b0(v0: u32): + // v1 = allocate + // store u32 0 at v1 + // v3 = allocate + // store v1 at v3 + // v4 = allocate + // store v0 at v4 + // v5 = allocate + // store v4 at v5 + // jmp b1(u32 0) + // b1(v6: u32): + // v7 = eq v6, u32 0 + // jmpif v7 then: b2, else: b3 + // b2(): + // v8 = load v5 + // store v8 at u2 2 + // v11 = add v6, u32 1 + // jmp b1(v11) + // b3(): + // v12 = load v4 + // constrain v12 == u2 2 + // v13 = load v5 + // v14 = load v13 + // constrain v14 == u2 2 + // v15 = load v3 + // v16 = load v15 + // v18 = lt v16, u32 4 + // constrain v18 == u32 1 + // return + // } + let main_id = Id::test_new(0); + let mut builder = FunctionBuilder::new("main".into(), main_id); + + let v0 = builder.add_parameter(Type::unsigned(32)); + + let v1 = builder.insert_allocate(Type::unsigned(32)); + let zero = builder.numeric_constant(0u128, Type::unsigned(32)); + builder.insert_store(v1, zero); + + let v1_type = builder.type_of_value(v1); + let v3 = builder.insert_allocate(v1_type.clone()); + builder.insert_store(v3, v1); + + let v4 = builder.insert_allocate(Type::unsigned(32)); + builder.insert_store(v4, v0); + + let v5 = builder.insert_allocate(Type::Reference(Arc::new(Type::unsigned(32)))); + builder.insert_store(v5, v4); + + let b1 = builder.insert_block(); + builder.terminate_with_jmp(b1, vec![zero]); + builder.switch_to_block(b1); + + let v6 = builder.add_block_parameter(b1, Type::unsigned(32)); + let is_zero = builder.insert_binary(v6, BinaryOp::Eq, zero); + + let b2 = builder.insert_block(); + let b3 = builder.insert_block(); + builder.terminate_with_jmpif(is_zero, b2, b3); + + builder.switch_to_block(b2); + let v4_type = builder.type_of_value(v4); + // let v0_type = builder.type_of_value(v4); + let v8 = builder.insert_load(v5, v4_type); + let two = builder.numeric_constant(2u128, Type::unsigned(2)); + builder.insert_store(v8, two); + let one = builder.numeric_constant(1u128, Type::unsigned(32)); + let v11 = builder.insert_binary(v6, BinaryOp::Add, one); + builder.terminate_with_jmp(b1, vec![v11]); + + builder.switch_to_block(b3); + + let v12 = builder.insert_load(v4, Type::unsigned(32)); + builder.insert_constrain(v12, two, None); + + let v3_type = builder.type_of_value(v3); + let v13 = builder.insert_load(v5, v3_type); + let v14 = builder.insert_load(v13, Type::unsigned(32)); + builder.insert_constrain(v14, two, None); + + let v15 = builder.insert_load(v3, v1_type); + let v16 = builder.insert_load(v15, Type::unsigned(32)); + let four = builder.numeric_constant(4u128, Type::unsigned(32)); + let less_than_four = builder.insert_binary(v16, BinaryOp::Lt, four); + builder.insert_constrain(less_than_four, one, None); + + builder.terminate_with_return(vec![]); + let ssa = builder.finish(); + + // We expect the same result as above. + let ssa = ssa.mem2reg(); + let main = ssa.main(); + + // We expect all the stores to remain. + // The references in b0 are aliased and those are aliases may never be stored to again, + // but they are loaded from and used in later instructions. + // We need to make sure that the store of the address being aliased, is not removed from the program. + assert_eq!(count_stores(main.entry_block(), &main.dfg), 4); + // The store inside of the loop should remain + assert_eq!(count_stores(b2, &main.dfg), 1); + + // We expect the loads to remain the same + assert_eq!(count_loads(b2, &main.dfg), 1); + assert_eq!(count_loads(b3, &main.dfg), 5); + } } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/mod.rs index bd9d0baff97..f3dbd58fa69 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/mod.rs @@ -6,7 +6,6 @@ mod array_set; mod as_slice_length; mod assert_constant; -mod bubble_up_constrains; mod constant_folding; mod defunctionalize; mod die; diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/rc.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/rc.rs index 4f109a27874..1750f2d80a5 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/rc.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/rc.rs @@ -2,9 +2,8 @@ use std::collections::{HashMap, HashSet}; use crate::ssa::{ ir::{ - basic_block::BasicBlockId, function::Function, - instruction::{Instruction, InstructionId, TerminatorInstruction}, + instruction::{Instruction, InstructionId}, types::Type, value::ValueId, }, @@ -107,7 +106,7 @@ impl Context { /// Find each dec_rc instruction and if the most recent inc_rc instruction for the same value /// 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 = Self::find_last_block(function); + let last_block = function.find_last_block(); let mut to_remove = HashSet::new(); for instruction in function.dfg[last_block].instructions() { @@ -124,20 +123,6 @@ impl Context { to_remove } - /// Finds the block of the function with the Return instruction - fn find_last_block(function: &Function) -> BasicBlockId { - for block in function.reachable_blocks() { - if matches!( - function.dfg[block].terminator(), - Some(TerminatorInstruction::Return { .. }) - ) { - return block; - } - } - - unreachable!("SSA Function {} has no reachable return instruction!", function.id()) - } - /// 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); diff --git a/noir/noir-repo/compiler/noirc_frontend/src/ast/expression.rs b/noir/noir-repo/compiler/noirc_frontend/src/ast/expression.rs index f242180134d..c581ea9d62a 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/ast/expression.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/ast/expression.rs @@ -7,14 +7,14 @@ use crate::ast::{ }; use crate::hir::def_collector::errors::DefCollectorErrorKind; use crate::macros_api::StructId; -use crate::node_interner::{ExprId, InternedExpressionKind, QuotedTypeId}; +use crate::node_interner::{ExprId, InternedExpressionKind, InternedStatementKind, QuotedTypeId}; use crate::token::{Attributes, FunctionAttribute, Token, Tokens}; use crate::{Kind, Type}; use acvm::{acir::AcirField, FieldElement}; use iter_extended::vecmap; use noirc_errors::{Span, Spanned}; -use super::{AsTraitPath, UnaryRhsMemberAccess}; +use super::{AsTraitPath, TypePath, UnaryRhsMemberAccess}; #[derive(Debug, PartialEq, Eq, Clone)] pub enum ExpressionKind { @@ -38,6 +38,7 @@ pub enum ExpressionKind { Comptime(BlockExpression, Span), Unsafe(BlockExpression, Span), AsTraitPath(AsTraitPath), + TypePath(TypePath), // This variant is only emitted when inlining the result of comptime // code. It is used to translate function values back into the AST while @@ -48,6 +49,10 @@ pub enum ExpressionKind { // The actual ExpressionKind can be retrieved with a NodeInterner. Interned(InternedExpressionKind), + /// Interned statements are allowed to be parsed as expressions in case they resolve + /// to an StatementKind::Expression or StatementKind::Semi. + InternedStatement(InternedStatementKind), + Error, } @@ -200,9 +205,11 @@ impl ExpressionKind { ExpressionKind::Literal(Literal::FmtStr(contents)) } - pub fn constructor((type_name, fields): (Path, Vec<(Ident, Expression)>)) -> ExpressionKind { + pub fn constructor( + (typ, fields): (UnresolvedType, Vec<(Ident, Expression)>), + ) -> ExpressionKind { ExpressionKind::Constructor(Box::new(ConstructorExpression { - type_name, + typ, fields, struct_type: None, })) @@ -536,7 +543,7 @@ pub struct MethodCallExpression { #[derive(Debug, PartialEq, Eq, Clone)] pub struct ConstructorExpression { - pub type_name: Path, + pub typ: UnresolvedType, pub fields: Vec<(Ident, Expression)>, /// This may be filled out during macro expansion @@ -615,6 +622,8 @@ impl Display for ExpressionKind { write!(f, "quote {{ {} }}", tokens.join(" ")) } AsTraitPath(path) => write!(f, "{path}"), + TypePath(path) => write!(f, "{path}"), + InternedStatement(_) => write!(f, "?InternedStatement"), } } } @@ -717,7 +726,7 @@ impl Display for ConstructorExpression { let fields = self.fields.iter().map(|(ident, expr)| format!("{ident}: {expr}")).collect::>(); - write!(f, "({} {{ {} }})", self.type_name, fields.join(", ")) + write!(f, "({} {{ {} }})", self.typ, fields.join(", ")) } } @@ -780,6 +789,16 @@ impl Display for AsTraitPath { } } +impl Display for TypePath { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}::{}", self.typ, self.item)?; + if !self.turbofish.is_empty() { + write!(f, "::{}", self.turbofish)?; + } + Ok(()) + } +} + impl FunctionDefinition { pub fn normal( name: &Ident, diff --git a/noir/noir-repo/compiler/noirc_frontend/src/ast/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/ast/mod.rs index 12a8aec05eb..94e81b19582 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/ast/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/ast/mod.rs @@ -344,6 +344,19 @@ impl UnresolvedType { pub(crate) fn is_type_expression(&self) -> bool { matches!(&self.typ, UnresolvedTypeData::Expression(_)) } + + pub fn from_path(mut path: Path) -> Self { + let span = path.span; + let last_segment = path.segments.last_mut().unwrap(); + let generics = last_segment.generics.take(); + let generic_type_args = if let Some(generics) = generics { + GenericTypeArgs { ordered_args: generics, named_args: Vec::new() } + } else { + GenericTypeArgs::default() + }; + let typ = UnresolvedTypeData::Named(path, generic_type_args, true); + UnresolvedType { typ, span } + } } impl UnresolvedTypeData { @@ -447,6 +460,7 @@ impl UnresolvedTypeExpression { ExpressionKind::AsTraitPath(path) => { Ok(UnresolvedTypeExpression::AsTraitPath(Box::new(path))) } + ExpressionKind::Parenthesized(expr) => Self::from_expr_helper(*expr), _ => Err(expr), } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/ast/statement.rs b/noir/noir-repo/compiler/noirc_frontend/src/ast/statement.rs index 52c39a49e8a..49568d42038 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/ast/statement.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/ast/statement.rs @@ -109,6 +109,8 @@ impl StatementKind { // Semicolons are optional for these expressions (ExpressionKind::Block(_), semi, _) | (ExpressionKind::Unsafe(..), semi, _) + | (ExpressionKind::Interned(..), semi, _) + | (ExpressionKind::InternedStatement(..), semi, _) | (ExpressionKind::If(_), semi, _) => { if semi.is_some() { StatementKind::Semi(expr) @@ -387,6 +389,16 @@ pub struct AsTraitPath { pub impl_item: Ident, } +/// A special kind of path in the form `Type::ident::` +/// Unlike normal paths, the type here can be a primitive type or +/// interned type. +#[derive(Debug, PartialEq, Eq, Clone, Hash)] +pub struct TypePath { + pub typ: UnresolvedType, + pub item: Ident, + pub turbofish: GenericTypeArgs, +} + // Note: Path deliberately doesn't implement Recoverable. // No matter which default value we could give in Recoverable::error, // it would most likely cause further errors during name resolution @@ -550,7 +562,27 @@ pub enum LValue { } #[derive(Debug, PartialEq, Eq, Clone)] -pub struct ConstrainStatement(pub Expression, pub Option, pub ConstrainKind); +pub struct ConstrainStatement { + pub kind: ConstrainKind, + pub arguments: Vec, + pub span: Span, +} + +impl Display for ConstrainStatement { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self.kind { + ConstrainKind::Assert | ConstrainKind::AssertEq => write!( + f, + "{}({})", + self.kind, + vecmap(&self.arguments, |arg| arg.to_string()).join(", ") + ), + ConstrainKind::Constrain => { + write!(f, "constrain {}", &self.arguments[0]) + } + } + } +} #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum ConstrainKind { @@ -559,6 +591,25 @@ pub enum ConstrainKind { Constrain, } +impl ConstrainKind { + pub fn required_arguments_count(&self) -> usize { + match self { + ConstrainKind::Assert | ConstrainKind::Constrain => 1, + ConstrainKind::AssertEq => 2, + } + } +} + +impl Display for ConstrainKind { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ConstrainKind::Assert => write!(f, "assert"), + ConstrainKind::AssertEq => write!(f, "assert_eq"), + ConstrainKind::Constrain => write!(f, "constrain"), + } + } +} + #[derive(Debug, PartialEq, Eq, Clone)] pub enum Pattern { Identifier(Ident), @@ -620,7 +671,7 @@ impl Pattern { } Some(Expression { kind: ExpressionKind::Constructor(Box::new(ConstructorExpression { - type_name: path.clone(), + typ: UnresolvedType::from_path(path.clone()), fields, struct_type: None, })), @@ -865,13 +916,11 @@ impl Display for StatementKind { impl Display for LetStatement { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "let {}: {} = {}", self.pattern, self.r#type, self.expression) - } -} - -impl Display for ConstrainStatement { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "constrain {}", self.0) + if matches!(&self.r#type.typ, UnresolvedTypeData::Unspecified) { + write!(f, "let {} = {}", self.pattern, self.expression) + } else { + write!(f, "let {}: {} = {}", self.pattern, self.r#type, self.expression) + } } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/ast/structure.rs b/noir/noir-repo/compiler/noirc_frontend/src/ast/structure.rs index cd42abb29c7..1675629ff14 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/ast/structure.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/ast/structure.rs @@ -6,13 +6,14 @@ use crate::token::SecondaryAttribute; use iter_extended::vecmap; use noirc_errors::Span; -use super::Documented; +use super::{Documented, ItemVisibility}; /// Ast node for a struct #[derive(Clone, Debug, PartialEq, Eq)] pub struct NoirStruct { pub name: Ident, pub attributes: Vec, + pub visibility: ItemVisibility, pub generics: UnresolvedGenerics, pub fields: Vec>, pub span: Span, diff --git a/noir/noir-repo/compiler/noirc_frontend/src/ast/traits.rs b/noir/noir-repo/compiler/noirc_frontend/src/ast/traits.rs index 0de1dbaa021..3df9939dc70 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/ast/traits.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/ast/traits.rs @@ -10,7 +10,7 @@ use crate::ast::{ use crate::macros_api::SecondaryAttribute; use crate::node_interner::TraitId; -use super::{Documented, GenericTypeArgs}; +use super::{Documented, GenericTypeArgs, ItemVisibility}; /// AST node for trait definitions: /// `trait name { ... items ... }` @@ -22,6 +22,7 @@ pub struct NoirTrait { pub span: Span, pub items: Vec>, pub attributes: Vec, + pub visibility: ItemVisibility, } /// Any declaration inside the body of a trait that a user is required to @@ -29,6 +30,9 @@ pub struct NoirTrait { #[derive(Clone, Debug)] pub enum TraitItem { Function { + is_unconstrained: bool, + visibility: ItemVisibility, + is_comptime: bool, name: Ident, generics: UnresolvedGenerics, parameters: Vec<(Ident, UnresolvedType)>, @@ -146,7 +150,17 @@ impl Display for NoirTrait { impl Display for TraitItem { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - TraitItem::Function { name, generics, parameters, return_type, where_clause, body } => { + TraitItem::Function { + name, + generics, + parameters, + return_type, + where_clause, + body, + is_unconstrained, + visibility, + is_comptime, + } => { let generics = vecmap(generics, |generic| generic.to_string()); let parameters = vecmap(parameters, |(name, typ)| format!("{name}: {typ}")); let where_clause = vecmap(where_clause, ToString::to_string); @@ -155,9 +169,17 @@ impl Display for TraitItem { let parameters = parameters.join(", "); let where_clause = where_clause.join(", "); + let unconstrained = if *is_unconstrained { "unconstrained " } else { "" }; + let visibility = if *visibility == ItemVisibility::Private { + "".to_string() + } else { + visibility.to_string() + }; + let is_comptime = if *is_comptime { "comptime " } else { "" }; + write!( f, - "fn {name}<{generics}>({parameters}) -> {return_type} where {where_clause}" + "{unconstrained}{visibility}{is_comptime}fn {name}<{generics}>({parameters}) -> {return_type} where {where_clause}" )?; if let Some(body) = body { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/ast/visitor.rs b/noir/noir-repo/compiler/noirc_frontend/src/ast/visitor.rs index 47083a5043b..fb116d34e8a 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/ast/visitor.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/ast/visitor.rs @@ -16,13 +16,13 @@ use crate::{ InternedUnresolvedTypeData, QuotedTypeId, }, parser::{Item, ItemKind, ParsedSubModule}, - token::{CustomAtrribute, SecondaryAttribute, Tokens}, + token::{CustomAttribute, SecondaryAttribute, Tokens}, ParsedModule, QuotedType, }; use super::{ FunctionReturnType, GenericTypeArgs, IntegerBitSize, ItemVisibility, Pattern, Signedness, - TraitImplItemKind, UnresolvedGenerics, UnresolvedTraitConstraint, UnresolvedType, + TraitImplItemKind, TypePath, UnresolvedGenerics, UnresolvedTraitConstraint, UnresolvedType, UnresolvedTypeData, UnresolvedTypeExpression, }; @@ -340,6 +340,10 @@ pub trait Visitor { true } + fn visit_type_path(&mut self, _: &TypePath, _: Span) -> bool { + true + } + fn visit_unresolved_type(&mut self, _: &UnresolvedType) -> bool { true } @@ -461,7 +465,7 @@ pub trait Visitor { true } - fn visit_custom_attribute(&mut self, _: &CustomAtrribute, _target: AttributeTarget) {} + fn visit_custom_attribute(&mut self, _: &CustomAttribute, _target: AttributeTarget) {} } impl ParsedModule { @@ -655,7 +659,17 @@ impl TraitItem { pub fn accept_children(&self, visitor: &mut impl Visitor) { match self { - TraitItem::Function { name, generics, parameters, return_type, where_clause, body } => { + TraitItem::Function { + name, + generics, + parameters, + return_type, + where_clause, + body, + is_unconstrained: _, + visibility: _, + is_comptime: _, + } => { if visitor.visit_trait_item_function( name, generics, @@ -828,9 +842,11 @@ impl Expression { ExpressionKind::AsTraitPath(as_trait_path) => { as_trait_path.accept(self.span, visitor); } + ExpressionKind::TypePath(path) => path.accept(self.span, visitor), ExpressionKind::Quote(tokens) => visitor.visit_quote(tokens), ExpressionKind::Resolved(expr_id) => visitor.visit_resolved_expression(*expr_id), ExpressionKind::Interned(id) => visitor.visit_interned_expression(*id), + ExpressionKind::InternedStatement(id) => visitor.visit_interned_statement(*id), ExpressionKind::Error => visitor.visit_error_expression(), } } @@ -938,7 +954,7 @@ impl ConstructorExpression { } pub fn accept_children(&self, visitor: &mut impl Visitor) { - self.type_name.accept(visitor); + self.typ.accept(visitor); for (_field_name, expression) in &self.fields { expression.accept(visitor); @@ -1101,11 +1117,7 @@ impl ConstrainStatement { } pub fn accept_children(&self, visitor: &mut impl Visitor) { - self.0.accept(visitor); - - if let Some(exp) = &self.1 { - exp.accept(visitor); - } + visit_expressions(&self.arguments, visitor); } } @@ -1197,6 +1209,19 @@ impl AsTraitPath { } } +impl TypePath { + pub fn accept(&self, span: Span, visitor: &mut impl Visitor) { + if visitor.visit_type_path(self, span) { + self.accept_children(visitor); + } + } + + pub fn accept_children(&self, visitor: &mut impl Visitor) { + self.typ.accept(visitor); + self.turbofish.accept(visitor); + } +} + impl UnresolvedType { pub fn accept(&self, visitor: &mut impl Visitor) { if visitor.visit_unresolved_type(self) { @@ -1367,7 +1392,7 @@ impl SecondaryAttribute { } } -impl CustomAtrribute { +impl CustomAttribute { pub fn accept(&self, target: AttributeTarget, visitor: &mut impl Visitor) { visitor.visit_custom_attribute(self, target); } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/comptime.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/comptime.rs index c2347adcbee..ca441758322 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/comptime.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/comptime.rs @@ -102,6 +102,9 @@ impl<'context> Elaborator<'context> { elaborator.function_context.push(FunctionContext::default()); elaborator.scopes.start_function(); + elaborator.local_module = self.local_module; + elaborator.file = self.file; + setup(&mut elaborator); elaborator.populate_scope_from_comptime_scopes(); @@ -316,7 +319,7 @@ impl<'context> Elaborator<'context> { // If the function is varargs, push the type of the last slice element N times // to account for N extra arguments. let modifiers = interpreter.elaborator.interner.function_modifiers(&function); - let is_varargs = modifiers.attributes.is_varargs(); + let is_varargs = modifiers.attributes.has_varargs(); let varargs_type = if is_varargs { parameters.pop() } else { None }; let varargs_elem_type = varargs_type.as_ref().and_then(|t| t.slice_element_type()); diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/expressions.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/expressions.rs index 15d6ed5506b..a3b71f3e211 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/expressions.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/expressions.rs @@ -5,8 +5,8 @@ use rustc_hash::FxHashSet as HashSet; use crate::{ ast::{ - ArrayLiteral, ConstructorExpression, IfExpression, InfixExpression, Lambda, - UnresolvedTypeExpression, + ArrayLiteral, ConstructorExpression, IfExpression, InfixExpression, Lambda, UnaryOp, + UnresolvedTypeData, UnresolvedTypeExpression, }, hir::{ comptime::{self, InterpreterError}, @@ -18,18 +18,18 @@ use crate::{ HirArrayLiteral, HirBinaryOp, HirBlockExpression, HirCallExpression, HirCastExpression, HirConstructorExpression, HirExpression, HirIfExpression, HirIndexExpression, HirInfixExpression, HirLambda, HirMemberAccess, HirMethodCallExpression, - HirMethodReference, HirPrefixExpression, + HirPrefixExpression, }, traits::TraitConstraint, }, macros_api::{ BlockExpression, CallExpression, CastExpression, Expression, ExpressionKind, HirLiteral, HirStatement, Ident, IndexExpression, Literal, MemberAccessExpression, - MethodCallExpression, PrefixExpression, + MethodCallExpression, PrefixExpression, StatementKind, }, - node_interner::{DefinitionKind, ExprId, FuncId, TraitMethodId}, + node_interner::{DefinitionKind, ExprId, FuncId, InternedStatementKind, TraitMethodId}, token::Tokens, - QuotedType, Shared, StructType, Type, + Kind, QuotedType, Shared, StructType, Type, }; use super::{Elaborator, LambdaContext}; @@ -67,12 +67,16 @@ impl<'context> Elaborator<'context> { let expr = Expression::new(expr_kind.clone(), expr.span); return self.elaborate_expression(expr); } + ExpressionKind::InternedStatement(id) => { + return self.elaborate_interned_statement_as_expr(id, expr.span); + } ExpressionKind::Error => (HirExpression::Error, Type::Error), ExpressionKind::Unquote(_) => { self.push_err(ResolverError::UnquoteUsedOutsideQuote { span: expr.span }); (HirExpression::Error, Type::Error) } ExpressionKind::AsTraitPath(_) => todo!("Implement AsTraitPath"), + ExpressionKind::TypePath(path) => return self.elaborate_type_path(path), }; let id = self.interner.push_expr(hir_expr); self.interner.push_expr_location(id, expr.span, self.file); @@ -80,6 +84,29 @@ impl<'context> Elaborator<'context> { (id, typ) } + fn elaborate_interned_statement_as_expr( + &mut self, + id: InternedStatementKind, + span: Span, + ) -> (ExprId, Type) { + match self.interner.get_statement_kind(id) { + StatementKind::Expression(expr) | StatementKind::Semi(expr) => { + self.elaborate_expression(expr.clone()) + } + StatementKind::Interned(id) => self.elaborate_interned_statement_as_expr(*id, span), + StatementKind::Error => { + let expr = Expression::new(ExpressionKind::Error, span); + self.elaborate_expression(expr) + } + other => { + let statement = other.to_string(); + self.push_err(ResolverError::InvalidInternedStatementInExpr { statement, span }); + let expr = Expression::new(ExpressionKind::Error, span); + self.elaborate_expression(expr) + } + } + } + pub(super) fn elaborate_block(&mut self, block: BlockExpression) -> (HirExpression, Type) { let (block, typ) = self.elaborate_block_expression(block); (HirExpression::Block(block), typ) @@ -136,7 +163,7 @@ impl<'context> Elaborator<'context> { (Lit(int), self.polymorphic_integer_or_field()) } Literal::Str(str) | Literal::RawStr(str, _) => { - let len = Type::Constant(str.len() as u32); + let len = Type::Constant(str.len() as u32, Kind::u32()); (Lit(HirLiteral::Str(str)), Type::String(Box::new(len))) } Literal::FmtStr(str) => self.elaborate_fmt_string(str, span), @@ -178,7 +205,7 @@ impl<'context> Elaborator<'context> { elem_id }); - let length = Type::Constant(elements.len() as u32); + let length = Type::Constant(elements.len() as u32, Kind::u32()); (HirArrayLiteral::Standard(elements), first_elem_type, length) } ArrayLiteral::Repeated { repeated_element, length } => { @@ -189,7 +216,7 @@ impl<'context> Elaborator<'context> { UnresolvedTypeExpression::Constant(0, span) }); - let length = self.convert_expression_type(length); + let length = self.convert_expression_type(length, &Kind::u32(), span); let (repeated_element, elem_type) = self.elaborate_expression(*repeated_element); let length_clone = length.clone(); @@ -242,16 +269,23 @@ impl<'context> Elaborator<'context> { } } - let len = Type::Constant(str.len() as u32); + let len = Type::Constant(str.len() as u32, Kind::u32()); let typ = Type::FmtString(Box::new(len), Box::new(Type::Tuple(capture_types))); (HirExpression::Literal(HirLiteral::FmtStr(str, fmt_str_idents)), typ) } fn elaborate_prefix(&mut self, prefix: PrefixExpression, span: Span) -> (ExprId, Type) { + let rhs_span = prefix.rhs.span; + let (rhs, rhs_type) = self.elaborate_expression(prefix.rhs); let trait_id = self.interner.get_prefix_operator_trait_method(&prefix.operator); let operator = prefix.operator; + + if let UnaryOp::MutableReference = operator { + self.check_can_mutate(rhs, rhs_span); + } + let expr = HirExpression::Prefix(HirPrefixExpression { operator, rhs, trait_method_id: trait_id }); let expr_id = self.interner.push_expr(expr); @@ -264,6 +298,26 @@ impl<'context> Elaborator<'context> { (expr_id, typ) } + fn check_can_mutate(&mut self, expr_id: ExprId, span: Span) { + let expr = self.interner.expression(&expr_id); + match expr { + HirExpression::Ident(hir_ident, _) => { + if let Some(definition) = self.interner.try_definition(hir_ident.id) { + if !definition.mutable { + self.push_err(TypeCheckError::CannotMutateImmutableVariable { + name: definition.name.clone(), + span, + }); + } + } + } + HirExpression::MemberAccess(member_access) => { + self.check_can_mutate(member_access.lhs, span); + } + _ => (), + } + } + fn elaborate_index(&mut self, index_expr: IndexExpression) -> (HirExpression, Type) { let span = index_expr.index.span; let (index, index_type) = self.elaborate_expression(index_expr.index); @@ -353,21 +407,13 @@ impl<'context> Elaborator<'context> { let method_name_span = method_call.method_name.span(); let method_name = method_call.method_name.0.contents.as_str(); - match self.lookup_method(&object_type, method_name, span) { + match self.lookup_method(&object_type, method_name, span, true) { Some(method_ref) => { // Automatically add `&mut` if the method expects a mutable reference and // the object is not already one. - let func_id = match &method_ref { - HirMethodReference::FuncId(func_id) => *func_id, - HirMethodReference::TraitMethodId(method_id, _) => { - let id = self.interner.trait_method_id(*method_id); - let definition = self.interner.definition(id); - let DefinitionKind::Function(func_id) = definition.kind else { - unreachable!("Expected trait function to be a DefinitionKind::Function") - }; - func_id - } - }; + let func_id = method_ref + .func_id(self.interner) + .expect("Expected trait function to be a DefinitionKind::Function"); let generics = if func_id != FuncId::dummy_id() { let function_type = self.interner.function_meta(&func_id).typ.clone(); @@ -425,7 +471,17 @@ impl<'context> Elaborator<'context> { // Type check the new call now that it has been changed from a method call // to a function call. This way we avoid duplicating code. - let typ = self.type_check_call(&function_call, func_type, function_args, span); + let mut typ = self.type_check_call(&function_call, func_type, function_args, span); + if is_macro_call { + if self.in_comptime_context() { + typ = self.interner.next_type_variable(); + } else { + let args = function_call.arguments.clone(); + return self + .call_macro(function_call.func, args, location, typ) + .unwrap_or_else(|| (HirExpression::Error, Type::Error)); + } + } (HirExpression::Call(function_call), typ) } None => (HirExpression::Error, Type::Error), @@ -436,11 +492,29 @@ impl<'context> Elaborator<'context> { &mut self, constructor: ConstructorExpression, ) -> (HirExpression, Type) { + let span = constructor.typ.span; + + // A constructor type can either be a Path or an interned UnresolvedType. + // We represent both as UnresolvedType (with Path being a Named UnresolvedType) + // and error if we don't get a Named path. + let mut typ = constructor.typ.typ; + if let UnresolvedTypeData::Interned(id) = typ { + typ = self.interner.get_unresolved_type_data(id).clone(); + } + let UnresolvedTypeData::Named(mut path, generics, _) = typ else { + self.push_err(ResolverError::NonStructUsedInConstructor { typ: typ.to_string(), span }); + return (HirExpression::Error, Type::Error); + }; + + let last_segment = path.segments.last_mut().unwrap(); + if !generics.ordered_args.is_empty() { + last_segment.generics = Some(generics.ordered_args); + } + let exclude_last_segment = true; - self.check_unsupported_turbofish_usage(&constructor.type_name, exclude_last_segment); + self.check_unsupported_turbofish_usage(&path, exclude_last_segment); - let span = constructor.type_name.span(); - let last_segment = constructor.type_name.last_segment(); + let last_segment = path.last_segment(); let is_self_type = last_segment.ident.is_self_type_name(); let (r#type, struct_generics) = if let Some(struct_id) = constructor.struct_type { @@ -448,10 +522,13 @@ impl<'context> Elaborator<'context> { let generics = typ.borrow().instantiate(self.interner); (typ, generics) } else { - match self.lookup_type_or_error(constructor.type_name) { + match self.lookup_type_or_error(path) { Some(Type::Struct(r#type, struct_generics)) => (r#type, struct_generics), Some(typ) => { - self.push_err(ResolverError::NonStructUsedInConstructor { typ, span }); + self.push_err(ResolverError::NonStructUsedInConstructor { + typ: typ.to_string(), + span, + }); return (HirExpression::Error, Type::Error); } None => return (HirExpression::Error, Type::Error), diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/mod.rs index 6871152edb5..f9016b1ca65 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/mod.rs @@ -17,7 +17,7 @@ use crate::{ }, hir_def::{ expr::{HirCapturedVar, HirIdent}, - function::{FunctionBody, Parameters}, + function::FunctionBody, traits::TraitConstraint, types::{Generics, Kind, ResolvedGeneric}, }, @@ -29,7 +29,7 @@ use crate::{ DefinitionKind, DependencyId, ExprId, FuncId, FunctionModifiers, GlobalId, ReferenceId, TraitId, TypeAliasId, }, - token::CustomAtrribute, + token::CustomAttribute, Shared, Type, TypeVariable, }; use crate::{ @@ -97,7 +97,7 @@ pub struct Elaborator<'context> { def_maps: &'context mut DefMaps, - file: FileId, + pub(crate) file: FileId, in_unsafe_block: bool, nested_loops: usize, @@ -415,7 +415,6 @@ impl<'context> Elaborator<'context> { self.add_existing_variable_to_scope(name, parameter.clone(), true); } - self.declare_numeric_generics(&func_meta.parameters, func_meta.return_type()); self.add_trait_constraints_to_scope(&func_meta); let (hir_func, body_type) = match kind { @@ -800,7 +799,7 @@ impl<'context> Elaborator<'context> { let attributes = func.secondary_attributes().iter(); let attributes = attributes.filter_map(|secondary_attribute| secondary_attribute.as_custom()); - let attributes: Vec = attributes.cloned().collect(); + let attributes: Vec = attributes.cloned().collect(); let meta = FuncMeta { name: name_ident, @@ -896,44 +895,6 @@ impl<'context> Elaborator<'context> { } } - // TODO(https://github.com/noir-lang/noir/issues/5156): Remove implicit numeric generics - fn declare_numeric_generics(&mut self, params: &Parameters, return_type: &Type) { - if self.generics.is_empty() { - return; - } - - for (name_to_find, type_variable) in Self::find_numeric_generics(params, return_type) { - // Declare any generics to let users use numeric generics in scope. - // Don't issue a warning if these are unused - // - // We can fail to find the generic in self.generics if it is an implicit one created - // by the compiler. This can happen when, e.g. eliding array lengths using the slice - // syntax [T]. - if let Some(ResolvedGeneric { name, span, kind, .. }) = - self.generics.iter_mut().find(|generic| generic.name.as_ref() == &name_to_find) - { - let scope = self.scopes.get_mut_scope(); - let value = scope.find(&name_to_find); - if value.is_some() { - // With the addition of explicit numeric generics we do not want to introduce numeric generics in this manner - // However, this is going to be a big breaking change so for now we simply issue a warning while users have time - // to transition to the new syntax - // e.g. this code would break with a duplicate definition error: - // ``` - // fn foo(arr: [Field; N]) { } - // ``` - continue; - } - *kind = Kind::Numeric(Box::new(Type::default_int_type())); - let ident = Ident::new(name.to_string(), *span); - let definition = DefinitionKind::GenericType(type_variable); - self.add_variable_decl_inner(ident.clone(), false, false, false, definition); - - self.push_err(ResolverError::UseExplicitNumericGeneric { ident }); - } - } - } - fn add_trait_constraints_to_scope(&mut self, func_meta: &FuncMeta) { for constraint in &func_meta.trait_constraints { let object = constraint.typ.clone(); @@ -1187,28 +1148,6 @@ impl<'context> Elaborator<'context> { let fields_len = fields.len(); self.interner.update_struct(*type_id, |struct_def| { struct_def.set_fields(fields); - - // TODO(https://github.com/noir-lang/noir/issues/5156): Remove this with implicit numeric generics - // This is only necessary for resolving named types when implicit numeric generics are used. - let mut found_names = Vec::new(); - struct_def.find_numeric_generics_in_fields(&mut found_names); - for generic in struct_def.generics.iter_mut() { - for found_generic in found_names.iter() { - if found_generic == generic.name.as_str() { - if matches!(generic.kind, Kind::Normal) { - let ident = Ident::new(generic.name.to_string(), generic.span); - self.errors.push(( - CompilationError::ResolverError( - ResolverError::UseExplicitNumericGeneric { ident }, - ), - self.file, - )); - generic.kind = Kind::Numeric(Box::new(Type::default_int_type())); - } - break; - } - } - } }); for field_index in 0..fields_len { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/patterns.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/patterns.rs index 09357e77c0b..7afa3215566 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/patterns.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/patterns.rs @@ -3,17 +3,17 @@ use noirc_errors::{Location, Span}; use rustc_hash::FxHashSet as HashSet; use crate::{ - ast::{UnresolvedType, ERROR_IDENT}, + ast::{TypePath, UnresolvedType, ERROR_IDENT}, hir::{ def_collector::dc_crate::CompilationError, resolution::errors::ResolverError, type_check::{Source, TypeCheckError}, }, hir_def::{ - expr::{HirIdent, ImplKind}, + expr::{HirIdent, HirMethodReference, ImplKind}, stmt::HirPattern, }, - macros_api::{HirExpression, Ident, Path, Pattern}, + macros_api::{Expression, ExpressionKind, HirExpression, Ident, Path, Pattern}, node_interner::{DefinitionId, DefinitionKind, ExprId, FuncId, GlobalId, TraitImplKind}, ResolvedGeneric, Shared, StructType, Type, TypeBindings, }; @@ -188,6 +188,7 @@ impl<'context> Elaborator<'context> { Some(Type::Struct(struct_type, generics)) => (struct_type, generics), None => return error_identifier(self), Some(typ) => { + let typ = typ.to_string(); self.push_err(ResolverError::NonStructUsedInConstructor { typ, span }); return error_identifier(self); } @@ -696,4 +697,43 @@ impl<'context> Elaborator<'context> { let id = DefinitionId::dummy_id(); (HirIdent::non_trait_method(id, location), 0) } + + pub(super) fn elaborate_type_path(&mut self, path: TypePath) -> (ExprId, Type) { + let span = path.item.span(); + let typ = self.resolve_type(path.typ); + + let Some(method) = self.lookup_method(&typ, &path.item.0.contents, span, false) else { + let error = Expression::new(ExpressionKind::Error, span); + return self.elaborate_expression(error); + }; + + let func_id = method + .func_id(self.interner) + .expect("Expected trait function to be a DefinitionKind::Function"); + + let generics = self.resolve_type_args(path.turbofish, func_id, span).0; + let generics = (!generics.is_empty()).then_some(generics); + + let location = Location::new(span, self.file); + let id = self.interner.function_definition_id(func_id); + + let impl_kind = match method { + HirMethodReference::FuncId(_) => ImplKind::NotATraitMethod, + HirMethodReference::TraitMethodId(method_id, generics) => { + let mut constraint = + self.interner.get_trait(method_id.trait_id).as_constraint(span); + constraint.trait_generics = generics; + ImplKind::TraitMethod(method_id, constraint, false) + } + }; + + let ident = HirIdent { location, id, impl_kind }; + let id = self.interner.push_expr(HirExpression::Ident(ident.clone(), generics.clone())); + self.interner.push_expr_location(id, location.span, location.file); + + let typ = self.type_check_variable(ident, id, generics); + self.interner.push_expr_type(id, typ.clone()); + + (id, typ) + } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/scope.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/scope.rs index 7a98e1856b3..8e746256142 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/scope.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/scope.rs @@ -38,11 +38,20 @@ impl<'context> Elaborator<'context> { }) } - pub(super) fn module_id(&self) -> ModuleId { + pub fn module_id(&self) -> ModuleId { assert_ne!(self.local_module, LocalModuleId::dummy_id(), "local_module is unset"); ModuleId { krate: self.crate_id, local_id: self.local_module } } + pub fn replace_module(&mut self, new_module: ModuleId) -> ModuleId { + assert_ne!(new_module.local_id, LocalModuleId::dummy_id(), "local_module is unset"); + let current_module = self.module_id(); + + self.crate_id = new_module.krate; + self.local_module = new_module.local_id; + current_module + } + pub(super) fn resolve_path_or_error( &mut self, path: Path, diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/statements.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/statements.rs index 543cf20b647..2d46c4c6341 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/statements.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/statements.rs @@ -1,7 +1,10 @@ -use noirc_errors::{Location, Span}; +use noirc_errors::{Location, Span, Spanned}; use crate::{ - ast::{AssignStatement, ConstrainStatement, LValue}, + ast::{ + AssignStatement, BinaryOpKind, ConstrainKind, ConstrainStatement, Expression, + ExpressionKind, InfixExpression, LValue, + }, hir::{ resolution::errors::ResolverError, type_check::{Source, TypeCheckError}, @@ -110,12 +113,51 @@ impl<'context> Elaborator<'context> { (HirStatement::Let(let_), Type::Unit) } - pub(super) fn elaborate_constrain(&mut self, stmt: ConstrainStatement) -> (HirStatement, Type) { - let expr_span = stmt.0.span; - let (expr_id, expr_type) = self.elaborate_expression(stmt.0); + pub(super) fn elaborate_constrain( + &mut self, + mut stmt: ConstrainStatement, + ) -> (HirStatement, Type) { + let span = stmt.span; + let min_args_count = stmt.kind.required_arguments_count(); + let max_args_count = min_args_count + 1; + let actual_args_count = stmt.arguments.len(); + + let (message, expr) = if !(min_args_count..=max_args_count).contains(&actual_args_count) { + self.push_err(TypeCheckError::AssertionParameterCountMismatch { + kind: stmt.kind, + found: actual_args_count, + span, + }); + + // Given that we already produced an error, let's make this an `assert(true)` so + // we don't get further errors. + let message = None; + let kind = ExpressionKind::Literal(crate::ast::Literal::Bool(true)); + let expr = Expression { kind, span }; + (message, expr) + } else { + let message = + (actual_args_count != min_args_count).then(|| stmt.arguments.pop().unwrap()); + let expr = match stmt.kind { + ConstrainKind::Assert | ConstrainKind::Constrain => stmt.arguments.pop().unwrap(), + ConstrainKind::AssertEq => { + let rhs = stmt.arguments.pop().unwrap(); + let lhs = stmt.arguments.pop().unwrap(); + let span = Span::from(lhs.span.start()..rhs.span.end()); + let operator = Spanned::from(span, BinaryOpKind::Equal); + let kind = + ExpressionKind::Infix(Box::new(InfixExpression { lhs, operator, rhs })); + Expression { kind, span } + } + }; + (message, expr) + }; + + let expr_span = expr.span; + let (expr_id, expr_type) = self.elaborate_expression(expr); // Must type check the assertion message expression so that we instantiate bindings - let msg = stmt.1.map(|assert_msg_expr| self.elaborate_expression(assert_msg_expr).0); + let msg = message.map(|assert_msg_expr| self.elaborate_expression(assert_msg_expr).0); self.unify(&expr_type, &Type::Bool, || TypeCheckError::TypeMismatch { expr_typ: expr_type.to_string(), diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/traits.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/traits.rs index d6bfd3aa647..0faaf409e6c 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/traits.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/traits.rs @@ -74,6 +74,9 @@ impl<'context> Elaborator<'context> { return_type, where_clause, body: _, + is_unconstrained, + visibility: _, + is_comptime: _, } = &item.item { self.recover_generics(|this| { @@ -134,9 +137,12 @@ impl<'context> Elaborator<'context> { }; let no_environment = Box::new(Type::Unit); - // TODO: unconstrained - let function_type = - Type::Function(arguments, Box::new(return_type), no_environment, false); + let function_type = Type::Function( + arguments, + Box::new(return_type), + no_environment, + *is_unconstrained, + ); functions.push(TraitFunction { name: name.clone(), @@ -223,6 +229,7 @@ pub(crate) fn check_trait_impl_method_matches_declaration( function: FuncId, ) -> Vec { let meta = interner.function_meta(&function); + let modifiers = interner.function_modifiers(&function); let method_name = interner.function_name(&function); let mut errors = Vec::new(); @@ -261,6 +268,14 @@ pub(crate) fn check_trait_impl_method_matches_declaration( // issue an error for it here. if let Some(trait_fn_id) = trait_info.method_ids.get(method_name) { let trait_fn_meta = interner.function_meta(trait_fn_id); + let trait_fn_modifiers = interner.function_modifiers(trait_fn_id); + + if modifiers.is_unconstrained != trait_fn_modifiers.is_unconstrained { + let expected = trait_fn_modifiers.is_unconstrained; + let span = meta.name.location.span; + let item = method_name.to_string(); + errors.push(TypeCheckError::UnconstrainedMismatch { item, expected, span }); + } if trait_fn_meta.direct_generics.len() != meta.direct_generics.len() { let expected = trait_fn_meta.direct_generics.len(); @@ -273,10 +288,10 @@ pub(crate) fn check_trait_impl_method_matches_declaration( // Substitute each generic on the trait function with the corresponding generic on the impl function for ( ResolvedGeneric { type_var: trait_fn_generic, .. }, - ResolvedGeneric { name, type_var: impl_fn_generic, .. }, + ResolvedGeneric { name, type_var: impl_fn_generic, kind, .. }, ) in trait_fn_meta.direct_generics.iter().zip(&meta.direct_generics) { - let arg = Type::NamedGeneric(impl_fn_generic.clone(), name.clone(), Kind::Normal); + let arg = Type::NamedGeneric(impl_fn_generic.clone(), name.clone(), kind.clone()); bindings.insert(trait_fn_generic.id(), (trait_fn_generic.clone(), arg)); } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/types.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/types.rs index 46c779dc4ff..264b83956f8 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/types.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/types.rs @@ -12,6 +12,7 @@ use crate::{ }, hir::{ comptime::{Interpreter, Value}, + def_collector::dc_crate::CompilationError, def_map::ModuleDefId, resolution::errors::ResolverError, type_check::{ @@ -76,45 +77,22 @@ impl<'context> Elaborator<'context> { FieldElement => Type::FieldElement, Array(size, elem) => { let elem = Box::new(self.resolve_type_inner(*elem, kind)); - let mut size = self.convert_expression_type(size); - // TODO(https://github.com/noir-lang/noir/issues/5156): Remove this once we only have explicit numeric generics - if let Type::NamedGeneric(type_var, name, _) = size { - size = Type::NamedGeneric( - type_var, - name, - Kind::Numeric(Box::new(Type::default_int_type())), - ); - } + let size = self.convert_expression_type(size, &Kind::u32(), span); Type::Array(Box::new(size), elem) } Slice(elem) => { let elem = Box::new(self.resolve_type_inner(*elem, kind)); Type::Slice(elem) } - Expression(expr) => self.convert_expression_type(expr), + Expression(expr) => self.convert_expression_type(expr, kind, span), Integer(sign, bits) => Type::Integer(sign, bits), Bool => Type::Bool, String(size) => { - let mut resolved_size = self.convert_expression_type(size); - // TODO(https://github.com/noir-lang/noir/issues/5156): Remove this once we only have explicit numeric generics - if let Type::NamedGeneric(type_var, name, _) = resolved_size { - resolved_size = Type::NamedGeneric( - type_var, - name, - Kind::Numeric(Box::new(Type::default_int_type())), - ); - } + let resolved_size = self.convert_expression_type(size, &Kind::u32(), span); Type::String(Box::new(resolved_size)) } FormatString(size, fields) => { - let mut resolved_size = self.convert_expression_type(size); - if let Type::NamedGeneric(type_var, name, _) = resolved_size { - resolved_size = Type::NamedGeneric( - type_var, - name, - Kind::Numeric(Box::new(Type::default_int_type())), - ); - } + let resolved_size = self.convert_expression_type(size, &Kind::u32(), span); let fields = self.resolve_type_inner(*fields, kind); Type::FmtString(Box::new(resolved_size), Box::new(fields)) } @@ -191,26 +169,18 @@ impl<'context> Elaborator<'context> { _ => (), } - // Check that any types with a type kind match the expected type kind supplied to this function - // TODO(https://github.com/noir-lang/noir/issues/5156): make this named generic check more general with `*resolved_kind != kind` - // as implicit numeric generics still existing makes this check more challenging to enforce - // An example of a more general check that we should switch to: - // if resolved_type.kind() != kind.clone() { - // let expected_typ_err = CompilationError::TypeError(TypeCheckError::TypeKindMismatch { - // expected_kind: kind.to_string(), - // expr_kind: resolved_type.kind().to_string(), - // expr_span: span.expect("Type should have span"), - // }); - // self.errors.push((expected_typ_err, self.file)); - // return Type::Error; - // } - if let Type::NamedGeneric(_, name, resolved_kind) = &resolved_type { - if matches!(resolved_kind, Kind::Numeric { .. }) && matches!(kind, Kind::Normal) { - let expected_typ_err = - ResolverError::NumericGenericUsedForType { name: name.to_string(), span }; - self.push_err(expected_typ_err); - return Type::Error; - } + if !kind.matches_opt(resolved_type.kind()) { + let expected_typ_err = CompilationError::TypeError(TypeCheckError::TypeKindMismatch { + expected_kind: kind.to_string(), + expr_kind: resolved_type + .kind() + .as_ref() + .map(Kind::to_string) + .unwrap_or("unknown".to_string()), + expr_span: span, + }); + self.errors.push((expected_typ_err, self.file)); + return Type::Error; } resolved_type @@ -441,30 +411,49 @@ impl<'context> Elaborator<'context> { let reference_location = Location::new(path.span(), self.file); self.interner.add_global_reference(id, reference_location); + let kind = self + .interner + .get_global_let_statement(id) + .map(|let_statement| Kind::Numeric(Box::new(let_statement.r#type))) + .unwrap_or(Kind::u32()); - Some(Type::Constant(self.eval_global_as_array_length(id, path))) + Some(Type::Constant(self.eval_global_as_array_length(id, path), kind)) } _ => None, } } - pub(super) fn convert_expression_type(&mut self, length: UnresolvedTypeExpression) -> Type { + pub(super) fn convert_expression_type( + &mut self, + length: UnresolvedTypeExpression, + expected_kind: &Kind, + span: Span, + ) -> Type { match length { UnresolvedTypeExpression::Variable(path) => { - self.lookup_generic_or_global_type(&path).unwrap_or_else(|| { - self.push_err(ResolverError::NoSuchNumericTypeVariable { path }); - Type::Constant(0) - }) + let typ = self.resolve_named_type(path, GenericTypeArgs::default()); + self.check_kind(typ, expected_kind, span) + } + UnresolvedTypeExpression::Constant(int, _span) => { + Type::Constant(int, expected_kind.clone()) } - UnresolvedTypeExpression::Constant(int, _) => Type::Constant(int), UnresolvedTypeExpression::BinaryOperation(lhs, op, rhs, span) => { - let lhs = self.convert_expression_type(*lhs); - let rhs = self.convert_expression_type(*rhs); + let (lhs_span, rhs_span) = (lhs.span(), rhs.span()); + let lhs = self.convert_expression_type(*lhs, expected_kind, lhs_span); + let rhs = self.convert_expression_type(*rhs, expected_kind, rhs_span); match (lhs, rhs) { - (Type::Constant(lhs), Type::Constant(rhs)) => { + (Type::Constant(lhs, lhs_kind), Type::Constant(rhs, rhs_kind)) => { + if !lhs_kind.unifies(&rhs_kind) { + self.push_err(TypeCheckError::TypeKindMismatch { + expected_kind: lhs_kind.to_string(), + expr_kind: rhs_kind.to_string(), + expr_span: span, + }); + return Type::Error; + } if let Some(result) = op.function(lhs, rhs) { - Type::Constant(result) + Type::Constant(result, lhs_kind) } else { self.push_err(ResolverError::OverflowInType { lhs, op, rhs, span }); Type::Error @@ -473,8 +462,25 @@ impl<'context> Elaborator<'context> { (lhs, rhs) => Type::InfixExpr(Box::new(lhs), op, Box::new(rhs)).canonicalize(), } } - UnresolvedTypeExpression::AsTraitPath(path) => self.resolve_as_trait_path(*path), + UnresolvedTypeExpression::AsTraitPath(path) => { + let typ = self.resolve_as_trait_path(*path); + self.check_kind(typ, expected_kind, span) + } + } + } + + fn check_kind(&mut self, typ: Type, expected_kind: &Kind, span: Span) -> Type { + if let Some(kind) = typ.kind() { + if !kind.unifies(expected_kind) { + self.push_err(TypeCheckError::TypeKindMismatch { + expected_kind: expected_kind.to_string(), + expr_kind: kind.to_string(), + expr_span: span, + }); + return Type::Error; + } } + typ } fn resolve_as_trait_path(&mut self, path: AsTraitPath) -> Type { @@ -616,7 +622,7 @@ impl<'context> Elaborator<'context> { let length = stmt.expression; let span = self.interner.expr_span(&length); - let result = self.try_eval_array_length_id(length, span); + let result = try_eval_array_length_id(self.interner, length, span); match result.map(|length| length.try_into()) { Ok(Ok(length_value)) => return length_value, @@ -627,85 +633,6 @@ impl<'context> Elaborator<'context> { 0 } - fn try_eval_array_length_id( - &self, - rhs: ExprId, - span: Span, - ) -> Result> { - // Arbitrary amount of recursive calls to try before giving up - let fuel = 100; - self.try_eval_array_length_id_with_fuel(rhs, span, fuel) - } - - fn try_eval_array_length_id_with_fuel( - &self, - rhs: ExprId, - span: Span, - fuel: u32, - ) -> Result> { - if fuel == 0 { - // If we reach here, it is likely from evaluating cyclic globals. We expect an error to - // be issued for them after name resolution so issue no error now. - return Err(None); - } - - match self.interner.expression(&rhs) { - HirExpression::Literal(HirLiteral::Integer(int, false)) => { - int.try_into_u128().ok_or(Some(ResolverError::IntegerTooLarge { span })) - } - HirExpression::Ident(ident, _) => { - let definition = self.interner.definition(ident.id); - match definition.kind { - DefinitionKind::Global(global_id) => { - let let_statement = self.interner.get_global_let_statement(global_id); - if let Some(let_statement) = let_statement { - let expression = let_statement.expression; - self.try_eval_array_length_id_with_fuel(expression, span, fuel - 1) - } else { - Err(Some(ResolverError::InvalidArrayLengthExpr { span })) - } - } - _ => Err(Some(ResolverError::InvalidArrayLengthExpr { span })), - } - } - HirExpression::Infix(infix) => { - let lhs = self.try_eval_array_length_id_with_fuel(infix.lhs, span, fuel - 1)?; - let rhs = self.try_eval_array_length_id_with_fuel(infix.rhs, span, fuel - 1)?; - - match infix.operator.kind { - BinaryOpKind::Add => Ok(lhs + rhs), - BinaryOpKind::Subtract => Ok(lhs - rhs), - BinaryOpKind::Multiply => Ok(lhs * rhs), - BinaryOpKind::Divide => Ok(lhs / rhs), - BinaryOpKind::Equal => Ok((lhs == rhs) as u128), - BinaryOpKind::NotEqual => Ok((lhs != rhs) as u128), - BinaryOpKind::Less => Ok((lhs < rhs) as u128), - BinaryOpKind::LessEqual => Ok((lhs <= rhs) as u128), - BinaryOpKind::Greater => Ok((lhs > rhs) as u128), - BinaryOpKind::GreaterEqual => Ok((lhs >= rhs) as u128), - BinaryOpKind::And => Ok(lhs & rhs), - BinaryOpKind::Or => Ok(lhs | rhs), - BinaryOpKind::Xor => Ok(lhs ^ rhs), - BinaryOpKind::ShiftRight => Ok(lhs >> rhs), - BinaryOpKind::ShiftLeft => Ok(lhs << rhs), - BinaryOpKind::Modulo => Ok(lhs % rhs), - } - } - HirExpression::Cast(cast) => { - let lhs = self.try_eval_array_length_id_with_fuel(cast.lhs, span, fuel - 1)?; - let lhs_value = Value::Field(lhs.into()); - let evaluated_value = - Interpreter::evaluate_cast_one_step(&cast, rhs, lhs_value, self.interner) - .map_err(|error| Some(ResolverError::ArrayLengthInterpreter { error }))?; - - evaluated_value - .to_u128() - .ok_or_else(|| Some(ResolverError::InvalidArrayLengthExpr { span })) - } - _other => Err(Some(ResolverError::InvalidArrayLengthExpr { span })), - } - } - pub(super) fn unify( &mut self, actual: &Type, @@ -717,6 +644,22 @@ impl<'context> Elaborator<'context> { } } + /// Do not apply type bindings even after a successful unification. + /// This function is used by the interpreter for some comptime code + /// which can change types e.g. on each iteration of a for loop. + pub fn unify_without_applying_bindings( + &mut self, + actual: &Type, + expected: &Type, + file: fm::FileId, + make_error: impl FnOnce() -> TypeCheckError, + ) { + let mut bindings = TypeBindings::new(); + if actual.try_unify(expected, &mut bindings).is_err() { + self.errors.push((make_error().into(), file)); + } + } + /// Wrapper of Type::unify_with_coercions using self.errors pub(super) fn unify_with_coercions( &mut self, @@ -1297,11 +1240,13 @@ impl<'context> Elaborator<'context> { object_type: &Type, method_name: &str, span: Span, + has_self_arg: bool, ) -> Option { match object_type.follow_bindings() { Type::Struct(typ, _args) => { let id = typ.borrow().id; - match self.interner.lookup_method(object_type, id, method_name, false) { + match self.interner.lookup_method(object_type, id, method_name, false, has_self_arg) + { Some(method_id) => Some(HirMethodReference::FuncId(method_id)), None => { self.push_err(TypeCheckError::UnresolvedMethodCall { @@ -1330,9 +1275,9 @@ impl<'context> Elaborator<'context> { // This may be a struct or a primitive type. Type::MutableReference(element) => self .interner - .lookup_primitive_trait_method_mut(element.as_ref(), method_name) + .lookup_primitive_trait_method_mut(element.as_ref(), method_name, has_self_arg) .map(HirMethodReference::FuncId) - .or_else(|| self.lookup_method(&element, method_name, span)), + .or_else(|| self.lookup_method(&element, method_name, span, has_self_arg)), // If we fail to resolve the object to a struct type, we have no way of type // checking its arguments as we can't even resolve the name of the function @@ -1344,7 +1289,8 @@ impl<'context> Elaborator<'context> { None } - other => match self.interner.lookup_primitive_method(&other, method_name) { + other => match self.interner.lookup_primitive_method(&other, method_name, has_self_arg) + { Some(method_id) => Some(HirMethodReference::FuncId(method_id)), None => { // It could be that this type is a composite type that is bound to a trait, @@ -1686,7 +1632,7 @@ impl<'context> Elaborator<'context> { | Type::Unit | Type::Error | Type::TypeVariable(_, _) - | Type::Constant(_) + | Type::Constant(..) | Type::NamedGeneric(_, _, _) | Type::Quoted(_) | Type::Forall(_, _) => (), @@ -1727,7 +1673,7 @@ impl<'context> Elaborator<'context> { Type::Struct(struct_type, generics) => { for (i, generic) in generics.iter().enumerate() { if let Type::NamedGeneric(type_variable, name, _) = generic { - if struct_type.borrow().generic_is_numeric(i) { + if struct_type.borrow().generics[i].is_numeric() { found.insert(name.to_string(), type_variable.clone()); } } else { @@ -1738,7 +1684,7 @@ impl<'context> Elaborator<'context> { Type::Alias(alias, generics) => { for (i, generic) in generics.iter().enumerate() { if let Type::NamedGeneric(type_variable, name, _) = generic { - if alias.borrow().generic_is_numeric(i) { + if alias.borrow().generics[i].is_numeric() { found.insert(name.to_string(), type_variable.clone()); } } else { @@ -1839,6 +1785,88 @@ impl<'context> Elaborator<'context> { } } +pub fn try_eval_array_length_id( + interner: &NodeInterner, + rhs: ExprId, + span: Span, +) -> Result> { + // Arbitrary amount of recursive calls to try before giving up + let fuel = 100; + try_eval_array_length_id_with_fuel(interner, rhs, span, fuel) +} + +fn try_eval_array_length_id_with_fuel( + interner: &NodeInterner, + rhs: ExprId, + span: Span, + fuel: u32, +) -> Result> { + if fuel == 0 { + // If we reach here, it is likely from evaluating cyclic globals. We expect an error to + // be issued for them after name resolution so issue no error now. + return Err(None); + } + + match interner.expression(&rhs) { + HirExpression::Literal(HirLiteral::Integer(int, false)) => { + int.try_into_u128().ok_or(Some(ResolverError::IntegerTooLarge { span })) + } + HirExpression::Ident(ident, _) => { + if let Some(definition) = interner.try_definition(ident.id) { + match definition.kind { + DefinitionKind::Global(global_id) => { + let let_statement = interner.get_global_let_statement(global_id); + if let Some(let_statement) = let_statement { + let expression = let_statement.expression; + try_eval_array_length_id_with_fuel(interner, expression, span, fuel - 1) + } else { + Err(Some(ResolverError::InvalidArrayLengthExpr { span })) + } + } + _ => Err(Some(ResolverError::InvalidArrayLengthExpr { span })), + } + } else { + Err(Some(ResolverError::InvalidArrayLengthExpr { span })) + } + } + HirExpression::Infix(infix) => { + let lhs = try_eval_array_length_id_with_fuel(interner, infix.lhs, span, fuel - 1)?; + let rhs = try_eval_array_length_id_with_fuel(interner, infix.rhs, span, fuel - 1)?; + + match infix.operator.kind { + BinaryOpKind::Add => Ok(lhs + rhs), + BinaryOpKind::Subtract => Ok(lhs - rhs), + BinaryOpKind::Multiply => Ok(lhs * rhs), + BinaryOpKind::Divide => Ok(lhs / rhs), + BinaryOpKind::Equal => Ok((lhs == rhs) as u128), + BinaryOpKind::NotEqual => Ok((lhs != rhs) as u128), + BinaryOpKind::Less => Ok((lhs < rhs) as u128), + BinaryOpKind::LessEqual => Ok((lhs <= rhs) as u128), + BinaryOpKind::Greater => Ok((lhs > rhs) as u128), + BinaryOpKind::GreaterEqual => Ok((lhs >= rhs) as u128), + BinaryOpKind::And => Ok(lhs & rhs), + BinaryOpKind::Or => Ok(lhs | rhs), + BinaryOpKind::Xor => Ok(lhs ^ rhs), + BinaryOpKind::ShiftRight => Ok(lhs >> rhs), + BinaryOpKind::ShiftLeft => Ok(lhs << rhs), + BinaryOpKind::Modulo => Ok(lhs % rhs), + } + } + HirExpression::Cast(cast) => { + let lhs = try_eval_array_length_id_with_fuel(interner, cast.lhs, span, fuel - 1)?; + let lhs_value = Value::Field(lhs.into()); + let evaluated_value = + Interpreter::evaluate_cast_one_step(&cast, rhs, lhs_value, interner) + .map_err(|error| Some(ResolverError::ArrayLengthInterpreter { error }))?; + + evaluated_value + .to_u128() + .ok_or_else(|| Some(ResolverError::InvalidArrayLengthExpr { span })) + } + _other => Err(Some(ResolverError::InvalidArrayLengthExpr { span })), + } +} + /// Gives an error if a user tries to create a mutable reference /// to an immutable variable. fn verify_mutable_reference(interner: &NodeInterner, rhs: ExprId) -> Result<(), ResolverError> { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/display.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/display.rs new file mode 100644 index 00000000000..143e0450bac --- /dev/null +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/display.rs @@ -0,0 +1,865 @@ +use std::{fmt::Display, rc::Rc}; + +use iter_extended::vecmap; +use noirc_errors::Span; + +use crate::{ + ast::{ + ArrayLiteral, AsTraitPath, AssignStatement, BlockExpression, CallExpression, + CastExpression, ConstrainStatement, ConstructorExpression, Expression, ExpressionKind, + ForLoopStatement, ForRange, GenericTypeArgs, IfExpression, IndexExpression, + InfixExpression, LValue, Lambda, LetStatement, Literal, MemberAccessExpression, + MethodCallExpression, Pattern, PrefixExpression, Statement, StatementKind, UnresolvedType, + UnresolvedTypeData, + }, + hir_def::traits::TraitConstraint, + macros_api::NodeInterner, + node_interner::InternedStatementKind, + token::{Keyword, Token}, + Type, +}; + +use super::{ + value::{ExprValue, TypedExpr}, + Value, +}; + +pub(super) fn display_quoted( + tokens: &[Token], + indent: usize, + interner: &NodeInterner, + f: &mut std::fmt::Formatter<'_>, +) -> std::fmt::Result { + if tokens.is_empty() { + write!(f, "quote {{ }}") + } else { + writeln!(f, "quote {{")?; + let indent = indent + 1; + write!(f, "{}", " ".repeat(indent * 4))?; + display_tokens(tokens, interner, indent, f)?; + writeln!(f)?; + let indent = indent - 1; + write!(f, "{}", " ".repeat(indent * 4))?; + write!(f, "}}") + } +} + +struct TokensPrettyPrinter<'tokens, 'interner> { + tokens: &'tokens [Token], + interner: &'interner NodeInterner, +} + +impl<'tokens, 'interner> Display for TokensPrettyPrinter<'tokens, 'interner> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + display_tokens(self.tokens, self.interner, 0, f) + } +} + +fn display_tokens( + tokens: &[Token], + interner: &NodeInterner, + indent: usize, + f: &mut std::fmt::Formatter<'_>, +) -> std::fmt::Result { + let mut token_printer = TokenPrettyPrinter::new(interner, indent); + for token in tokens { + token_printer.print(token, f)?; + } + Ok(()) +} + +pub(super) fn tokens_to_string(tokens: Rc>, interner: &NodeInterner) -> String { + let tokens: Vec = tokens.iter().cloned().collect(); + TokensPrettyPrinter { tokens: &tokens, interner }.to_string() +} + +/// Tries to print tokens in a way that it'll be easier for the user to understand a +/// stream of tokens without having to format it themselves. +/// +/// The gist is: +/// - Keep track of the current indent level +/// - When '{' is found, a newline is inserted and the indent is incremented +/// - When '}' is found, a newline is inserted and the indent is decremented +/// - When ';' is found a newline is inserted +/// - When interned values are encountered, they are turned into strings and indented +/// according to the current indentation. +/// +/// There are a few more details that needs to be taken into account: +/// - two consecutive words shouldn't be glued together (as they are separate tokens) +/// - inserting spaces when needed +/// - not inserting extra newlines if possible +/// - ';' shouldn't always insert newlines (this is when it's something like `[Field; 2]`) +struct TokenPrettyPrinter<'interner> { + interner: &'interner NodeInterner, + indent: usize, + last_was_alphanumeric: bool, + last_was_right_brace: bool, + last_was_semicolon: bool, +} + +impl<'interner> TokenPrettyPrinter<'interner> { + fn new(interner: &'interner NodeInterner, indent: usize) -> Self { + Self { + interner, + indent, + last_was_alphanumeric: false, + last_was_right_brace: false, + last_was_semicolon: false, + } + } + + fn print(&mut self, token: &Token, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let last_was_alphanumeric = self.last_was_alphanumeric; + self.last_was_alphanumeric = false; + + // After `}` we usually want a newline... but not always! + if self.last_was_right_brace { + self.last_was_right_brace = false; + + match token { + Token::Keyword(Keyword::Else) => { + // If we have `} else` we don't want a newline + write!(f, " else")?; + self.last_was_alphanumeric = true; + return Ok(()); + } + Token::RightBrace => { + // Because we insert a newline right before `}`, if we have two + // (or more) in a row we don't want extra newlines. + } + _ => { + writeln!(f)?; + self.write_indent(f)?; + } + } + } + + // Heuristic: if we have `; 2` then we assume we are inside something like `[Field; 2]` + // and don't include a newline. + // The only consequence of getting this wrong is that we'll end with two consecutive + // statements in a single line (not a big deal). + if self.last_was_semicolon { + self.last_was_semicolon = false; + + match token { + Token::Int(..) => { + write!(f, " ")?; + } + Token::Ident(ident) => { + if ident.chars().all(|char| char.is_ascii_uppercase()) { + write!(f, " ")?; + } else { + writeln!(f)?; + self.write_indent(f)?; + } + } + Token::RightBrace => { + // We don't want an extra newline in this case + } + _ => { + writeln!(f)?; + self.write_indent(f)?; + } + } + } + + match token { + Token::QuotedType(id) => write!(f, "{}", self.interner.get_quoted_type(*id)), + Token::InternedExpr(id) => { + let value = Value::expression(ExpressionKind::Interned(*id)); + self.print_value(&value, f) + } + Token::InternedStatement(id) => { + let value = Value::statement(StatementKind::Interned(*id)); + self.print_value(&value, f) + } + Token::InternedLValue(id) => { + let value = Value::lvalue(LValue::Interned(*id, Span::default())); + self.print_value(&value, f) + } + Token::InternedUnresolvedTypeData(id) => { + let value = Value::UnresolvedType(UnresolvedTypeData::Interned(*id)); + self.print_value(&value, f) + } + Token::InternedPattern(id) => { + let value = Value::pattern(Pattern::Interned(*id, Span::default())); + self.print_value(&value, f) + } + Token::UnquoteMarker(id) => { + let value = Value::TypedExpr(TypedExpr::ExprId(*id)); + self.print_value(&value, f) + } + Token::Keyword(..) + | Token::Ident(..) + | Token::IntType(..) + | Token::Int(..) + | Token::Bool(..) => { + if last_was_alphanumeric { + write!(f, " ")?; + } + self.last_was_alphanumeric = true; + write!(f, "{token}") + } + Token::Comma => { + write!(f, "{token} ") + } + Token::LeftBrace => { + writeln!(f, " {{")?; + self.indent += 1; + self.write_indent(f) + } + Token::RightBrace => { + self.last_was_right_brace = true; + writeln!(f)?; + self.indent -= 1; + self.write_indent(f)?; + write!(f, "}}") + } + Token::Semicolon => { + self.last_was_semicolon = true; + write!(f, ";") + } + Token::Quote(tokens) => { + if last_was_alphanumeric { + write!(f, " ")?; + } + let tokens = vecmap(&tokens.0, |spanned_token| spanned_token.clone().into_token()); + display_quoted(&tokens, self.indent, self.interner, f) + } + Token::Colon => { + write!(f, "{token} ") + } + Token::Less + | Token::LessEqual + | Token::Greater + | Token::GreaterEqual + | Token::Equal + | Token::NotEqual + | Token::Plus + | Token::Minus + | Token::Star + | Token::Slash + | Token::Percent + | Token::Ampersand + | Token::ShiftLeft + | Token::ShiftRight + | Token::Assign + | Token::Arrow => write!(f, " {token} "), + Token::LeftParen + | Token::RightParen + | Token::LeftBracket + | Token::RightBracket + | Token::Dot + | Token::DoubleColon + | Token::DoubleDot + | Token::Caret + | Token::Pound + | Token::Pipe + | Token::Bang + | Token::DollarSign => { + write!(f, "{token}") + } + Token::Str(..) + | Token::RawStr(..) + | Token::FmtStr(..) + | Token::Whitespace(_) + | Token::LineComment(..) + | Token::BlockComment(..) + | Token::Attribute(..) + | Token::InnerAttribute(..) + | Token::Invalid(_) => { + if last_was_alphanumeric { + write!(f, " ")?; + } + write!(f, "{token}") + } + Token::EOF => Ok(()), + } + } + + fn print_value(&mut self, value: &Value, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let string = value.display(self.interner).to_string(); + for (index, line) in string.lines().enumerate() { + if index > 0 { + writeln!(f)?; + self.write_indent(f)?; + } + line.fmt(f)?; + } + + self.last_was_alphanumeric = string.bytes().all(|byte| byte.is_ascii_alphanumeric()); + self.last_was_right_brace = string.ends_with('}'); + self.last_was_semicolon = string.ends_with(';'); + + Ok(()) + } + + fn write_indent(&mut self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", " ".repeat(self.indent * 4)) + } +} + +impl Value { + pub fn display<'value, 'interner>( + &'value self, + interner: &'interner NodeInterner, + ) -> ValuePrinter<'value, 'interner> { + ValuePrinter { value: self, interner } + } +} + +pub struct ValuePrinter<'value, 'interner> { + value: &'value Value, + interner: &'interner NodeInterner, +} + +impl<'value, 'interner> Display for ValuePrinter<'value, 'interner> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self.value { + Value::Unit => write!(f, "()"), + Value::Bool(value) => { + let msg = if *value { "true" } else { "false" }; + write!(f, "{msg}") + } + Value::Field(value) => write!(f, "{value}"), + Value::I8(value) => write!(f, "{value}"), + Value::I16(value) => write!(f, "{value}"), + Value::I32(value) => write!(f, "{value}"), + Value::I64(value) => write!(f, "{value}"), + Value::U1(value) => write!(f, "{value}"), + Value::U8(value) => write!(f, "{value}"), + Value::U16(value) => write!(f, "{value}"), + Value::U32(value) => write!(f, "{value}"), + Value::U64(value) => write!(f, "{value}"), + Value::String(value) => write!(f, "{value}"), + Value::CtString(value) => write!(f, "{value}"), + Value::FormatString(value, _) => write!(f, "{value}"), + Value::Function(..) => write!(f, "(function)"), + Value::Closure(..) => write!(f, "(closure)"), + Value::Tuple(fields) => { + let fields = vecmap(fields, |field| field.display(self.interner).to_string()); + write!(f, "({})", fields.join(", ")) + } + Value::Struct(fields, typ) => { + let typename = match typ.follow_bindings() { + Type::Struct(def, _) => def.borrow().name.to_string(), + other => other.to_string(), + }; + let fields = vecmap(fields, |(name, value)| { + format!("{}: {}", name, value.display(self.interner)) + }); + write!(f, "{typename} {{ {} }}", fields.join(", ")) + } + Value::Pointer(value, _) => write!(f, "&mut {}", value.borrow().display(self.interner)), + Value::Array(values, _) => { + let values = vecmap(values, |value| value.display(self.interner).to_string()); + write!(f, "[{}]", values.join(", ")) + } + Value::Slice(values, _) => { + let values = vecmap(values, |value| value.display(self.interner).to_string()); + write!(f, "&[{}]", values.join(", ")) + } + Value::Quoted(tokens) => display_quoted(tokens, 0, self.interner, f), + Value::StructDefinition(id) => { + let def = self.interner.get_struct(*id); + let def = def.borrow(); + write!(f, "{}", def.name) + } + Value::TraitConstraint(trait_id, generics) => { + let trait_ = self.interner.get_trait(*trait_id); + write!(f, "{}{generics}", trait_.name) + } + Value::TraitDefinition(trait_id) => { + let trait_ = self.interner.get_trait(*trait_id); + write!(f, "{}", trait_.name) + } + Value::TraitImpl(trait_impl_id) => { + let trait_impl = self.interner.get_trait_implementation(*trait_impl_id); + let trait_impl = trait_impl.borrow(); + + let generic_string = + vecmap(&trait_impl.trait_generics, ToString::to_string).join(", "); + let generic_string = if generic_string.is_empty() { + generic_string + } else { + format!("<{}>", generic_string) + }; + + let where_clause = vecmap(&trait_impl.where_clause, |trait_constraint| { + display_trait_constraint(self.interner, trait_constraint) + }); + let where_clause = where_clause.join(", "); + let where_clause = if where_clause.is_empty() { + where_clause + } else { + format!(" where {}", where_clause) + }; + + write!( + f, + "impl {}{} for {}{}", + trait_impl.ident, generic_string, trait_impl.typ, where_clause + ) + } + Value::FunctionDefinition(function_id) => { + write!(f, "{}", self.interner.function_name(function_id)) + } + Value::ModuleDefinition(module_id) => { + if let Some(attributes) = self.interner.try_module_attributes(module_id) { + write!(f, "{}", &attributes.name) + } else { + write!(f, "(crate root)") + } + } + Value::Zeroed(typ) => write!(f, "(zeroed {typ})"), + Value::Type(typ) => write!(f, "{}", typ), + Value::Expr(ExprValue::Expression(expr)) => { + let expr = remove_interned_in_expression_kind(self.interner, expr.clone()); + write!(f, "{}", expr) + } + Value::Expr(ExprValue::Statement(statement)) => { + write!(f, "{}", remove_interned_in_statement_kind(self.interner, statement.clone())) + } + Value::Expr(ExprValue::LValue(lvalue)) => { + write!(f, "{}", remove_interned_in_lvalue(self.interner, lvalue.clone())) + } + Value::Expr(ExprValue::Pattern(pattern)) => { + write!(f, "{}", remove_interned_in_pattern(self.interner, pattern.clone())) + } + Value::TypedExpr(TypedExpr::ExprId(id)) => { + let hir_expr = self.interner.expression(id); + let expr = hir_expr.to_display_ast(self.interner, Span::default()); + write!(f, "{}", expr.kind) + } + Value::TypedExpr(TypedExpr::StmtId(id)) => { + let hir_statement = self.interner.statement(id); + let stmt = hir_statement.to_display_ast(self.interner, Span::default()); + write!(f, "{}", stmt.kind) + } + Value::UnresolvedType(typ) => { + write!(f, "{}", remove_interned_in_unresolved_type_data(self.interner, typ.clone())) + } + } + } +} + +impl Token { + pub fn display<'token, 'interner>( + &'token self, + interner: &'interner NodeInterner, + ) -> TokenPrinter<'token, 'interner> { + TokenPrinter { token: self, interner } + } +} + +pub struct TokenPrinter<'token, 'interner> { + token: &'token Token, + interner: &'interner NodeInterner, +} + +impl<'token, 'interner> Display for TokenPrinter<'token, 'interner> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self.token { + Token::QuotedType(id) => { + write!(f, "{}", self.interner.get_quoted_type(*id)) + } + Token::InternedExpr(id) => { + let value = Value::expression(ExpressionKind::Interned(*id)); + value.display(self.interner).fmt(f) + } + Token::InternedStatement(id) => { + let value = Value::statement(StatementKind::Interned(*id)); + value.display(self.interner).fmt(f) + } + Token::InternedLValue(id) => { + let value = Value::lvalue(LValue::Interned(*id, Span::default())); + value.display(self.interner).fmt(f) + } + Token::InternedUnresolvedTypeData(id) => { + let value = Value::UnresolvedType(UnresolvedTypeData::Interned(*id)); + value.display(self.interner).fmt(f) + } + Token::InternedPattern(id) => { + let value = Value::pattern(Pattern::Interned(*id, Span::default())); + value.display(self.interner).fmt(f) + } + Token::UnquoteMarker(id) => { + let value = Value::TypedExpr(TypedExpr::ExprId(*id)); + value.display(self.interner).fmt(f) + } + other => write!(f, "{other}"), + } + } +} + +fn display_trait_constraint(interner: &NodeInterner, trait_constraint: &TraitConstraint) -> String { + let trait_ = interner.get_trait(trait_constraint.trait_id); + format!("{}: {}{}", trait_constraint.typ, trait_.name, trait_constraint.trait_generics) +} + +// Returns a new Expression where all Interned and Resolved expressions have been turned into non-interned ExpressionKind. +fn remove_interned_in_expression(interner: &NodeInterner, expr: Expression) -> Expression { + Expression { kind: remove_interned_in_expression_kind(interner, expr.kind), span: expr.span } +} + +// Returns a new ExpressionKind where all Interned and Resolved expressions have been turned into non-interned ExpressionKind. +fn remove_interned_in_expression_kind( + interner: &NodeInterner, + expr: ExpressionKind, +) -> ExpressionKind { + match expr { + ExpressionKind::Literal(literal) => { + ExpressionKind::Literal(remove_interned_in_literal(interner, literal)) + } + ExpressionKind::Block(block) => { + let statements = + vecmap(block.statements, |stmt| remove_interned_in_statement(interner, stmt)); + ExpressionKind::Block(BlockExpression { statements }) + } + ExpressionKind::Prefix(prefix) => ExpressionKind::Prefix(Box::new(PrefixExpression { + rhs: remove_interned_in_expression(interner, prefix.rhs), + ..*prefix + })), + ExpressionKind::Index(index) => ExpressionKind::Index(Box::new(IndexExpression { + collection: remove_interned_in_expression(interner, index.collection), + index: remove_interned_in_expression(interner, index.index), + })), + ExpressionKind::Call(call) => ExpressionKind::Call(Box::new(CallExpression { + func: Box::new(remove_interned_in_expression(interner, *call.func)), + arguments: vecmap(call.arguments, |arg| remove_interned_in_expression(interner, arg)), + ..*call + })), + ExpressionKind::MethodCall(call) => { + ExpressionKind::MethodCall(Box::new(MethodCallExpression { + object: remove_interned_in_expression(interner, call.object), + arguments: vecmap(call.arguments, |arg| { + remove_interned_in_expression(interner, arg) + }), + ..*call + })) + } + ExpressionKind::Constructor(constructor) => { + ExpressionKind::Constructor(Box::new(ConstructorExpression { + fields: vecmap(constructor.fields, |(name, expr)| { + (name, remove_interned_in_expression(interner, expr)) + }), + ..*constructor + })) + } + ExpressionKind::MemberAccess(member_access) => { + ExpressionKind::MemberAccess(Box::new(MemberAccessExpression { + lhs: remove_interned_in_expression(interner, member_access.lhs), + ..*member_access + })) + } + ExpressionKind::Cast(cast) => ExpressionKind::Cast(Box::new(CastExpression { + lhs: remove_interned_in_expression(interner, cast.lhs), + ..*cast + })), + ExpressionKind::Infix(infix) => ExpressionKind::Infix(Box::new(InfixExpression { + lhs: remove_interned_in_expression(interner, infix.lhs), + rhs: remove_interned_in_expression(interner, infix.rhs), + ..*infix + })), + ExpressionKind::If(if_expr) => ExpressionKind::If(Box::new(IfExpression { + condition: remove_interned_in_expression(interner, if_expr.condition), + consequence: remove_interned_in_expression(interner, if_expr.consequence), + alternative: if_expr + .alternative + .map(|alternative| remove_interned_in_expression(interner, alternative)), + })), + ExpressionKind::Variable(_) => expr, + ExpressionKind::Tuple(expressions) => ExpressionKind::Tuple(vecmap(expressions, |expr| { + remove_interned_in_expression(interner, expr) + })), + ExpressionKind::Lambda(lambda) => ExpressionKind::Lambda(Box::new(Lambda { + body: remove_interned_in_expression(interner, lambda.body), + ..*lambda + })), + ExpressionKind::Parenthesized(expr) => { + ExpressionKind::Parenthesized(Box::new(remove_interned_in_expression(interner, *expr))) + } + ExpressionKind::Quote(_) => expr, + ExpressionKind::Unquote(expr) => { + ExpressionKind::Unquote(Box::new(remove_interned_in_expression(interner, *expr))) + } + ExpressionKind::Comptime(block, span) => { + let statements = + vecmap(block.statements, |stmt| remove_interned_in_statement(interner, stmt)); + ExpressionKind::Comptime(BlockExpression { statements }, span) + } + ExpressionKind::Unsafe(block, span) => { + let statements = + vecmap(block.statements, |stmt| remove_interned_in_statement(interner, stmt)); + ExpressionKind::Unsafe(BlockExpression { statements }, span) + } + ExpressionKind::AsTraitPath(mut path) => { + path.typ = remove_interned_in_unresolved_type(interner, path.typ); + path.trait_generics = + remove_interned_in_generic_type_args(interner, path.trait_generics); + ExpressionKind::AsTraitPath(path) + } + ExpressionKind::TypePath(mut path) => { + path.typ = remove_interned_in_unresolved_type(interner, path.typ); + path.turbofish = remove_interned_in_generic_type_args(interner, path.turbofish); + ExpressionKind::TypePath(path) + } + ExpressionKind::Resolved(id) => { + let expr = interner.expression(&id); + expr.to_display_ast(interner, Span::default()).kind + } + ExpressionKind::Interned(id) => { + let expr = interner.get_expression_kind(id).clone(); + remove_interned_in_expression_kind(interner, expr) + } + ExpressionKind::Error => expr, + ExpressionKind::InternedStatement(id) => remove_interned_in_statement_expr(interner, id), + } +} + +fn remove_interned_in_statement_expr( + interner: &NodeInterner, + id: InternedStatementKind, +) -> ExpressionKind { + let expr = match interner.get_statement_kind(id).clone() { + StatementKind::Expression(expr) | StatementKind::Semi(expr) => expr.kind, + StatementKind::Interned(id) => remove_interned_in_statement_expr(interner, id), + _ => ExpressionKind::Error, + }; + remove_interned_in_expression_kind(interner, expr) +} + +fn remove_interned_in_literal(interner: &NodeInterner, literal: Literal) -> Literal { + match literal { + Literal::Array(array_literal) => { + Literal::Array(remove_interned_in_array_literal(interner, array_literal)) + } + Literal::Slice(array_literal) => { + Literal::Array(remove_interned_in_array_literal(interner, array_literal)) + } + Literal::Bool(_) + | Literal::Integer(_, _) + | Literal::Str(_) + | Literal::RawStr(_, _) + | Literal::FmtStr(_) + | Literal::Unit => literal, + } +} + +fn remove_interned_in_array_literal( + interner: &NodeInterner, + literal: ArrayLiteral, +) -> ArrayLiteral { + match literal { + ArrayLiteral::Standard(expressions) => { + ArrayLiteral::Standard(vecmap(expressions, |expr| { + remove_interned_in_expression(interner, expr) + })) + } + ArrayLiteral::Repeated { repeated_element, length } => ArrayLiteral::Repeated { + repeated_element: Box::new(remove_interned_in_expression(interner, *repeated_element)), + length: Box::new(remove_interned_in_expression(interner, *length)), + }, + } +} + +// Returns a new Statement where all Interned statements have been turned into non-interned StatementKind. +fn remove_interned_in_statement(interner: &NodeInterner, statement: Statement) -> Statement { + Statement { + kind: remove_interned_in_statement_kind(interner, statement.kind), + span: statement.span, + } +} + +// Returns a new StatementKind where all Interned statements have been turned into non-interned StatementKind. +fn remove_interned_in_statement_kind( + interner: &NodeInterner, + statement: StatementKind, +) -> StatementKind { + match statement { + StatementKind::Let(let_statement) => StatementKind::Let(LetStatement { + pattern: remove_interned_in_pattern(interner, let_statement.pattern), + expression: remove_interned_in_expression(interner, let_statement.expression), + r#type: remove_interned_in_unresolved_type(interner, let_statement.r#type), + ..let_statement + }), + StatementKind::Constrain(constrain) => StatementKind::Constrain(ConstrainStatement { + arguments: vecmap(constrain.arguments, |expr| { + remove_interned_in_expression(interner, expr) + }), + ..constrain + }), + StatementKind::Expression(expr) => { + StatementKind::Expression(remove_interned_in_expression(interner, expr)) + } + StatementKind::Assign(assign) => StatementKind::Assign(AssignStatement { + lvalue: assign.lvalue, + expression: remove_interned_in_expression(interner, assign.expression), + }), + StatementKind::For(for_loop) => StatementKind::For(ForLoopStatement { + range: match for_loop.range { + ForRange::Range(from, to) => ForRange::Range( + remove_interned_in_expression(interner, from), + remove_interned_in_expression(interner, to), + ), + ForRange::Array(expr) => { + ForRange::Array(remove_interned_in_expression(interner, expr)) + } + }, + block: remove_interned_in_expression(interner, for_loop.block), + ..for_loop + }), + StatementKind::Comptime(statement) => { + StatementKind::Comptime(Box::new(remove_interned_in_statement(interner, *statement))) + } + StatementKind::Semi(expr) => { + StatementKind::Semi(remove_interned_in_expression(interner, expr)) + } + StatementKind::Interned(id) => { + let statement = interner.get_statement_kind(id).clone(); + remove_interned_in_statement_kind(interner, statement) + } + StatementKind::Break | StatementKind::Continue | StatementKind::Error => statement, + } +} + +// Returns a new LValue where all Interned LValues have been turned into LValue. +fn remove_interned_in_lvalue(interner: &NodeInterner, lvalue: LValue) -> LValue { + match lvalue { + LValue::Ident(_) => lvalue, + LValue::MemberAccess { object, field_name, span } => LValue::MemberAccess { + object: Box::new(remove_interned_in_lvalue(interner, *object)), + field_name, + span, + }, + LValue::Index { array, index, span } => LValue::Index { + array: Box::new(remove_interned_in_lvalue(interner, *array)), + index: remove_interned_in_expression(interner, index), + span, + }, + LValue::Dereference(lvalue, span) => { + LValue::Dereference(Box::new(remove_interned_in_lvalue(interner, *lvalue)), span) + } + LValue::Interned(id, span) => { + let lvalue = interner.get_lvalue(id, span); + remove_interned_in_lvalue(interner, lvalue) + } + } +} + +fn remove_interned_in_unresolved_type( + interner: &NodeInterner, + typ: UnresolvedType, +) -> UnresolvedType { + UnresolvedType { + typ: remove_interned_in_unresolved_type_data(interner, typ.typ), + span: typ.span, + } +} + +fn remove_interned_in_unresolved_type_data( + interner: &NodeInterner, + typ: UnresolvedTypeData, +) -> UnresolvedTypeData { + match typ { + UnresolvedTypeData::Array(expr, typ) => UnresolvedTypeData::Array( + expr, + Box::new(remove_interned_in_unresolved_type(interner, *typ)), + ), + UnresolvedTypeData::Slice(typ) => { + UnresolvedTypeData::Slice(Box::new(remove_interned_in_unresolved_type(interner, *typ))) + } + UnresolvedTypeData::FormatString(expr, typ) => UnresolvedTypeData::FormatString( + expr, + Box::new(remove_interned_in_unresolved_type(interner, *typ)), + ), + UnresolvedTypeData::Parenthesized(typ) => UnresolvedTypeData::Parenthesized(Box::new( + remove_interned_in_unresolved_type(interner, *typ), + )), + UnresolvedTypeData::Named(path, generic_type_args, is_synthesized) => { + UnresolvedTypeData::Named( + path, + remove_interned_in_generic_type_args(interner, generic_type_args), + is_synthesized, + ) + } + UnresolvedTypeData::TraitAsType(path, generic_type_args) => { + UnresolvedTypeData::TraitAsType( + path, + remove_interned_in_generic_type_args(interner, generic_type_args), + ) + } + UnresolvedTypeData::MutableReference(typ) => UnresolvedTypeData::MutableReference( + Box::new(remove_interned_in_unresolved_type(interner, *typ)), + ), + UnresolvedTypeData::Tuple(types) => UnresolvedTypeData::Tuple(vecmap(types, |typ| { + remove_interned_in_unresolved_type(interner, typ) + })), + UnresolvedTypeData::Function(arg_types, ret_type, env_type, unconstrained) => { + UnresolvedTypeData::Function( + vecmap(arg_types, |typ| remove_interned_in_unresolved_type(interner, typ)), + Box::new(remove_interned_in_unresolved_type(interner, *ret_type)), + Box::new(remove_interned_in_unresolved_type(interner, *env_type)), + unconstrained, + ) + } + UnresolvedTypeData::AsTraitPath(as_trait_path) => { + UnresolvedTypeData::AsTraitPath(Box::new(AsTraitPath { + typ: remove_interned_in_unresolved_type(interner, as_trait_path.typ), + trait_generics: remove_interned_in_generic_type_args( + interner, + as_trait_path.trait_generics, + ), + ..*as_trait_path + })) + } + UnresolvedTypeData::Interned(id) => interner.get_unresolved_type_data(id).clone(), + UnresolvedTypeData::FieldElement + | UnresolvedTypeData::Integer(_, _) + | UnresolvedTypeData::Bool + | UnresolvedTypeData::Unit + | UnresolvedTypeData::String(_) + | UnresolvedTypeData::Resolved(_) + | UnresolvedTypeData::Quoted(_) + | UnresolvedTypeData::Expression(_) + | UnresolvedTypeData::Unspecified + | UnresolvedTypeData::Error => typ, + } +} + +fn remove_interned_in_generic_type_args( + interner: &NodeInterner, + args: GenericTypeArgs, +) -> GenericTypeArgs { + GenericTypeArgs { + ordered_args: vecmap(args.ordered_args, |typ| { + remove_interned_in_unresolved_type(interner, typ) + }), + named_args: vecmap(args.named_args, |(name, typ)| { + (name, remove_interned_in_unresolved_type(interner, typ)) + }), + } +} + +// Returns a new Pattern where all Interned Patterns have been turned into Pattern. +fn remove_interned_in_pattern(interner: &NodeInterner, pattern: Pattern) -> Pattern { + match pattern { + Pattern::Identifier(_) => pattern, + Pattern::Mutable(pattern, span, is_synthesized) => Pattern::Mutable( + Box::new(remove_interned_in_pattern(interner, *pattern)), + span, + is_synthesized, + ), + Pattern::Tuple(patterns, span) => Pattern::Tuple( + vecmap(patterns, |pattern| remove_interned_in_pattern(interner, pattern)), + span, + ), + Pattern::Struct(path, patterns, span) => { + let patterns = vecmap(patterns, |(name, pattern)| { + (name, remove_interned_in_pattern(interner, pattern)) + }); + Pattern::Struct(path, patterns, span) + } + Pattern::Interned(id, _) => interner.get_pattern(id).clone(), + } +} diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/errors.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/errors.rs index 9c4761f3156..5217bbd1e71 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/errors.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/errors.rs @@ -5,12 +5,10 @@ use crate::{ ast::TraitBound, hir::{def_collector::dc_crate::CompilationError, type_check::NoMatchingImplFoundError}, parser::ParserError, - token::Token, Type, }; use acvm::{acir::AcirField, BlackBoxResolutionError, FieldElement}; use fm::FileId; -use iter_extended::vecmap; use noirc_errors::{CustomDiagnostic, Location}; /// The possible errors that can halt the interpreter. @@ -145,7 +143,7 @@ pub enum InterpreterError { }, FailedToParseMacro { error: ParserError, - tokens: Rc>, + tokens: String, rule: &'static str, file: FileId, }, @@ -391,15 +389,9 @@ impl<'a> From<&'a InterpreterError> for CustomDiagnostic { Some(msg) => (msg.clone(), "Assertion failed".into()), None => ("Assertion failed".into(), String::new()), }; - let mut diagnostic = - CustomDiagnostic::simple_error(primary, secondary, location.span); + let diagnostic = CustomDiagnostic::simple_error(primary, secondary, location.span); - // Only take at most 3 frames starting from the top of the stack to avoid producing too much output - for frame in call_stack.iter().rev().take(3) { - diagnostic.add_secondary_with_file("".to_string(), frame.span, frame.file); - } - - diagnostic + diagnostic.with_call_stack(call_stack.into_iter().copied().collect()) } InterpreterError::NoMethodFound { name, typ, location } => { let msg = format!("No method named `{name}` found for type `{typ}`"); @@ -494,10 +486,9 @@ impl<'a> From<&'a InterpreterError> for CustomDiagnostic { InterpreterError::DebugEvaluateComptime { diagnostic, .. } => diagnostic.clone(), InterpreterError::FailedToParseMacro { error, tokens, rule, file: _ } => { let message = format!("Failed to parse macro's token stream into {rule}"); - let tokens = vecmap(tokens.iter(), ToString::to_string).join(" "); - // 10 is an aribtrary number of tokens here chosen to fit roughly onto one line - let token_stream = if tokens.len() > 10 { + // If it's less than 48 chars, the error message fits in a single line (less than 80 chars total) + let token_stream = if tokens.len() <= 48 && !tokens.contains('\n') { format!("The resulting token stream was: {tokens}") } else { format!( diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/hir_to_display_ast.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/hir_to_display_ast.rs index c404b95d4b2..972826f5b7c 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/hir_to_display_ast.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/hir_to_display_ast.rs @@ -11,7 +11,7 @@ use crate::ast::{ use crate::ast::{ConstrainStatement, Expression, Statement, StatementKind}; use crate::hir_def::expr::{HirArrayLiteral, HirBlockExpression, HirExpression, HirIdent}; use crate::hir_def::stmt::{HirLValue, HirPattern, HirStatement}; -use crate::hir_def::types::{Type, TypeBinding, TypeVariableKind}; +use crate::hir_def::types::{Type, TypeBinding}; use crate::macros_api::HirLiteral; use crate::node_interner::{ExprId, NodeInterner, StmtId}; @@ -33,10 +33,17 @@ impl HirStatement { } HirStatement::Constrain(constrain) => { let expr = constrain.0.to_display_ast(interner); - let message = constrain.2.map(|message| message.to_display_ast(interner)); + let mut arguments = vec![expr]; + if let Some(message) = constrain.2 { + arguments.push(message.to_display_ast(interner)); + } // TODO: Find difference in usage between Assert & AssertEq - StatementKind::Constrain(ConstrainStatement(expr, message, ConstrainKind::Assert)) + StatementKind::Constrain(ConstrainStatement { + kind: ConstrainKind::Assert, + arguments, + span, + }) } HirStatement::Assign(assign) => StatementKind::Assign(AssignStatement { lvalue: assign.lvalue.to_display_ast(interner), @@ -141,7 +148,7 @@ impl HirExpression { let struct_type = None; ExpressionKind::Constructor(Box::new(ConstructorExpression { - type_name, + typ: UnresolvedType::from_path(type_name), fields, struct_type, })) @@ -308,28 +315,15 @@ impl Type { let name = Path::from_ident(type_def.name.clone()); UnresolvedTypeData::Named(name, generics, false) } - Type::TypeVariable(binding, kind) => { - match &*binding.borrow() { - TypeBinding::Bound(typ) => return typ.to_display_ast(), - TypeBinding::Unbound(id) => { - let expression = match kind { - // TODO: fix span or make Option - TypeVariableKind::Constant(value) => { - UnresolvedTypeExpression::Constant(*value, Span::empty(0)) - } - other_kind => { - let name = format!("var_{:?}_{}", other_kind, id); - - // TODO: fix span or make Option - let path = Path::from_single(name, Span::empty(0)); - UnresolvedTypeExpression::Variable(path) - } - }; - - UnresolvedTypeData::Expression(expression) - } + Type::TypeVariable(binding, kind) => match &*binding.borrow() { + TypeBinding::Bound(typ) => return typ.to_display_ast(), + TypeBinding::Unbound(id) => { + let name = format!("var_{:?}_{}", kind, id); + let path = Path::from_single(name, Span::empty(0)); + let expression = UnresolvedTypeExpression::Variable(path); + UnresolvedTypeData::Expression(expression) } - } + }, Type::TraitAsType(_, name, generics) => { let ordered_args = vecmap(&generics.ordered, |generic| generic.to_display_ast()); let named_args = vecmap(&generics.named, |named_type| { @@ -358,7 +352,7 @@ impl Type { // Since there is no UnresolvedTypeData equivalent for Type::Forall, we use // this to ignore this case since it shouldn't be needed anyway. Type::Forall(_, typ) => return typ.to_display_ast(), - Type::Constant(_) => panic!("Type::Constant where a type was expected: {self:?}"), + Type::Constant(..) => panic!("Type::Constant where a type was expected: {self:?}"), Type::Quoted(quoted_type) => UnresolvedTypeData::Quoted(*quoted_type), Type::Error => UnresolvedTypeData::Error, Type::InfixExpr(lhs, op, rhs) => { @@ -378,7 +372,7 @@ impl Type { let span = Span::default(); match self.follow_bindings() { - Type::Constant(length) => UnresolvedTypeExpression::Constant(length, span), + Type::Constant(length, _kind) => UnresolvedTypeExpression::Constant(length, span), Type::NamedGeneric(_var, name, _kind) => { let path = Path::from_single(name.as_ref().clone(), span); UnresolvedTypeExpression::Variable(path) @@ -421,10 +415,10 @@ impl HirArrayLiteral { HirArrayLiteral::Repeated { repeated_element, length } => { let repeated_element = Box::new(repeated_element.to_display_ast(interner)); let length = match length { - Type::Constant(length) => { + Type::Constant(length, _kind) => { let literal = Literal::Integer((*length as u128).into(), false); - let kind = ExpressionKind::Literal(literal); - Box::new(Expression::new(kind, span)) + let expr_kind = ExpressionKind::Literal(literal); + Box::new(Expression::new(expr_kind, span)) } other => panic!("Cannot convert non-constant type for repeated array literal from Hir -> Ast: {other:?}"), }; diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter.rs index 281318c5b7e..e920073b453 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter.rs @@ -12,6 +12,7 @@ use crate::ast::{BinaryOpKind, FunctionKind, IntegerBitSize, Signedness}; use crate::elaborator::Elaborator; use crate::graph::CrateId; use crate::hir::def_map::ModuleId; +use crate::hir::type_check::TypeCheckError; use crate::hir_def::expr::ImplKind; use crate::hir_def::function::FunctionBody; use crate::macros_api::UnaryOp; @@ -133,9 +134,14 @@ impl<'local, 'interner> Interpreter<'local, 'interner> { return self.call_special(function, arguments, return_type, location); } - // Wait until after call_special to set the current function so that builtin functions like - // `.as_type()` still call the resolver in the caller's scope. - let old_function = self.current_function.replace(function); + // Don't change the current function scope if we're in a #[use_callers_scope] function. + // This will affect where `Expression::resolve`, `Quoted::as_type`, and similar functions resolve. + let mut old_function = self.current_function; + let modifiers = self.elaborator.interner.function_modifiers(&function); + if !modifiers.attributes.has_use_callers_scope() { + self.current_function = Some(function); + } + let result = self.call_user_defined_function(function, arguments, location); self.current_function = old_function; result @@ -242,6 +248,26 @@ impl<'local, 'interner> Interpreter<'local, 'interner> { } fn call_closure( + &mut self, + closure: HirLambda, + environment: Vec, + arguments: Vec<(Value, Location)>, + function_scope: Option, + module_scope: ModuleId, + call_location: Location, + ) -> IResult { + // Set the closure's scope to that of the function it was originally evaluated in + let old_module = self.elaborator.replace_module(module_scope); + let old_function = std::mem::replace(&mut self.current_function, function_scope); + + let result = self.call_closure_inner(closure, environment, arguments, call_location); + + self.current_function = old_function; + self.elaborator.replace_module(old_module); + result + } + + fn call_closure_inner( &mut self, closure: HirLambda, environment: Vec, @@ -1273,10 +1299,21 @@ impl<'local, 'interner> Interpreter<'local, 'interner> { elaborator.elaborate_expression(expr).0 }); result = self.evaluate(expr)?; + + // Macro calls are typed as type variables during type checking. + // Now that we know the type we need to further unify it in case there + // are inconsistencies or the type needs to be known. + // We don't commit any type bindings made this way in case the type of + // the macro result changes across loop iterations. + let expected_type = self.elaborator.interner.id_type(id); + let actual_type = result.get_type(); + self.unify_without_binding(&actual_type, &expected_type, location); } Ok(result) } - Value::Closure(closure, env, _) => self.call_closure(closure, env, arguments, location), + Value::Closure(closure, env, _, function_scope, module_scope) => { + self.call_closure(closure, env, arguments, function_scope, module_scope, location) + } value => { let typ = value.get_type().into_owned(); Err(InterpreterError::NonFunctionCalled { typ, location }) @@ -1284,6 +1321,16 @@ impl<'local, 'interner> Interpreter<'local, 'interner> { } } + fn unify_without_binding(&mut self, actual: &Type, expected: &Type, location: Location) { + self.elaborator.unify_without_applying_bindings(actual, expected, location.file, || { + TypeCheckError::TypeMismatch { + expected_typ: expected.to_string(), + expr_typ: actual.to_string(), + expr_span: location.span, + } + }); + } + fn evaluate_method_call( &mut self, call: HirMethodCallExpression, @@ -1305,8 +1352,9 @@ impl<'local, 'interner> Interpreter<'local, 'interner> { struct_def.borrow().id, method_name, false, + true, ), - _ => self.elaborator.interner.lookup_primitive_method(&typ, method_name), + _ => self.elaborator.interner.lookup_primitive_method(&typ, method_name, true), }; if let Some(method) = method { @@ -1458,7 +1506,8 @@ impl<'local, 'interner> Interpreter<'local, 'interner> { try_vecmap(&lambda.captures, |capture| self.lookup_id(capture.ident.id, location))?; let typ = self.elaborator.interner.id_type(id).follow_bindings(); - Ok(Value::Closure(lambda, environment, typ)) + let module = self.elaborator.module_id(); + Ok(Value::Closure(lambda, environment, typ, self.current_function, module)) } fn evaluate_quote(&mut self, mut tokens: Tokens, expr_id: ExprId) -> IResult { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs index 9d1349b5209..4678d29a452 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs @@ -7,9 +7,10 @@ use builtin_helpers::{ get_format_string, get_function_def, get_module, get_quoted, get_slice, get_struct, get_trait_constraint, get_trait_def, get_trait_impl, get_tuple, get_type, get_typed_expr, get_u32, get_unresolved_type, has_named_attribute, hir_pattern_to_tokens, - mutate_func_meta_type, parse, replace_func_meta_parameters, replace_func_meta_return_type, + mutate_func_meta_type, parse, quote_ident, replace_func_meta_parameters, + replace_func_meta_return_type, }; -use chumsky::{chain::Chain, prelude::choice, Parser}; +use chumsky::{chain::Chain, prelude::choice, primitive::just, Parser}; use im::Vector; use iter_extended::{try_vecmap, vecmap}; use noirc_errors::Location; @@ -18,29 +19,28 @@ use rustc_hash::FxHashMap as HashMap; use crate::{ ast::{ - ArrayLiteral, BlockExpression, ConstrainKind, Expression, ExpressionKind, FunctionKind, - FunctionReturnType, IntegerBitSize, LValue, Literal, Pattern, Statement, StatementKind, - UnaryOp, UnresolvedType, UnresolvedTypeData, Visibility, + ArrayLiteral, BlockExpression, ConstrainKind, Expression, ExpressionKind, ForRange, + FunctionKind, FunctionReturnType, IntegerBitSize, LValue, Literal, Pattern, Statement, + StatementKind, UnaryOp, UnresolvedType, UnresolvedTypeData, Visibility, }, - hir::def_collector::dc_crate::CollectedItems, hir::{ comptime::{ errors::IResult, value::{ExprValue, TypedExpr}, InterpreterError, Value, }, + def_collector::dc_crate::CollectedItems, def_map::ModuleId, }, hir_def::function::FunctionBody, - lexer::Lexer, macros_api::{HirExpression, HirLiteral, Ident, ModuleDefId, NodeInterner, Signedness}, node_interner::{DefinitionKind, TraitImplKind}, - parser::{self}, + parser, token::{Attribute, SecondaryAttribute, Token}, Kind, QuotedType, ResolvedGeneric, Shared, Type, TypeVariable, }; -use self::builtin_helpers::{eq_item, get_array, get_str, get_u8, hash_item}; +use self::builtin_helpers::{eq_item, get_array, get_ctstring, get_str, get_u8, hash_item, lex}; use super::Interpreter; pub(crate) mod builtin_helpers; @@ -60,6 +60,8 @@ impl<'local, 'context> Interpreter<'local, 'context> { "array_len" => array_len(interner, arguments, location), "assert_constant" => Ok(Value::Bool(true)), "as_slice" => as_slice(interner, arguments, location), + "ctstring_eq" => ctstring_eq(arguments, location), + "ctstring_hash" => ctstring_hash(arguments, location), "expr_as_array" => expr_as_array(interner, arguments, return_type, location), "expr_as_assert" => expr_as_assert(interner, arguments, return_type, location), "expr_as_assert_eq" => expr_as_assert_eq(interner, arguments, return_type, location), @@ -69,12 +71,18 @@ impl<'local, 'context> Interpreter<'local, 'context> { "expr_as_bool" => expr_as_bool(interner, arguments, return_type, location), "expr_as_cast" => expr_as_cast(interner, arguments, return_type, location), "expr_as_comptime" => expr_as_comptime(interner, arguments, return_type, location), + "expr_as_constructor" => { + expr_as_constructor(interner, arguments, return_type, location) + } + "expr_as_for" => expr_as_for(interner, arguments, return_type, location), + "expr_as_for_range" => expr_as_for_range(interner, arguments, return_type, location), "expr_as_function_call" => { expr_as_function_call(interner, arguments, return_type, location) } "expr_as_if" => expr_as_if(interner, arguments, return_type, location), "expr_as_index" => expr_as_index(interner, arguments, return_type, location), "expr_as_integer" => expr_as_integer(interner, arguments, return_type, location), + "expr_as_lambda" => expr_as_lambda(interner, arguments, return_type, location), "expr_as_let" => expr_as_let(interner, arguments, return_type, location), "expr_as_member_access" => { expr_as_member_access(interner, arguments, return_type, location) @@ -97,6 +105,7 @@ impl<'local, 'context> Interpreter<'local, 'context> { "expr_is_continue" => expr_is_continue(interner, arguments, location), "expr_resolve" => expr_resolve(self, arguments, location), "is_unconstrained" => Ok(Value::Bool(true)), + "fmtstr_as_ctstring" => fmtstr_as_ctstring(interner, arguments, location), "fmtstr_quoted_contents" => fmtstr_quoted_contents(interner, arguments, location), "fresh_type_variable" => fresh_type_variable(interner), "function_def_add_attribute" => function_def_add_attribute(self, arguments, location), @@ -137,7 +146,7 @@ impl<'local, 'context> Interpreter<'local, 'context> { "modulus_le_bits" => modulus_le_bits(arguments, location), "modulus_le_bytes" => modulus_le_bytes(arguments, location), "modulus_num_bits" => modulus_num_bits(arguments, location), - "quoted_as_expr" => quoted_as_expr(arguments, return_type, location), + "quoted_as_expr" => quoted_as_expr(interner, arguments, return_type, location), "quoted_as_module" => quoted_as_module(self, arguments, return_type, location), "quoted_as_trait_constraint" => quoted_as_trait_constraint(self, arguments, location), "quoted_as_type" => quoted_as_type(self, arguments, location), @@ -151,6 +160,7 @@ impl<'local, 'context> Interpreter<'local, 'context> { "slice_push_front" => slice_push_front(interner, arguments, location), "slice_remove" => slice_remove(interner, arguments, location, call_stack), "str_as_bytes" => str_as_bytes(interner, arguments, location), + "str_as_ctstring" => str_as_ctstring(interner, arguments, location), "struct_def_add_attribute" => struct_def_add_attribute(interner, arguments, location), "struct_def_add_generic" => struct_def_add_generic(interner, arguments, location), "struct_def_as_type" => struct_def_as_type(interner, arguments, location), @@ -164,6 +174,7 @@ impl<'local, 'context> Interpreter<'local, 'context> { "struct_def_module" => struct_def_module(self, arguments, location), "struct_def_name" => struct_def_name(interner, arguments, location), "struct_def_set_fields" => struct_def_set_fields(interner, arguments, location), + "to_be_radix" => to_be_radix(arguments, return_type, location), "to_le_radix" => to_le_radix(arguments, return_type, location), "trait_constraint_eq" => trait_constraint_eq(arguments, location), "trait_constraint_hash" => trait_constraint_hash(arguments, location), @@ -291,12 +302,23 @@ fn str_as_bytes( let bytes: im::Vector = string.bytes().map(Value::U8).collect(); let byte_array_type = Type::Array( - Box::new(Type::Constant(bytes.len() as u32)), + Box::new(Type::Constant(bytes.len() as u32, Kind::u32())), Box::new(Type::Integer(Signedness::Unsigned, IntegerBitSize::Eight)), ); Ok(Value::Array(bytes, byte_array_type)) } +// fn str_as_ctstring(self) -> CtString +fn str_as_ctstring( + interner: &NodeInterner, + arguments: Vec<(Value, Location)>, + location: Location, +) -> IResult { + let self_argument = check_one_argument(arguments, location)?; + let string = get_str(interner, self_argument)?; + Ok(Value::CtString(string)) +} + // fn add_attribute(self, attribute: str) fn struct_def_add_attribute( interner: &mut NodeInterner, @@ -307,10 +329,7 @@ fn struct_def_add_attribute( let attribute_location = attribute.1; let attribute = get_str(interner, attribute)?; - let mut tokens = Lexer::lex(&format!("#[{}]", attribute)).0 .0; - if let Some(Token::EOF) = tokens.last().map(|token| token.token()) { - tokens.pop(); - } + let mut tokens = lex(&format!("#[{}]", attribute)); if tokens.len() != 1 { return Err(InterpreterError::InvalidAttribute { attribute: attribute.to_string(), @@ -318,7 +337,7 @@ fn struct_def_add_attribute( }); } - let token = tokens.into_iter().next().unwrap().into_token(); + let token = tokens.remove(0); let Token::Attribute(attribute) = token else { return Err(InterpreterError::InvalidAttribute { attribute: attribute.to_string(), @@ -351,11 +370,7 @@ fn struct_def_add_generic( let generic_location = generic.1; let generic = get_str(interner, generic)?; - let mut tokens = Lexer::lex(&generic).0 .0; - if let Some(Token::EOF) = tokens.last().map(|token| token.token()) { - tokens.pop(); - } - + let mut tokens = lex(&generic); if tokens.len() != 1 { return Err(InterpreterError::GenericNameShouldBeAnIdent { name: generic, @@ -363,7 +378,7 @@ fn struct_def_add_generic( }); } - let Token::Ident(generic_name) = tokens.pop().unwrap().into_token() else { + let Token::Ident(generic_name) = tokens.remove(0) else { return Err(InterpreterError::GenericNameShouldBeAnIdent { name: generic, location: generic_location, @@ -657,6 +672,7 @@ fn slice_insert( // fn as_expr(quoted: Quoted) -> Option fn quoted_as_expr( + interner: &NodeInterner, arguments: Vec<(Value, Location)>, return_type: Type, location: Location, @@ -667,8 +683,9 @@ fn quoted_as_expr( let statement_parser = parser::fresh_statement().map(Value::statement); let lvalue_parser = parser::lvalue(parser::expression()).map(Value::lvalue); let parser = choice((expr_parser, statement_parser, lvalue_parser)); + let parser = parser.then_ignore(just(Token::Semicolon).or_not()); - let expr = parse(argument, parser, "an expression").ok(); + let expr = parse(interner, argument, parser, "an expression").ok(); option(return_type, expr) } @@ -682,7 +699,9 @@ fn quoted_as_module( ) -> IResult { let argument = check_one_argument(arguments, location)?; - let path = parse(argument, parser::path_no_turbofish(), "a path").ok(); + let path = + parse(interpreter.elaborator.interner, argument, parser::path_no_turbofish(), "a path") + .ok(); let option_value = path.and_then(|path| { let module = interpreter .elaborate_in_function(interpreter.current_function, |elaborator| { @@ -701,7 +720,12 @@ fn quoted_as_trait_constraint( location: Location, ) -> IResult { let argument = check_one_argument(arguments, location)?; - let trait_bound = parse(argument, parser::trait_bound(), "a trait constraint")?; + let trait_bound = parse( + interpreter.elaborator.interner, + argument, + parser::trait_bound(), + "a trait constraint", + )?; let bound = interpreter .elaborate_in_function(interpreter.current_function, |elaborator| { elaborator.resolve_trait_bound(&trait_bound, Type::Unit) @@ -718,7 +742,7 @@ fn quoted_as_type( location: Location, ) -> IResult { let argument = check_one_argument(arguments, location)?; - let typ = parse(argument, parser::parse_type(), "a type")?; + let typ = parse(interpreter.elaborator.interner, argument, parser::parse_type(), "a type")?; let typ = interpreter .elaborate_in_function(interpreter.current_function, |elab| elab.resolve_type(typ)); Ok(Value::Type(typ)) @@ -735,6 +759,21 @@ fn quoted_tokens(arguments: Vec<(Value, Location)>, location: Location) -> IResu )) } +fn to_be_radix( + arguments: Vec<(Value, Location)>, + return_type: Type, + location: Location, +) -> IResult { + let le_radix_limbs = to_le_radix(arguments, return_type, location)?; + + let Value::Array(limbs, typ) = le_radix_limbs else { + unreachable!("`to_le_radix` should always return an array"); + }; + let be_radix_limbs = limbs.into_iter().rev().collect(); + + Ok(Value::Array(be_radix_limbs, typ)) +} + fn to_le_radix( arguments: Vec<(Value, Location)>, return_type: Type, @@ -745,7 +784,7 @@ fn to_le_radix( let value = get_field(value)?; let radix = get_u32(radix)?; let limb_count = if let Type::Array(length, _) = return_type { - if let Type::Constant(limb_count) = *length { + if let Type::Constant(limb_count, _kind) = *length { limb_count } else { return Err(InterpreterError::TypeAnnotationsNeededForMethodCall { location }); @@ -1163,7 +1202,7 @@ fn zeroed(return_type: Type) -> IResult { // Optimistically assume we can resolve this type later or that the value is unused Type::TypeVariable(_, _) | Type::Forall(_, _) - | Type::Constant(_) + | Type::Constant(..) | Type::InfixExpr(..) | Type::Quoted(_) | Type::Error @@ -1201,9 +1240,17 @@ fn expr_as_assert( location: Location, ) -> IResult { expr_as(interner, arguments, return_type.clone(), location, |expr| { - if let ExprValue::Statement(StatementKind::Constrain(constrain)) = expr { - if constrain.2 == ConstrainKind::Assert { - let predicate = Value::expression(constrain.0.kind); + if let ExprValue::Statement(StatementKind::Constrain(mut constrain)) = expr { + if constrain.kind == ConstrainKind::Assert + && !constrain.arguments.is_empty() + && constrain.arguments.len() <= 2 + { + let (message, predicate) = if constrain.arguments.len() == 1 { + (None, constrain.arguments.pop().unwrap()) + } else { + (Some(constrain.arguments.pop().unwrap()), constrain.arguments.pop().unwrap()) + }; + let predicate = Value::expression(predicate.kind); let option_type = extract_option_generic_type(return_type); let Type::Tuple(mut tuple_types) = option_type else { @@ -1212,7 +1259,7 @@ fn expr_as_assert( assert_eq!(tuple_types.len(), 2); let option_type = tuple_types.pop().unwrap(); - let message = constrain.1.map(|message| Value::expression(message.kind)); + let message = message.map(|msg| Value::expression(msg.kind)); let message = option(option_type, message).ok()?; Some(Value::Tuple(vec![predicate, message])) @@ -1233,14 +1280,23 @@ fn expr_as_assert_eq( location: Location, ) -> IResult { expr_as(interner, arguments, return_type.clone(), location, |expr| { - if let ExprValue::Statement(StatementKind::Constrain(constrain)) = expr { - if constrain.2 == ConstrainKind::AssertEq { - let ExpressionKind::Infix(infix) = constrain.0.kind else { - panic!("Expected AssertEq constrain statement to have an infix expression"); + if let ExprValue::Statement(StatementKind::Constrain(mut constrain)) = expr { + if constrain.kind == ConstrainKind::AssertEq + && constrain.arguments.len() >= 2 + && constrain.arguments.len() <= 3 + { + let (message, rhs, lhs) = if constrain.arguments.len() == 2 { + (None, constrain.arguments.pop().unwrap(), constrain.arguments.pop().unwrap()) + } else { + ( + Some(constrain.arguments.pop().unwrap()), + constrain.arguments.pop().unwrap(), + constrain.arguments.pop().unwrap(), + ) }; - let lhs = Value::expression(infix.lhs.kind); - let rhs = Value::expression(infix.rhs.kind); + let lhs = Value::expression(lhs.kind); + let rhs = Value::expression(rhs.kind); let option_type = extract_option_generic_type(return_type); let Type::Tuple(mut tuple_types) = option_type else { @@ -1249,7 +1305,7 @@ fn expr_as_assert_eq( assert_eq!(tuple_types.len(), 3); let option_type = tuple_types.pop().unwrap(); - let message = constrain.1.map(|message| Value::expression(message.kind)); + let message = message.map(|message| Value::expression(message.kind)); let message = option(option_type, message).ok()?; Some(Value::Tuple(vec![lhs, rhs, message])) @@ -1397,6 +1453,87 @@ fn expr_as_comptime( }) } +// fn as_constructor(self) -> Option<(Quoted, [(Quoted, Expr)])> +fn expr_as_constructor( + interner: &NodeInterner, + arguments: Vec<(Value, Location)>, + return_type: Type, + location: Location, +) -> IResult { + let self_argument = check_one_argument(arguments, location)?; + let expr_value = get_expr(interner, self_argument)?; + let expr_value = unwrap_expr_value(interner, expr_value); + + let option_value = + if let ExprValue::Expression(ExpressionKind::Constructor(constructor)) = expr_value { + let typ = Value::UnresolvedType(constructor.typ.typ); + let fields = constructor.fields.into_iter(); + let fields = fields.map(|(name, value)| { + Value::Tuple(vec![quote_ident(&name), Value::expression(value.kind)]) + }); + let fields = fields.collect(); + let fields_type = Type::Slice(Box::new(Type::Tuple(vec![ + Type::Quoted(QuotedType::Quoted), + Type::Quoted(QuotedType::Expr), + ]))); + let fields = Value::Slice(fields, fields_type); + Some(Value::Tuple(vec![typ, fields])) + } else { + None + }; + + option(return_type, option_value) +} + +// fn as_for(self) -> Option<(Quoted, Expr, Expr)> +fn expr_as_for( + interner: &NodeInterner, + arguments: Vec<(Value, Location)>, + return_type: Type, + location: Location, +) -> IResult { + expr_as(interner, arguments, return_type, location, |expr| { + if let ExprValue::Statement(StatementKind::For(for_statement)) = expr { + if let ForRange::Array(array) = for_statement.range { + let identifier = + Value::Quoted(Rc::new(vec![Token::Ident(for_statement.identifier.0.contents)])); + let array = Value::expression(array.kind); + let body = Value::expression(for_statement.block.kind); + Some(Value::Tuple(vec![identifier, array, body])) + } else { + None + } + } else { + None + } + }) +} + +// fn as_for_range(self) -> Option<(Quoted, Expr, Expr, Expr)> +fn expr_as_for_range( + interner: &NodeInterner, + arguments: Vec<(Value, Location)>, + return_type: Type, + location: Location, +) -> IResult { + expr_as(interner, arguments, return_type, location, |expr| { + if let ExprValue::Statement(StatementKind::For(for_statement)) = expr { + if let ForRange::Range(from, to) = for_statement.range { + let identifier = + Value::Quoted(Rc::new(vec![Token::Ident(for_statement.identifier.0.contents)])); + let from = Value::expression(from.kind); + let to = Value::expression(to.kind); + let body = Value::expression(for_statement.block.kind); + Some(Value::Tuple(vec![identifier, from, to, body])) + } else { + None + } + } else { + None + } + }) +} + // fn as_function_call(self) -> Option<(Expr, [Expr])> fn expr_as_function_call( interner: &NodeInterner, @@ -1494,6 +1631,68 @@ fn expr_as_integer( }) } +// fn as_lambda(self) -> Option<([(Expr, Option)], Option, Expr)> +fn expr_as_lambda( + interner: &NodeInterner, + arguments: Vec<(Value, Location)>, + return_type: Type, + location: Location, +) -> IResult { + expr_as(interner, arguments, return_type.clone(), location, |expr| { + if let ExprValue::Expression(ExpressionKind::Lambda(lambda)) = expr { + // ([(Expr, Option)], Option, Expr) + let option_type = extract_option_generic_type(return_type); + let Type::Tuple(mut tuple_types) = option_type else { + panic!("Expected the return type option generic arg to be a tuple"); + }; + assert_eq!(tuple_types.len(), 3); + + // Expr + tuple_types.pop().unwrap(); + + // Option + let option_unresolved_type = tuple_types.pop().unwrap(); + + let parameters = lambda + .parameters + .into_iter() + .map(|(pattern, typ)| { + let pattern = Value::pattern(pattern); + let typ = if let UnresolvedTypeData::Unspecified = typ.typ { + None + } else { + Some(Value::UnresolvedType(typ.typ)) + }; + let typ = option(option_unresolved_type.clone(), typ).unwrap(); + Value::Tuple(vec![pattern, typ]) + }) + .collect(); + let parameters = Value::Slice( + parameters, + Type::Slice(Box::new(Type::Tuple(vec![ + Type::Quoted(QuotedType::Expr), + Type::Quoted(QuotedType::UnresolvedType), + ]))), + ); + + let return_type = lambda.return_type.typ; + let return_type = if let UnresolvedTypeData::Unspecified = return_type { + None + } else { + Some(return_type) + }; + let return_type = return_type.map(Value::UnresolvedType); + let return_type = option(option_unresolved_type, return_type).ok()?; + + let body = Value::expression(lambda.body.kind); + + Some(Value::Tuple(vec![parameters, return_type, body])) + } else { + None + } + }) +} + // fn as_let(self) -> Option<(Expr, Option, Expr)> fn expr_as_let( interner: &NodeInterner, @@ -1538,15 +1737,13 @@ fn expr_as_member_access( ) -> IResult { expr_as(interner, arguments, return_type, location, |expr| match expr { ExprValue::Expression(ExpressionKind::MemberAccess(member_access)) => { - let tokens = Rc::new(vec![Token::Ident(member_access.rhs.0.contents.clone())]); Some(Value::Tuple(vec![ Value::expression(member_access.lhs.kind), - Value::Quoted(tokens), + quote_ident(&member_access.rhs), ])) } ExprValue::LValue(crate::ast::LValue::MemberAccess { object, field_name, span: _ }) => { - let tokens = Rc::new(vec![Token::Ident(field_name.0.contents.clone())]); - Some(Value::Tuple(vec![Value::lvalue(*object), Value::Quoted(tokens)])) + Some(Value::Tuple(vec![Value::lvalue(*object), quote_ident(&field_name)])) } _ => None, }) @@ -1563,9 +1760,7 @@ fn expr_as_method_call( if let ExprValue::Expression(ExpressionKind::MethodCall(method_call)) = expr { let object = Value::expression(method_call.object.kind); - let name_tokens = - Rc::new(vec![Token::Ident(method_call.method_name.0.contents.clone())]); - let name = Value::Quoted(name_tokens); + let name = quote_ident(&method_call.method_name); let generics = method_call.generics.unwrap_or_default().into_iter(); let generics = generics.map(|generic| Value::UnresolvedType(generic.typ)).collect(); @@ -1863,6 +2058,17 @@ fn unwrap_expr_value(interner: &NodeInterner, mut expr_value: ExprValue) -> Expr expr_value } +// fn fmtstr_as_ctstring(self) -> CtString +fn fmtstr_as_ctstring( + interner: &NodeInterner, + arguments: Vec<(Value, Location)>, + location: Location, +) -> IResult { + let self_argument = check_one_argument(arguments, location)?; + let (string, _) = get_format_string(interner, self_argument)?; + Ok(Value::CtString(string)) +} + // fn quoted_contents(self) -> Quoted fn fmtstr_quoted_contents( interner: &NodeInterner, @@ -1871,12 +2077,7 @@ fn fmtstr_quoted_contents( ) -> IResult { let self_argument = check_one_argument(arguments, location)?; let (string, _) = get_format_string(interner, self_argument)?; - let (tokens, _) = Lexer::lex(&string); - let mut tokens: Vec<_> = tokens.0.into_iter().map(|token| token.into_token()).collect(); - if let Some(Token::EOF) = tokens.last() { - tokens.pop(); - } - + let tokens = lex(&string); Ok(Value::Quoted(Rc::new(tokens))) } @@ -1895,10 +2096,7 @@ fn function_def_add_attribute( let attribute_location = attribute.1; let attribute = get_str(interpreter.elaborator.interner, attribute)?; - let mut tokens = Lexer::lex(&format!("#[{}]", attribute)).0 .0; - if let Some(Token::EOF) = tokens.last().map(|token| token.token()) { - tokens.pop(); - } + let mut tokens = lex(&format!("#[{}]", attribute)); if tokens.len() != 1 { return Err(InterpreterError::InvalidAttribute { attribute: attribute.to_string(), @@ -1906,7 +2104,7 @@ fn function_def_add_attribute( }); } - let token = tokens.into_iter().next().unwrap().into_token(); + let token = tokens.remove(0); let Token::Attribute(attribute) = token else { return Err(InterpreterError::InvalidAttribute { attribute: attribute.to_string(), @@ -2128,6 +2326,7 @@ fn function_def_set_parameters( )?; let parameter_type = get_type((tuple.pop().unwrap(), parameters_argument_location))?; let parameter_pattern = parse( + interpreter.elaborator.interner, (tuple.pop().unwrap(), parameters_argument_location), parser::pattern(), "a pattern", @@ -2230,7 +2429,8 @@ fn module_add_item( let module_data = interpreter.elaborator.get_module(module_id); let parser = parser::top_level_items(); - let top_level_statements = parse(item, parser, "a top-level item")?; + let top_level_statements = + parse(interpreter.elaborator.interner, item, parser, "a top-level item")?; interpreter.elaborate_in_module(module_id, module_data.location.file, |elaborator| { let mut generated_items = CollectedItems::default(); @@ -2435,3 +2635,11 @@ pub(crate) fn extract_option_generic_type(typ: Type) -> Type { generics.pop().expect("Expected Option to have a T generic type") } + +fn ctstring_eq(arguments: Vec<(Value, Location)>, location: Location) -> IResult { + eq_item(arguments, location, get_ctstring) +} + +fn ctstring_hash(arguments: Vec<(Value, Location)>, location: Location) -> IResult { + hash_item(arguments, location, get_ctstring) +} diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin/builtin_helpers.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin/builtin_helpers.rs index 911e89a52ec..20303e49e15 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin/builtin_helpers.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin/builtin_helpers.rs @@ -4,9 +4,11 @@ use std::{hash::Hasher, rc::Rc}; use acvm::FieldElement; use noirc_errors::Location; +use crate::hir::comptime::display::tokens_to_string; +use crate::lexer::Lexer; use crate::{ ast::{ - BlockExpression, ExpressionKind, IntegerBitSize, LValue, Pattern, Signedness, + BlockExpression, ExpressionKind, Ident, IntegerBitSize, LValue, Pattern, Signedness, StatementKind, UnresolvedTypeData, }, hir::{ @@ -125,6 +127,13 @@ pub(crate) fn get_str( } } +pub(crate) fn get_ctstring((value, location): (Value, Location)) -> IResult> { + match value { + Value::CtString(string) => Ok(string), + value => type_mismatch(value, Type::Quoted(QuotedType::CtString), location), + } +} + pub(crate) fn get_tuple( interner: &NodeInterner, (value, location): (Value, Location), @@ -385,25 +394,38 @@ pub(super) fn check_function_not_yet_resolved( } } +pub(super) fn lex(input: &str) -> Vec { + let (tokens, _) = Lexer::lex(input); + let mut tokens: Vec<_> = tokens.0.into_iter().map(|token| token.into_token()).collect(); + if let Some(Token::EOF) = tokens.last() { + tokens.pop(); + } + tokens +} + pub(super) fn parse( + interner: &NodeInterner, (value, location): (Value, Location), parser: impl NoirParser, rule: &'static str, ) -> IResult { + let parser = parser.then_ignore(chumsky::primitive::end()); let tokens = get_quoted((value, location))?; let quoted = add_token_spans(tokens.clone(), location.span); - parse_tokens(tokens, quoted, location, parser, rule) + parse_tokens(tokens, quoted, interner, location, parser, rule) } pub(super) fn parse_tokens( tokens: Rc>, quoted: Tokens, + interner: &NodeInterner, location: Location, parser: impl NoirParser, rule: &'static str, ) -> IResult { parser.parse(quoted).map_err(|mut errors| { let error = errors.swap_remove(0); + let tokens = tokens_to_string(tokens, interner); InterpreterError::FailedToParseMacro { error, tokens, rule, file: location.file } }) } @@ -461,6 +483,14 @@ pub(super) fn has_named_attribute(name: &str, attributes: &[SecondaryAttribute]) false } +pub(super) fn quote_ident(ident: &Ident) -> Value { + Value::Quoted(ident_to_tokens(ident)) +} + +pub(super) fn ident_to_tokens(ident: &Ident) -> Rc> { + Rc::new(vec![Token::Ident(ident.0.contents.clone())]) +} + pub(super) fn hash_item( arguments: Vec<(Value, Location)>, location: Location, diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/mod.rs index 16090c64174..2e2753001b4 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/mod.rs @@ -1,3 +1,4 @@ +mod display; mod errors; mod hir_to_display_ast; mod interpreter; diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/value.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/value.rs index 4eee59489a9..f01e188e498 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/value.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/value.rs @@ -1,4 +1,4 @@ -use std::{borrow::Cow, fmt::Display, rc::Rc, vec}; +use std::{borrow::Cow, rc::Rc, vec}; use acvm::{AcirField, FieldElement}; use chumsky::Parser; @@ -9,17 +9,11 @@ use strum_macros::Display; use crate::{ ast::{ - ArrayLiteral, AsTraitPath, AssignStatement, BlockExpression, CallExpression, - CastExpression, ConstrainStatement, ConstructorExpression, ForLoopStatement, ForRange, - GenericTypeArgs, Ident, IfExpression, IndexExpression, InfixExpression, IntegerBitSize, - LValue, Lambda, LetStatement, MemberAccessExpression, MethodCallExpression, Pattern, - PrefixExpression, Signedness, Statement, StatementKind, UnresolvedType, UnresolvedTypeData, + ArrayLiteral, BlockExpression, ConstructorExpression, Ident, IntegerBitSize, LValue, + Pattern, Signedness, Statement, StatementKind, UnresolvedType, UnresolvedTypeData, }, hir::{def_map::ModuleId, type_check::generics::TraitGenerics}, - hir_def::{ - expr::{HirArrayLiteral, HirConstructorExpression, HirIdent, HirLambda, ImplKind}, - traits::TraitConstraint, - }, + hir_def::expr::{HirArrayLiteral, HirConstructorExpression, HirIdent, HirLambda, ImplKind}, macros_api::{ Expression, ExpressionKind, HirExpression, HirLiteral, Literal, NodeInterner, Path, StructId, @@ -27,11 +21,14 @@ use crate::{ node_interner::{ExprId, FuncId, StmtId, TraitId, TraitImplId}, parser::{self, NoirParser, TopLevelStatement}, token::{SpannedToken, Token, Tokens}, - QuotedType, Shared, Type, TypeBindings, + Kind, QuotedType, Shared, Type, TypeBindings, }; use rustc_hash::FxHashMap as HashMap; -use super::errors::{IResult, InterpreterError}; +use super::{ + display::tokens_to_string, + errors::{IResult, InterpreterError}, +}; #[derive(Debug, Clone, PartialEq, Eq)] pub enum Value { @@ -49,8 +46,13 @@ pub enum Value { U64(u64), String(Rc), FormatString(Rc, Type), + CtString(Rc), Function(FuncId, Type, Rc), - Closure(HirLambda, Vec, Type), + + // Closures also store their original scope (function & module) + // in case they use functions such as `Quoted::as_type` which require them. + Closure(HirLambda, Vec, Type, Option, ModuleId), + Tuple(Vec), Struct(HashMap, Value>, Type), Pointer(Shared, /* auto_deref */ bool), @@ -119,12 +121,12 @@ impl Value { Value::U32(_) => Type::Integer(Signedness::Unsigned, IntegerBitSize::ThirtyTwo), Value::U64(_) => Type::Integer(Signedness::Unsigned, IntegerBitSize::SixtyFour), Value::String(value) => { - let length = Type::Constant(value.len() as u32); + let length = Type::Constant(value.len() as u32, Kind::u32()); Type::String(Box::new(length)) } Value::FormatString(_, typ) => return Cow::Borrowed(typ), Value::Function(_, typ, _) => return Cow::Borrowed(typ), - Value::Closure(_, _, typ) => return Cow::Borrowed(typ), + Value::Closure(_, _, typ, ..) => return Cow::Borrowed(typ), Value::Tuple(fields) => { Type::Tuple(vecmap(fields, |field| field.get_type().into_owned())) } @@ -151,6 +153,7 @@ impl Value { Value::Expr(_) => Type::Quoted(QuotedType::Expr), Value::TypedExpr(_) => Type::Quoted(QuotedType::TypedExpr), Value::UnresolvedType(_) => Type::Quoted(QuotedType::UnresolvedType), + Value::CtString(_) => Type::Quoted(QuotedType::CtString), }) } @@ -202,7 +205,9 @@ impl Value { Value::U64(value) => { ExpressionKind::Literal(Literal::Integer((value as u128).into(), false)) } - Value::String(value) => ExpressionKind::Literal(Literal::Str(unwrap_rc(value))), + Value::String(value) | Value::CtString(value) => { + ExpressionKind::Literal(Literal::Str(unwrap_rc(value))) + } // Format strings are lowered as normal strings since they are already interpolated. Value::FormatString(value, _) => { ExpressionKind::Literal(Literal::Str(unwrap_rc(value))) @@ -217,11 +222,6 @@ impl Value { interner.store_instantiation_bindings(expr_id, unwrap_rc(bindings)); ExpressionKind::Resolved(expr_id) } - Value::Closure(_lambda, _env, _typ) => { - // TODO: How should a closure's environment be inlined? - let item = "Returning closures from a comptime fn".into(); - return Err(InterpreterError::Unimplemented { item, location }); - } Value::Tuple(fields) => { let fields = try_vecmap(fields, |field| field.into_expression(interner, location))?; ExpressionKind::Tuple(fields) @@ -240,7 +240,7 @@ impl Value { // Since we've provided the struct_type, the path should be ignored. let type_name = Path::from_single(String::new(), location.span); ExpressionKind::Constructor(Box::new(ConstructorExpression { - type_name, + typ: UnresolvedType::from_path(type_name), fields, struct_type, })) @@ -267,6 +267,7 @@ impl Value { let error = errors.swap_remove(0); let file = location.file; let rule = "an expression"; + let tokens = tokens_to_string(tokens, interner); Err(InterpreterError::FailedToParseMacro { error, file, tokens, rule }) } }; @@ -289,6 +290,7 @@ impl Value { | Value::Zeroed(_) | Value::Type(_) | Value::UnresolvedType(_) + | Value::Closure(..) | Value::ModuleDefinition(_) => { let typ = self.get_type().into_owned(); let value = self.display(interner).to_string(); @@ -349,7 +351,9 @@ impl Value { Value::U64(value) => { HirExpression::Literal(HirLiteral::Integer((value as u128).into(), false)) } - Value::String(value) => HirExpression::Literal(HirLiteral::Str(unwrap_rc(value))), + Value::String(value) | Value::CtString(value) => { + HirExpression::Literal(HirLiteral::Str(unwrap_rc(value))) + } // Format strings are lowered as normal strings since they are already interpolated. Value::FormatString(value, _) => { HirExpression::Literal(HirLiteral::Str(unwrap_rc(value))) @@ -364,11 +368,6 @@ impl Value { interner.store_instantiation_bindings(expr_id, unwrap_rc(bindings)); return Ok(expr_id); } - Value::Closure(_lambda, _env, _typ) => { - // TODO: How should a closure's environment be inlined? - let item = "Returning closures from a comptime fn".into(); - return Err(InterpreterError::Unimplemented { item, location }); - } Value::Tuple(fields) => { let fields = try_vecmap(fields, |field| field.into_hir_expression(interner, location))?; @@ -421,6 +420,7 @@ impl Value { | Value::Zeroed(_) | Value::Type(_) | Value::UnresolvedType(_) + | Value::Closure(..) | Value::ModuleDefinition(_) => { let typ = self.get_type().into_owned(); let value = self.display(interner).to_string(); @@ -448,6 +448,9 @@ impl Value { Value::Expr(ExprValue::Expression(expr)) => { Token::InternedExpr(interner.push_expression_kind(expr)) } + Value::Expr(ExprValue::Statement(StatementKind::Expression(expr))) => { + Token::InternedExpr(interner.push_expression_kind(expr.kind)) + } Value::Expr(ExprValue::Statement(statement)) => { Token::InternedStatement(interner.push_statement_kind(statement)) } @@ -521,8 +524,11 @@ impl Value { location: Location, interner: &NodeInterner, ) -> IResult> { + let parser = parser::top_level_items(); match self { - Value::Quoted(tokens) => parse_tokens(tokens, parser::top_level_items(), location), + Value::Quoted(tokens) => { + parse_tokens(tokens, interner, parser, location, "top-level item") + } _ => { let typ = self.get_type().into_owned(); let value = self.display(interner).to_string(); @@ -530,13 +536,6 @@ impl Value { } } } - - pub fn display<'value, 'interner>( - &'value self, - interner: &'interner NodeInterner, - ) -> ValuePrinter<'value, 'interner> { - ValuePrinter { value: self, interner } - } } /// Unwraps an Rc value without cloning the inner value if the reference count is 1. Clones otherwise. @@ -546,15 +545,18 @@ pub(crate) fn unwrap_rc(rc: Rc) -> T { fn parse_tokens( tokens: Rc>, + interner: &NodeInterner, parser: impl NoirParser, location: Location, + rule: &'static str, ) -> IResult { + let parser = parser.then_ignore(chumsky::primitive::end()); match parser.parse(add_token_spans(tokens.clone(), location.span)) { Ok(expr) => Ok(expr), Err(mut errors) => { let error = errors.swap_remove(0); - let rule = "an expression"; let file = location.file; + let tokens = tokens_to_string(tokens, interner); Err(InterpreterError::FailedToParseMacro { error, file, tokens, rule }) } } @@ -564,540 +566,3 @@ pub(crate) fn add_token_spans(tokens: Rc>, span: Span) -> Tokens { let tokens = unwrap_rc(tokens); Tokens(vecmap(tokens, |token| SpannedToken::new(token, span))) } - -pub struct ValuePrinter<'value, 'interner> { - value: &'value Value, - interner: &'interner NodeInterner, -} - -impl<'value, 'interner> Display for ValuePrinter<'value, 'interner> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self.value { - Value::Unit => write!(f, "()"), - Value::Bool(value) => { - let msg = if *value { "true" } else { "false" }; - write!(f, "{msg}") - } - Value::Field(value) => write!(f, "{value}"), - Value::I8(value) => write!(f, "{value}"), - Value::I16(value) => write!(f, "{value}"), - Value::I32(value) => write!(f, "{value}"), - Value::I64(value) => write!(f, "{value}"), - Value::U1(value) => write!(f, "{value}"), - Value::U8(value) => write!(f, "{value}"), - Value::U16(value) => write!(f, "{value}"), - Value::U32(value) => write!(f, "{value}"), - Value::U64(value) => write!(f, "{value}"), - Value::String(value) => write!(f, "{value}"), - Value::FormatString(value, _) => write!(f, "{value}"), - Value::Function(..) => write!(f, "(function)"), - Value::Closure(_, _, _) => write!(f, "(closure)"), - Value::Tuple(fields) => { - let fields = vecmap(fields, |field| field.display(self.interner).to_string()); - write!(f, "({})", fields.join(", ")) - } - Value::Struct(fields, typ) => { - let typename = match typ.follow_bindings() { - Type::Struct(def, _) => def.borrow().name.to_string(), - other => other.to_string(), - }; - let fields = vecmap(fields, |(name, value)| { - format!("{}: {}", name, value.display(self.interner)) - }); - write!(f, "{typename} {{ {} }}", fields.join(", ")) - } - Value::Pointer(value, _) => write!(f, "&mut {}", value.borrow().display(self.interner)), - Value::Array(values, _) => { - let values = vecmap(values, |value| value.display(self.interner).to_string()); - write!(f, "[{}]", values.join(", ")) - } - Value::Slice(values, _) => { - let values = vecmap(values, |value| value.display(self.interner).to_string()); - write!(f, "&[{}]", values.join(", ")) - } - Value::Quoted(tokens) => { - write!(f, "quote {{")?; - for token in tokens.iter() { - write!(f, " ")?; - token.display(self.interner).fmt(f)?; - } - write!(f, " }}") - } - Value::StructDefinition(id) => { - let def = self.interner.get_struct(*id); - let def = def.borrow(); - write!(f, "{}", def.name) - } - Value::TraitConstraint(trait_id, generics) => { - let trait_ = self.interner.get_trait(*trait_id); - write!(f, "{}{generics}", trait_.name) - } - Value::TraitDefinition(trait_id) => { - let trait_ = self.interner.get_trait(*trait_id); - write!(f, "{}", trait_.name) - } - Value::TraitImpl(trait_impl_id) => { - let trait_impl = self.interner.get_trait_implementation(*trait_impl_id); - let trait_impl = trait_impl.borrow(); - - let generic_string = - vecmap(&trait_impl.trait_generics, ToString::to_string).join(", "); - let generic_string = if generic_string.is_empty() { - generic_string - } else { - format!("<{}>", generic_string) - }; - - let where_clause = vecmap(&trait_impl.where_clause, |trait_constraint| { - display_trait_constraint(self.interner, trait_constraint) - }); - let where_clause = where_clause.join(", "); - let where_clause = if where_clause.is_empty() { - where_clause - } else { - format!(" where {}", where_clause) - }; - - write!( - f, - "impl {}{} for {}{}", - trait_impl.ident, generic_string, trait_impl.typ, where_clause - ) - } - Value::FunctionDefinition(function_id) => { - write!(f, "{}", self.interner.function_name(function_id)) - } - Value::ModuleDefinition(module_id) => { - if let Some(attributes) = self.interner.try_module_attributes(module_id) { - write!(f, "{}", &attributes.name) - } else { - write!(f, "(crate root)") - } - } - Value::Zeroed(typ) => write!(f, "(zeroed {typ})"), - Value::Type(typ) => write!(f, "{:?}", typ), - Value::Expr(ExprValue::Expression(expr)) => { - write!(f, "{}", remove_interned_in_expression_kind(self.interner, expr.clone())) - } - Value::Expr(ExprValue::Statement(statement)) => { - write!(f, "{}", remove_interned_in_statement_kind(self.interner, statement.clone())) - } - Value::Expr(ExprValue::LValue(lvalue)) => { - write!(f, "{}", remove_interned_in_lvalue(self.interner, lvalue.clone())) - } - Value::Expr(ExprValue::Pattern(pattern)) => { - write!(f, "{}", remove_interned_in_pattern(self.interner, pattern.clone())) - } - Value::TypedExpr(TypedExpr::ExprId(id)) => { - let hir_expr = self.interner.expression(id); - let expr = hir_expr.to_display_ast(self.interner, Span::default()); - write!(f, "{}", expr.kind) - } - Value::TypedExpr(TypedExpr::StmtId(id)) => { - let hir_statement = self.interner.statement(id); - let stmt = hir_statement.to_display_ast(self.interner, Span::default()); - write!(f, "{}", stmt.kind) - } - Value::UnresolvedType(typ) => { - write!(f, "{}", remove_interned_in_unresolved_type_data(self.interner, typ.clone())) - } - } - } -} - -impl Token { - pub fn display<'token, 'interner>( - &'token self, - interner: &'interner NodeInterner, - ) -> TokenPrinter<'token, 'interner> { - TokenPrinter { token: self, interner } - } -} - -pub struct TokenPrinter<'token, 'interner> { - token: &'token Token, - interner: &'interner NodeInterner, -} - -impl<'token, 'interner> Display for TokenPrinter<'token, 'interner> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self.token { - Token::QuotedType(id) => { - write!(f, "{}", self.interner.get_quoted_type(*id)) - } - Token::InternedExpr(id) => { - let value = Value::expression(ExpressionKind::Interned(*id)); - value.display(self.interner).fmt(f) - } - Token::InternedStatement(id) => { - let value = Value::statement(StatementKind::Interned(*id)); - value.display(self.interner).fmt(f) - } - Token::InternedLValue(id) => { - let value = Value::lvalue(LValue::Interned(*id, Span::default())); - value.display(self.interner).fmt(f) - } - Token::InternedUnresolvedTypeData(id) => { - let value = Value::UnresolvedType(UnresolvedTypeData::Interned(*id)); - value.display(self.interner).fmt(f) - } - Token::InternedPattern(id) => { - let value = Value::pattern(Pattern::Interned(*id, Span::default())); - value.display(self.interner).fmt(f) - } - Token::UnquoteMarker(id) => { - let value = Value::TypedExpr(TypedExpr::ExprId(*id)); - value.display(self.interner).fmt(f) - } - other => write!(f, "{other}"), - } - } -} - -fn display_trait_constraint(interner: &NodeInterner, trait_constraint: &TraitConstraint) -> String { - let trait_ = interner.get_trait(trait_constraint.trait_id); - format!("{}: {}{}", trait_constraint.typ, trait_.name, trait_constraint.trait_generics) -} - -// Returns a new Expression where all Interned and Resolved expressions have been turned into non-interned ExpressionKind. -fn remove_interned_in_expression(interner: &NodeInterner, expr: Expression) -> Expression { - Expression { kind: remove_interned_in_expression_kind(interner, expr.kind), span: expr.span } -} - -// Returns a new ExpressionKind where all Interned and Resolved expressions have been turned into non-interned ExpressionKind. -fn remove_interned_in_expression_kind( - interner: &NodeInterner, - expr: ExpressionKind, -) -> ExpressionKind { - match expr { - ExpressionKind::Literal(literal) => { - ExpressionKind::Literal(remove_interned_in_literal(interner, literal)) - } - ExpressionKind::Block(block) => { - let statements = - vecmap(block.statements, |stmt| remove_interned_in_statement(interner, stmt)); - ExpressionKind::Block(BlockExpression { statements }) - } - ExpressionKind::Prefix(prefix) => ExpressionKind::Prefix(Box::new(PrefixExpression { - rhs: remove_interned_in_expression(interner, prefix.rhs), - ..*prefix - })), - ExpressionKind::Index(index) => ExpressionKind::Index(Box::new(IndexExpression { - collection: remove_interned_in_expression(interner, index.collection), - index: remove_interned_in_expression(interner, index.index), - })), - ExpressionKind::Call(call) => ExpressionKind::Call(Box::new(CallExpression { - func: Box::new(remove_interned_in_expression(interner, *call.func)), - arguments: vecmap(call.arguments, |arg| remove_interned_in_expression(interner, arg)), - ..*call - })), - ExpressionKind::MethodCall(call) => { - ExpressionKind::MethodCall(Box::new(MethodCallExpression { - object: remove_interned_in_expression(interner, call.object), - arguments: vecmap(call.arguments, |arg| { - remove_interned_in_expression(interner, arg) - }), - ..*call - })) - } - ExpressionKind::Constructor(constructor) => { - ExpressionKind::Constructor(Box::new(ConstructorExpression { - fields: vecmap(constructor.fields, |(name, expr)| { - (name, remove_interned_in_expression(interner, expr)) - }), - ..*constructor - })) - } - ExpressionKind::MemberAccess(member_access) => { - ExpressionKind::MemberAccess(Box::new(MemberAccessExpression { - lhs: remove_interned_in_expression(interner, member_access.lhs), - ..*member_access - })) - } - ExpressionKind::Cast(cast) => ExpressionKind::Cast(Box::new(CastExpression { - lhs: remove_interned_in_expression(interner, cast.lhs), - ..*cast - })), - ExpressionKind::Infix(infix) => ExpressionKind::Infix(Box::new(InfixExpression { - lhs: remove_interned_in_expression(interner, infix.lhs), - rhs: remove_interned_in_expression(interner, infix.rhs), - ..*infix - })), - ExpressionKind::If(if_expr) => ExpressionKind::If(Box::new(IfExpression { - condition: remove_interned_in_expression(interner, if_expr.condition), - consequence: remove_interned_in_expression(interner, if_expr.consequence), - alternative: if_expr - .alternative - .map(|alternative| remove_interned_in_expression(interner, alternative)), - })), - ExpressionKind::Variable(_) => expr, - ExpressionKind::Tuple(expressions) => ExpressionKind::Tuple(vecmap(expressions, |expr| { - remove_interned_in_expression(interner, expr) - })), - ExpressionKind::Lambda(lambda) => ExpressionKind::Lambda(Box::new(Lambda { - body: remove_interned_in_expression(interner, lambda.body), - ..*lambda - })), - ExpressionKind::Parenthesized(expr) => { - ExpressionKind::Parenthesized(Box::new(remove_interned_in_expression(interner, *expr))) - } - ExpressionKind::Quote(_) => expr, - ExpressionKind::Unquote(expr) => { - ExpressionKind::Unquote(Box::new(remove_interned_in_expression(interner, *expr))) - } - ExpressionKind::Comptime(block, span) => { - let statements = - vecmap(block.statements, |stmt| remove_interned_in_statement(interner, stmt)); - ExpressionKind::Comptime(BlockExpression { statements }, span) - } - ExpressionKind::Unsafe(block, span) => { - let statements = - vecmap(block.statements, |stmt| remove_interned_in_statement(interner, stmt)); - ExpressionKind::Unsafe(BlockExpression { statements }, span) - } - ExpressionKind::AsTraitPath(_) => expr, - ExpressionKind::Resolved(id) => { - let expr = interner.expression(&id); - expr.to_display_ast(interner, Span::default()).kind - } - ExpressionKind::Interned(id) => { - let expr = interner.get_expression_kind(id).clone(); - remove_interned_in_expression_kind(interner, expr) - } - ExpressionKind::Error => expr, - } -} - -fn remove_interned_in_literal(interner: &NodeInterner, literal: Literal) -> Literal { - match literal { - Literal::Array(array_literal) => { - Literal::Array(remove_interned_in_array_literal(interner, array_literal)) - } - Literal::Slice(array_literal) => { - Literal::Array(remove_interned_in_array_literal(interner, array_literal)) - } - Literal::Bool(_) - | Literal::Integer(_, _) - | Literal::Str(_) - | Literal::RawStr(_, _) - | Literal::FmtStr(_) - | Literal::Unit => literal, - } -} - -fn remove_interned_in_array_literal( - interner: &NodeInterner, - literal: ArrayLiteral, -) -> ArrayLiteral { - match literal { - ArrayLiteral::Standard(expressions) => { - ArrayLiteral::Standard(vecmap(expressions, |expr| { - remove_interned_in_expression(interner, expr) - })) - } - ArrayLiteral::Repeated { repeated_element, length } => ArrayLiteral::Repeated { - repeated_element: Box::new(remove_interned_in_expression(interner, *repeated_element)), - length: Box::new(remove_interned_in_expression(interner, *length)), - }, - } -} - -// Returns a new Statement where all Interned statements have been turned into non-interned StatementKind. -fn remove_interned_in_statement(interner: &NodeInterner, statement: Statement) -> Statement { - Statement { - kind: remove_interned_in_statement_kind(interner, statement.kind), - span: statement.span, - } -} - -// Returns a new StatementKind where all Interned statements have been turned into non-interned StatementKind. -fn remove_interned_in_statement_kind( - interner: &NodeInterner, - statement: StatementKind, -) -> StatementKind { - match statement { - StatementKind::Let(let_statement) => StatementKind::Let(LetStatement { - pattern: remove_interned_in_pattern(interner, let_statement.pattern), - expression: remove_interned_in_expression(interner, let_statement.expression), - r#type: remove_interned_in_unresolved_type(interner, let_statement.r#type), - ..let_statement - }), - StatementKind::Constrain(constrain) => StatementKind::Constrain(ConstrainStatement( - remove_interned_in_expression(interner, constrain.0), - constrain.1.map(|expr| remove_interned_in_expression(interner, expr)), - constrain.2, - )), - StatementKind::Expression(expr) => { - StatementKind::Expression(remove_interned_in_expression(interner, expr)) - } - StatementKind::Assign(assign) => StatementKind::Assign(AssignStatement { - lvalue: assign.lvalue, - expression: remove_interned_in_expression(interner, assign.expression), - }), - StatementKind::For(for_loop) => StatementKind::For(ForLoopStatement { - range: match for_loop.range { - ForRange::Range(from, to) => ForRange::Range( - remove_interned_in_expression(interner, from), - remove_interned_in_expression(interner, to), - ), - ForRange::Array(expr) => { - ForRange::Array(remove_interned_in_expression(interner, expr)) - } - }, - block: remove_interned_in_expression(interner, for_loop.block), - ..for_loop - }), - StatementKind::Comptime(statement) => { - StatementKind::Comptime(Box::new(remove_interned_in_statement(interner, *statement))) - } - StatementKind::Semi(expr) => { - StatementKind::Semi(remove_interned_in_expression(interner, expr)) - } - StatementKind::Interned(id) => { - let statement = interner.get_statement_kind(id).clone(); - remove_interned_in_statement_kind(interner, statement) - } - StatementKind::Break | StatementKind::Continue | StatementKind::Error => statement, - } -} - -// Returns a new LValue where all Interned LValues have been turned into LValue. -fn remove_interned_in_lvalue(interner: &NodeInterner, lvalue: LValue) -> LValue { - match lvalue { - LValue::Ident(_) => lvalue, - LValue::MemberAccess { object, field_name, span } => LValue::MemberAccess { - object: Box::new(remove_interned_in_lvalue(interner, *object)), - field_name, - span, - }, - LValue::Index { array, index, span } => LValue::Index { - array: Box::new(remove_interned_in_lvalue(interner, *array)), - index: remove_interned_in_expression(interner, index), - span, - }, - LValue::Dereference(lvalue, span) => { - LValue::Dereference(Box::new(remove_interned_in_lvalue(interner, *lvalue)), span) - } - LValue::Interned(id, span) => { - let lvalue = interner.get_lvalue(id, span); - remove_interned_in_lvalue(interner, lvalue) - } - } -} - -fn remove_interned_in_unresolved_type( - interner: &NodeInterner, - typ: UnresolvedType, -) -> UnresolvedType { - UnresolvedType { - typ: remove_interned_in_unresolved_type_data(interner, typ.typ), - span: typ.span, - } -} - -fn remove_interned_in_unresolved_type_data( - interner: &NodeInterner, - typ: UnresolvedTypeData, -) -> UnresolvedTypeData { - match typ { - UnresolvedTypeData::Array(expr, typ) => UnresolvedTypeData::Array( - expr, - Box::new(remove_interned_in_unresolved_type(interner, *typ)), - ), - UnresolvedTypeData::Slice(typ) => { - UnresolvedTypeData::Slice(Box::new(remove_interned_in_unresolved_type(interner, *typ))) - } - UnresolvedTypeData::FormatString(expr, typ) => UnresolvedTypeData::FormatString( - expr, - Box::new(remove_interned_in_unresolved_type(interner, *typ)), - ), - UnresolvedTypeData::Parenthesized(typ) => UnresolvedTypeData::Parenthesized(Box::new( - remove_interned_in_unresolved_type(interner, *typ), - )), - UnresolvedTypeData::Named(path, generic_type_args, is_synthesized) => { - UnresolvedTypeData::Named( - path, - remove_interned_in_generic_type_args(interner, generic_type_args), - is_synthesized, - ) - } - UnresolvedTypeData::TraitAsType(path, generic_type_args) => { - UnresolvedTypeData::TraitAsType( - path, - remove_interned_in_generic_type_args(interner, generic_type_args), - ) - } - UnresolvedTypeData::MutableReference(typ) => UnresolvedTypeData::MutableReference( - Box::new(remove_interned_in_unresolved_type(interner, *typ)), - ), - UnresolvedTypeData::Tuple(types) => UnresolvedTypeData::Tuple(vecmap(types, |typ| { - remove_interned_in_unresolved_type(interner, typ) - })), - UnresolvedTypeData::Function(arg_types, ret_type, env_type, unconstrained) => { - UnresolvedTypeData::Function( - vecmap(arg_types, |typ| remove_interned_in_unresolved_type(interner, typ)), - Box::new(remove_interned_in_unresolved_type(interner, *ret_type)), - Box::new(remove_interned_in_unresolved_type(interner, *env_type)), - unconstrained, - ) - } - UnresolvedTypeData::AsTraitPath(as_trait_path) => { - UnresolvedTypeData::AsTraitPath(Box::new(AsTraitPath { - typ: remove_interned_in_unresolved_type(interner, as_trait_path.typ), - trait_generics: remove_interned_in_generic_type_args( - interner, - as_trait_path.trait_generics, - ), - ..*as_trait_path - })) - } - UnresolvedTypeData::Interned(id) => interner.get_unresolved_type_data(id).clone(), - UnresolvedTypeData::FieldElement - | UnresolvedTypeData::Integer(_, _) - | UnresolvedTypeData::Bool - | UnresolvedTypeData::Unit - | UnresolvedTypeData::String(_) - | UnresolvedTypeData::Resolved(_) - | UnresolvedTypeData::Quoted(_) - | UnresolvedTypeData::Expression(_) - | UnresolvedTypeData::Unspecified - | UnresolvedTypeData::Error => typ, - } -} - -fn remove_interned_in_generic_type_args( - interner: &NodeInterner, - args: GenericTypeArgs, -) -> GenericTypeArgs { - GenericTypeArgs { - ordered_args: vecmap(args.ordered_args, |typ| { - remove_interned_in_unresolved_type(interner, typ) - }), - named_args: vecmap(args.named_args, |(name, typ)| { - (name, remove_interned_in_unresolved_type(interner, typ)) - }), - } -} - -// Returns a new Pattern where all Interned Patterns have been turned into Pattern. -fn remove_interned_in_pattern(interner: &NodeInterner, pattern: Pattern) -> Pattern { - match pattern { - Pattern::Identifier(_) => pattern, - Pattern::Mutable(pattern, span, is_synthesized) => Pattern::Mutable( - Box::new(remove_interned_in_pattern(interner, *pattern)), - span, - is_synthesized, - ), - Pattern::Tuple(patterns, span) => Pattern::Tuple( - vecmap(patterns, |pattern| remove_interned_in_pattern(interner, pattern)), - span, - ), - Pattern::Struct(path, patterns, span) => { - let patterns = vecmap(patterns, |(name, pattern)| { - (name, remove_interned_in_pattern(interner, pattern)) - }); - Pattern::Struct(path, patterns, span) - } - Pattern::Interned(id, _) => interner.get_pattern(id).clone(), - } -} diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs index 57c7fdd9cdb..508765f943c 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs @@ -392,8 +392,20 @@ impl<'a> ModCollector<'a> { context.def_interner.set_doc_comments(ReferenceId::Trait(trait_id), doc_comments); // Add the trait to scope so its path can be looked up later - let result = self.def_collector.def_map.modules[self.module_id.0] - .declare_trait(name.clone(), trait_id); + let visibility = trait_definition.visibility; + let result = self.def_collector.def_map.modules[self.module_id.0].declare_trait( + name.clone(), + visibility, + trait_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::Trait(trait_id), + visibility, + ); if let Err((first_def, second_def)) = result { let error = DefCollectorErrorKind::Duplicate { @@ -424,6 +436,9 @@ impl<'a> ModCollector<'a> { return_type, where_clause, body, + is_unconstrained, + visibility: _, + is_comptime, } => { let func_id = context.def_interner.push_empty_fn(); method_ids.insert(name.to_string(), func_id); @@ -434,9 +449,9 @@ impl<'a> ModCollector<'a> { visibility: ItemVisibility::Public, // TODO(Maddiaa): Investigate trait implementations with attributes see: https://github.com/noir-lang/noir/issues/2629 attributes: crate::token::Attributes::empty(), - is_unconstrained: false, + is_unconstrained: *is_unconstrained, generic_count: generics.len(), - is_comptime: false, + is_comptime: *is_comptime, name_location: location, }; @@ -973,7 +988,17 @@ pub fn collect_struct( } // Add the struct to scope so its path can be looked up later - let result = def_map.modules[module_id.0].declare_struct(name.clone(), id); + let visibility = unresolved.struct_def.visibility; + let result = def_map.modules[module_id.0].declare_struct(name.clone(), visibility, id); + + let parent_module_id = ModuleId { krate, local_id: module_id }; + + interner.usage_tracker.add_unused_item( + parent_module_id, + name.clone(), + UnusedItem::Struct(id), + visibility, + ); if let Err((first_def, second_def)) = result { let error = DefCollectorErrorKind::Duplicate { @@ -985,8 +1010,7 @@ pub fn collect_struct( } if interner.is_in_lsp_mode() { - let parent_module_id = ModuleId { krate, local_id: module_id }; - interner.register_struct(id, name.to_string(), parent_module_id); + interner.register_struct(id, name.to_string(), visibility, parent_module_id); } Some((id, unresolved)) diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/module_data.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/module_data.rs index 6a0f472ef75..645d8650c7e 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/module_data.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/module_data.rs @@ -100,8 +100,13 @@ impl ModuleData { self.declare(name, ItemVisibility::Public, id.into(), None) } - pub fn declare_struct(&mut self, name: Ident, id: StructId) -> Result<(), (Ident, Ident)> { - self.declare(name, ItemVisibility::Public, ModuleDefId::TypeId(id), None) + pub fn declare_struct( + &mut self, + name: Ident, + visibility: ItemVisibility, + id: StructId, + ) -> Result<(), (Ident, Ident)> { + self.declare(name, visibility, ModuleDefId::TypeId(id), None) } pub fn declare_type_alias( @@ -112,8 +117,13 @@ impl ModuleData { self.declare(name, ItemVisibility::Public, id.into(), None) } - pub fn declare_trait(&mut self, name: Ident, id: TraitId) -> Result<(), (Ident, Ident)> { - self.declare(name, ItemVisibility::Public, ModuleDefId::TraitId(id), None) + pub fn declare_trait( + &mut self, + name: Ident, + visibility: ItemVisibility, + id: TraitId, + ) -> Result<(), (Ident, Ident)> { + self.declare(name, visibility, ModuleDefId::TraitId(id), None) } pub fn declare_child_module( diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/errors.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/errors.rs index cb726a01dec..1e7f29527e2 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/errors.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/errors.rs @@ -55,7 +55,7 @@ pub enum ResolverError { #[error("Test functions are not allowed to have any parameters")] TestFunctionHasParameters { span: Span }, #[error("Only struct types can be used in constructor expressions")] - NonStructUsedInConstructor { typ: Type, span: Span }, + NonStructUsedInConstructor { typ: String, span: Span }, #[error("Only struct types can have generics")] NonStructWithGenerics { span: Span }, #[error("Cannot apply generics on Self type")] @@ -102,8 +102,6 @@ pub enum ResolverError { FoldAttributeOnUnconstrained { ident: Ident }, #[error("The only supported types of numeric generics are integers, fields, and booleans")] UnsupportedNumericGenericType { ident: Ident, typ: Type }, - #[error("Numeric generics should be explicit")] - UseExplicitNumericGeneric { ident: Ident }, #[error("expected type, found numeric generic parameter")] NumericGenericUsedForType { name: String, span: Span }, #[error("Invalid array length construction")] @@ -130,6 +128,8 @@ pub enum ResolverError { ComptimeTypeInRuntimeCode { typ: String, span: Span }, #[error("Comptime variable `{name}` cannot be mutated in a non-comptime context")] MutatingComptimeInNonComptimeContext { name: String, span: Span }, + #[error("Failed to parse `{statement}` as an expression")] + InvalidInternedStatementInExpr { statement: String, span: Span }, } impl ResolverError { @@ -437,15 +437,6 @@ impl<'a> From<&'a ResolverError> for Diagnostic { ident.0.span(), ) } - ResolverError::UseExplicitNumericGeneric { ident } => { - let name = &ident.0.contents; - - Diagnostic::simple_warning( - String::from("Noir now supports explicit numeric generics. Support for implicit numeric generics will be removed in the following release."), - format!("Numeric generic `{name}` should now be specified with `let {name}: `"), - ident.0.span(), - ) - } ResolverError::NumericGenericUsedForType { name, span } => { Diagnostic::simple_error( format!("expected type, found numeric generic parameter {name}"), @@ -531,6 +522,13 @@ impl<'a> From<&'a ResolverError> for Diagnostic { *span, ) }, + ResolverError::InvalidInternedStatementInExpr { statement, span } => { + Diagnostic::simple_error( + format!("Failed to parse `{statement}` as an expression"), + "The statement was used from a macro here".to_string(), + *span, + ) + }, } } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs index 5eb7a40dcd7..00e73e682e8 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs @@ -5,6 +5,7 @@ use noirc_errors::CustomDiagnostic as Diagnostic; use noirc_errors::Span; use thiserror::Error; +use crate::ast::ConstrainKind; use crate::ast::{BinaryOpKind, FunctionReturnType, IntegerBitSize, Signedness}; use crate::hir::resolution::errors::ResolverError; use crate::hir_def::expr::HirBinaryOp; @@ -59,14 +60,20 @@ pub enum TypeCheckError { AccessUnknownMember { lhs_type: Type, field_name: String, span: Span }, #[error("Function expects {expected} parameters but {found} were given")] ParameterCountMismatch { expected: usize, found: usize, span: Span }, + #[error("{} expects {} or {} parameters but {found} were given", kind, kind.required_arguments_count(), kind.required_arguments_count() + 1)] + AssertionParameterCountMismatch { kind: ConstrainKind, found: usize, span: Span }, #[error("{item} expects {expected} generics but {found} were given")] GenericCountMismatch { item: String, expected: usize, found: usize, span: Span }, + #[error("{item} has incompatible `unconstrained`")] + UnconstrainedMismatch { item: String, expected: bool, span: Span }, #[error("Only integer and Field types may be casted to")] UnsupportedCast { span: Span }, #[error("Index {index} is out of bounds for this tuple {lhs_type} of length {length}")] TupleIndexOutOfBounds { index: usize, lhs_type: Type, length: usize, span: Span }, - #[error("Variable {name} must be mutable to be assigned to")] + #[error("Variable `{name}` must be mutable to be assigned to")] VariableMustBeMutable { name: String, span: Span }, + #[error("Cannot mutate immutable variable `{name}`")] + CannotMutateImmutableVariable { name: String, span: Span }, #[error("No method named '{method_name}' found for type '{object_type}'")] UnresolvedMethodCall { method_name: String, object_type: Type, span: Span }, #[error("Integers must have the same signedness LHS is {sign_x:?}, RHS is {sign_y:?}")] @@ -256,18 +263,34 @@ impl<'a> From<&'a TypeCheckError> for Diagnostic { let msg = format!("Function expects {expected} parameter{empty_or_s} but {found} {was_or_were} given"); Diagnostic::simple_error(msg, String::new(), *span) } + TypeCheckError::AssertionParameterCountMismatch { kind, found, span } => { + let was_or_were = if *found == 1 { "was" } else { "were" }; + let min = kind.required_arguments_count(); + let max = min + 1; + let msg = format!("{kind} expects {min} or {max} parameters but {found} {was_or_were} given"); + Diagnostic::simple_error(msg, String::new(), *span) + } TypeCheckError::GenericCountMismatch { item, expected, found, span } => { let empty_or_s = if *expected == 1 { "" } else { "s" }; let was_or_were = if *found == 1 { "was" } else { "were" }; let msg = format!("{item} expects {expected} generic{empty_or_s} but {found} {was_or_were} given"); Diagnostic::simple_error(msg, String::new(), *span) } + TypeCheckError::UnconstrainedMismatch { item, expected, span } => { + let msg = if *expected { + format!("{item} is expected to be unconstrained") + } else { + format!("{item} is not expected to be unconstrained") + }; + Diagnostic::simple_error(msg, String::new(), *span) + } TypeCheckError::InvalidCast { span, .. } | TypeCheckError::ExpectedFunction { span, .. } | TypeCheckError::AccessUnknownMember { span, .. } | TypeCheckError::UnsupportedCast { span } | TypeCheckError::TupleIndexOutOfBounds { span, .. } | TypeCheckError::VariableMustBeMutable { span, .. } + | TypeCheckError::CannotMutateImmutableVariable { span, .. } | TypeCheckError::UnresolvedMethodCall { span, .. } | TypeCheckError::IntegerSignedness { span, .. } | TypeCheckError::IntegerBitWidth { span, .. } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/generics.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/generics.rs index 697c78745f9..b86e2350279 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/generics.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/generics.rs @@ -5,7 +5,7 @@ use iter_extended::vecmap; use crate::{ hir_def::traits::NamedType, macros_api::NodeInterner, - node_interner::{TraitId, TypeAliasId}, + node_interner::{FuncId, TraitId, TypeAliasId}, ResolvedGeneric, StructType, Type, }; @@ -97,6 +97,28 @@ impl Generic for Ref<'_, StructType> { } } +impl Generic for FuncId { + fn item_kind(&self) -> &'static str { + "function" + } + + fn item_name(&self, interner: &NodeInterner) -> String { + interner.function_name(self).to_string() + } + + fn generics(&self, interner: &NodeInterner) -> Vec { + interner.function_meta(self).direct_generics.clone() + } + + fn accepts_named_type_args(&self) -> bool { + false + } + + fn named_generics(&self, _interner: &NodeInterner) -> Vec { + Vec::new() + } +} + /// TraitGenerics are different from regular generics in that they can /// also contain associated type arguments. #[derive(Default, PartialEq, Eq, Clone, Hash, Ord, PartialOrd)] diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/expr.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/expr.rs index 40c16d00356..063b960863c 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/expr.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/expr.rs @@ -4,7 +4,9 @@ use noirc_errors::Location; use crate::ast::{BinaryOp, BinaryOpKind, Ident, UnaryOp}; use crate::hir::type_check::generics::TraitGenerics; -use crate::node_interner::{DefinitionId, ExprId, FuncId, NodeInterner, StmtId, TraitMethodId}; +use crate::node_interner::{ + DefinitionId, DefinitionKind, ExprId, FuncId, NodeInterner, StmtId, TraitMethodId, +}; use crate::token::Tokens; use crate::Shared; @@ -203,6 +205,21 @@ pub enum HirMethodReference { TraitMethodId(TraitMethodId, TraitGenerics), } +impl HirMethodReference { + pub fn func_id(&self, interner: &NodeInterner) -> Option { + match self { + HirMethodReference::FuncId(func_id) => Some(*func_id), + HirMethodReference::TraitMethodId(method_id, _) => { + let id = interner.trait_method_id(*method_id); + match &interner.try_definition(id)?.kind { + DefinitionKind::Function(func_id) => Some(*func_id), + _ => None, + } + } + } + } +} + impl HirMethodCallExpression { /// Converts a method call into a function call /// diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/function.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/function.rs index 8e3baef1d00..39c87607446 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/function.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/function.rs @@ -10,7 +10,7 @@ use crate::graph::CrateId; use crate::hir::def_map::LocalModuleId; use crate::macros_api::{BlockExpression, StructId}; use crate::node_interner::{ExprId, NodeInterner, TraitId, TraitImplId}; -use crate::token::CustomAtrribute; +use crate::token::CustomAttribute; use crate::{ResolvedGeneric, Type}; /// A Hir function is a block expression with a list of statements. @@ -167,7 +167,7 @@ pub struct FuncMeta { pub self_type: Option, /// Custom attributes attached to this function. - pub custom_attributes: Vec, + pub custom_attributes: Vec, } #[derive(Debug, Clone)] diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/types.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/types.rs index bcbcc8ad789..c170d2cc08f 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/types.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/types.rs @@ -112,7 +112,7 @@ pub enum Type { /// A type-level integer. Included to let an Array's size type variable /// bind to an integer without special checks to bind it to a non-type. - Constant(u32), + Constant(u32, Kind), /// The type of quoted code in macros. This is always a comptime-only type Quoted(QuotedType), @@ -138,6 +138,51 @@ pub enum Kind { Numeric(Box), } +impl Kind { + pub(crate) fn is_error(&self) -> bool { + match self { + Self::Numeric(typ) => **typ == Type::Error, + _ => false, + } + } + + pub(crate) fn is_numeric(&self) -> bool { + matches!(self, Self::Numeric { .. }) + } + + pub(crate) fn matches_opt(&self, other: Option) -> bool { + other.as_ref().map_or(true, |other_kind| self.unifies(other_kind)) + } + + pub(crate) fn u32() -> Self { + Self::Numeric(Box::new(Type::Integer(Signedness::Unsigned, IntegerBitSize::ThirtyTwo))) + } + + /// Unifies this kind with the other. Returns true on success + pub(crate) fn unifies(&self, other: &Kind) -> bool { + match (self, other) { + (Kind::Normal, Kind::Normal) => true, + (Kind::Numeric(lhs), Kind::Numeric(rhs)) => { + let mut bindings = TypeBindings::new(); + let unifies = lhs.try_unify(rhs, &mut bindings).is_ok(); + if unifies { + Type::apply_type_bindings(bindings); + } + unifies + } + _ => false, + } + } + + pub(crate) fn unify(&self, other: &Kind) -> Result<(), UnificationError> { + if self.unifies(other) { + Ok(()) + } else { + Err(UnificationError) + } + } +} + impl std::fmt::Display for Kind { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { @@ -161,6 +206,7 @@ pub enum QuotedType { UnresolvedType, FunctionDefinition, Module, + CtString, } /// A list of TypeVariableIds to bind to a type. Storing the @@ -210,6 +256,10 @@ impl ResolvedGeneric { pub fn as_named_generic(self) -> Type { Type::NamedGeneric(self.type_var, self.name, self.kind) } + + pub(crate) fn is_numeric(&self) -> bool { + self.kind.is_numeric() + } } enum FunctionCoercionResult { @@ -327,15 +377,6 @@ impl StructType { } } - /// True if the given index is the same index as a generic type of this struct - /// which is expected to be a numeric generic. - /// This is needed because we infer type kinds in Noir and don't have extensive kind checking. - /// TODO(https://github.com/noir-lang/noir/issues/5156): This is outdated and we should remove this implicit searching for numeric generics - pub fn generic_is_numeric(&self, index_of_generic: usize) -> bool { - let target_id = self.generics[index_of_generic].type_var.id(); - self.fields.iter().any(|(_, field)| field.contains_numeric_typevar(target_id)) - } - /// Instantiate this struct type, returning a Vec of the new generic args (in /// the same order as self.generics) pub fn instantiate(&self, interner: &mut NodeInterner) -> Vec { @@ -418,14 +459,6 @@ impl TypeAlias { self.typ.substitute(&substitutions) } - - /// True if the given index is the same index as a generic type of this alias - /// which is expected to be a numeric generic. - /// This is needed because we infer type kinds in Noir and don't have extensive kind checking. - pub fn generic_is_numeric(&self, index_of_generic: usize) -> bool { - let target_id = self.generics[index_of_generic].type_var.id(); - self.typ.contains_numeric_typevar(target_id) - } } /// A shared, mutable reference to some T. @@ -509,11 +542,6 @@ pub enum TypeVariableKind { /// A generic integer type. This is a more specific kind of TypeVariable /// that can only be bound to Type::Integer, or other polymorphic integers. Integer, - - /// A potentially constant array size. This will only bind to itself or - /// Type::Constant(n) with a matching size. This defaults to Type::Constant(n) if still unbound - /// during monomorphization. - Constant(u32), } /// A TypeVariable is a mutable reference that is either @@ -637,14 +665,6 @@ impl std::fmt::Display for Type { write!(f, "{}", binding.borrow()) } } - Type::TypeVariable(binding, TypeVariableKind::Constant(n)) => { - if let TypeBinding::Unbound(_) = &*binding.borrow() { - // TypeVariableKind::Constant(n) binds to Type::Constant(n) by default, so just show that. - write!(f, "{n}") - } else { - write!(f, "{}", binding.borrow()) - } - } Type::Struct(s, args) => { let args = vecmap(args, |arg| arg.to_string()); if args.is_empty() { @@ -680,7 +700,7 @@ impl std::fmt::Display for Type { TypeBinding::Unbound(_) if name.is_empty() => write!(f, "_"), TypeBinding::Unbound(_) => write!(f, "{name}"), }, - Type::Constant(x) => x.fmt(f), + Type::Constant(x, _kind) => write!(f, "{x}"), Type::Forall(typevars, typ) => { let typevars = vecmap(typevars, |var| var.id().to_string()); write!(f, "forall {}. {}", typevars.join(" "), typ) @@ -759,6 +779,7 @@ impl std::fmt::Display for QuotedType { QuotedType::UnresolvedType => write!(f, "UnresolvedType"), QuotedType::FunctionDefinition => write!(f, "FunctionDefinition"), QuotedType::Module => write!(f, "Module"), + QuotedType::CtString => write!(f, "CtString"), } } } @@ -779,15 +800,6 @@ impl Type { Type::TypeVariable(var, TypeVariableKind::Normal) } - /// Returns a TypeVariable(_, TypeVariableKind::Constant(length)) to bind to - /// a constant integer for e.g. an array length. - pub fn constant_variable(length: u32, interner: &mut NodeInterner) -> Type { - let id = interner.next_type_variable_id(); - let kind = TypeVariableKind::Constant(length); - let var = TypeVariable::unbound(id); - Type::TypeVariable(var, kind) - } - pub fn polymorphic_integer_or_field(interner: &mut NodeInterner) -> Type { let id = interner.next_type_variable_id(); let kind = TypeVariableKind::IntegerOrField; @@ -846,78 +858,6 @@ impl Type { ) } - fn contains_numeric_typevar(&self, target_id: TypeVariableId) -> bool { - // True if the given type is a NamedGeneric with the target_id - let named_generic_id_matches_target = |typ: &Type| { - if let Type::NamedGeneric(type_variable, _, _) = typ { - match &*type_variable.borrow() { - TypeBinding::Bound(_) => { - unreachable!("Named generics should not be bound until monomorphization") - } - TypeBinding::Unbound(id) => target_id == *id, - } - } else { - false - } - }; - - match self { - Type::FieldElement - | Type::Integer(_, _) - | Type::Bool - | Type::Unit - | Type::Error - | Type::TypeVariable(_, _) - | Type::Constant(_) - | Type::NamedGeneric(_, _, _) - | Type::Forall(_, _) - | Type::Quoted(_) => false, - - Type::TraitAsType(_, _, generics) => { - generics.ordered.iter().any(|generic| generic.contains_numeric_typevar(target_id)) - || generics.named.iter().any(|typ| typ.typ.contains_numeric_typevar(target_id)) - } - Type::Array(length, elem) => { - elem.contains_numeric_typevar(target_id) || named_generic_id_matches_target(length) - } - Type::Slice(elem) => elem.contains_numeric_typevar(target_id), - Type::Tuple(fields) => { - fields.iter().any(|field| field.contains_numeric_typevar(target_id)) - } - Type::Function(parameters, return_type, env, _unconstrained) => { - parameters.iter().any(|parameter| parameter.contains_numeric_typevar(target_id)) - || return_type.contains_numeric_typevar(target_id) - || env.contains_numeric_typevar(target_id) - } - Type::Struct(struct_type, generics) => { - generics.iter().enumerate().any(|(i, generic)| { - if named_generic_id_matches_target(generic) { - struct_type.borrow().generic_is_numeric(i) - } else { - generic.contains_numeric_typevar(target_id) - } - }) - } - Type::Alias(alias, generics) => generics.iter().enumerate().any(|(i, generic)| { - if named_generic_id_matches_target(generic) { - alias.borrow().generic_is_numeric(i) - } else { - generic.contains_numeric_typevar(target_id) - } - }), - Type::MutableReference(element) => element.contains_numeric_typevar(target_id), - Type::String(length) => named_generic_id_matches_target(length), - Type::FmtString(length, elements) => { - elements.contains_numeric_typevar(target_id) - || named_generic_id_matches_target(length) - } - Type::InfixExpr(lhs, _op, rhs) => { - lhs.contains_numeric_typevar(target_id) || rhs.contains_numeric_typevar(target_id) - } - } - } - - /// TODO(https://github.com/noir-lang/noir/issues/5156): Remove with explicit numeric generics pub fn find_numeric_type_vars(&self, found_names: &mut Vec) { // Return whether the named generic has a TypeKind::Numeric and save its name let named_generic_is_numeric = |typ: &Type, found_names: &mut Vec| { @@ -935,7 +875,7 @@ impl Type { | Type::Bool | Type::Unit | Type::Error - | Type::Constant(_) + | Type::Constant(_, _) | Type::Forall(_, _) | Type::Quoted(_) => {} @@ -1018,7 +958,7 @@ impl Type { | Type::Integer(_, _) | Type::Bool | Type::Unit - | Type::Constant(_) + | Type::Constant(_, _) | Type::Error => true, Type::FmtString(_, _) @@ -1064,7 +1004,7 @@ impl Type { | Type::Integer(_, _) | Type::Bool | Type::Unit - | Type::Constant(_) + | Type::Constant(_, _) | Type::TypeVariable(_, _) | Type::NamedGeneric(_, _, _) | Type::InfixExpr(..) @@ -1107,7 +1047,7 @@ impl Type { | Type::Integer(_, _) | Type::Bool | Type::Unit - | Type::Constant(_) + | Type::Constant(_, _) | Type::Slice(_) | Type::Function(_, _, _, _) | Type::FmtString(_, _) @@ -1190,35 +1130,53 @@ impl Type { } } - // TODO(https://github.com/noir-lang/noir/issues/5156): Bring back this method when we remove implicit numeric generics - // It has been commented out as to not trigger clippy for an unused method - // pub(crate) fn kind(&self) -> Kind { - // match self { - // Type::NamedGeneric(_, _, kind) => kind.clone(), - // Type::Constant(_) => Kind::Numeric(Box::new(Type::Integer( - // Signedness::Unsigned, - // IntegerBitSize::ThirtyTwo, - // ))), - // Type::FieldElement - // | Type::Array(_, _) - // | Type::Slice(_) - // | Type::Integer(_, _) - // | Type::Bool - // | Type::String(_) - // | Type::FmtString(_, _) - // | Type::Unit - // | Type::Tuple(_) - // | Type::Struct(_, _) - // | Type::Alias(_, _) - // | Type::TypeVariable(_, _) - // | Type::TraitAsType(_, _, _) - // | Type::Function(_, _, _) - // | Type::MutableReference(_) - // | Type::Forall(_, _) - // | Type::Quoted(_) - // | Type::Error => Kind::Normal, - // } - // } + pub(crate) fn kind(&self) -> Option { + match self { + Type::NamedGeneric(_, _, kind) => Some(kind.clone()), + Type::Constant(_, kind) => Some(kind.clone()), + Type::TypeVariable(var, _) => match *var.borrow() { + TypeBinding::Bound(ref typ) => typ.kind(), + TypeBinding::Unbound(_) => None, + }, + Type::InfixExpr(lhs, _op, rhs) => Some(lhs.infix_kind(rhs)), + Type::FieldElement + | Type::Array(..) + | Type::Slice(..) + | Type::Integer(..) + | Type::Bool + | Type::String(..) + | Type::FmtString(..) + | Type::Unit + | Type::Tuple(..) + | Type::Struct(..) + | Type::Alias(..) + | Type::TraitAsType(..) + | Type::Function(..) + | Type::MutableReference(..) + | Type::Forall(..) + | Type::Quoted(..) + | Type::Error => Some(Kind::Normal), + } + } + + /// if both Kind's are equal to Some(_), return that Kind, + /// otherwise return a Kind error + /// if both Kind's are None, default to u32 + /// if exactly one Kind is None, return the other one + fn infix_kind(&self, other: &Self) -> Kind { + match (self.kind(), other.kind()) { + (Some(self_kind), Some(other_kind)) => { + if self_kind == other_kind { + self_kind + } else { + Kind::Numeric(Box::new(Type::Error)) + } + } + (None, None) => Kind::u32(), + (Some(self_kind), None) => self_kind, + (None, Some(other_kind)) => other_kind, + } + } /// Returns the number of field elements required to represent the type once encoded. pub fn field_count(&self) -> u32 { @@ -1251,7 +1209,7 @@ impl Type { | Type::Function(_, _, _, _) | Type::MutableReference(_) | Type::Forall(_, _) - | Type::Constant(_) + | Type::Constant(_, _) | Type::Quoted(_) | Type::Slice(_) | Type::InfixExpr(..) @@ -1292,65 +1250,6 @@ impl Type { } } - /// Try to bind a MaybeConstant variable to self, succeeding if self is a Constant, - /// MaybeConstant, or type variable. If successful, the binding is placed in the - /// given TypeBindings map rather than linked immediately. - fn try_bind_to_maybe_constant( - &self, - var: &TypeVariable, - target_length: u32, - bindings: &mut TypeBindings, - ) -> Result<(), UnificationError> { - let target_id = match &*var.borrow() { - TypeBinding::Bound(_) => unreachable!(), - TypeBinding::Unbound(id) => *id, - }; - - let this = self.substitute(bindings).follow_bindings(); - - match &this { - Type::Constant(length) if *length == target_length => { - bindings.insert(target_id, (var.clone(), this)); - Ok(()) - } - // A TypeVariable is less specific than a MaybeConstant, so we bind - // to the other type variable instead. - Type::TypeVariable(new_var, kind) => { - let borrow = new_var.borrow(); - match &*borrow { - TypeBinding::Bound(typ) => { - typ.try_bind_to_maybe_constant(var, target_length, bindings) - } - // Avoid infinitely recursive bindings - TypeBinding::Unbound(id) if *id == target_id => Ok(()), - TypeBinding::Unbound(new_target_id) => match kind { - TypeVariableKind::Normal => { - let clone = Type::TypeVariable( - var.clone(), - TypeVariableKind::Constant(target_length), - ); - bindings.insert(*new_target_id, (new_var.clone(), clone)); - Ok(()) - } - TypeVariableKind::Constant(length) if *length == target_length => { - let clone = Type::TypeVariable( - var.clone(), - TypeVariableKind::Constant(target_length), - ); - bindings.insert(*new_target_id, (new_var.clone(), clone)); - Ok(()) - } - // *length != target_length - TypeVariableKind::Constant(_) => Err(UnificationError), - TypeVariableKind::IntegerOrField => Err(UnificationError), - TypeVariableKind::Integer => Err(UnificationError), - }, - } - } - _ => Err(UnificationError), - } - } - /// Try to bind a PolymorphicInt variable to self, succeeding if self is an integer, field, /// other PolymorphicInt type, or type variable. If successful, the binding is placed in the /// given TypeBindings map rather than linked immediately. @@ -1541,12 +1440,6 @@ impl Type { }) } - (TypeVariable(var, Kind::Constant(length)), other) - | (other, TypeVariable(var, Kind::Constant(length))) => other - .try_unify_to_type_variable(var, bindings, |bindings| { - other.try_bind_to_maybe_constant(var, *length, bindings) - }), - (Array(len_a, elem_a), Array(len_b, elem_b)) => { len_a.try_unify(len_b, bindings)?; elem_a.try_unify(elem_b, bindings) @@ -1596,13 +1489,13 @@ impl Type { } } - (NamedGeneric(binding_a, name_a, _), NamedGeneric(binding_b, name_b, _)) => { + (NamedGeneric(binding_a, name_a, kind_a), NamedGeneric(binding_b, name_b, kind_b)) => { // Bound NamedGenerics are caught by the check above assert!(binding_a.borrow().is_unbound()); assert!(binding_b.borrow().is_unbound()); if name_a == name_b { - Ok(()) + kind_a.unify(kind_b) } else { Err(UnificationError) } @@ -1647,9 +1540,9 @@ impl Type { } } - (Constant(value), other) | (other, Constant(value)) => { + (Constant(value, kind), other) | (other, Constant(value, kind)) => { if let Some(other_value) = other.evaluate_to_u32() { - if *value == other_value { + if *value == other_value && kind.matches_opt(other.kind()) { Ok(()) } else { Err(UnificationError) @@ -1657,7 +1550,11 @@ impl Type { } else if let InfixExpr(lhs, op, rhs) = other { if let Some(inverse) = op.inverse() { // Handle cases like `4 = a + b` by trying to solve to `a = 4 - b` - let new_type = InfixExpr(Box::new(Constant(*value)), inverse, rhs.clone()); + let new_type = InfixExpr( + Box::new(Constant(*value, kind.clone())), + inverse, + rhs.clone(), + ); new_type.try_unify(lhs, bindings)?; Ok(()) } else { @@ -1783,7 +1680,7 @@ impl Type { if let (Type::Array(_size, element1), Type::Slice(element2)) = (&this, &target) { // We can only do the coercion if the `as_slice` method exists. // This is usually true, but some tests don't have access to the standard library. - if let Some(as_slice) = interner.lookup_primitive_method(&this, "as_slice") { + if let Some(as_slice) = interner.lookup_primitive_method(&this, "as_slice", true) { // Still have to ensure the element types match. // Don't need to issue an error here if not, it will be done in unify_with_coercions let mut bindings = TypeBindings::new(); @@ -1815,9 +1712,8 @@ impl Type { } match self.canonicalize() { - Type::TypeVariable(_, TypeVariableKind::Constant(size)) => Some(size), Type::Array(len, _elem) => len.evaluate_to_u32(), - Type::Constant(x) => Some(x), + Type::Constant(x, _) => Some(x), Type::InfixExpr(lhs, op, rhs) => { let lhs = lhs.evaluate_to_u32()?; let rhs = rhs.evaluate_to_u32()?; @@ -2095,7 +1991,7 @@ impl Type { Type::FieldElement | Type::Integer(_, _) | Type::Bool - | Type::Constant(_) + | Type::Constant(_, _) | Type::Error | Type::Quoted(_) | Type::Unit => self.clone(), @@ -2143,7 +2039,7 @@ impl Type { Type::FieldElement | Type::Integer(_, _) | Type::Bool - | Type::Constant(_) + | Type::Constant(_, _) | Type::Error | Type::Quoted(_) | Type::Unit => false, @@ -2211,7 +2107,7 @@ impl Type { // Expect that this function should only be called on instantiated types Forall(..) => unreachable!(), - FieldElement | Integer(_, _) | Bool | Constant(_) | Unit | Quoted(_) | Error => { + FieldElement | Integer(_, _) | Bool | Constant(_, _) | Unit | Quoted(_) | Error => { self.clone() } } @@ -2227,7 +2123,7 @@ impl Type { pub fn replace_named_generics_with_type_variables(&mut self) { match self { Type::FieldElement - | Type::Constant(_) + | Type::Constant(_, _) | Type::Integer(_, _) | Type::Bool | Type::Unit @@ -2381,7 +2277,6 @@ impl TypeVariableKind { match self { TypeVariableKind::IntegerOrField => Some(Type::default_int_or_field_type()), TypeVariableKind::Integer => Some(Type::default_int_type()), - TypeVariableKind::Constant(length) => Some(Type::Constant(*length)), TypeVariableKind::Normal => None, } } @@ -2432,7 +2327,7 @@ impl From<&Type> for PrintableType { Type::FmtString(_, _) => unreachable!("format strings cannot be printed"), Type::Error => unreachable!(), Type::Unit => PrintableType::Unit, - Type::Constant(_) => unreachable!(), + Type::Constant(_, _) => unreachable!(), Type::Struct(def, ref args) => { let struct_type = def.borrow(); let fields = struct_type.get_fields(args); @@ -2483,9 +2378,6 @@ impl std::fmt::Debug for Type { Type::TypeVariable(binding, TypeVariableKind::Integer) => { write!(f, "Int{:?}", binding) } - Type::TypeVariable(binding, TypeVariableKind::Constant(n)) => { - write!(f, "{}{:?}", n, binding) - } Type::Struct(s, args) => { let args = vecmap(args, |arg| format!("{:?}", arg)); if args.is_empty() { @@ -2522,7 +2414,7 @@ impl std::fmt::Debug for Type { write!(f, "({} : {}){:?}", name, typ, binding) } }, - Type::Constant(x) => x.fmt(f), + Type::Constant(x, kind) => write!(f, "({}: {})", x, kind), Type::Forall(typevars, typ) => { let typevars = vecmap(typevars, |var| format!("{:?}", var)); write!(f, "forall {}. {:?}", typevars.join(" "), typ) @@ -2627,7 +2519,7 @@ impl std::hash::Hash for Type { vars.hash(state); typ.hash(state); } - Type::Constant(value) => value.hash(state), + Type::Constant(value, _) => value.hash(state), Type::Quoted(typ) => typ.hash(state), Type::InfixExpr(lhs, op, rhs) => { lhs.hash(state); @@ -2687,7 +2579,9 @@ impl PartialEq for Type { (Forall(lhs_vars, lhs_type), Forall(rhs_vars, rhs_type)) => { lhs_vars == rhs_vars && lhs_type == rhs_type } - (Constant(lhs), Constant(rhs)) => lhs == rhs, + (Constant(lhs, lhs_kind), Constant(rhs, rhs_kind)) => { + lhs == rhs && lhs_kind == rhs_kind + } (Quoted(lhs), Quoted(rhs)) => lhs == rhs, (InfixExpr(l_lhs, l_op, l_rhs), InfixExpr(r_lhs, r_op, r_rhs)) => { l_lhs == r_lhs && l_op == r_op && l_rhs == r_rhs diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/types/arithmetic.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/types/arithmetic.rs index 44a7526c894..54b4c27a1f3 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/types/arithmetic.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/types/arithmetic.rs @@ -1,4 +1,4 @@ -use std::collections::BTreeSet; +use std::collections::BTreeMap; use crate::{BinaryTypeOperator, Type, TypeBindings, UnificationError}; @@ -17,9 +17,11 @@ impl Type { Type::InfixExpr(lhs, op, rhs) => { // evaluate_to_u32 also calls canonicalize so if we just called // `self.evaluate_to_u32()` we'd get infinite recursion. - if let (Some(lhs), Some(rhs)) = (lhs.evaluate_to_u32(), rhs.evaluate_to_u32()) { - if let Some(result) = op.function(lhs, rhs) { - return Type::Constant(result); + if let (Some(lhs_u32), Some(rhs_u32)) = + (lhs.evaluate_to_u32(), rhs.evaluate_to_u32()) + { + if let Some(result) = op.function(lhs_u32, rhs_u32) { + return Type::Constant(result, lhs.infix_kind(&rhs)); } } @@ -52,7 +54,8 @@ impl Type { fn sort_commutative(lhs: &Type, op: BinaryTypeOperator, rhs: &Type) -> Type { let mut queue = vec![lhs.clone(), rhs.clone()]; - let mut sorted = BTreeSet::new(); + // Maps each term to the number of times that term was used. + let mut sorted = BTreeMap::new(); let zero_value = if op == BinaryTypeOperator::Addition { 0 } else { 1 }; let mut constant = zero_value; @@ -64,34 +67,43 @@ impl Type { queue.push(*lhs); queue.push(*rhs); } - Type::Constant(new_constant) => { + Type::Constant(new_constant, new_constant_kind) => { if let Some(result) = op.function(constant, new_constant) { constant = result; } else { - sorted.insert(Type::Constant(new_constant)); + let constant = Type::Constant(new_constant, new_constant_kind); + *sorted.entry(constant).or_default() += 1; } } other => { - sorted.insert(other); + *sorted.entry(other).or_default() += 1; } } } if let Some(first) = sorted.pop_first() { - let mut typ = first.clone(); + let (mut typ, first_type_count) = first.clone(); - for rhs in sorted { - typ = Type::InfixExpr(Box::new(typ), op, Box::new(rhs.clone())); + // - 1 since `typ` already is set to the first instance + for _ in 0..first_type_count - 1 { + typ = Type::InfixExpr(Box::new(typ), op, Box::new(first.0.clone())); + } + + for (rhs, rhs_count) in sorted { + for _ in 0..rhs_count { + typ = Type::InfixExpr(Box::new(typ), op, Box::new(rhs.clone())); + } } if constant != zero_value { - typ = Type::InfixExpr(Box::new(typ), op, Box::new(Type::Constant(constant))); + let constant = Type::Constant(constant, lhs.infix_kind(rhs)); + typ = Type::InfixExpr(Box::new(typ), op, Box::new(constant)); } typ } else { // Every type must have been a constant - Type::Constant(constant) + Type::Constant(constant, lhs.infix_kind(rhs)) } } @@ -194,7 +206,8 @@ impl Type { op = op.inverse()?; } let result = op.function(l_const, r_const)?; - Some(Type::InfixExpr(l_type, l_op, Box::new(Type::Constant(result)))) + let constant = Type::Constant(result, lhs.infix_kind(rhs)); + Some(Type::InfixExpr(l_type, l_op, Box::new(constant))) } (Multiplication | Division, Multiplication | Division) => { // If l_op is a division we want to inverse the rhs operator. @@ -206,7 +219,8 @@ impl Type { None } else { let result = op.function(l_const, r_const)?; - Some(Type::InfixExpr(l_type, l_op, Box::new(Type::Constant(result)))) + let constant = Box::new(Type::Constant(result, lhs.infix_kind(rhs))); + Some(Type::InfixExpr(l_type, l_op, constant)) } } _ => None, @@ -222,8 +236,8 @@ impl Type { ) -> Result<(), UnificationError> { if let Type::InfixExpr(lhs_a, op_a, rhs_a) = self { if let Some(inverse) = op_a.inverse() { - if let Some(rhs_a) = rhs_a.evaluate_to_u32() { - let rhs_a = Box::new(Type::Constant(rhs_a)); + if let Some(rhs_a_u32) = rhs_a.evaluate_to_u32() { + let rhs_a = Box::new(Type::Constant(rhs_a_u32, lhs_a.infix_kind(rhs_a))); let new_other = Type::InfixExpr(Box::new(other.clone()), inverse, rhs_a); let mut tmp_bindings = bindings.clone(); @@ -237,8 +251,8 @@ impl Type { if let Type::InfixExpr(lhs_b, op_b, rhs_b) = other { if let Some(inverse) = op_b.inverse() { - if let Some(rhs_b) = rhs_b.evaluate_to_u32() { - let rhs_b = Box::new(Type::Constant(rhs_b)); + if let Some(rhs_b_u32) = rhs_b.evaluate_to_u32() { + let rhs_b = Box::new(Type::Constant(rhs_b_u32, lhs_b.infix_kind(rhs_b))); let new_self = Type::InfixExpr(Box::new(self.clone()), inverse, rhs_b); let mut tmp_bindings = bindings.clone(); diff --git a/noir/noir-repo/compiler/noirc_frontend/src/lexer/lexer.rs b/noir/noir-repo/compiler/noirc_frontend/src/lexer/lexer.rs index 7fbbb4fccef..a4ec19ba363 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/lexer/lexer.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/lexer/lexer.rs @@ -690,7 +690,7 @@ mod tests { use iter_extended::vecmap; use super::*; - use crate::token::{CustomAtrribute, FunctionAttribute, SecondaryAttribute, TestScope}; + use crate::token::{CustomAttribute, FunctionAttribute, SecondaryAttribute, TestScope}; #[test] fn test_single_double_char() { @@ -818,7 +818,7 @@ mod tests { let token = lexer.next_token().unwrap(); assert_eq!( token.token(), - &Token::Attribute(Attribute::Secondary(SecondaryAttribute::Custom(CustomAtrribute { + &Token::Attribute(Attribute::Secondary(SecondaryAttribute::Custom(CustomAttribute { contents: "custom(hello)".to_string(), span: Span::from(0..16), contents_span: Span::from(2..15) @@ -916,7 +916,7 @@ mod tests { let token = lexer.next_token().unwrap(); assert_eq!( token.token(), - &Token::InnerAttribute(SecondaryAttribute::Custom(CustomAtrribute { + &Token::InnerAttribute(SecondaryAttribute::Custom(CustomAttribute { contents: "something".to_string(), span: Span::from(0..13), contents_span: Span::from(3..12), diff --git a/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs b/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs index 012b21a8904..f7e0a85c79c 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs @@ -698,9 +698,13 @@ impl Attributes { self.function.as_ref().map_or(false, |func_attribute| func_attribute.is_no_predicates()) } - pub fn is_varargs(&self) -> bool { + pub fn has_varargs(&self) -> bool { self.secondary.iter().any(|attr| matches!(attr, SecondaryAttribute::Varargs)) } + + pub fn has_use_callers_scope(&self) -> bool { + self.secondary.iter().any(|attr| matches!(attr, SecondaryAttribute::UseCallersScope)) + } } /// An Attribute can be either a Primary Attribute or a Secondary Attribute @@ -799,9 +803,10 @@ impl Attribute { )) } ["varargs"] => Attribute::Secondary(SecondaryAttribute::Varargs), + ["use_callers_scope"] => Attribute::Secondary(SecondaryAttribute::UseCallersScope), tokens => { tokens.iter().try_for_each(|token| validate(token))?; - Attribute::Secondary(SecondaryAttribute::Custom(CustomAtrribute { + Attribute::Secondary(SecondaryAttribute::Custom(CustomAttribute { contents: word.to_owned(), span, contents_span, @@ -910,15 +915,20 @@ pub enum SecondaryAttribute { ContractLibraryMethod, Export, Field(String), - Custom(CustomAtrribute), + Custom(CustomAttribute), Abi(String), /// A variable-argument comptime function. Varargs, + + /// Treat any metaprogramming functions within this one as resolving + /// within the scope of the calling function/module rather than this one. + /// This affects functions such as `Expression::resolve` or `Quoted::as_type`. + UseCallersScope, } impl SecondaryAttribute { - pub(crate) fn as_custom(&self) -> Option<&CustomAtrribute> { + pub(crate) fn as_custom(&self) -> Option<&CustomAttribute> { if let Self::Custom(attribute) = self { Some(attribute) } else { @@ -937,6 +947,7 @@ impl SecondaryAttribute { SecondaryAttribute::Custom(custom) => custom.name(), SecondaryAttribute::Abi(_) => Some("abi".to_string()), SecondaryAttribute::Varargs => Some("varargs".to_string()), + SecondaryAttribute::UseCallersScope => Some("use_callers_scope".to_string()), } } } @@ -954,12 +965,13 @@ impl fmt::Display for SecondaryAttribute { SecondaryAttribute::Field(ref k) => write!(f, "#[field({k})]"), SecondaryAttribute::Abi(ref k) => write!(f, "#[abi({k})]"), SecondaryAttribute::Varargs => write!(f, "#[varargs]"), + SecondaryAttribute::UseCallersScope => write!(f, "#[use_callers_scope]"), } } } #[derive(PartialEq, Eq, Hash, Debug, Clone, PartialOrd, Ord)] -pub struct CustomAtrribute { +pub struct CustomAttribute { pub contents: String, // The span of the entire attribute, including leading `#[` and trailing `]` pub span: Span, @@ -967,7 +979,7 @@ pub struct CustomAtrribute { pub contents_span: Span, } -impl CustomAtrribute { +impl CustomAttribute { fn name(&self) -> Option { let mut lexer = Lexer::new(&self.contents); let token = lexer.next()?.ok()?; @@ -1003,6 +1015,7 @@ impl AsRef for SecondaryAttribute { SecondaryAttribute::ContractLibraryMethod => "", SecondaryAttribute::Export => "", SecondaryAttribute::Varargs => "", + SecondaryAttribute::UseCallersScope => "", } } } @@ -1023,6 +1036,7 @@ pub enum Keyword { Continue, Contract, Crate, + CtString, Dep, Else, Expr, @@ -1079,6 +1093,7 @@ impl fmt::Display for Keyword { Keyword::Continue => write!(f, "continue"), Keyword::Contract => write!(f, "contract"), Keyword::Crate => write!(f, "crate"), + Keyword::CtString => write!(f, "CtString"), Keyword::Dep => write!(f, "dep"), Keyword::Else => write!(f, "else"), Keyword::Expr => write!(f, "Expr"), @@ -1138,6 +1153,7 @@ impl Keyword { "continue" => Keyword::Continue, "contract" => Keyword::Contract, "crate" => Keyword::Crate, + "CtString" => Keyword::CtString, "dep" => Keyword::Dep, "else" => Keyword::Else, "Expr" => Keyword::Expr, diff --git a/noir/noir-repo/compiler/noirc_frontend/src/locations.rs b/noir/noir-repo/compiler/noirc_frontend/src/locations.rs index 58de235455c..cba667d5dcb 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/locations.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/locations.rs @@ -298,11 +298,10 @@ impl NodeInterner { &mut self, id: StructId, name: String, + visibility: ItemVisibility, parent_module_id: ModuleId, ) { self.add_definition_location(ReferenceId::Struct(id), Some(parent_module_id)); - - let visibility = ItemVisibility::Public; self.register_name_for_auto_import(name, ModuleDefId::TypeId(id), visibility, None); } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/errors.rs b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/errors.rs index 7f4172017e2..4b1951a1aac 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/errors.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/errors.rs @@ -5,6 +5,7 @@ use crate::{hir::comptime::InterpreterError, Type}; #[derive(Debug)] pub enum MonomorphizationError { UnknownArrayLength { length: Type, location: Location }, + UnknownConstant { location: Location }, NoDefaultType { location: Location }, InternalError { message: &'static str, location: Location }, InterpreterError(InterpreterError), @@ -16,6 +17,7 @@ impl MonomorphizationError { fn location(&self) -> Location { match self { MonomorphizationError::UnknownArrayLength { location, .. } + | MonomorphizationError::UnknownConstant { location } | MonomorphizationError::InternalError { location, .. } | MonomorphizationError::ComptimeFnInRuntimeCode { location, .. } | MonomorphizationError::ComptimeTypeInRuntimeCode { location, .. } @@ -30,7 +32,7 @@ impl From for FileDiagnostic { let location = error.location(); let call_stack = vec![location]; let diagnostic = error.into_diagnostic(); - diagnostic.in_file(location.file).with_call_stack(call_stack) + diagnostic.with_call_stack(call_stack).in_file(location.file) } } @@ -40,6 +42,9 @@ impl MonomorphizationError { MonomorphizationError::UnknownArrayLength { length, .. } => { format!("Could not determine array length `{length}`") } + MonomorphizationError::UnknownConstant { .. } => { + "Could not resolve constant".to_string() + } MonomorphizationError::NoDefaultType { location } => { let message = "Type annotation needed".into(); let secondary = "Could not determine type of generic argument".into(); diff --git a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs index fd06a2b04a8..12cc3b55b1f 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -1049,7 +1049,7 @@ impl<'interner> Monomorphizer<'interner> { ast::Type::MutableReference(Box::new(element)) } - HirType::Forall(_, _) | HirType::Constant(_) | HirType::InfixExpr(..) => { + HirType::Forall(_, _) | HirType::Constant(..) | HirType::InfixExpr(..) => { unreachable!("Unexpected type {typ} found") } HirType::Error => { @@ -1073,9 +1073,15 @@ impl<'interner> Monomorphizer<'interner> { | HirType::Unit | HirType::TraitAsType(..) | HirType::Forall(_, _) - | HirType::Constant(_) | HirType::Error | HirType::Quoted(_) => Ok(()), + HirType::Constant(_value, kind) => { + if kind.is_error() { + Err(MonomorphizationError::UnknownConstant { location }) + } else { + Ok(()) + } + } HirType::FmtString(_size, fields) => Self::check_type(fields.as_ref(), location), HirType::Array(_length, element) => Self::check_type(element.as_ref(), location), HirType::Slice(element) => Self::check_type(element.as_ref(), location), diff --git a/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs b/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs index f298559e65c..8c00fcde2ef 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs @@ -361,7 +361,16 @@ pub enum ImplSearchErrorKind { #[derive(Default, Debug, Clone)] pub struct Methods { pub direct: Vec, - pub trait_impl_methods: Vec, + pub trait_impl_methods: Vec, +} + +#[derive(Debug, Clone)] +pub struct TraitImplMethod { + // This type is only stored for primitive types to be able to + // select the correct static methods between multiple options keyed + // under TypeMethodKey::FieldOrInt + pub typ: Option, + pub method: FuncId, } /// All the information from a function that is filled out during definition collection rather than @@ -1373,7 +1382,8 @@ impl NodeInterner { Type::Struct(struct_type, _generics) => { let id = struct_type.borrow().id; - if let Some(existing) = self.lookup_method(self_type, id, &method_name, true) { + if let Some(existing) = self.lookup_method(self_type, id, &method_name, true, true) + { return Some(existing); } @@ -1382,7 +1392,7 @@ impl NodeInterner { .or_default() .entry(method_name) .or_default() - .add_method(method_id, is_trait_method); + .add_method(method_id, None, is_trait_method); None } Type::Error => None, @@ -1394,12 +1404,16 @@ impl NodeInterner { let key = get_type_method_key(self_type).unwrap_or_else(|| { unreachable!("Cannot add a method to the unsupported type '{}'", other) }); + // Only remember the actual type if it's FieldOrInt, + // so later we can disambiguate on calls like `u32::call`. + let typ = + if key == TypeMethodKey::FieldOrInt { Some(self_type.clone()) } else { None }; self.primitive_methods .entry(key) .or_default() .entry(method_name) .or_default() - .add_method(method_id, is_trait_method); + .add_method(method_id, typ, is_trait_method); None } } @@ -1770,6 +1784,7 @@ impl NodeInterner { id: StructId, method_name: &str, force_type_check: bool, + has_self_arg: bool, ) -> Option { let methods = self.struct_methods.get(&id).and_then(|h| h.get(method_name)); @@ -1781,7 +1796,7 @@ impl NodeInterner { } } - self.find_matching_method(typ, methods, method_name) + self.find_matching_method(typ, methods, method_name, has_self_arg) } /// Select the 1 matching method with an object type matching `typ` @@ -1790,32 +1805,40 @@ impl NodeInterner { typ: &Type, methods: Option<&Methods>, method_name: &str, + has_self_arg: bool, ) -> Option { - if let Some(method) = methods.and_then(|m| m.find_matching_method(typ, self)) { + if let Some(method) = methods.and_then(|m| m.find_matching_method(typ, has_self_arg, self)) + { Some(method) } else { // Failed to find a match for the type in question, switch to looking at impls // for all types `T`, e.g. `impl Foo for T` let global_methods = self.primitive_methods.get(&TypeMethodKey::Generic)?.get(method_name)?; - global_methods.find_matching_method(typ, self) + global_methods.find_matching_method(typ, has_self_arg, self) } } /// Looks up a given method name on the given primitive type. - pub fn lookup_primitive_method(&self, typ: &Type, method_name: &str) -> Option { + pub fn lookup_primitive_method( + &self, + typ: &Type, + method_name: &str, + has_self_arg: bool, + ) -> Option { let key = get_type_method_key(typ)?; let methods = self.primitive_methods.get(&key)?.get(method_name)?; - self.find_matching_method(typ, Some(methods), method_name) + self.find_matching_method(typ, Some(methods), method_name, has_self_arg) } pub fn lookup_primitive_trait_method_mut( &self, typ: &Type, method_name: &str, + has_self_arg: bool, ) -> Option { let typ = Type::MutableReference(Box::new(typ.clone())); - self.lookup_primitive_method(&typ, method_name) + self.lookup_primitive_method(&typ, method_name, has_self_arg) } /// Returns what the next trait impl id is expected to be. @@ -2236,37 +2259,57 @@ impl Methods { if self.direct.len() == 1 { Some(self.direct[0]) } else if self.direct.is_empty() && self.trait_impl_methods.len() == 1 { - Some(self.trait_impl_methods[0]) + Some(self.trait_impl_methods[0].method) } else { None } } - fn add_method(&mut self, method: FuncId, is_trait_method: bool) { + fn add_method(&mut self, method: FuncId, typ: Option, is_trait_method: bool) { if is_trait_method { - self.trait_impl_methods.push(method); + let trait_impl_method = TraitImplMethod { typ, method }; + self.trait_impl_methods.push(trait_impl_method); } else { self.direct.push(method); } } /// Iterate through each method, starting with the direct methods - pub fn iter(&self) -> impl Iterator + '_ { - self.direct.iter().copied().chain(self.trait_impl_methods.iter().copied()) + pub fn iter(&self) -> impl Iterator)> + '_ { + let trait_impl_methods = self.trait_impl_methods.iter().map(|m| (m.method, &m.typ)); + let direct = self.direct.iter().copied().map(|func_id| { + let typ: &Option = &None; + (func_id, typ) + }); + direct.chain(trait_impl_methods) } /// Select the 1 matching method with an object type matching `typ` - fn find_matching_method(&self, typ: &Type, interner: &NodeInterner) -> Option { + fn find_matching_method( + &self, + typ: &Type, + has_self_param: bool, + interner: &NodeInterner, + ) -> Option { // When adding methods we always check they do not overlap, so there should be // at most 1 matching method in this list. - for method in self.iter() { + for (method, method_type) in self.iter() { match interner.function_meta(&method).typ.instantiate(interner).0 { Type::Function(args, _, _, _) => { - if let Some(object) = args.first() { - let mut bindings = TypeBindings::new(); - - if object.try_unify(typ, &mut bindings).is_ok() { - Type::apply_type_bindings(bindings); + if has_self_param { + if let Some(object) = args.first() { + if object.unify(typ).is_ok() { + return Some(method); + } + } + } else { + // If we recorded the concrete type this trait impl method belongs to, + // and it matches typ, it's an exact match and we return that. + if let Some(method_type) = method_type { + if method_type.unify(typ).is_ok() { + return Some(method); + } + } else { return Some(method); } } @@ -2275,6 +2318,7 @@ impl Methods { other => unreachable!("Expected function type, found {other}"), } } + None } } @@ -2321,7 +2365,7 @@ fn get_type_method_key(typ: &Type) -> Option { // We do not support adding methods to these types Type::TypeVariable(_, _) | Type::Forall(_, _) - | Type::Constant(_) + | Type::Constant(..) | Type::Error | Type::Struct(_, _) | Type::InfixExpr(..) diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/errors.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/errors.rs index 6ba4cb68500..75fe1bf747f 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/errors.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/errors.rs @@ -31,6 +31,8 @@ pub enum ParserErrorReason { ExpectedLeftBracketOrWhereOrLeftBraceOrArrowAfterImplType, #[error("expected <, where or {{ after trait impl for type")] ExpectedLeftBracketOrWhereOrLeftBraceOrArrowAfterTraitImplForType, + #[error("expected ( or < after function name")] + ExpectedLeftParenOrLeftBracketAfterFunctionName, #[error("Expected a ; separating these two statements")] MissingSeparatingSemi, #[error("constrain keyword is deprecated")] @@ -43,8 +45,8 @@ pub enum ParserErrorReason { PatternInTraitFunctionParameter, #[error("Patterns aren't allowed in a trait impl's associated constants")] PatternInAssociatedConstant, - #[error("Modifiers are ignored on a trait impl method")] - TraitImplFunctionModifiers, + #[error("Visibility is ignored on a trait impl method")] + TraitImplVisibilityIgnored, #[error("comptime keyword is deprecated")] ComptimeDeprecated, #[error("{0} are experimental and aren't fully supported yet")] @@ -200,7 +202,7 @@ impl<'a> From<&'a ParserError> for Diagnostic { ParserErrorReason::ExperimentalFeature(_) => { Diagnostic::simple_warning(reason.to_string(), "".into(), error.span) } - ParserErrorReason::TraitImplFunctionModifiers => { + ParserErrorReason::TraitImplVisibilityIgnored => { Diagnostic::simple_warning(reason.to_string(), "".into(), error.span) } ParserErrorReason::ExpectedPatternButFoundType(ty) => Diagnostic::simple_error( diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser.rs index 0ffeb691d35..b007653062b 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser.rs @@ -23,11 +23,15 @@ //! prevent other parsers from being tried afterward since there is no longer an error. Thus, they should //! be limited to cases like the above `fn` example where it is clear we shouldn't back out of the //! current parser to try alternative parsers in a `choice` expression. -use self::path::as_trait_path; -use self::primitives::{keyword, macro_quote_marker, mutable_reference, variable}; +use self::path::{as_trait_path, type_path}; +use self::primitives::{ + interned_statement, interned_statement_expr, keyword, macro_quote_marker, mutable_reference, + variable, +}; use self::types::{generic_type_args, maybe_comp_time}; use attributes::{attributes, inner_attribute, validate_secondary_attributes}; use doc_comments::{inner_doc_comments, outer_doc_comments}; +use types::interned_unresolved_type; pub use types::parse_type; use visibility::item_visibility; pub use visibility::visibility; @@ -461,7 +465,6 @@ where choice(( assertion::constrain(expr_parser.clone()), assertion::assertion(expr_parser.clone()), - assertion::assertion_eq(expr_parser.clone()), declaration(expr_parser.clone()), assignment(expr_parser.clone()), if_statement(expr_no_constructors.clone(), statement.clone()), @@ -511,15 +514,6 @@ where keyword(Keyword::Comptime).ignore_then(comptime_statement).map(StatementKind::Comptime) } -pub(super) fn interned_statement() -> impl NoirParser { - token_kind(TokenKind::InternedStatement).map(|token| match token { - Token::InternedStatement(id) => StatementKind::Interned(id), - _ => { - unreachable!("token_kind(InternedStatement) guarantees we parse an interned statement") - } - }) -} - /// Comptime in an expression position only accepts entire blocks fn comptime_expr<'a, S>(statement: S) -> impl NoirParser + 'a where @@ -1155,8 +1149,10 @@ where variable(), literal(), as_trait_path(parse_type()).map(ExpressionKind::AsTraitPath), + type_path(parse_type()), macro_quote_marker(), interned_expr(), + interned_statement_expr(), )) .map_with_span(Expression::new) .or(parenthesized(expr_parser.clone()).map_with_span(|sub_expr, span| { @@ -1228,7 +1224,11 @@ fn constructor(expr_parser: impl ExprParser) -> impl NoirParser .allow_trailing() .delimited_by(just(Token::LeftBrace), just(Token::RightBrace)); - path(super::parse_type()).then(args).map(ExpressionKind::constructor) + let path = path(super::parse_type()).map(UnresolvedType::from_path); + let interned_unresolved_type = interned_unresolved_type(); + let typ = choice((path, interned_unresolved_type)); + + typ.then(args).map(ExpressionKind::constructor) } fn constructor_field

(expr_parser: P) -> impl NoirParser<(Ident, Expression)> @@ -1621,24 +1621,20 @@ mod test { #[test] fn statement_recovery() { let cases = vec![ - Case { source: "let a = 4 + 3", expect: "let a: unspecified = (4 + 3)", errors: 0 }, + Case { source: "let a = 4 + 3", expect: "let a = (4 + 3)", errors: 0 }, Case { source: "let a: = 4 + 3", expect: "let a: error = (4 + 3)", errors: 1 }, - Case { source: "let = 4 + 3", expect: "let $error: unspecified = (4 + 3)", errors: 1 }, - Case { source: "let = ", expect: "let $error: unspecified = Error", errors: 2 }, - Case { source: "let", expect: "let $error: unspecified = Error", errors: 3 }, + Case { source: "let = 4 + 3", expect: "let $error = (4 + 3)", errors: 1 }, + Case { source: "let = ", expect: "let $error = Error", errors: 2 }, + Case { source: "let", expect: "let $error = Error", errors: 3 }, Case { source: "foo = one two three", expect: "foo = one", errors: 1 }, Case { source: "constrain", expect: "constrain Error", errors: 2 }, - Case { source: "assert", expect: "constrain Error", errors: 1 }, + Case { source: "assert", expect: "assert()", errors: 1 }, Case { source: "constrain x ==", expect: "constrain (x == Error)", errors: 2 }, - Case { source: "assert(x ==)", expect: "constrain (x == Error)", errors: 1 }, - Case { source: "assert(x == x, x)", expect: "constrain (x == x)", errors: 0 }, - Case { source: "assert_eq(x,)", expect: "constrain (Error == Error)", errors: 1 }, - Case { - source: "assert_eq(x, x, x, x)", - expect: "constrain (Error == Error)", - errors: 1, - }, - Case { source: "assert_eq(x, x, x)", expect: "constrain (x == x)", errors: 0 }, + Case { source: "assert(x ==)", expect: "assert((x == Error))", errors: 1 }, + Case { source: "assert(x == x, x)", expect: "assert((x == x), x)", errors: 0 }, + Case { source: "assert_eq(x,)", expect: "assert_eq(x)", errors: 0 }, + Case { source: "assert_eq(x, x, x, x)", expect: "assert_eq(x, x, x, x)", errors: 0 }, + Case { source: "assert_eq(x, x, x)", expect: "assert_eq(x, x, x)", errors: 0 }, ]; check_cases_with_errors(&cases[..], fresh_statement()); @@ -1659,7 +1655,7 @@ mod test { }, Case { source: "{ return 123; let foo = 4 + 3; }", - expect: concat!("{\n", " Error\n", " let foo: unspecified = (4 + 3)\n", "}"), + expect: concat!("{\n", " Error\n", " let foo = (4 + 3)\n", "}"), errors: 1, }, Case { @@ -1709,7 +1705,7 @@ mod test { expect: concat!( "{\n", " if ({\n", - " let foo: unspecified = (bar { baz: 42 })\n", + " let foo = (bar { baz: 42 })\n", " (foo == (bar { baz: 42 }))\n", " }) {\n", " }\n", diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser.rs:28:9 b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser.rs:28:9 deleted file mode 100644 index 47dfb32b53b..00000000000 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser.rs:28:9 +++ /dev/null @@ -1,45 +0,0 @@ -[?1049h[?1h[?2004h[?2026$p[?u[?12h[?25h[?25l(B[38:2:235:219:178m[48:2:168:153:132m [No Name]  (B[38:2:168:153:132m(B[38:2:235:219:178m (B[38:2:80:73:69m(B[38:2:168:153:132m[48:2:80:73:69m buffers -(B[38:2:124:111:100m 1 (B[38:2:235:219:178m -(B[38:2:80:73:69m~ -~ -~ -~ -~ -~ -~ -~ -~ -~ -~ -~ -~ -~ -~ -~ -~ -~ -~ -~ -(B[38:2:235:219:178m[48:2:168:153:132m (B[38:2:235:219:178m[48:2:168:153:132mNORMAL(B[38:2:235:219:178m[48:2:168:153:132m (B[38:2:168:153:132m[48:2:80:73:69m  jf/quoted-as-type (B[38:2:80:73:69m[48:2:60:56:54m(B[38:2:168:153:132m[48:2:60:56:54m (B[38:2:60:56:54m[48:2:60:56:54m(B[38:2:168:153:132m[48:2:60:56:54m  (B[38:2:80:73:69m[48:2:60:56:54m(B[38:2:168:153:132m[48:2:80:73:69m(B[38:2:235:219:178m[48:2:168:153:132m 100% (B[38:2:235:219:178m[48:2:168:153:132m☰ 0/1 (B[38:2:235:219:178m[48:2:168:153:132m : 1 (B[38:2:254:128:25m[48:2:168:153:132m(B[38:2:235:219:178mNVIM v0.10.0Nvim is open source and freely distributablehttps://neovim.io/#chattype :help nvim(B[38:2:80:73:69m(B[38:2:235:219:178m if you are new! type :checkhealth(B[38:2:80:73:69m(B[38:2:235:219:178m to optimize Nvimtype :q(B[38:2:80:73:69m(B[38:2:235:219:178m to exit type :help(B[38:2:80:73:69m(B[38:2:235:219:178m for help type :help news(B[38:2:80:73:69m(B[38:2:235:219:178m to see changes in v0.10Help poor children in Uganda!type :help iccf(B[38:2:80:73:69m(B[38:2:235:219:178m for information ]112[2 q]112[2 q[?1002h[?1006h(B[38:2:235:219:178m[48:2:168:153:132m [No Name]  (B[38:2:168:153:132m(B[38:2:235:219:178m (B[38:2:80:73:69m(B[38:2:168:153:132m[48:2:80:73:69m buffers -(B[38:2:124:111:100m 1 (B[38:2:235:219:178m -(B[38:2:80:73:69m~ -~ -~ (B[38:2:235:219:178mNVIM v0.10.0(B[38:2:80:73:69m -~ -~ (B[38:2:235:219:178mNvim is open source and freely distributable(B[38:2:80:73:69m -~ (B[38:2:235:219:178mhttps://neovim.io/#chat(B[38:2:80:73:69m -~ -~ (B[38:2:235:219:178mtype :help nvim(B[38:2:80:73:69m(B[38:2:235:219:178m if you are new! (B[38:2:80:73:69m -~ (B[38:2:235:219:178mtype :checkhealth(B[38:2:80:73:69m(B[38:2:235:219:178m to optimize Nvim(B[38:2:80:73:69m -~ (B[38:2:235:219:178mtype :q(B[38:2:80:73:69m(B[38:2:235:219:178m to exit (B[38:2:80:73:69m -~ (B[38:2:235:219:178mtype :help(B[38:2:80:73:69m(B[38:2:235:219:178m for help (B[38:2:80:73:69m -~ -~ (B[38:2:235:219:178mtype :help news(B[38:2:80:73:69m(B[38:2:235:219:178m to see changes in v0.10(B[38:2:80:73:69m -~ -~ (B[38:2:235:219:178mHelp poor children in Uganda!(B[38:2:80:73:69m -~ (B[38:2:235:219:178mtype :help iccf(B[38:2:80:73:69m(B[38:2:235:219:178m for information (B[38:2:80:73:69m -~ -~ -~ -~ -(B[38:2:235:219:178m[48:2:168:153:132m (B[38:2:235:219:178m[48:2:168:153:132mNORMAL(B[38:2:235:219:178m[48:2:168:153:132m (B[38:2:168:153:132m[48:2:80:73:69m  jf/quoted-as-type (B[38:2:80:73:69m[48:2:60:56:54m(B[38:2:168:153:132m[48:2:60:56:54m (B[38:2:60:56:54m[48:2:60:56:54m(B[38:2:168:153:132m[48:2:60:56:54m  (B[38:2:80:73:69m[48:2:60:56:54m(B[38:2:168:153:132m[48:2:80:73:69m(B[38:2:235:219:178m[48:2:168:153:132m 100% (B[38:2:235:219:178m[48:2:168:153:132m☰ 0/1 (B[38:2:235:219:178m[48:2:168:153:132m : 1 (B[38:2:254:128:25m[48:2:168:153:132m(B[38:2:235:219:178m[?12h[?25h[?25l[?1004h[?12h[?25h \ No newline at end of file diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/assertion.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/assertion.rs index ed08a4c9922..9eb429ef295 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/assertion.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/assertion.rs @@ -1,14 +1,11 @@ -use crate::ast::{Expression, ExpressionKind, StatementKind}; -use crate::parser::{ - ignore_then_commit, labels::ParsingRuleLabel, parenthesized, ExprParser, NoirParser, - ParserError, ParserErrorReason, -}; +use crate::ast::StatementKind; +use crate::parser::{ignore_then_commit, then_commit, ParserError, ParserErrorReason}; +use crate::parser::{labels::ParsingRuleLabel, parenthesized, ExprParser, NoirParser}; -use crate::ast::{BinaryOpKind, ConstrainKind, ConstrainStatement, InfixExpression, Recoverable}; +use crate::ast::{ConstrainKind, ConstrainStatement}; use crate::token::{Keyword, Token}; use chumsky::prelude::*; -use noirc_errors::Spanned; use super::keyword; @@ -20,7 +17,13 @@ where keyword(Keyword::Constrain).labelled(ParsingRuleLabel::Statement), expr_parser, ) - .map(|expr| StatementKind::Constrain(ConstrainStatement(expr, None, ConstrainKind::Constrain))) + .map_with_span(|expr, span| { + StatementKind::Constrain(ConstrainStatement { + kind: ConstrainKind::Constrain, + arguments: vec![expr], + span, + }) + }) .validate(|expr, span, emit| { emit(ParserError::with_reason(ParserErrorReason::ConstrainDeprecated, span)); expr @@ -31,42 +34,17 @@ pub(super) fn assertion<'a, P>(expr_parser: P) -> impl NoirParser where P: ExprParser + 'a, { - let argument_parser = - expr_parser.separated_by(just(Token::Comma)).allow_trailing().at_least(1).at_most(2); - - ignore_then_commit(keyword(Keyword::Assert), parenthesized(argument_parser)) - .labelled(ParsingRuleLabel::Statement) - .validate(|expressions, span, _| { - let condition = expressions.first().unwrap_or(&Expression::error(span)).clone(); - let message = expressions.get(1).cloned(); - StatementKind::Constrain(ConstrainStatement(condition, message, ConstrainKind::Assert)) - }) -} + let keyword = choice(( + keyword(Keyword::Assert).map(|_| ConstrainKind::Assert), + keyword(Keyword::AssertEq).map(|_| ConstrainKind::AssertEq), + )); -pub(super) fn assertion_eq<'a, P>(expr_parser: P) -> impl NoirParser + 'a -where - P: ExprParser + 'a, -{ - let argument_parser = - expr_parser.separated_by(just(Token::Comma)).allow_trailing().at_least(2).at_most(3); + let argument_parser = expr_parser.separated_by(just(Token::Comma)).allow_trailing(); - ignore_then_commit(keyword(Keyword::AssertEq), parenthesized(argument_parser)) + then_commit(keyword, parenthesized(argument_parser)) .labelled(ParsingRuleLabel::Statement) - .validate(|exprs: Vec, span, _| { - let predicate = Expression::new( - ExpressionKind::Infix(Box::new(InfixExpression { - lhs: exprs.first().unwrap_or(&Expression::error(span)).clone(), - rhs: exprs.get(1).unwrap_or(&Expression::error(span)).clone(), - operator: Spanned::from(span, BinaryOpKind::Equal), - })), - span, - ); - let message = exprs.get(2).cloned(); - StatementKind::Constrain(ConstrainStatement( - predicate, - message, - ConstrainKind::AssertEq, - )) + .map_with_span(|(kind, arguments), span| { + StatementKind::Constrain(ConstrainStatement { arguments, kind, span }) }) } @@ -74,7 +52,7 @@ where mod test { use super::*; use crate::{ - ast::Literal, + ast::{BinaryOpKind, ExpressionKind, Literal}, parser::parser::{ expression, test_helpers::{parse_all, parse_all_failing, parse_with}, @@ -174,11 +152,11 @@ mod test { match parse_with(assertion(expression()), "assert(x == y, \"assertion message\")").unwrap() { - StatementKind::Constrain(ConstrainStatement(_, message, _)) => { - let message = message.unwrap(); - match message.kind { + StatementKind::Constrain(ConstrainStatement { arguments, .. }) => { + let message = arguments.last().unwrap(); + match &message.kind { ExpressionKind::Literal(Literal::Str(message_string)) => { - assert_eq!(message_string, "assertion message".to_owned()); + assert_eq!(message_string, "assertion message"); } _ => unreachable!(), } @@ -191,7 +169,7 @@ mod test { #[test] fn parse_assert_eq() { parse_all( - assertion_eq(expression()), + assertion(expression()), vec![ "assert_eq(x, y)", "assert_eq(((x + y) == k) + z, y)", @@ -201,14 +179,13 @@ mod test { "assert_eq(x + x ^ x, y | m)", ], ); - match parse_with(assertion_eq(expression()), "assert_eq(x, y, \"assertion message\")") - .unwrap() + match parse_with(assertion(expression()), "assert_eq(x, y, \"assertion message\")").unwrap() { - StatementKind::Constrain(ConstrainStatement(_, message, _)) => { - let message = message.unwrap(); - match message.kind { + StatementKind::Constrain(ConstrainStatement { arguments, .. }) => { + let message = arguments.last().unwrap(); + match &message.kind { ExpressionKind::Literal(Literal::Str(message_string)) => { - assert_eq!(message_string, "assertion message".to_owned()); + assert_eq!(message_string, "assertion message"); } _ => unreachable!(), } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/function.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/function.rs index 05138bfffd9..dc8b968ea7a 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/function.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/function.rs @@ -48,37 +48,73 @@ pub(super) fn function_definition(allow_self: bool) -> impl NoirParser impl NoirParser<(bool, ItemVisibility, bool)> { +pub(super) fn function_modifiers() -> impl NoirParser<(bool, ItemVisibility, bool)> { keyword(Keyword::Unconstrained).or_not().then(item_visibility()).then(maybe_comp_time()).map( |((unconstrained, visibility), comptime)| (unconstrained.is_some(), visibility, comptime), ) diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/path.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/path.rs index ea121c6f6db..1c9c24f5376 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/path.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/path.rs @@ -1,13 +1,15 @@ -use crate::ast::{AsTraitPath, Path, PathKind, PathSegment, UnresolvedType}; +use crate::ast::{AsTraitPath, Ident, Path, PathKind, PathSegment, TypePath, UnresolvedType}; +use crate::macros_api::ExpressionKind; use crate::parser::{NoirParser, ParserError, ParserErrorReason}; use crate::token::{Keyword, Token}; use chumsky::prelude::*; +use noirc_errors::Span; use super::keyword; -use super::primitives::{ident, path_segment, path_segment_no_turbofish}; -use super::types::generic_type_args; +use super::primitives::{ident, path_segment, path_segment_no_turbofish, turbofish}; +use super::types::{generic_type_args, primitive_type}; pub(super) fn path<'a>( type_parser: impl NoirParser + 'a, @@ -68,6 +70,32 @@ pub(super) fn as_trait_path<'a>( }) } +/// Parses `MyType::path_segment` +/// These paths only support exactly two segments. +/// Unlike normal paths `MyType` here can also be a primitive type or interned type +/// in addition to a named type. +pub(super) fn type_path<'a>( + type_parser: impl NoirParser + 'a, +) -> impl NoirParser + 'a { + primitive_type() + .then_ignore(just(Token::DoubleColon)) + .then(ident().or_not()) + .then(turbofish(type_parser)) + .validate(|((typ, item), turbofish), span, emit| { + let turbofish = turbofish.unwrap_or_default(); + let item = if let Some(item) = item { + item + } else { + emit(ParserError::with_reason( + ParserErrorReason::ExpectedIdentifierAfterColons, + span, + )); + Ident::new(String::new(), Span::from(span.end()..span.end())) + }; + ExpressionKind::TypePath(TypePath { typ, item, turbofish }) + }) +} + fn empty_path() -> impl NoirParser { let make_path = |kind| move |_, span| Path { segments: Vec::new(), kind, span }; let path_kind = |key, kind| keyword(key).map_with_span(make_path(kind)); diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/primitives.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/primitives.rs index c1516e2c927..7fcca89f70c 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/primitives.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/primitives.rs @@ -1,7 +1,7 @@ use chumsky::prelude::*; use crate::ast::{ExpressionKind, GenericTypeArgs, Ident, PathSegment, UnaryOp}; -use crate::macros_api::UnresolvedType; +use crate::macros_api::{StatementKind, UnresolvedType}; use crate::parser::ParserErrorReason; use crate::{ parser::{labels::ParsingRuleLabel, ExprParser, NoirParser, ParserError}, @@ -126,6 +126,26 @@ pub(super) fn interned_expr() -> impl NoirParser { }) } +pub(super) fn interned_statement() -> impl NoirParser { + token_kind(TokenKind::InternedStatement).map(|token| match token { + Token::InternedStatement(id) => StatementKind::Interned(id), + _ => { + unreachable!("token_kind(InternedStatement) guarantees we parse an interned statement") + } + }) +} + +// This rule is so that we can re-parse StatementKind::Expression and Semi in +// an expression position (ignoring the semicolon) if needed. +pub(super) fn interned_statement_expr() -> impl NoirParser { + token_kind(TokenKind::InternedStatement).map(|token| match token { + Token::InternedStatement(id) => ExpressionKind::InternedStatement(id), + _ => { + unreachable!("token_kind(InternedStatement) guarantees we parse an interned statement") + } + }) +} + #[cfg(test)] mod test { use crate::parser::parser::{ diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/structs.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/structs.rs index 66d30a6f407..729f276e9b8 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/structs.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/structs.rs @@ -1,6 +1,7 @@ use chumsky::prelude::*; use crate::ast::{Documented, NoirStruct, StructField}; +use crate::parser::parser::visibility::item_visibility; use crate::{ parser::{ parser::{ @@ -30,13 +31,21 @@ pub(super) fn struct_definition() -> impl NoirParser { .or(just(Semicolon).to(Vec::new())); attributes() + .then(item_visibility()) .then_ignore(keyword(Struct)) .then(ident()) .then(function::generics()) .then(fields) - .validate(|(((attributes, name), generics), fields), span, emit| { + .validate(|((((attributes, visibility), name), generics), fields), span, emit| { let attributes = validate_secondary_attributes(attributes, span, emit); - TopLevelStatementKind::Struct(NoirStruct { name, attributes, generics, fields, span }) + TopLevelStatementKind::Struct(NoirStruct { + name, + attributes, + visibility, + generics, + fields, + span, + }) }) } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/traits.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/traits.rs index 58db2465f22..b95319f6da0 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/traits.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/traits.rs @@ -2,8 +2,9 @@ use chumsky::prelude::*; use super::attributes::{attributes, validate_secondary_attributes}; use super::doc_comments::outer_doc_comments; -use super::function::function_return_type; +use super::function::{function_modifiers, function_return_type}; use super::path::path_no_turbofish; +use super::visibility::item_visibility; use super::{ block, expression, fresh_statement, function, function_declaration_parameters, let_statement, }; @@ -42,22 +43,26 @@ pub(super) fn trait_definition() -> impl NoirParser { }); attributes() + .then(item_visibility()) .then_ignore(keyword(Keyword::Trait)) .then(ident()) .then(function::generics()) .then(where_clause()) .then(trait_body_or_error) - .validate(|((((attributes, name), generics), where_clause), items), span, emit| { - let attributes = validate_secondary_attributes(attributes, span, emit); - TopLevelStatementKind::Trait(NoirTrait { - name, - generics, - where_clause, - span, - items, - attributes, - }) - }) + .validate( + |(((((attributes, visibility), name), generics), where_clause), items), span, emit| { + let attributes = validate_secondary_attributes(attributes, span, emit); + TopLevelStatementKind::Trait(NoirTrait { + name, + generics, + where_clause, + span, + items, + attributes, + visibility, + }) + }, + ) } fn trait_body() -> impl NoirParser>> { @@ -101,16 +106,29 @@ fn trait_function_declaration() -> impl NoirParser { } }); - keyword(Keyword::Fn) - .ignore_then(ident()) + function_modifiers() + .then_ignore(keyword(Keyword::Fn)) + .then(ident()) .then(function::generics()) .then(parenthesized(function_declaration_parameters())) .then(function_return_type().map(|(_, typ)| typ)) .then(where_clause()) .then(trait_function_body_or_semicolon_or_error) - .map(|(((((name, generics), parameters), return_type), where_clause), body)| { - TraitItem::Function { name, generics, parameters, return_type, where_clause, body } - }) + .map( + |((((((modifiers, name), generics), parameters), return_type), where_clause), body)| { + TraitItem::Function { + name, + generics, + parameters, + return_type, + where_clause, + body, + is_unconstrained: modifiers.0, + visibility: modifiers.1, + is_comptime: modifiers.2, + } + }, + ) } /// trait_type_declaration: 'type' ident generics @@ -169,8 +187,8 @@ pub(super) fn trait_implementation() -> impl NoirParser { fn trait_implementation_body() -> impl NoirParser>> { let function = function::function_definition(true).validate(|mut f, span, emit| { - if f.def().is_unconstrained || f.def().visibility != ItemVisibility::Private { - emit(ParserError::with_reason(ParserErrorReason::TraitImplFunctionModifiers, span)); + if f.def().visibility != ItemVisibility::Private { + emit(ParserError::with_reason(ParserErrorReason::TraitImplVisibilityIgnored, span)); } // Trait impl functions are always public f.def_mut().visibility = ItemVisibility::Public; diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/types.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/types.rs index 9dabb8b83b6..9dd41d1a288 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/types.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/types.rs @@ -24,12 +24,7 @@ pub(super) fn parse_type_inner<'a>( recursive_type_parser: impl NoirParser + 'a, ) -> impl NoirParser + 'a { choice(( - field_type(), - int_type(), - bool_type(), - string_type(), - comptime_type(), - resolved_type(), + primitive_type(), format_string_type(recursive_type_parser.clone()), named_type(recursive_type_parser.clone()), named_trait(recursive_type_parser.clone()), @@ -40,6 +35,17 @@ pub(super) fn parse_type_inner<'a>( function_type(recursive_type_parser.clone()), mutable_reference_type(recursive_type_parser.clone()), as_trait_path_type(recursive_type_parser), + )) +} + +pub(super) fn primitive_type() -> impl NoirParser { + choice(( + field_type(), + int_type(), + bool_type(), + string_type(), + comptime_type(), + resolved_type(), interned_unresolved_type(), )) } @@ -89,6 +95,7 @@ pub(super) fn comptime_type() -> impl NoirParser { top_level_item_type(), quoted_type(), typed_expr_type(), + comptime_string_type(), )) } @@ -166,6 +173,12 @@ fn typed_expr_type() -> impl NoirParser { .map_with_span(|_, span| UnresolvedTypeData::Quoted(QuotedType::TypedExpr).with_span(span)) } +/// This is the `CtString` type for dynamically-sized compile-time strings +fn comptime_string_type() -> impl NoirParser { + keyword(Keyword::CtString) + .map_with_span(|_, span| UnresolvedTypeData::Quoted(QuotedType::CtString).with_span(span)) +} + /// This is the type of an already resolved type. /// The only way this can appear in the token input is if an already resolved `Type` object /// was spliced into a macro's token stream via the `$` operator. diff --git a/noir/noir-repo/compiler/noirc_frontend/src/tests.rs b/noir/noir-repo/compiler/noirc_frontend/src/tests.rs index 414bfa5fa5b..dc54fd624e4 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/tests.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/tests.rs @@ -14,6 +14,7 @@ use fm::FileId; use iter_extended::vecmap; use noirc_errors::Location; +use crate::ast::IntegerBitSize; use crate::hir::comptime::InterpreterError; use crate::hir::def_collector::dc_crate::CompilationError; use crate::hir::def_collector::errors::{DefCollectorErrorKind, DuplicateType}; @@ -514,7 +515,7 @@ fn check_trait_wrong_parameter2() { #[test] fn check_trait_wrong_parameter_type() { let src = " - trait Default { + pub trait Default { fn default(x: Field, y: NotAType) -> Field; } @@ -1296,8 +1297,8 @@ fn type_aliases_in_entry_point() { #[test] fn operators_in_global_used_in_type() { let src = r#" - global ONE = 1; - global COUNT = ONE + 2; + global ONE: u32 = 1; + global COUNT: u32 = ONE + 2; fn main() { let _array: [Field; COUNT] = [1, 2, 3]; } @@ -1337,7 +1338,7 @@ fn break_and_continue_outside_loop() { #[test] fn for_loop_over_array() { let src = r#" - fn hello(_array: [u1; N]) { + fn hello(_array: [u1; N]) { for _ in 0..N {} } @@ -1347,12 +1348,7 @@ fn for_loop_over_array() { } "#; let errors = get_program_errors(src); - assert_eq!(get_program_errors(src).len(), 1); - - assert!(matches!( - errors[0].0, - CompilationError::ResolverError(ResolverError::UseExplicitNumericGeneric { .. }) - )); + assert_eq!(errors.len(), 0); } // Regression for #4545 @@ -1565,11 +1561,11 @@ fn struct_numeric_generic_in_function() { #[test] fn struct_numeric_generic_in_struct() { let src = r#" - struct Foo { + pub struct Foo { inner: u64 } - struct Bar { } + pub struct Bar { } "#; let errors = get_program_errors(src); assert_eq!(errors.len(), 1); @@ -1620,25 +1616,30 @@ fn numeric_generic_binary_operation_type_mismatch() { #[test] fn bool_generic_as_loop_bound() { let src = r#" - pub fn read() { - let mut fields = [0; N]; - for i in 0..N { + pub fn read() { // error here + let mut fields = [0; N]; // error here + for i in 0..N { // error here fields[i] = i + 1; } assert(fields[0] == 1); } "#; let errors = get_program_errors(src); - assert_eq!(errors.len(), 2); + assert_eq!(errors.len(), 3); assert!(matches!( errors[0].0, CompilationError::ResolverError(ResolverError::UnsupportedNumericGenericType { .. }), )); + assert!(matches!( + errors[1].0, + CompilationError::TypeError(TypeCheckError::TypeKindMismatch { .. }), + )); + let CompilationError::TypeError(TypeCheckError::TypeMismatch { expected_typ, expr_typ, .. - }) = &errors[1].0 + }) = &errors[2].0 else { panic!("Got an error other than a type mismatch"); }; @@ -1650,15 +1651,15 @@ fn bool_generic_as_loop_bound() { #[test] fn numeric_generic_in_function_signature() { let src = r#" - pub fn foo(arr: [Field; N]) -> [Field; N] { arr } + pub fn foo(arr: [Field; N]) -> [Field; N] { arr } "#; assert_no_errors(src); } #[test] -fn numeric_generic_as_struct_field_type() { +fn numeric_generic_as_struct_field_type_fails() { let src = r#" - struct Foo { + pub struct Foo { a: Field, b: N, } @@ -1667,25 +1668,23 @@ fn numeric_generic_as_struct_field_type() { assert_eq!(errors.len(), 1); assert!(matches!( errors[0].0, - CompilationError::ResolverError(ResolverError::NumericGenericUsedForType { .. }), + CompilationError::TypeError(TypeCheckError::TypeKindMismatch { .. }), )); } #[test] fn normal_generic_as_array_length() { let src = r#" - struct Foo { + pub struct Foo { a: Field, b: [Field; N], } "#; let errors = get_program_errors(src); assert_eq!(errors.len(), 1); - // TODO(https://github.com/noir-lang/noir/issues/5156): This should be switched to a hard type error rather than - // the `UseExplicitNumericGeneric` once implicit numeric generics are removed. assert!(matches!( errors[0].0, - CompilationError::ResolverError(ResolverError::UseExplicitNumericGeneric { .. }), + CompilationError::TypeError(TypeCheckError::TypeKindMismatch { .. }), )); } @@ -1699,31 +1698,32 @@ fn numeric_generic_as_param_type() { "#; let errors = get_program_errors(src); assert_eq!(errors.len(), 3); + // Error from the parameter type assert!(matches!( errors[0].0, - CompilationError::ResolverError(ResolverError::NumericGenericUsedForType { .. }), + CompilationError::TypeError(TypeCheckError::TypeKindMismatch { .. }), )); // Error from the let statement annotated type assert!(matches!( errors[1].0, - CompilationError::ResolverError(ResolverError::NumericGenericUsedForType { .. }), + CompilationError::TypeError(TypeCheckError::TypeKindMismatch { .. }), )); // Error from the return type assert!(matches!( errors[2].0, - CompilationError::ResolverError(ResolverError::NumericGenericUsedForType { .. }), + CompilationError::TypeError(TypeCheckError::TypeKindMismatch { .. }), )); } #[test] -fn numeric_generic_used_in_nested_type_fail() { +fn numeric_generic_used_in_nested_type_fails() { let src = r#" - struct Foo { + pub struct Foo { a: Field, b: Bar, } - struct Bar { + struct Bar { inner: N } "#; @@ -1731,24 +1731,27 @@ fn numeric_generic_used_in_nested_type_fail() { assert_eq!(errors.len(), 1); assert!(matches!( errors[0].0, - CompilationError::ResolverError(ResolverError::NumericGenericUsedForType { .. }), + CompilationError::TypeError(TypeCheckError::TypeKindMismatch { .. }), )); } #[test] fn normal_generic_used_in_nested_array_length_fail() { let src = r#" - struct Foo { + pub struct Foo { a: Field, b: Bar, } - struct Bar { + pub struct Bar { inner: [Field; N] } "#; let errors = get_program_errors(src); - // TODO(https://github.com/noir-lang/noir/issues/5156): This should be switched to a hard type error once implicit numeric generics are removed. - assert_eq!(errors.len(), 0); + assert_eq!(errors.len(), 1); + assert!(matches!( + errors[0].0, + CompilationError::TypeError(TypeCheckError::TypeKindMismatch { .. }), + )); } #[test] @@ -1756,11 +1759,11 @@ fn numeric_generic_used_in_nested_type_pass() { // The order of these structs should not be changed to make sure // that we are accurately resolving all struct generics before struct fields let src = r#" - struct NestedNumeric { + pub struct NestedNumeric { a: Field, b: InnerNumeric } - struct InnerNumeric { + pub struct InnerNumeric { inner: [u64; N], } "#; @@ -1894,7 +1897,7 @@ fn normal_generic_used_when_numeric_expected_in_where_clause() { assert_eq!(errors.len(), 1); assert!(matches!( errors[0].0, - CompilationError::TypeError(TypeCheckError::TypeMismatch { .. }), + CompilationError::TypeError(TypeCheckError::TypeKindMismatch { .. }), )); let src = r#" @@ -1911,26 +1914,65 @@ fn normal_generic_used_when_numeric_expected_in_where_clause() { } "#; let errors = get_program_errors(src); - assert_eq!(errors.len(), 1); + assert_eq!(errors.len(), 4); assert!(matches!( errors[0].0, + CompilationError::TypeError(TypeCheckError::TypeKindMismatch { .. }), + )); + assert!(matches!( + errors[1].0, + CompilationError::TypeError(TypeCheckError::TypeKindMismatch { .. }), + )); + assert!(matches!( + errors[2].0, + CompilationError::TypeError(TypeCheckError::TypeKindMismatch { .. }), + )); + // N + assert!(matches!( + errors[3].0, CompilationError::ResolverError(ResolverError::VariableNotDeclared { .. }), )); } -// TODO(https://github.com/noir-lang/noir/issues/5156): Remove this test once we ban implicit numeric generics #[test] -fn implicit_numeric_generics_elaborator() { +fn numeric_generics_type_kind_mismatch() { + let src = r#" + fn foo() -> u16 { + N as u16 + } + + global J: u16 = 10; + + fn bar() -> u16 { + foo::() + } + + global M: u16 = 3; + + fn main() { + let _ = bar::(); + } + "#; + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); + assert!(matches!( + errors[0].0, + CompilationError::TypeError(TypeCheckError::TypeKindMismatch { .. }), + )); +} + +#[test] +fn numeric_generics_value_kind_mismatch_u32_u64() { let src = r#" - struct BoundedVec { + struct BoundedVec { storage: [T; MaxLen], + // can't be compared to MaxLen: u32 + // can't be used to index self.storage len: u64, } - - impl BoundedVec { - // Test that we have an implicit numeric generic for "Len" as well as "MaxLen" - pub fn extend_from_bounded_vec(&mut self, _vec: BoundedVec) { + impl BoundedVec { + pub fn extend_from_bounded_vec(&mut self, _vec: BoundedVec) { // We do this to avoid an unused variable warning on `self` let _ = self.len; for _ in 0..Len { } @@ -1944,17 +1986,15 @@ fn implicit_numeric_generics_elaborator() { } "#; let errors = get_program_errors(src); - assert_eq!(errors.len(), 4); - - for error in errors.iter() { - if let CompilationError::ResolverError(ResolverError::UseExplicitNumericGeneric { ident }) = - &errors[0].0 - { - assert!(matches!(ident.0.contents.as_str(), "MaxLen" | "Len")); - } else { - panic!("Expected ResolverError::UseExplicitNumericGeneric but got {:?}", error); - } - } + assert_eq!(errors.len(), 1); + assert!(matches!( + errors[0].0, + CompilationError::TypeError(TypeCheckError::IntegerBitWidth { + bit_width_x: IntegerBitSize::SixtyFour, + bit_width_y: IntegerBitSize::ThirtyTwo, + .. + }), + )); } #[test] @@ -2721,7 +2761,7 @@ fn bit_not_on_untyped_integer() { #[test] fn duplicate_struct_field() { let src = r#" - struct Foo { + pub struct Foo { x: i32, x: i32, } @@ -2742,8 +2782,8 @@ fn duplicate_struct_field() { assert_eq!(first_def.to_string(), "x"); assert_eq!(second_def.to_string(), "x"); - assert_eq!(first_def.span().start(), 26); - assert_eq!(second_def.span().start(), 42); + assert_eq!(first_def.span().start(), 30); + assert_eq!(second_def.span().start(), 46); } #[test] @@ -2996,11 +3036,11 @@ fn uses_self_type_inside_trait() { #[test] fn uses_self_type_in_trait_where_clause() { let src = r#" - trait Trait { + pub trait Trait { fn trait_func() -> bool; } - trait Foo where Self: Trait { + pub trait Foo where Self: Trait { fn foo(self) -> bool { self.trait_func() } @@ -3222,7 +3262,7 @@ fn errors_on_unused_private_import() { pub fn bar() {} pub fn baz() {} - trait Foo { + pub trait Foo { } } @@ -3258,7 +3298,7 @@ fn errors_on_unused_pub_crate_import() { pub fn bar() {} pub fn baz() {} - trait Foo { + pub trait Foo { } } @@ -3423,6 +3463,58 @@ fn errors_on_unused_function() { assert_eq!(*item_type, "function"); } +#[test] +fn errors_on_unused_struct() { + let src = r#" + struct Foo {} + struct Bar {} + + fn main() { + let _ = Bar {}; + } + "#; + + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); + + let CompilationError::ResolverError(ResolverError::UnusedItem { ident, item_type }) = + &errors[0].0 + else { + panic!("Expected an unused item error"); + }; + + assert_eq!(ident.to_string(), "Foo"); + assert_eq!(*item_type, "struct"); +} + +#[test] +fn errors_on_unused_trait() { + let src = r#" + trait Foo {} + trait Bar {} + + pub struct Baz { + } + + impl Bar for Baz {} + + fn main() { + } + "#; + + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); + + let CompilationError::ResolverError(ResolverError::UnusedItem { ident, item_type }) = + &errors[0].0 + else { + panic!("Expected an unused item error"); + }; + + assert_eq!(ident.to_string(), "Foo"); + assert_eq!(*item_type, "trait"); +} + #[test] fn constrained_reference_to_unconstrained() { let src = r#" @@ -3462,3 +3554,197 @@ fn comptime_type_in_runtime_code() { CompilationError::ResolverError(ResolverError::ComptimeTypeInRuntimeCode { .. }) )); } + +#[test] +fn arithmetic_generics_canonicalization_deduplication_regression() { + let source = r#" + struct ArrData { + a: [Field; N], + b: [Field; N + N - 1], + } + + fn main() { + let _f: ArrData<5> = ArrData { + a: [0; 5], + b: [0; 9], + }; + } + "#; + let errors = get_program_errors(source); + assert_eq!(errors.len(), 0); +} + +#[test] +fn cannot_mutate_immutable_variable() { + let src = r#" + fn main() { + let array = [1]; + mutate(&mut array); + } + + fn mutate(_: &mut [Field; 1]) {} + "#; + + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); + + let CompilationError::TypeError(TypeCheckError::CannotMutateImmutableVariable { name, .. }) = + &errors[0].0 + else { + panic!("Expected a CannotMutateImmutableVariable error"); + }; + + assert_eq!(name, "array"); +} + +#[test] +fn cannot_mutate_immutable_variable_on_member_access() { + let src = r#" + struct Foo { + x: Field + } + + fn main() { + let foo = Foo { x: 0 }; + mutate(&mut foo.x); + } + + fn mutate(foo: &mut Field) { + *foo = 1; + } + "#; + + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); + + let CompilationError::TypeError(TypeCheckError::CannotMutateImmutableVariable { name, .. }) = + &errors[0].0 + else { + panic!("Expected a CannotMutateImmutableVariable error"); + }; + + assert_eq!(name, "foo"); +} + +#[test] +fn does_not_crash_when_passing_mutable_undefined_variable() { + let src = r#" + fn main() { + mutate(&mut undefined); + } + + fn mutate(foo: &mut Field) { + *foo = 1; + } + "#; + + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); + + let CompilationError::ResolverError(ResolverError::VariableNotDeclared { name, .. }) = + &errors[0].0 + else { + panic!("Expected a VariableNotDeclared error"); + }; + + assert_eq!(name, "undefined"); +} + +#[test] +fn infer_globals_to_u32_from_type_use() { + let src = r#" + global ARRAY_LEN = 3; + global STR_LEN = 2; + global FMT_STR_LEN = 2; + + fn main() { + let _a: [u32; ARRAY_LEN] = [1, 2, 3]; + let _b: str = "hi"; + let _c: fmtstr = f"hi"; + } + "#; + + let errors = get_program_errors(src); + assert_eq!(errors.len(), 0); +} + +#[test] +fn non_u32_in_array_length() { + let src = r#" + global ARRAY_LEN: u8 = 3; + + fn main() { + let _a: [u32; ARRAY_LEN] = [1, 2, 3]; + } + "#; + + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); + + assert!(matches!( + errors[0].0, + CompilationError::TypeError(TypeCheckError::TypeKindMismatch { .. }) + )); +} + +#[test] +fn use_non_u32_generic_in_struct() { + let src = r#" + struct S {} + + fn main() { + let _: S<3> = S {}; + } + "#; + + let errors = get_program_errors(src); + assert_eq!(errors.len(), 0); +} + +#[test] +fn use_numeric_generic_in_trait_method() { + let src = r#" + trait Foo { + fn foo(self, x: [u8; N]) -> Self; + } + + struct Bar; + + impl Foo for Bar { + fn foo(self, _x: [u8; N]) -> Self { + self + } + } + + fn main() { + let _ = Bar{}.foo([1,2,3]); + } + "#; + + let errors = get_program_errors(src); + println!("{errors:?}"); + assert_eq!(errors.len(), 0); +} + +#[test] +fn macro_result_type_mismatch() { + let src = r#" + fn main() { + comptime { + let x = unquote!(quote { "test" }); + let _: Field = x; + } + } + + comptime fn unquote(q: Quoted) -> Quoted { + q + } + "#; + + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); + assert!(matches!( + errors[0].0, + CompilationError::TypeError(TypeCheckError::TypeMismatch { .. }) + )); +} diff --git a/noir/noir-repo/compiler/noirc_frontend/src/usage_tracker.rs b/noir/noir-repo/compiler/noirc_frontend/src/usage_tracker.rs index 836f9824436..b6f41dc72f2 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/usage_tracker.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/usage_tracker.rs @@ -3,13 +3,16 @@ use std::collections::HashMap; use crate::{ ast::{Ident, ItemVisibility}, hir::def_map::ModuleId, - node_interner::FuncId, + macros_api::StructId, + node_interner::{FuncId, TraitId}, }; #[derive(Debug)] pub enum UnusedItem { Import, Function(FuncId), + Struct(StructId), + Trait(TraitId), } impl UnusedItem { @@ -17,6 +20,8 @@ impl UnusedItem { match self { UnusedItem::Import => "import", UnusedItem::Function(_) => "function", + UnusedItem::Struct(_) => "struct", + UnusedItem::Trait(_) => "trait", } } } diff --git a/noir/noir-repo/compiler/wasm/package.json b/noir/noir-repo/compiler/wasm/package.json index 5abe5dd4c2f..e20abe5f4ff 100644 --- a/noir/noir-repo/compiler/wasm/package.json +++ b/noir/noir-repo/compiler/wasm/package.json @@ -3,7 +3,7 @@ "contributors": [ "The Noir Team " ], - "version": "0.33.0", + "version": "0.34.0", "license": "(MIT OR Apache-2.0)", "main": "dist/main.js", "types": "./dist/types/src/index.d.cts", diff --git a/noir/noir-repo/cspell.json b/noir/noir-repo/cspell.json index 4d83c535e7d..3ace51689fb 100644 --- a/noir/noir-repo/cspell.json +++ b/noir/noir-repo/cspell.json @@ -56,6 +56,7 @@ "cranelift", "critesjosh", "csat", + "ctstring", "curvegroup", "databus", "debouncer", diff --git a/noir/noir-repo/docs/docs/noir/concepts/comptime.md b/noir/noir-repo/docs/docs/noir/concepts/comptime.md index ba078c763d0..cea3a896c17 100644 --- a/noir/noir-repo/docs/docs/noir/concepts/comptime.md +++ b/noir/noir-repo/docs/docs/noir/concepts/comptime.md @@ -238,6 +238,17 @@ The following is an incomplete list of some `comptime` types along with some use There are many more functions available by exploring the `std::meta` module and its submodules. Using these methods is the key to writing powerful metaprogramming libraries. +## `#[use_callers_scope]` + +Since certain functions such as `Quoted::as_type`, `Expression::as_type`, or `Quoted::as_trait_constraint` will attempt +to resolve their contents in a particular scope - it can be useful to change the scope they resolve in. By default +these functions will resolve in the current function's scope which is usually the attribute function they are called in. +If you're working on a library however, this may be a completely different module or crate to the item you're trying to +use the attribute on. If you want to be able to use `Quoted::as_type` to refer to types local to the caller's scope for +example, you can annotate your attribute function with `#[use_callers_scope]`. This will ensure your attribute, and any +closures it uses, can refer to anything in the caller's scope. `#[use_callers_scope]` also works recursively. So if both +your attribute function and a helper function it calls use it, then they can both refer to the same original caller. + --- # Example: Derive diff --git a/noir/noir-repo/docs/docs/noir/concepts/data_types/arrays.md b/noir/noir-repo/docs/docs/noir/concepts/data_types/arrays.md index d0d8eb70aa6..bb68e60fe53 100644 --- a/noir/noir-repo/docs/docs/noir/concepts/data_types/arrays.md +++ b/noir/noir-repo/docs/docs/noir/concepts/data_types/arrays.md @@ -251,7 +251,6 @@ fn main() { let any = arr.any(|a| a == 5); assert(any); } - ``` ### as_str_unchecked diff --git a/noir/noir-repo/docs/docs/noir/concepts/data_types/slices.mdx b/noir/noir-repo/docs/docs/noir/concepts/data_types/slices.mdx index a0c87c29259..cfee564a302 100644 --- a/noir/noir-repo/docs/docs/noir/concepts/data_types/slices.mdx +++ b/noir/noir-repo/docs/docs/noir/concepts/data_types/slices.mdx @@ -175,7 +175,7 @@ Make sure to specify the size of the resulting array. Panics if the resulting array length is different than the slice's length. ```rust -fn as_array(self) -> [T; N] +fn as_array(self) -> [T; N] ``` Example: diff --git a/noir/noir-repo/docs/docs/noir/concepts/data_types/structs.md b/noir/noir-repo/docs/docs/noir/concepts/data_types/structs.md index dbf68c99813..e529347f27d 100644 --- a/noir/noir-repo/docs/docs/noir/concepts/data_types/structs.md +++ b/noir/noir-repo/docs/docs/noir/concepts/data_types/structs.md @@ -68,3 +68,15 @@ fn get_octopus() -> Animal { The new variables can be bound with names different from the original struct field names, as showcased in the `legs --> feet` binding in the example above. + +By default, like functions, structs are private to the module the exist in. You can use `pub` +to make the struct public or `pub(crate)` to make it public to just its crate: + +```rust +// This struct is now public +pub struct Animal { + hands: Field, + legs: Field, + eyes: u8, +} +``` \ No newline at end of file diff --git a/noir/noir-repo/docs/docs/noir/concepts/generics.md b/noir/noir-repo/docs/docs/noir/concepts/generics.md index 6dbde4ed53b..8925666aa20 100644 --- a/noir/noir-repo/docs/docs/noir/concepts/generics.md +++ b/noir/noir-repo/docs/docs/noir/concepts/generics.md @@ -18,6 +18,32 @@ fn id(x: T) -> T { } ``` +## Numeric Generics + +If we want to be generic over array lengths (which are type-level integers), we can use numeric +generics. Using these looks similar to using regular generics, but introducing them into scope +requires declaring them with `let MyGenericName: IntegerType`. This can be done anywhere a normal +generic is declared. Instead of types, these generics resolve to integers at compile-time. +Here's an example of a struct that is generic over the size of the array it contains internally: + +```rust +struct BigInt { + limbs: [u32; N], +} + +impl BigInt { + // `N` is in scope of all methods in the impl + fn first(first: BigInt, second: BigInt) -> Self { + assert(first.limbs != second.limbs); + first + + fn second(first: BigInt, second: Self) -> Self { + assert(first.limbs != second.limbs); + second + } +} +``` + ## In Structs Generics are useful for specifying types in structs. For example, we can specify that a field in a @@ -45,32 +71,6 @@ fn main() { The `print` function will print `Hello!` an arbitrary number of times, twice in this case. -## Numeric Generics - -If we want to be generic over array lengths (which are type-level integers), we can use numeric -generics. Using these looks similar to using regular generics, but introducing them into scope -requires declaring them with `let MyGenericName: IntegerType`. This can be done anywhere a normal -generic is declared. Instead of types, these generics resolve to integers at compile-time. -Here's an example of a struct that is generic over the size of the array it contains internally: - -```rust -struct BigInt { - limbs: [u32; N], -} - -impl BigInt { - // `N` is in scope of all methods in the impl - fn first(first: BigInt, second: BigInt) -> Self { - assert(first.limbs != second.limbs); - first - - fn second(first: BigInt, second: Self) -> Self { - assert(first.limbs != second.limbs); - second - } -} -``` - ## Calling functions on generic parameters Since a generic type `T` can represent any type, how can we call functions on the underlying type? @@ -125,15 +125,8 @@ fn main() { let array = slice.as_array::<2>(); } ``` -```rust -fn double() -> u32 { - N * 2 -} -fn example() { - assert(double::<9>() == 18); - assert(double::<7 + 8>() == 30); -} -``` + + ```rust trait MyTrait { fn ten() -> Self; diff --git a/noir/noir-repo/docs/docs/noir/concepts/globals.md b/noir/noir-repo/docs/docs/noir/concepts/globals.md index 063a3d89248..97a92a86e72 100644 --- a/noir/noir-repo/docs/docs/noir/concepts/globals.md +++ b/noir/noir-repo/docs/docs/noir/concepts/globals.md @@ -37,7 +37,7 @@ global T = foo(T); // dependency error If they are initialized to a literal integer, globals can be used to specify an array's length: ```rust -global N: Field = 2; +global N: u32 = 2; fn main(y : [Field; N]) { assert(y[0] == y[1]) diff --git a/noir/noir-repo/docs/docs/noir/concepts/traits.md b/noir/noir-repo/docs/docs/noir/concepts/traits.md index 597c62c737c..5d07e0c68f0 100644 --- a/noir/noir-repo/docs/docs/noir/concepts/traits.md +++ b/noir/noir-repo/docs/docs/noir/concepts/traits.md @@ -153,7 +153,7 @@ will implement `Foo` only for types that also implement `Bar`. This is often use For example, here is the implementation for array equality: ```rust -impl Eq for [T; N] where T: Eq { +impl Eq for [T; let N: u32] where T: Eq { // Test if two arrays have the same elements. // Because both arrays must have length N, we know their lengths already match. fn eq(self, other: Self) -> bool { @@ -463,3 +463,13 @@ impl Default for Wrapper { Since we have an impl for our own type, the behavior of this code will not change even if `some_library` is updated to provide its own `impl Default for Foo`. The downside of this pattern is that it requires extra wrapping and unwrapping of values when converting to and from the `Wrapper` and `Foo` types. + +### Visibility + +By default, like functions, traits are private to the module the exist in. You can use `pub` +to make the trait public or `pub(crate)` to make it public to just its crate: + +```rust +// This trait is now public +pub trait Trait {} +``` \ No newline at end of file diff --git a/noir/noir-repo/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx b/noir/noir-repo/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx index 6ff47a77df9..d2a8204bccb 100644 --- a/noir/noir-repo/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx +++ b/noir/noir-repo/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx @@ -144,7 +144,7 @@ fn mimc(x: Field, k: Field, constants: [Field; N], exp : Field) -> Field otherwise, use the `mimc_bn254` method: ```rust -fn mimc_bn254(array: [Field; N]) -> Field +fn mimc_bn254(array: [Field; N]) -> Field ``` example: diff --git a/noir/noir-repo/docs/docs/noir/standard_library/meta/ctstring.md b/noir/noir-repo/docs/docs/noir/standard_library/meta/ctstring.md new file mode 100644 index 00000000000..30c257120a3 --- /dev/null +++ b/noir/noir-repo/docs/docs/noir/standard_library/meta/ctstring.md @@ -0,0 +1,71 @@ +--- +title: CtString +--- + +`std::meta::ctstring` contains methods on the built-in `CtString` type which is +a compile-time, dynamically-sized string type. Compared to `str` and `fmtstr`, +`CtString` is useful because its size does not need to be specified in its type. This +can be used for formatting items at compile-time or general string handling in `comptime` +code. + +Since `fmtstr`s can be converted into `CtString`s, you can make use of their formatting +abilities in CtStrings by formatting in `fmtstr`s then converting the result to a CtString +afterward. + +## Traits + +### AsCtString + +#include_code as-ctstring noir_stdlib/src/meta/ctstring.nr rust + +Converts an object into a compile-time string. + +Implementations: + +```rust +impl AsCtString for str { ... } +impl AsCtString for fmtstr { ... } +``` + +## Methods + +### new + +#include_code new noir_stdlib/src/meta/ctstring.nr rust + +Creates an empty `CtString`. + +### append_str + +#include_code append_str noir_stdlib/src/meta/ctstring.nr rust + +Returns a new CtString with the given str appended onto the end. + +### append_fmtstr + +#include_code append_fmtstr noir_stdlib/src/meta/ctstring.nr rust + +Returns a new CtString with the given fmtstr appended onto the end. + +### as_quoted_str + +#include_code as_quoted_str noir_stdlib/src/meta/ctstring.nr rust + +Returns a quoted string literal from this string's contents. + +There is no direct conversion from a `CtString` to a `str` since +the size would not be known. To get around this, this function can +be used in combination with macro insertion (`!`) to insert this string +literal at this function's call site. + +Example: + +#include_code as_quoted_str_example noir_stdlib/src/meta/ctstring.nr rust + +## Trait Implementations + +```rust +impl Eq for CtString +impl Hash for CtString +impl Append for CtString +``` diff --git a/noir/noir-repo/docs/docs/noir/standard_library/meta/expr.md b/noir/noir-repo/docs/docs/noir/standard_library/meta/expr.md index 7ee33027354..4e2d09102b5 100644 --- a/noir/noir-repo/docs/docs/noir/standard_library/meta/expr.md +++ b/noir/noir-repo/docs/docs/noir/standard_library/meta/expr.md @@ -52,6 +52,13 @@ a slice containing each statement. If this expression is a boolean literal, return that literal. +### as_cast + +#include_code as_cast noir_stdlib/src/meta/expr.nr rust + +If this expression is a cast expression (`expr as type`), returns the casted +expression and the type to cast to. + ### as_comptime #include_code as_comptime noir_stdlib/src/meta/expr.nr rust @@ -59,6 +66,27 @@ If this expression is a boolean literal, return that literal. If this expression is a `comptime { stmt1; stmt2; ...; stmtN }` block, return each statement in the block. +### as_constructor + +#include_code as_constructor noir_stdlib/src/meta/expr.nr rust + +If this expression is a constructor `Type { field1: expr1, ..., fieldN: exprN }`, +return the type and the fields. + +### as_for + +#include_code as_for noir_stdlib/src/meta/expr.nr rust + +If this expression is a for statement over a single expression, return the identifier, +the expression and the for loop body. + +### as_for_range + +#include_code as_for noir_stdlib/src/meta/expr.nr rust + +If this expression is a for statement over a range, return the identifier, +the range start, the range end and the for loop body. + ### as_function_call #include_code as_function_call noir_stdlib/src/meta/expr.nr rust @@ -88,6 +116,12 @@ array and the index. If this expression is an integer literal, return the integer as a field as well as whether the integer is negative (true) or not (false). +### as_lambda + +#include_code as_lambda noir_stdlib/src/meta/expr.nr rust + +If this expression is a lambda, returns the parameters, return type and body. + ### as_let #include_code as_let noir_stdlib/src/meta/expr.nr rust diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/examples/merkle-proof.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/examples/merkle-proof.mdx deleted file mode 100644 index 6430780817c..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/examples/merkle-proof.mdx +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Merkle Proof Membership -description: - Learn how to use merkle membership proof in Noir to prove that a given leaf is a member of a - merkle tree with a specified root, at a given index. -keywords: - [merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree] ---- - -Let's walk through an example of a merkle membership proof in Noir that proves that a given leaf is -in a merkle tree. - -```rust -use dep::std; - -fn main(message : [Field; 62], index : Field, hashpath : [Field; 40], root : Field) { - let leaf = std::hash::hash_to_field(message); - let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); - assert(merkle_root == root); -} - -``` - -The message is hashed using `hash_to_field`. The specific hash function that is being used is chosen -by the backend. The only requirement is that this hash function can heuristically be used as a -random oracle. If only collision resistance is needed, then one can call `std::hash::pedersen` -instead. - -```rust -let leaf = std::hash::hash_to_field(message); -``` - -The leaf is then passed to a compute_merkle_root function with the root, index and hashpath. The returned root can then be asserted to be the same as the provided root. - -```rust -let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); -assert (merkle_root == root); -``` - -> **Note:** It is possible to re-implement the merkle tree implementation without standard library. -> However, for most usecases, it is enough. In general, the standard library will always opt to be -> as conservative as possible, while striking a balance with efficiency. - -An example, the merkle membership proof, only requires a hash function that has collision -resistance, hence a hash function like Pedersen is allowed, which in most cases is more efficient -than the even more conservative sha256. - -[View an example on the starter repo](https://github.com/noir-lang/noir-examples/blob/3ea09545cabfa464124ec2f3ea8e60c608abe6df/stealthdrop/circuits/src/main.nr#L20) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/getting_started/00_nargo_installation.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/getting_started/00_nargo_installation.md deleted file mode 100644 index 0de5597c213..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/getting_started/00_nargo_installation.md +++ /dev/null @@ -1,249 +0,0 @@ ---- -title: Nargo Installation -description: - nargo is a command line tool for interacting with Noir programs (e.g. compiling, proving, - verifying and more). Learn how to install and use Nargo for your projects with this comprehensive - guide. -keywords: [Nargo, command line tool, Noir programs, installation guide, how to use Nargo] ---- - -`nargo` is a command line tool for interacting with Noir programs (e.g. compiling, proving, -verifying and more). - -Alternatively, the interactions can also be performed in [NoirJS](../noir_js/noir_js.md). - -### UltraPlonk - -Nargo versions \<0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk -version of Aztec Backend, which lacks efficient implementations of useful primitives (e.g. Keccak256 in 18k constraints, ECDSA verification in 36k constraints) that the UltraPlonk version offers. - -## Installation - -There are four approaches for installing Nargo: - -- [Option 1: Noirup](#option-1-noirup) -- [Option 2: Binaries](#option-2-binaries) -- [Option 3: Compile from Source](#option-3-compile-from-source) -- [Option 4: WSL for Windows](#option-4-wsl-for-windows) - -Optionally you can also install [Noir VS Code extension] for syntax highlighting. - -### Option 1: Noirup - -If you're on OSX or Linux, the easiest way to start using Noir and Nargo is via noirup. Just open a -terminal and run: - -```bash -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -Close the terminal, open another one, and run - -```bash -noirup -``` - -Done, you should have the latest version working. You can check with `nargo --version`. - -You can also install nightlies, specific versions -or branches, check out the [noirup repository](https://github.com/noir-lang/noirup) for more -information. - -#### GitHub Actions - -You can use `noirup` with GitHub Actions for CI/CD and automated testing. It is as simple as -installing `noirup` and running tests in your GitHub Action `yml` file. - -See the -[config file](https://github.com/TomAFrench/noir-hashes/blob/master/.github/workflows/noir.yml) in -this repo containing hash functions in Noir for an example. - -#### Nightly versions - -To install the nightly version of Noir (updated daily) run: - -```bash -noirup -n -``` - -### Option 2: Binaries - -See [GitHub Releases](https://github.com/noir-lang/noir/releases) for the latest and previous -platform specific binaries. - -#### Step 1 - -Paste and run the following in the terminal to extract and install the binary: - -> **macOS / Linux:** If you are prompted with `Permission denied` when running commands, prepend -> `sudo` and re-run it. - -##### macOS (Apple Silicon) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-aarch64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### macOS (Intel) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### Linux (Bash) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-unknown-linux-gnu.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -C $HOME/.nargo/bin/ && \ -echo -e '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.bashrc && \ -source ~/.bashrc -``` - -#### Step 2 - -Check if the installation was successful by running `nargo --help`. - -> **macOS:** If you are prompted with an OS alert, right-click and open the _nargo_ executable from -> Finder. Close the new terminal popped up and `nargo` should now be accessible. - -For a successful installation, you should see something similar to the following after running the -command: - -```sh -$ nargo --help - -Noir's package manager - -Usage: nargo - -Commands: - check Checks the constraint system for errors - codegen-verifier Generates a Solidity verifier smart contract for the program - compile Compile the program and its secret execution trace into ACIR format - new Create a new binary project - execute Executes a circuit to calculate its return value - prove Create proof for this program. The proof is returned as a hex encoded string - verify Given a proof and a program, verify whether the proof is valid - test Run the tests for this program - gates Counts the occurrences of different gates in circuit - help Print this message or the help of the given subcommand(s) -``` - -### Option 3: Compile from Source - -Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. It helps mitigating issues commonly associated with dependency management, such as conflicts between required package versions for different projects (often referred to as "dependency hell"). - -Combined with direnv, which automatically sets or clears environment variables based on the directory, it further simplifies the development process by seamlessly integrating with the developer's shell, facilitating an efficient and reliable workflow for managing and deploying Noir projects with multiple dependencies. - -#### Setting up your environment - -For the best experience, please follow these instructions to setup your environment: - -1. Install Nix following [their guide](https://nixos.org/download.html) for your operating system. -2. Create the file `~/.config/nix/nix.conf` with the contents: - -```ini -experimental-features = nix-command -extra-experimental-features = flakes -``` - -3. Install direnv into your Nix profile by running: - -```sh -nix profile install nixpkgs#direnv -``` - -4. Add direnv to your shell following [their guide](https://direnv.net/docs/hook.html). - 1. For bash or zshell, add `eval "$(direnv hook bash)"` or `eval "$(direnv hook zsh)"` to your ~/.bashrc or ~/.zshrc file, respectively. -5. Restart your shell. - -#### Shell & editor experience - -Now that your environment is set up, you can get to work on the project. - -1. Clone the repository, such as: - -```sh -git clone git@github.com:noir-lang/noir -``` - -> Replacing `noir` with whichever repository you want to work on. - -2. Navigate to the directory: - -```sh -cd noir -``` - -> Replacing `noir` with whichever repository you cloned. - -3. You should see a **direnv error** because projects aren't allowed by default. Make sure you've reviewed and trust our `.envrc` file, then you need to run: - -```sh -direnv allow -``` - -4. Now, wait awhile for all the native dependencies to be built. This will take some time and direnv will warn you that it is taking a long time, but we just need to let it run. - -5. Once you are presented with your prompt again, you can start your editor within the project directory (we recommend [VSCode](https://code.visualstudio.com/)): - -```sh -code . -``` - -6. (Recommended) When launching VSCode for the first time, you should be prompted to install our recommended plugins. We highly recommend installing these for the best development experience. - -#### Building and testing - -Assuming you are using `direnv` to populate your environment, building and testing the project can be done -with the typical `cargo build`, `cargo test`, and `cargo clippy` commands. You'll notice that the `cargo` version matches the version we specify in `flake.nix`, which is 1.66.0 at the time of this writing. - -If you want to build the entire project in an isolated sandbox, you can use Nix commands: - -1. `nix build .` (or `nix build . -L` for verbose output) to build the project in a Nix sandbox. -2. `nix flake check` (or `nix flake check -L` for verbose output) to run clippy and tests in a Nix sandbox. - -#### Without `direnv` - -If you have hesitations with using direnv, you can launch a subshell with `nix develop` and then launch your editor from within the subshell. However, if VSCode was already launched in the project directory, the environment won't be updated. - -Advanced: If you aren't using direnv nor launching your editor within the subshell, you can try to install Barretenberg and other global dependencies the package needs. This is an advanced workflow and likely won't receive support! - -### Option 4: WSL (for Windows) - -Windows is not directly supported at this time. To install Noir on a Windows machine, it is recommended to use WSL. - -Step 1: Follow the instructions [here](https://learn.microsoft.com/en-us/windows/wsl/install) to install and run WSL. - -step 2: Follow the [Noirup instructions](#option-1-noirup). - -## Uninstalling Nargo - -### Noirup - -If you installed Noir with `noirup`, you can uninstall Noir by removing the files in `~/.nargo`, `~/nargo` and `~/noir_cache`. - -```bash -rm -r ~/.nargo -rm -r ~/nargo -rm -r ~/noir_cache -``` - -### Nix - -If you installed Noir with Nix or from source, you can remove the binary located at `~/.nix-profile/bin/nargo`. - -```bash -rm ~/.nix-profile/bin/nargo -``` - -[noir vs code extension]: https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/getting_started/01_hello_world.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/getting_started/01_hello_world.md deleted file mode 100644 index 34f8cd96fcd..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/getting_started/01_hello_world.md +++ /dev/null @@ -1,147 +0,0 @@ ---- -title: Create A Project -description: - Learn how to create and verify your first Noir program using Nargo, a programming language for - zero-knowledge proofs. -keywords: - [ - Nargo, - Noir, - zero-knowledge proofs, - programming language, - create Noir program, - verify Noir program, - step-by-step guide, - ] ---- - -Now that we have installed Nargo, it is time to make our first hello world program! - -## Create a Project Directory - -Noir code can live anywhere on your computer. Let us create a _projects_ folder in the home -directory to house our Noir programs. - -For Linux, macOS, and Windows PowerShell, create the directory and change directory into it by -running: - -```sh -mkdir ~/projects -cd ~/projects -``` - -For Windows CMD, run: - -```sh -> mkdir "%USERPROFILE%\projects" -> cd /d "%USERPROFILE%\projects" -``` - -## Create Our First Nargo Project - -Now that we are in the projects directory, create a new Nargo project by running: - -```sh -nargo new hello_world -``` - -> **Note:** `hello_world` can be any arbitrary project name, we are simply using `hello_world` for -> demonstration. -> -> In production, the common practice is to name the project folder as `circuits` for better -> identifiability when sitting alongside other folders in the codebase (e.g. `contracts`, `scripts`, -> `test`). - -A `hello_world` folder would be created. Similar to Rust, the folder houses _src/main.nr_ and -_Nargo.toml_ that contains the source code and environmental options of your Noir program -respectively. - -### Intro to Noir Syntax - -Let us take a closer look at _main.nr_. The default _main.nr_ generated should look like this: - -```rust -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` - -The first line of the program specifies the program's inputs: - -```rust -x : Field, y : pub Field -``` - -Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the -keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](../language_concepts/data_types.md) section. - -The next line of the program specifies its body: - -```rust -assert(x != y); -``` - -The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. - -For more Noir syntax, check the [Language Concepts](../language_concepts/comments.md) chapter. - -## Build In/Output Files - -Change directory into _hello_world_ and build in/output files for your Noir program by running: - -```sh -cd hello_world -nargo check -``` - -Two additional files would be generated in your project directory: - -_Prover.toml_ houses input values, and _Verifier.toml_ houses public values. - -## Prove Our Noir Program - -Now that the project is set up, we can create a proof of correct execution on our Noir program. - -Fill in input values for execution in the _Prover.toml_ file. For example: - -```toml -x = "1" -y = "2" -``` - -Prove the valid execution of your Noir program: - -```sh -nargo prove -``` - -A new folder _proofs_ would then be generated in your project directory, containing the proof file -`.proof`, where the project name is defined in Nargo.toml. - -The _Verifier.toml_ file would also be updated with the public values computed from program -execution (in this case the value of `y`): - -```toml -y = "0x0000000000000000000000000000000000000000000000000000000000000002" -``` - -> **Note:** Values in _Verifier.toml_ are computed as 32-byte hex values. - -## Verify Our Noir Program - -Once a proof is generated, we can verify correct execution of our Noir program by verifying the -proof file. - -Verify your proof by running: - -```sh -nargo verify -``` - -The verification will complete in silence if it is successful. If it fails, it will log the -corresponding error instead. - -Congratulations, you have now created and verified a proof for your very first Noir program! - -In the [next section](./02_breakdown.md), we will go into more detail on each step performed. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/getting_started/02_breakdown.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/getting_started/02_breakdown.md deleted file mode 100644 index 8616feee917..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/getting_started/02_breakdown.md +++ /dev/null @@ -1,198 +0,0 @@ ---- -title: Project Breakdown -description: - Learn about the anatomy of a Nargo project, including the purpose of the Prover and Verifier TOML - files, and how to prove and verify your program. -keywords: - [Nargo, Nargo project, Prover.toml, Verifier.toml, proof verification, private asset transfer] ---- - -This section breaks down our hello world program in section _1.2_. We elaborate on the project -structure and what the `prove` and `verify` commands did in the previous section. - -## Anatomy of a Nargo Project - -Upon creating a new project with `nargo new` and building the in/output files with `nargo check` -commands, you would get a minimal Nargo project of the following structure: - - - src - - Prover.toml - - Verifier.toml - - Nargo.toml - -The source directory _src_ holds the source code for your Noir program. By default only a _main.nr_ -file will be generated within it. - -### Prover.toml - -_Prover.toml_ is used for specifying the input values for executing and proving the program. You can specify `toml` files with different names by using the `--prover-name` or `-p` flags, see the [Prover](#provertoml) section below. Optionally you may specify expected output values for prove-time checking as well. - -### Verifier.toml - -_Verifier.toml_ contains public in/output values computed when executing the Noir program. - -### Nargo.toml - -_Nargo.toml_ contains the environmental options of your project. It contains a "package" section and a "dependencies" section. - -Example Nargo.toml: - -```toml -[package] -name = "noir_starter" -type = "bin" -authors = ["Alice"] -compiler_version = "0.9.0" -description = "Getting started with Noir" -entry = "circuit/main.nr" -license = "MIT" - -[dependencies] -ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} -``` - -Nargo.toml for a [workspace](../modules_packages_crates/workspaces.md) will look a bit different. For example: - -```toml -[workspace] -members = ["crates/a", "crates/b"] -default-member = "crates/a" -``` - -#### Package section - -The package section requires a number of fields including: - -- `name` (**required**) - the name of the package -- `type` (**required**) - can be "bin", "lib", or "contract" to specify whether its a binary, library or Aztec contract -- `authors` (optional) - authors of the project -- `compiler_version` (optional) - specifies the version of the compiler to use. This is not currently enforced by the compiler, but will be in future versions. -- `description` (optional) -- `entry` (optional) - a relative filepath to use as the entry point into your package (overrides the default of `src/lib.nr` or `src/main.nr`) -- `backend` (optional) -- `license` (optional) - -#### Dependencies section - -This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies.md)for more info. - -`./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or -verifier contract respectively. - -### main.nr - -The _main.nr_ file contains a `main` method, this method is the entry point into your Noir program. - -In our sample program, _main.nr_ looks like this: - -```rust -fn main(x : Field, y : Field) { - assert(x != y); -} -``` - -The parameters `x` and `y` can be seen as the API for the program and must be supplied by the -prover. Since neither `x` nor `y` is marked as public, the verifier does not supply any inputs, when -verifying the proof. - -The prover supplies the values for `x` and `y` in the _Prover.toml_ file. - -As for the program body, `assert` ensures the satisfaction of the condition (e.g. `x != y`) is -constrained by the proof of the execution of said program (i.e. if the condition was not met, the -verifier would reject the proof as an invalid proof). - -### Prover.toml - -The _Prover.toml_ file is a file which the prover uses to supply his witness values(both private and -public). - -In our hello world program the _Prover.toml_ file looks like this: - -```toml -x = "1" -y = "2" -``` - -When the command `nargo prove` is executed, two processes happen: - -1. Noir creates a proof that `x` which holds the value of `1` and `y` which holds the value of `2` - is not equal. This not equal constraint is due to the line `assert(x != y)`. - -2. Noir creates and stores the proof of this statement in the _proofs_ directory in a file called your-project.proof. So if your project is named "private_voting" (defined in the project Nargo.toml), the proof will be saved at `./proofs/private_voting.proof`. Opening this file will display the proof in hex format. - -#### Arrays of Structs - -The following code shows how to pass an array of structs to a Noir program to generate a proof. - -```rust -// main.nr -struct Foo { - bar: Field, - baz: Field, -} - -fn main(foos: [Foo; 3]) -> pub Field { - foos[2].bar + foos[2].baz -} -``` - -Prover.toml: - -```toml -[[foos]] # foos[0] -bar = 0 -baz = 0 - -[[foos]] # foos[1] -bar = 0 -baz = 0 - -[[foos]] # foos[2] -bar = 1 -baz = 2 -``` - -#### Custom toml files - -You can specify a `toml` file with a different name to use for proving by using the `--prover-name` or `-p` flags. - -This command looks for proof inputs in the default **Prover.toml** and generates the proof and saves it at `./proofs/.proof`: - -```bash -nargo prove -``` - -This command looks for proof inputs in the custom **OtherProver.toml** and generates proof and saves it at `./proofs/.proof`: - -```bash -nargo prove -p OtherProver -``` - -## Verifying a Proof - -When the command `nargo verify` is executed, two processes happen: - -1. Noir checks in the _proofs_ directory for a proof file with the project name (eg. test_project.proof) - -2. If that file is found, the proof's validity is checked - -> **Note:** The validity of the proof is linked to the current Noir program; if the program is -> changed and the verifier verifies the proof, it will fail because the proof is not valid for the -> _modified_ Noir program. - -In production, the prover and the verifier are usually two separate entities. A prover would -retrieve the necessary inputs, execute the Noir program, generate a proof and pass it to the -verifier. The verifier would then retrieve the public inputs from usually external sources and -verifies the validity of the proof against it. - -Take a private asset transfer as an example: - -A user on browser as the prover would retrieve private inputs (e.g. the user's private key) and -public inputs (e.g. the user's encrypted balance on-chain), compute the transfer, generate a proof -and submit it to the verifier smart contract. - -The verifier contract would then draw the user's encrypted balance directly from the blockchain and -verify the proof submitted against it. If the verification passes, additional functions in the -verifier contract could trigger (e.g. approve the asset transfer). - -Now that you understand the concepts, you'll probably want some editor feedback while you are writing more complex code. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/index.md deleted file mode 100644 index c88aabf0ac1..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/index.md +++ /dev/null @@ -1,99 +0,0 @@ ---- -title: Introducing Noir -description: - Learn about the public alpha release of Noir, a domain specific language heavily influenced by - Rust that compiles to an intermediate language which can be compiled to an arithmetic circuit or a - rank-1 constraint system. -keywords: - [ - Noir, - Domain Specific Language, - Rust, - Intermediate Language, - Arithmetic Circuit, - Rank-1 Constraint System, - Ethereum Developers, - Protocol Developers, - Blockchain Developers, - Proving System, - Smart Contract Language, - ] -slug: / ---- - -## What is Noir? - -Noir is a Domain Specific Language for SNARK proving systems. It has been designed to use any ACIR compatible proving system. - -Its design choices are influenced heavily by Rust and focuses on a simple, familiar syntax. - -## Who is Noir for? - -Noir can be used for a variety of purposes. - -### Solidity Developers - -Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will -be modularized in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands.md#nargo-codegen-verifier) command to create -a verifier contract. - -### Protocol Developers - -As a protocol developer, you may not want to use the Aztec backend due to it not being a fit for -your stack, or maybe you simply want to use a different proving system. Since Noir does not compile -to a specific proof system, it is possible for protocol developers to replace the PLONK-based -proving system with a different proving system altogether. - -### Blockchain developers - -As a blockchain developer, you will be constrained by parameters set by your blockchain (for example, the -proving system and smart contract language has been pre-defined). In order for you to use Noir in -your blockchain, a proving system backend and a smart contract interface -must be implemented for it. - -## What's new about Noir? - -Noir is simple and flexible in its design, as it does not compile immediately to a fixed -NP-complete language. Instead, Noir compiles to an intermediate language (ACIR), which itself can be compiled -to an arithmetic circuit (if choosing to target Aztec's barretenberg backend) or a rank-1 constraint system (if choosing to target an R1CS backend like Arkworks' Marlin backend, or others). - -This in itself brings up a few challenges within the design process, but allows one to decouple the programming language completely from the backend. This is similar in theory to LLVM. - -## Current Features - -Compiler: - -- Module System -- For expressions -- Arrays -- Bit Operations -- Binary operations (\<, \<=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] -- Unsigned integers -- If statements -- Structures and Tuples -- Generics - -ACIR Supported OPCODES: - -- Sha256 -- Blake2s -- Schnorr signature verification -- MerkleMembership -- Pedersen -- HashToField - -## Libraries - -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). - -Some libraries that are available today include: - -- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library -- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) -- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers -- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address -- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees -- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir -- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers - -See the section on [dependencies](./modules_packages_crates/dependencies.md) for more information. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/01_functions.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/01_functions.md deleted file mode 100644 index 5eb22170e54..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/01_functions.md +++ /dev/null @@ -1,225 +0,0 @@ ---- -title: Functions -description: - Learn how to declare functions and methods in Noir, a programming language with Rust semantics. - This guide covers parameter declaration, return types, call expressions, and more. -keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] ---- - -Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. - -To declare a function the `fn` keyword is used. - -```rust -fn foo() {} -``` - -By default, functions are visible only within the package they are defined. To make them visible outside of that package (for example, as part of a [library](../modules_packages_crates/crates_and_packages.md#libraries)), you should mark them as `pub`: - -```rust -pub fn foo() {} -``` - -You can also restrict the visibility of the function to only the crate it was defined in, by specifying `pub(crate)`: - -```rust -pub(crate) fn foo() {} //foo can only be called within its crate -``` - -All parameters in a function must have a type and all types are known at compile time. The parameter -is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. - -```rust -fn foo(x : Field, y : Field){} -``` - -The return type of a function can be stated by using the `->` arrow notation. The function below -states that the foo function must return a `Field`. If the function returns no value, then the arrow -is omitted. - -```rust -fn foo(x : Field, y : Field) -> Field { - x + y -} -``` - -Note that a `return` keyword is unneeded in this case - the last expression in a function's body is -returned. - -## Main function - -If you're writing a binary, the `main` function is the starting point of your program. You can pass all types of expressions to it, as long as they have a fixed size at compile time: - -```rust -fn main(x : Field) // this is fine: passing a Field -fn main(x : [Field; 2]) // this is also fine: passing a Field with known size at compile-time -fn main(x : (Field, bool)) // 👌: passing a (Field, bool) tuple means size 2 -fn main(x : str<5>) // this is fine, as long as you pass a string of size 5 - -fn main(x : Vec) // can't compile, has variable size -fn main(x : [Field]) // can't compile, has variable size -fn main(....// i think you got it by now -``` - -Keep in mind [tests](../nargo/02_testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: - -```rust -fn main(x : [Field]) { - assert(x[0] == 1); -} - -#[test] -fn test_one() { - main([1, 2]); -} -``` - -```bash -$ nargo test -[testing] Running 1 test functions -[testing] Testing test_one... ok -[testing] All tests passed - -$ nargo check -The application panicked (crashed). -Message: Cannot have variable sized arrays as a parameter to main -``` - -## Call Expressions - -Calling a function in Noir is executed by using the function name and passing in the necessary -arguments. - -Below we show how to call the `foo` function from the `main` function using a call expression: - -```rust -fn main(x : Field, y : Field) { - let z = foo(x); -} - -fn foo(x : Field) -> Field { - x + x -} -``` - -## Methods - -You can define methods in Noir on any struct type in scope. - -```rust -struct MyStruct { - foo: Field, - bar: Field, -} - -impl MyStruct { - fn new(foo: Field) -> MyStruct { - MyStruct { - foo, - bar: 2, - } - } - - fn sum(self) -> Field { - self.foo + self.bar - } -} - -fn main() { - let s = MyStruct::new(40); - assert(s.sum() == 42); -} -``` - -Methods are just syntactic sugar for functions, so if we wanted to we could also call `sum` as -follows: - -```rust -assert(MyStruct::sum(s) == 42); -``` - -It is also possible to specialize which method is chosen depending on the [generic](./06_generics.md) type that is used. In this example, the `foo` function returns different values depending on its type: - -```rust -struct Foo {} - -impl Foo { - fn foo(self) -> Field { 1 } -} - -impl Foo { - fn foo(self) -> Field { 2 } -} - -fn main() { - let f1: Foo = Foo{}; - let f2: Foo = Foo{}; - assert(f1.foo() + f2.foo() == 3); -} -``` - -Also note that impls with the same method name defined in them cannot overlap. For example, if we already have `foo` defined for `Foo` and `Foo` like we do above, we cannot also define `foo` in an `impl Foo` since it would be ambiguous which version of `foo` to choose. - -```rust -// Including this impl in the same project as the above snippet would -// cause an overlapping impls error -impl Foo { - fn foo(self) -> Field { 3 } -} -``` - -## Lambdas - -Lambdas are anonymous functions. They follow the syntax of Rust - `|arg1, arg2, ..., argN| return_expression`. - -```rust -let add_50 = |val| val + 50; -assert(add_50(100) == 150); -``` - -See [Lambdas](./08_lambdas.md) for more details. - -## Attributes - -Attributes are metadata that can be applied to a function, using the following syntax: `#[attribute(value)]`. - -Supported attributes include: - -- **builtin**: the function is implemented by the compiler, for efficiency purposes. -- **deprecated**: mark the function as _deprecated_. Calling the function will generate a warning: `warning: use of deprecated function` -- **field**: Used to enable conditional compilation of code depending on the field size. See below for more details -- **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./05_unconstrained.md) and [NoirJS](../noir_js/noir_js.md) for more details. -- **test**: mark the function as unit tests. See [Tests](../nargo/02_testing.md) for more details - -### Field Attribute - -The field attribute defines which field the function is compatible for. The function is conditionally compiled, under the condition that the field attribute matches the Noir native field. -The field can be defined implicitly, by using the name of the elliptic curve usually associated to it - for instance bn254, bls12_381 - or explicitly by using the field (prime) order, in decimal or hexadecimal form. -As a result, it is possible to define multiple versions of a function with each version specialized for a different field attribute. This can be useful when a function requires different parameters depending on the underlying elliptic curve. - -Example: we define the function `foo()` three times below. Once for the default Noir bn254 curve, once for the field $\mathbb F_{23}$, which will normally never be used by Noir, and once again for the bls12_381 curve. - -```rust -#[field(bn254)] -fn foo() -> u32 { - 1 -} - -#[field(23)] -fn foo() -> u32 { - 2 -} - -// This commented code would not compile as foo would be defined twice because it is the same field as bn254 -// #[field(21888242871839275222246405745257275088548364400416034343698204186575808495617)] -// fn foo() -> u32 { -// 2 -// } - -#[field(bls12_381)] -fn foo() -> u32 { - 3 -} -``` - -If the field name is not known to Noir, it will discard the function. Field names are case insensitive. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/02_control_flow.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/02_control_flow.md deleted file mode 100644 index a7f85360197..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/02_control_flow.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Control Flow -description: - Learn how to use loops and if expressions in the Noir programming language. Discover the syntax - and examples for for loops and if-else statements. -keywords: [Noir programming language, loops, for loop, if-else statements, Rust syntax] ---- - -## Loops - -Noir has one kind of loop: the `for` loop. `for` loops allow you to repeat a block of code multiple -times. - -The following block of code between the braces is run 10 times. - -```rust -for i in 0..10 { - // do something -}; -``` - -The index for loops is of type `u64`. - -## If Expressions - -Noir supports `if-else` statements. The syntax is most similar to Rust's where it is not required -for the statement's conditional to be surrounded by parentheses. - -```rust -let a = 0; -let mut x: u32 = 0; - -if a == 0 { - if a != 0 { - x = 6; - } else { - x = 2; - } -} else { - x = 5; - assert(x == 5); -} -assert(x == 2); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/03_ops.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/03_ops.md deleted file mode 100644 index 0e35ef5e584..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/03_ops.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -title: Logical Operations -description: - Learn about the supported arithmetic and logical operations in the Noir programming language. - Discover how to perform operations on private input types, integers, and booleans. -keywords: - [ - Noir programming language, - supported operations, - arithmetic operations, - logical operations, - predicate operators, - bitwise operations, - short-circuiting, - backend, - ] ---- - -# Operations - -## Table of Supported Operations - -| Operation | Description | Requirements | -| :-------- | :------------------------------------------------------------: | -------------------------------------: | -| + | Adds two private input types together | Types must be private input | -| - | Subtracts two private input types together | Types must be private input | -| \* | Multiplies two private input types together | Types must be private input | -| / | Divides two private input types together | Types must be private input | -| ^ | XOR two private input types together | Types must be integer | -| & | AND two private input types together | Types must be integer | -| \| | OR two private input types together | Types must be integer | -| \<\< | Left shift an integer by another integer amount | Types must be integer | -| >> | Right shift an integer by another integer amount | Types must be integer | -| ! | Bitwise not of a value | Type must be integer or boolean | -| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | -| > | returns a bool if one value is more than the other | Upper bound must have a known bit size | -| >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | -| == | returns a bool if one value is equal to the other | Both types must not be constants | -| != | returns a bool if one value is not equal to the other | Both types must not be constants | - -### Predicate Operators - -`<,<=, !=, == , >, >=` are known as predicate/comparison operations because they compare two values. -This differs from the operations such as `+` where the operands are used in _computation_. - -### Bitwise Operations Example - -```rust -fn main(x : Field) { - let y = x as u32; - let z = y & y; -} -``` - -`z` is implicitly constrained to be the result of `y & y`. The `&` operand is used to denote bitwise -`&`. - -> `x & x` would not compile as `x` is a `Field` and not an integer type. - -### Logical Operators - -Noir has no support for the logical operators `||` and `&&`. This is because encoding the -short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can -use the bitwise operators `|` and `&` which operate identically for booleans, just without the -short-circuiting. - -```rust -let my_val = 5; - -let mut flag = 1; -if (my_val > 6) | (my_val == 0) { - flag = 0; -} -assert(flag == 1); - -if (my_val != 10) & (my_val < 50) { - flag = 0; -} -assert(flag == 0); -``` - -### Shorthand operators - -Noir shorthand operators for most of the above operators, namely `+=, -=, *=, /=, %=, &=, |=, ^=, <<=`, and `>>=`. These allow for more concise syntax. For example: - -```rust -let mut i = 0; -i = i + 1; -``` - -could be written as: - -```rust -let mut i = 0; -i += 1; -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/04_assert.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/04_assert.md deleted file mode 100644 index 7427ec6cc63..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/04_assert.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Assert Function -description: - Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or - comparison expression that follows to be true, and what happens if the expression is false at - runtime. -keywords: [Noir programming language, assert statement, predicate expression, comparison expression] ---- - -Noir includes a special `assert` function which will explicitly constrain the predicate/comparison -expression that follows to be true. If this expression is false at runtime, the program will fail to -be proven. Example: - -```rust -fn main(x : Field, y : Field) { - assert(x == y); -} -``` - -You can optionally provide a message to be logged when the assertion fails: - -```rust -assert(x == y, "x and y are not equal"); -``` - -> Assertions only work for predicate operations, such as `==`. If there's any ambiguity on the operation, the program will fail to compile. For example, it is unclear if `assert(x + y)` would check for `x + y == 0` or simply would return `true`. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/05_unconstrained.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/05_unconstrained.md deleted file mode 100644 index 097d6ee9894..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/05_unconstrained.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: Unconstrained Functions -description: "Learn about what unconstrained functions in Noir are, how to use them and when you'd want to." - -keywords: [Noir programming language, unconstrained, open] ---- - - - -Unconstrained functions are functions which do not constrain any of the included computation and allow for non-deterministic computation. - -## Why? - -Zero-knowledge (ZK) domain-specific languages (DSL) enable developers to generate ZK proofs from their programs by compiling code down to the constraints of an NP complete language (such as R1CS or PLONKish languages). However, the hard bounds of a constraint system can be very limiting to the functionality of a ZK DSL. - -Enabling a circuit language to perform unconstrained execution is a powerful tool. Said another way, unconstrained execution lets developers generate witnesses from code that does not generate any constraints. Being able to execute logic outside of a circuit is critical for both circuit performance and constructing proofs on information that is external to a circuit. - -Fetching information from somewhere external to a circuit can also be used to enable developers to improve circuit efficiency. - -A ZK DSL does not just prove computation, but proves that some computation was handled correctly. Thus, it is necessary that when we switch from performing some operation directly inside of a circuit to inside of an unconstrained environment that the appropriate constraints are still laid down elsewhere in the circuit. - -## Example - -An in depth example might help drive the point home. This example comes from the excellent [post](https://discord.com/channels/1113924620781883405/1124022445054111926/1128747641853972590) by Tom in the Noir Discord. - -Let's look at how we can optimize a function to turn a `u72` into an array of `u8`s. - -```rust -fn main(num: u72) -> pub [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8)) as u72 & 0xff) as u8; - } - - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 91 -Backend circuit size: 3619 -``` - -A lot of the operations in this function are optimized away by the compiler (all the bit-shifts turn into divisions by constants). However we can save a bunch of gates by casting to u8 a bit earlier. This automatically truncates the bit-shifted value to fit in a u8 which allows us to remove the XOR against 0xff. This saves us ~480 gates in total. - -```rust -fn main(num: u72) -> pub [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8)) as u8; - } - - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 75 -Backend circuit size: 3143 -``` - -Those are some nice savings already but we can do better. This code is all constrained so we're proving every step of calculating out using num, but we don't actually care about how we calculate this, just that it's correct. This is where brillig comes in. - -It turns out that truncating a u72 into a u8 is hard to do inside a snark, each time we do as u8 we lay down 4 ACIR opcodes which get converted into multiple gates. It's actually much easier to calculate num from out than the other way around. All we need to do is multiply each element of out by a constant and add them all together, both relatively easy operations inside a snark. - -We can then run u72_to_u8 as unconstrained brillig code in order to calculate out, then use that result in our constrained function and assert that if we were to do the reverse calculation we'd get back num. This looks a little like the below: - -```rust -fn main(num: u72) -> pub [u8; 8] { - let out = u72_to_u8(num); - - let mut reconstructed_num: u72 = 0; - for i in 0..8 { - reconstructed_num += (out[i] as u72 << (56 - (8 * i))); - } - assert(num == reconstructed_num); - out -} - -unconstrained fn u72_to_u8(num: u72) -> [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8))) as u8; - } - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 78 -Backend circuit size: 2902 -``` - -This ends up taking off another ~250 gates from our circuit! We've ended up with more ACIR opcodes than before but they're easier for the backend to prove (resulting in fewer gates). - -Generally we want to use brillig whenever there's something that's easy to verify but hard to compute within the circuit. For example, if you wanted to calculate a square root of a number it'll be a much better idea to calculate this in brillig and then assert that if you square the result you get back your number. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/06_generics.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/06_generics.md deleted file mode 100644 index 36c2b593fcd..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/06_generics.md +++ /dev/null @@ -1,113 +0,0 @@ ---- -title: Generics -description: Learn how to use Generics in Noir -keywords: [Noir, Rust, generics, functions, structs] ---- - -Generics allow you to use the same functions with multiple different concrete data types. You can -read more about the concept of generics in the Rust documentation -[here](https://doc.rust-lang.org/book/ch10-01-syntax.html). - -Here is a trivial example showing the identity function that supports any type. In Rust, it is -common to refer to the most general type as `T`. We follow the same convention in Noir. - -```rust -fn id(x: T) -> T { - x -} -``` - -## In Structs - -Generics are useful for specifying types in structs. For example, we can specify that a field in a -struct will be of a certain generic type. In this case `value` is of type `T`. - -```rust -struct RepeatedValue { - value: T, - count: Field, -} - -impl RepeatedValue { - fn new(value: T) -> Self { - Self { value, count: 1 } - } - - fn increment(mut repeated: Self) -> Self { - repeated.count += 1; - repeated - } - - fn print(self) { - for _i in 0 .. self.count { - dep::std::println(self.value); - } - } -} - -fn main() { - let mut repeated = RepeatedValue::new("Hello!"); - repeated = repeated.increment(); - repeated.print(); -} -``` - -The `print` function will print `Hello!` an arbitrary number of times, twice in this case. - -If we want to be generic over array lengths (which are type-level integers), we can use numeric -generics. Using these looks just like using regular generics, but these generics can resolve to -integers at compile-time, rather than resolving to types. Here's an example of a struct that is -generic over the size of the array it contains internally: - -```rust -struct BigInt { - limbs: [u32; N], -} - -impl BigInt { - // `N` is in scope of all methods in the impl - fn first(first: BigInt, second: BigInt) -> Self { - assert(first.limbs != second.limbs); - first - - fn second(first: BigInt, second: Self) -> Self { - assert(first.limbs != second.limbs); - second - } -} -``` - -## Calling functions on generic parameters - -Unlike Rust, Noir does not have traits, so how can one translate the equivalent of a trait bound in -Rust into Noir? That is, how can we write a function that is generic over some type `T`, while also -requiring there is a function like `eq: fn(T, T) -> bool` that works on the type? - -The answer is that we can translate this by passing in the function manually. Here's an example of -implementing array equality in Noir: - -```rust -fn array_eq(array1: [T; N], array2: [T; N], elem_eq: fn(T, T) -> bool) -> bool { - if array1.len() != array2.len() { - false - } else { - let mut result = true; - for i in 0 .. array1.len() { - result &= elem_eq(array1[i], array2[i]); - } - result - } -} - -fn main() { - assert(array_eq([1, 2, 3], [1, 2, 3], |a, b| a == b)); - - // We can use array_eq even for arrays of structs, as long as we have - // an equality function for these structs we can pass in - let array = [MyStruct::new(), MyStruct::new()]; - assert(array_eq(array, array, MyStruct::eq)); -} -``` - -You can see an example of generics in the tests -[here](https://github.com/noir-lang/noir/blob/master/test_programs/execution_success/generics/src/main.nr). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/07_mutability.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/07_mutability.md deleted file mode 100644 index ed3fed820ec..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/07_mutability.md +++ /dev/null @@ -1,92 +0,0 @@ ---- -title: Mutability -description: - Learn about mutable variables, constants, and globals in Noir programming language. Discover how - to declare, modify, and use them in your programs. -keywords: [noir programming language, mutability in noir, mutable variables, constants, globals] ---- - -Variables in noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned -to via an assignment expression. - -```rust -let x = 2; -x = 3; // error: x must be mutable to be assigned to - -let mut y = 3; -let y = 4; // OK -``` - -The `mut` modifier can also apply to patterns: - -```rust -let (a, mut b) = (1, 2); -a = 11; // error: a must be mutable to be assigned to -b = 12; // OK - -let mut (c, d) = (3, 4); -c = 13; // OK -d = 14; // OK - -// etc. -let MyStruct { x: mut y } = MyStruct { x: a }; -// y is now in scope -``` - -Note that mutability in noir is local and everything is passed by value, so if a called function -mutates its parameters then the parent function will keep the old value of the parameters. - -```rust -fn main() -> pub Field { - let x = 3; - helper(x); - x // x is still 3 -} - -fn helper(mut x: i32) { - x = 4; -} -``` - -## Comptime Values - -:::warning - -The 'comptime' keyword was removed in version 0.10. The comptime keyword and syntax are currently still kept and parsed for backwards compatibility, but are now deprecated and will issue a warning when used. `comptime` has been removed because it is no longer needed for accessing arrays. - -::: - -## Globals - -Noir also supports global variables. However, they must be known at compile-time. The global type can also be inferred by the compiler entirely. Globals can also be used to specify array -annotations for function parameters and can be imported from submodules. - -```rust -global N: Field = 5; // Same as `global N: Field = 5` - -fn main(x : Field, y : [Field; N]) { - let res = x * N; - - assert(res == y[0]); - - let res2 = x * my_submodule::N; - assert(res != res2); -} - -mod my_submodule { - use dep::std; - - global N: Field = 10; - - fn my_helper() -> Field { - let x = N; - x - } -} -``` - -## Why only local mutability? - -Witnesses in a proving system are immutable in nature. Noir aims to _closely_ mirror this setting -without applying additional overhead to the user. Modeling a mutable reference is not as -straightforward as on conventional architectures and would incur some possibly unexpected overhead. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/08_lambdas.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/08_lambdas.md deleted file mode 100644 index ae1e6aecab1..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/08_lambdas.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: Lambdas -description: Learn how to use anonymous functions in Noir programming language. -keywords: [Noir programming language, lambda, closure, function, anonymous function] ---- - -## Introduction - -Lambdas are anonymous functions. The syntax is `|arg1, arg2, ..., argN| return_expression`. - -```rust -let add_50 = |val| val + 50; -assert(add_50(100) == 150); -``` - -A block can be used as the body of a lambda, allowing you to declare local variables inside it: - -```rust -let cool = || { - let x = 100; - let y = 100; - x + y -} - -assert(cool() == 200); -``` - -## Closures - -Inside the body of a lambda, you can use variables defined in the enclosing function. Such lambdas are called **closures**. In this example `x` is defined inside `main` and is accessed from within the lambda: - -```rust -fn main() { - let x = 100; - let closure = || x + 150; - assert(closure() == 250); -} -``` - -## Passing closures to higher-order functions - -It may catch you by surprise that the following code fails to compile: - -```rust -fn foo(f: fn () -> Field) -> Field { - f() -} - -fn main() { - let (x, y) = (50, 50); - assert(foo(|| x + y) == 100); // error :( -} -``` - -The reason is that the closure's capture environment affects its type - we have a closure that captures two Fields and `foo` -expects a regular function as an argument - those are incompatible. -:::note - -Variables contained within the `||` are the closure's parameters, and the expression that follows it is the closure's body. The capture environment is comprised of any variables used in the closure's body that are not parameters. - -E.g. in |x| x + y, y would be a captured variable, but x would not be, since it is a parameter of the closure. - -::: -The syntax for the type of a closure is `fn[env](args) -> ret_type`, where `env` is the capture environment of the closure - -in this example that's `(Field, Field)`. - -The best solution in our case is to make `foo` generic over the environment type of its parameter, so that it can be called -with closures with any environment, as well as with regular functions: - -```rust -fn foo(f: fn[Env]() -> Field) -> Field { - f() -} - -fn main() { - let (x, y) = (50, 50); - assert(foo(|| x + y) == 100); // compiles fine - assert(foo(|| 60) == 60); // compiles fine -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/09_comments.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/09_comments.md deleted file mode 100644 index 3bb4d2f25a4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/09_comments.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: Comments -description: - Learn how to write comments in Noir programming language. A comment is a line of code that is - ignored by the compiler, but it can be read by programmers. Single-line and multi-line comments - are supported in Noir. -keywords: [Noir programming language, comments, single-line comments, multi-line comments] ---- - -A comment is a line in your codebase which the compiler ignores, however it can be read by -programmers. - -Here is a single line comment: - -```rust -// This is a comment and is ignored -``` - -`//` is used to tell the compiler to ignore the rest of the line. - -Noir also supports multi-line block comments. Start a block comment with `/*` and end the block with `*/`. - -Noir does not natively support doc comments. You may be able to use [Rust doc comments](https://doc.rust-lang.org/reference/comments.html) in your code to leverage some Rust documentation build tools with Noir code. - -```rust -/* - This is a block comment describing a complex function. -*/ -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/10_distinct.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/10_distinct.md deleted file mode 100644 index e7ff7f5017a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/10_distinct.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: Distinct Witnesses ---- - -The `distinct` keyword prevents repetitions of witness indices in the program's ABI. This ensures -that the witnesses being returned as public inputs are all unique. - -The `distinct` keyword is only used for return values on program entry points (usually the `main()` -function). - -When using `distinct` and `pub` simultaneously, `distinct` comes first. See the example below. - -You can read more about the problem this solves -[here](https://github.com/noir-lang/noir/issues/1183). - -## Example - -Without the `distinct` keyword, the following program - -```rust -fn main(x : pub Field, y : pub Field) -> pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - "return_witnesses": [3, 2, 4, 4] - } -} -``` - -Whereas (with the `distinct` keyword) - -```rust -fn main(x : pub Field, y : pub Field) -> distinct pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - //... - "return_witnesses": [3, 4, 5, 6] - } -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/11_shadowing.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/11_shadowing.md deleted file mode 100644 index efd743e764f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/11_shadowing.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Shadowing ---- - -Noir allows for inheriting variables' values and re-declaring them with the same name similar to Rust, known as shadowing. - -For example, the following function is valid in Noir: - -```rust -fn main() { - let x = 5; - - { - let x = x * 2; - assert (x == 10); - } - - assert (x == 5); -} -``` - -In this example, a variable x is first defined with the value 5. - -The local scope that follows shadows the original x, i.e. creates a local mutable x based on the value of the original x. It is given a value of 2 times the original x. - -When we return to the main scope, x once again refers to just the original x, which stays at the value of 5. - -## Temporal mutability - -One way that shadowing is useful, in addition to ergonomics across scopes, is for temporarily mutating variables. - -```rust -fn main() { - let age = 30; - // age = age + 5; // Would error as `age` is immutable by default. - - let mut age = age + 5; // Temporarily mutates `age` with a new value. - - let age = age; // Locks `age`'s mutability again. - - assert (age == 35); -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types.md deleted file mode 100644 index 74f573f7d3f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: Data Types -description: - Get a clear understanding of the two categories of Noir data types - primitive types and compound - types. Learn about their characteristics, differences, and how to use them in your Noir - programming. -keywords: - [ - noir, - data types, - primitive types, - compound types, - private types, - public types, - ] ---- - -Every value in Noir has a type, which determines which operations are valid for it. - -All values in Noir are fundamentally composed of `Field` elements. For a more approachable -developing experience, abstractions are added on top to introduce different data types in Noir. - -Noir has two category of data types: primitive types (e.g. `Field`, integers, `bool`) and compound -types that group primitive types (e.g. arrays, tuples, structs). Each value can either be private or -public. - -## Private & Public Types - -A **private value** is known only to the Prover, while a **public value** is known by both the -Prover and Verifier. Mark values as `private` when the value should only be known to the prover. All -primitive types (including individual fields of compound types) in Noir are private by default, and -can be marked public when certain values are intended to be revealed to the Verifier. - -> **Note:** For public values defined in Noir programs paired with smart contract verifiers, once -> the proofs are verified on-chain the values can be considered known to everyone that has access to -> that blockchain. - -Public data types are treated no differently to private types apart from the fact that their values -will be revealed in proofs generated. Simply changing the value of a public type will not change the -circuit (where the same goes for changing values of private types as well). - -_Private values_ are also referred to as _witnesses_ sometimes. - -> **Note:** The terms private and public when applied to a type (e.g. `pub Field`) have a different -> meaning than when applied to a function (e.g. `pub fn foo() {}`). -> -> The former is a visibility modifier for the Prover to interpret if a value should be made known to -> the Verifier, while the latter is a visibility modifier for the compiler to interpret if a -> function should be made accessible to external Noir programs like in other languages. - -### pub Modifier - -All data types in Noir are private by default. Types are explicitly declared as public using the -`pub` modifier: - -```rust -fn main(x : Field, y : pub Field) -> pub Field { - x + y -} -``` - -In this example, `x` is **private** while `y` and `x + y` (the return value) are **public**. Note -that visibility is handled **per variable**, so it is perfectly valid to have one input that is -private and another that is public. - -> **Note:** Public types can only be declared through parameters on `main`. - -## Type Aliases - -A type alias is a new name for an existing type. Type aliases are declared with the keyword `type`: - -```rust -type Id = u8; - -fn main() { - let id: Id = 1; - let zero: u8 = 0; - assert(zero + 1 == id); -} -``` - -Type aliases can also be used with [generics](./06_generics.md): - -```rust -type Id = Size; - -fn main() { - let id: Id = 1; - let zero: u32 = 0; - assert(zero + 1 == id); -} -``` - -### BigInt - -You can achieve BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/00_fields.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/00_fields.md deleted file mode 100644 index 78d3d2af166..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/00_fields.md +++ /dev/null @@ -1,165 +0,0 @@ ---- -title: Fields -description: - Dive deep into the Field data type in Noir. Understand its methods, practical examples, and best practices to effectively use Fields in your Noir programs. -keywords: - [ - noir, - field type, - methods, - examples, - best practices, - ] ---- - -The field type corresponds to the native field type of the proving backend. - -The size of a Noir field depends on the elliptic curve's finite field for the proving backend -adopted. For example, a field would be a 254-bit integer when paired with the default backend that -spans the Grumpkin curve. - -Fields support integer arithmetic and are often used as the default numeric type in Noir: - -```rust -fn main(x : Field, y : Field) { - let z = x + y; -} -``` - -`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new -private value `z` constrained to be equal to `x + y`. - -If proving efficiency is of priority, fields should be used as a default for solving problems. -Smaller integer types (e.g. `u64`) incur extra range constraints. - -## Methods - -After declaring a Field, you can use these common methods on it: - -### to_le_bits - -Transforms the field into an array of bits, Little Endian. - -```rust -fn to_le_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_le_bits(32); -} -``` - -### to_be_bits - -Transforms the field into an array of bits, Big Endian. - -```rust -fn to_be_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_be_bits(32); -} -``` - -### to_le_bytes - -Transforms into an array of bytes, Little Endian - -```rust -fn to_le_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_le_bytes(4); -} -``` - -### to_be_bytes - -Transforms into an array of bytes, Big Endian - -```rust -fn to_be_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_be_bytes(4); -} -``` - -### to_le_radix - -Decomposes into a vector over the specified base, Little Endian - -```rust -fn to_le_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_le_radix(256, 4); -} -``` - -### to_be_radix - -Decomposes into a vector over the specified base, Big Endian - -```rust -fn to_be_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_be_radix(256, 4); -} -``` - -### pow_32 - -Returns the value to the power of the specified exponent - -```rust -fn pow_32(self, exponent: Field) -> Field -``` - -example: - -```rust -fn main() { - let field = 2 - let pow = field.pow_32(4); - assert(pow == 16); -} -``` - -### sgn0 - -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. - -```rust -fn sgn0(self) -> u1 -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/01_integers.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/01_integers.md deleted file mode 100644 index d9c5e20e795..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/01_integers.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Integers -description: - Explore the Integer data type in Noir. Learn about its methods, see real-world examples, and grasp how to efficiently use Integers in your Noir code. -keywords: - [ - noir, - integer types, - methods, - examples, - arithmetic, - ] ---- - -An integer type is a range constrained field type. The Noir frontend currently supports unsigned, -arbitrary-sized integer types. - -An integer type is specified first with the letter `u`, indicating its unsigned nature, followed by -its length in bits (e.g. `32`). For example, a `u32` variable can store a value in the range of -$\\([0,2^{32}-1]\\)$: - -```rust -fn main(x : Field, y : u32) { - let z = x as u32 + y; -} -``` - -`x`, `y` and `z` are all private values in this example. However, `x` is a field while `y` and `z` -are unsigned 32-bit integers. If `y` or `z` exceeds the range $\\([0,2^{32}-1]\\)$, proofs created -will be rejected by the verifier. - -> **Note:** The default backend supports both even (e.g. `u16`, `u48`) and odd (e.g. `u5`, `u3`) -> sized integer types. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/02_booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/02_booleans.md deleted file mode 100644 index d353606210a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/02_booleans.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: Booleans -description: - Delve into the Boolean data type in Noir. Understand its methods, practical examples, and best practices for using Booleans in your Noir programs. -keywords: - [ - noir, - boolean type, - methods, - examples, - logical operations, - ] ---- - - -The `bool` type in Noir has two possible values: `true` and `false`: - -```rust -fn main() { - let t = true; - let f: bool = false; -} -``` - -> **Note:** When returning a boolean value, it will show up as a value of 1 for `true` and 0 for -> `false` in _Verifier.toml_. - -The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and -[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/03_strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/03_strings.md deleted file mode 100644 index 4360893e9a2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/03_strings.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: Strings -description: - Discover the String data type in Noir. Learn about its methods, see real-world examples, and understand how to effectively manipulate and use Strings in Noir. -keywords: - [ - noir, - string type, - methods, - examples, - concatenation, - ] ---- - - -The string type is a fixed length value defined with `str`. - -You can use strings in `assert()` functions or print them with -`std::println()`. See more about [Logging](../../standard_library/logging.md). - -```rust -use dep::std; - -fn main(message : pub str<11>, hex_as_string : str<4>) { - std::println(message); - assert(message == "hello world"); - assert(hex_as_string == "0x41"); -} -``` - -You can convert a `str` to a byte array by calling `as_bytes()` -or a vector by calling `as_bytes_vec()`. - -```rust -fn main() { - let message = "hello world"; - let message_bytes = message.as_bytes(); - let mut message_vec = message.as_bytes_vec(); - assert(message_bytes.len() == 11); - assert(message_bytes[0] == 104); - assert(message_bytes[0] == message_vec.get(0)); -} -``` - -## Escape characters - -You can use escape characters for your strings: - -| Escape Sequence | Description | -|-----------------|-----------------| -| `\r` | Carriage Return | -| `\n` | Newline | -| `\t` | Tab | -| `\0` | Null Character | -| `\"` | Double Quote | -| `\\` | Backslash | - -Example: - -```rust -let s = "Hello \"world" // prints "Hello "world" -let s = "hey \tyou"; // prints "hey you" -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/04_arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/04_arrays.md deleted file mode 100644 index 3c84da3f8ad..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/04_arrays.md +++ /dev/null @@ -1,244 +0,0 @@ ---- -title: Arrays -description: - Dive into the Array data type in Noir. Grasp its methods, practical examples, and best practices for efficiently using Arrays in your Noir code. -keywords: - [ - noir, - array type, - methods, - examples, - indexing, - ] ---- - -An array is one way of grouping together values into one compound type. Array types can be inferred -or explicitly specified via the syntax `[; ]`: - -```rust -fn main(x : Field, y : Field) { - let my_arr = [x, y]; - let your_arr: [Field; 2] = [x, y]; -} -``` - -Here, both `my_arr` and `your_arr` are instantiated as an array containing two `Field` elements. - -Array elements can be accessed using indexing: - -```rust -fn main() { - let a = [1, 2, 3, 4, 5]; - - let first = a[0]; - let second = a[1]; -} -``` - -All elements in an array must be of the same type (i.e. homogeneous). That is, an array cannot group -a `Field` value and a `u8` value together for example. - -You can write mutable arrays, like: - -```rust -fn main() { - let mut arr = [1, 2, 3, 4, 5]; - assert(arr[0] == 1); - - arr[0] = 42; - assert(arr[0] == 42); -} -``` - -You can instantiate a new array of a fixed size with the same value repeated for each element. The following example instantiates an array of length 32 where each element is of type Field and has the value 0. - -```rust -let array: [Field; 32] = [0; 32]; -``` - -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: - -```rust -let array: [Field; 32] = [0; 32]; -let sl = array.as_slice() -``` - -You can define multidimensional arrays: - -```rust -let array : [[Field; 2]; 2]; -let element = array[0][0]; -``` - -## Types - -You can create arrays of primitive types or structs. There is not yet support for nested arrays -(arrays of arrays) or arrays of structs that contain arrays. - -## Methods - -For convenience, the STD provides some ready-to-use, common methods for arrays: - -### len - -Returns the length of an array - -```rust -fn len(_array: [T; N]) -> comptime Field -``` - -example - -```rust -fn main() { - let array = [42, 42]; - assert(array.len() == 2); -} -``` - -### sort - -Returns a new sorted array. The original array remains untouched. Notice that this function will -only work for arrays of fields or integers, not for any arbitrary type. This is because the sorting -logic it uses internally is optimized specifically for these values. If you need a sort function to -sort any type, you should use the function `sort_via` described below. - -```rust -fn sort(_array: [T; N]) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32]; - let sorted = arr.sort(); - assert(sorted == [32, 42]); -} -``` - -### sort_via - -Sorts the array with a custom comparison function - -```rust -fn sort_via(mut a: [T; N], ordering: fn(T, T) -> bool) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32] - let sorted_ascending = arr.sort_via(|a, b| a <= b); - assert(sorted_ascending == [32, 42]); // verifies - - let sorted_descending = arr.sort_via(|a, b| a >= b); - assert(sorted_descending == [32, 42]); // does not verify -} -``` - -### map - -Applies a function to each element of the array, returning a new array containing the mapped elements. - -```rust -fn map(f: fn(T) -> U) -> [U; N] -``` - -example - -```rust -let a = [1, 2, 3]; -let b = a.map(|a| a * 2); // b is now [2, 4, 6] -``` - -### fold - -Applies a function to each element of the array, returning the final accumulated value. The first -parameter is the initial value. - -```rust -fn fold(mut accumulator: U, f: fn(U, T) -> U) -> U -``` - -This is a left fold, so the given function will be applied to the accumulator and first element of -the array, then the second, and so on. For a given call the expected result would be equivalent to: - -```rust -let a1 = [1]; -let a2 = [1, 2]; -let a3 = [1, 2, 3]; - -let f = |a, b| a - b; -a1.fold(10, f) //=> f(10, 1) -a2.fold(10, f) //=> f(f(10, 1), 2) -a3.fold(10, f) //=> f(f(f(10, 1), 2), 3) -``` - -example: - -```rust - -fn main() { - let arr = [2, 2, 2, 2, 2]; - let folded = arr.fold(0, |a, b| a + b); - assert(folded == 10); -} - -``` - -### reduce - -Same as fold, but uses the first element as starting element. - -```rust -fn reduce(f: fn(T, T) -> T) -> T -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let reduced = arr.reduce(|a, b| a + b); - assert(reduced == 10); -} -``` - -### all - -Returns true if all the elements satisfy the given predicate - -```rust -fn all(predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let all = arr.all(|a| a == 2); - assert(all); -} -``` - -### any - -Returns true if any of the elements satisfy the given predicate - -```rust -fn any(predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 5]; - let any = arr.any(|a| a == 5); - assert(any); -} - -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/05_slices.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/05_slices.mdx deleted file mode 100644 index f45f56daee1..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/05_slices.mdx +++ /dev/null @@ -1,146 +0,0 @@ ---- -title: Slices -description: Explore the Slice data type in Noir. Understand its methods, see real-world examples, and learn how to effectively use Slices in your Noir programs. -keywords: [noir, slice type, methods, examples, subarrays] ---- - -import Experimental from '@site/src/components/Notes/_experimental.mdx'; - - - -A slice is a dynamically-sized view into a sequence of elements. They can be resized at runtime, but because they don't own the data, they cannot be returned from a circuit. You can treat slices as arrays without a constrained size. - -```rust -use dep::std::slice; - -fn main() -> pub Field { - let mut slice: [Field] = [0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -View the corresponding test file [here]([test-file]. - -[test-file]: https://github.com/noir-lang/noir/blob/f387ec1475129732f72ba294877efdf6857135ac/crates/nargo_cli/tests/test_data_ssa_refactor/slices/src/main.nr - -## Methods - -For convenience, the STD provides some ready-to-use, common methods for slices: - -### push_back - -Pushes a new element to the end of the slice, returning a new slice with a length one greater than the original unmodified slice. - -```rust -fn push_back(_self: [T], _elem: T) -> [T] -``` - -example: - -```rust -fn main() -> pub Field { - let mut slice: [Field] = [0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -View the corresponding test file [here][test-file]. - -### push_front - -Returns a new array with the specified element inserted at index 0. The existing elements indexes are incremented by 1. - -```rust -fn push_front(_self: Self, _elem: T) -> Self -``` - -Example: - -```rust -let mut new_slice: [Field] = []; -new_slice = new_slice.push_front(20); -assert(new_slice[0] == 20); // returns true -``` - -View the corresponding test file [here][test-file]. - -### pop_front - -Returns a tuple of two items, the first element of the array and the rest of the array. - -```rust -fn pop_front(_self: Self) -> (T, Self) -``` - -Example: - -```rust -let (first_elem, rest_of_slice) = slice.pop_front(); -``` - -View the corresponding test file [here][test-file]. - -### pop_back - -Returns a tuple of two items, the beginning of the array with the last element omitted and the last element. - -```rust -fn pop_back(_self: Self) -> (Self, T) -``` - -Example: - -```rust -let (popped_slice, last_elem) = slice.pop_back(); -``` - -View the corresponding test file [here][test-file]. - -### append - -Loops over a slice and adds it to the end of another. - -```rust -fn append(mut self, other: Self) -> Self -``` - -Example: - -```rust -let append = [1, 2].append([3, 4, 5]); -``` - -### insert - -Inserts an element at a specified index and shifts all following elements by 1. - -```rust -fn insert(_self: Self, _index: Field, _elem: T) -> Self -``` - -Example: - -```rust -new_slice = rest_of_slice.insert(2, 100); -assert(new_slice[2] == 100); -``` - -View the corresponding test file [here][test-file]. - -### remove - -Remove an element at a specified index, shifting all elements after it to the left, returning the altered slice and the removed element. - -```rust -fn remove(_self: Self, _index: Field) -> (Self, T) -``` - -Example: - -```rust -let (remove_slice, removed_elem) = slice.remove(3); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/06_vectors.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/06_vectors.mdx deleted file mode 100644 index 4617e90d038..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/06_vectors.mdx +++ /dev/null @@ -1,172 +0,0 @@ ---- -title: Vectors -description: Delve into the Vector data type in Noir. Learn about its methods, practical examples, and best practices for using Vectors in your Noir code. -keywords: [noir, vector type, methods, examples, dynamic arrays] ---- - -import Experimental from '@site/src/components/Notes/_experimental.mdx'; - - - -A vector is a collection type similar to Rust's Vector type. It's convenient way to use slices as mutable arrays. - -Example: - -```rust -use dep::std::collections::vec::Vec; - -let mut vector: Vec = Vec::new(); -for i in 0..5 { - vector.push(i); -} -assert(vector.len() == 5); -``` - -## Methods - -### new - -Creates a new, empty vector. - -```rust -pub fn new() -> Self { - Self { slice: [] } -} -``` - -Example: - -```rust -let empty_vector: Vec = Vec::new(); -assert(empty_vector.len() == 0); -``` - -### from_slice - -Creates a vector containing each element from a given slice. Mutations to the resulting vector will not affect the original slice. - -```rust -pub fn from_slice(slice: [T]) -> Self { - Self { slice } -} -``` - -Example: - -```rust -let arr: [Field] = [1, 2, 3]; -let vector_from_slice = Vec::from_slice(arr); -assert(vector_from_slice.len() == 3); -``` - -### get - -Retrieves an element from the vector at a given index. Panics if the index points beyond the vector's end. - -```rust -pub fn get(self, index: Field) -> T { - self.slice[index] -} -``` - -Example: - -```rust -let vector: Vec = Vec::from_slice([10, 20, 30]); -assert(vector.get(1) == 20); -``` - -### push - -Adds a new element to the vector's end, returning a new vector with a length one greater than the original unmodified vector. - -```rust -pub fn push(&mut self, elem: T) { - self.slice = self.slice.push_back(elem); -} -``` - -Example: - -```rust -let mut vector: Vec = Vec::new(); -vector.push(10); -assert(vector.len() == 1); -``` - -### pop - -Removes an element from the vector's end, returning a new vector with a length one less than the original vector, along with the removed element. Panics if the vector's length is zero. - -```rust -pub fn pop(&mut self) -> T { - let (popped_slice, last_elem) = self.slice.pop_back(); - self.slice = popped_slice; - last_elem -} -``` - -Example: - -```rust -let mut vector = Vec::from_slice([10, 20]); -let popped_elem = vector.pop(); -assert(popped_elem == 20); -assert(vector.len() == 1); -``` - -### insert - -Inserts an element at a specified index, shifting subsequent elements to the right. - -```rust -pub fn insert(&mut self, index: Field, elem: T) { - self.slice = self.slice.insert(index, elem); -} -``` - -Example: - -```rust -let mut vector = Vec::from_slice([10, 30]); -vector.insert(1, 20); -assert(vector.get(1) == 20); -``` - -### remove - -Removes an element at a specified index, shifting subsequent elements to the left, and returns the removed element. - -```rust -pub fn remove(&mut self, index: Field) -> T { - let (new_slice, elem) = self.slice.remove(index); - self.slice = new_slice; - elem -} -``` - -Example: - -```rust -let mut vector = Vec::from_slice([10, 20, 30]); -let removed_elem = vector.remove(1); -assert(removed_elem == 20); -assert(vector.len() == 2); -``` - -### len - -Returns the number of elements in the vector. - -```rust -pub fn len(self) -> Field { - self.slice.len() -} -``` - -Example: - -```rust -let empty_vector: Vec = Vec::new(); -assert(empty_vector.len() == 0); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/07_tuples.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/07_tuples.md deleted file mode 100644 index 5f6cab974a8..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/07_tuples.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: Tuples -description: - Dive into the Tuple data type in Noir. Understand its methods, practical examples, and best practices for efficiently using Tuples in your Noir code. -keywords: - [ - noir, - tuple type, - methods, - examples, - multi-value containers, - ] ---- - -A tuple collects multiple values like an array, but with the added ability to collect values of -different types: - -```rust -fn main() { - let tup: (u8, u64, Field) = (255, 500, 1000); -} -``` - -One way to access tuple elements is via destructuring using pattern matching: - -```rust -fn main() { - let tup = (1, 2); - - let (one, two) = tup; - - let three = one + two; -} -``` - -Another way to access tuple elements is via direct member access, using a period (`.`) followed by -the index of the element we want to access. Index `0` corresponds to the first tuple element, `1` to -the second and so on: - -```rust -fn main() { - let tup = (5, 6, 7, 8); - - let five = tup.0; - let eight = tup.3; -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/08_structs.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/08_structs.md deleted file mode 100644 index 85649dfb389..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/08_structs.md +++ /dev/null @@ -1,73 +0,0 @@ ---- -title: Structs -description: - Explore the Struct data type in Noir. Learn about its methods, see real-world examples, and grasp how to effectively define and use Structs in your Noir programs. -keywords: - [ - noir, - struct type, - methods, - examples, - data structures, - ] ---- - -A struct also allows for grouping multiple values of different types. Unlike tuples, we can also -name each field. - -> **Note:** The usage of _field_ here refers to each element of the struct and is unrelated to the -> field type of Noir. - -Defining a struct requires giving it a name and listing each field within as `: ` pairs: - -```rust -struct Animal { - hands: Field, - legs: Field, - eyes: u8, -} -``` - -An instance of a struct can then be created with actual values in `: ` pairs in any -order. Struct fields are accessible using their given names: - -```rust -fn main() { - let legs = 4; - - let dog = Animal { - eyes: 2, - hands: 0, - legs, - }; - - let zero = dog.hands; -} -``` - -Structs can also be destructured in a pattern, binding each field to a new variable: - -```rust -fn main() { - let Animal { hands, legs: feet, eyes } = get_octopus(); - - let ten = hands + feet + eyes as u8; -} - -fn get_octopus() -> Animal { - let octopus = Animal { - hands: 0, - legs: 8, - eyes: 2, - }; - - octopus -} -``` - -The new variables can be bound with names different from the original struct field names, as -showcased in the `legs --> feet` binding in the example above. - -:::note -You can use Structs as inputs to the `main` function, but you can't output them -::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/09_references.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/09_references.md deleted file mode 100644 index b0c35ce2cb9..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/09_references.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: References ---- - -Noir supports first-class references. References are a bit like pointers: they point to a specific address that can be followed to access the data stored at that address. You can use Rust-like syntax to use pointers in Noir: the `&` operator references the variable, the `*` operator dereferences it. - -Example: - -```rust -fn main() { - let mut x = 2; - - // you can reference x as &mut and pass it to multiplyBy2 - multiplyBy2(&mut x); -} - -// you can access &mut here -fn multiplyBy2(x: &mut Field) { - // and dereference it with * - *x = *x * 2; -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/10_function_types.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/10_function_types.md deleted file mode 100644 index 1ec92efd594..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/10_function_types.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: Function types ---- - -Noir supports higher-order functions. The syntax for a function type is as follows: - -```rust -fn(arg1_type, arg2_type, ...) -> return_type -``` - -Example: - -```rust -fn assert_returns_100(f: fn() -> Field) { // f takes no args and returns a Field - assert(f() == 100); -} - -fn main() { - assert_returns_100(|| 100); // ok - assert_returns_100(|| 150); // fails -} -``` - -A function type also has an optional capture environment - this is necessary to support closures. -See [Lambdas](../08_lambdas.md) for more details. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/migration_notes.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/migration_notes.md deleted file mode 100644 index 1a81af04b3a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/migration_notes.md +++ /dev/null @@ -1,83 +0,0 @@ ---- -title: Migration notes -description: Read about migration notes from previous versions, which could solve problems while updating -keywords: [Noir, notes, migration, updating, upgrading] ---- - -Noir is in full-speed development. Things break fast, wild, and often. This page attempts to leave some notes on errors you might encounter when upgrading and how to resolve them until proper patches are built. - -## ≥0.14 - -The index of the [for loops](./language_concepts/02_control_flow.md#loops) is now of type `u64` instead of `Field`. An example refactor would be: - -```rust -for i in 0..10 { - let i = i as Field; -} -``` - -## ≥v0.11.0 and Nargo backend - -From this version onwards, Nargo starts managing backends through the `nargo backend` command. Upgrading to the versions per usual steps might lead to: - -### `backend encountered an error` - -This is likely due to the existing locally installed version of proving backend (e.g. barretenberg) is incompatible with the version of Nargo in use. - -To fix the issue: - -1. Uninstall the existing backend - -```bash -nargo backend uninstall acvm-backend-barretenberg -``` - -You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. - -2. Reinstall a compatible version of the proving backend. - -If you are using the default barretenberg backend, simply run: - -``` -nargo prove -``` - -with your Noir program. - -This will trigger the download and installation of the latest version of barretenberg compatible with your Nargo in use. - -### `backend encountered an error: illegal instruction` - -On certain Intel-based systems, an `illegal instruction` error may arise due to incompatibility of barretenberg with certain CPU instructions. - -To fix the issue: - -1. Uninstall the existing backend - -```bash -nargo backend uninstall acvm-backend-barretenberg -``` - -You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. - -2. Reinstall a compatible version of the proving backend. - -If you are using the default barretenberg backend, simply run: - -``` -nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/barretenberg-js-binary/raw/master/run-bb.tar.gz -``` - -This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. - -The gzipped file is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. - -Then run: - -``` -DESIRED_BINARY_VERSION=0.8.1 nargo info -``` - -This overrides the bb native binary with a bb.js node application instead, which should be compatible with most if not all hardware. This does come with the drawback of being generally slower than native binary. - -0.8.1 indicates bb.js version 0.8.1, so if you change that it will update to a different version or the default version in the script if none was supplied. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/modules_packages_crates/crates_and_packages.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/modules_packages_crates/crates_and_packages.md deleted file mode 100644 index 23f60855c30..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/modules_packages_crates/crates_and_packages.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Crates and Packages -description: Learn how to use Crates and Packages in your Noir project -keywords: [Nargo, dependencies, package management, crates, package] ---- - -## Crates - -A crate is the smallest amount of code that the Noir compiler considers at a time. -Crates can contain modules, and the modules may be defined in other files that get compiled with the crate, as we’ll see in the coming sections. - -### Crate Types - -A Noir crate can come in several forms: binaries, libraries or contracts. - -#### Binaries - -_Binary crates_ are programs which you can compile to an ACIR circuit which you can then create proofs against. Each must have a function called `main` that defines the ACIR circuit which is to be proved. - -#### Libraries - -_Library crates_ don't have a `main` function and they don't compile down to ACIR. Instead they define functionality intended to be shared with multiple projects, and eventually included in a binary crate. - -#### Contracts - -Contract crates are similar to binary crates in that they compile to ACIR which you can create proofs against. They are different in that they do not have a single `main` function, but are a collection of functions to be deployed to the [Aztec network](https://aztec.network). You can learn more about the technical details of Aztec in the [monorepo](https://github.com/AztecProtocol/aztec-packages) or contract [examples](https://github.com/AztecProtocol/aztec-packages/tree/master/noir-projects/noir-contracts/contracts). - -### Crate Root - -Every crate has a root, which is the source file that the compiler starts, this is also known as the root module. The Noir compiler does not enforce any conditions on the name of the file which is the crate root, however if you are compiling via Nargo the crate root must be called `lib.nr` or `main.nr` for library or binary crates respectively. - -## Packages - -A Nargo _package_ is a collection of one of more crates that provides a set of functionality. A package must include a Nargo.toml file. - -A package _must_ contain either a library or a binary crate, but not both. - -### Differences from Cargo Packages - -One notable difference between Rust's Cargo and Noir's Nargo is that while Cargo allows a package to contain an unlimited number of binary crates and a single library crate, Nargo currently only allows a package to contain a single crate. - -In future this restriction may be lifted to allow a Nargo package to contain both a binary and library crate or multiple binary crates. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/modules_packages_crates/dependencies.md deleted file mode 100644 index 87a09293ea8..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/modules_packages_crates/dependencies.md +++ /dev/null @@ -1,123 +0,0 @@ ---- -title: Dependencies -description: - Learn how to specify and manage dependencies in Nargo, allowing you to upload packages to GitHub - and use them easily in your project. -keywords: [Nargo, dependencies, GitHub, package management, versioning] ---- - -Nargo allows you to upload packages to GitHub and use them as dependencies. - -## Specifying a dependency - -Specifying a dependency requires a tag to a specific commit and the git url to the url containing -the package. - -Currently, there are no requirements on the tag contents. If requirements are added, it would follow -semver 2.0 guidelines. - -> Note: Without a `tag` , there would be no versioning and dependencies would change each time you -> compile your project. - -For example, to add the [ecrecover-noir library](https://github.com/colinnielsen/ecrecover-noir) to your project, add it to `Nargo.toml`: - -```toml -# Nargo.toml - -[dependencies] -ecrecover = {tag = "v0.8.0", git = "https://github.com/colinnielsen/ecrecover-noir"} -``` - -If the module is in a subdirectory, you can define a subdirectory in your git repository, for example: - -```toml -# Nargo.toml - -[dependencies] -easy_private_token_contract = {tag ="v0.1.0-alpha62", git = "https://github.com/AztecProtocol/aztec-packages", directory = "yarn-project/noir-contracts/contracts/easy_private_token_contract"} -``` - -## Specifying a local dependency - -You can also specify dependencies that are local to your machine. - -For example, this file structure has a library and binary crate - -```tree -├── binary_crate -│   ├── Nargo.toml -│   └── src -│   └── main.nr -└── lib_a - ├── Nargo.toml - └── src - └── lib.nr -``` - -Inside of the binary crate, you can specify: - -```toml -# Nargo.toml - -[dependencies] -lib_a = { path = "../lib_a" } -``` - -## Importing dependencies - -You can import a dependency to a Noir file using the following syntax. For example, to import the -ecrecover-noir library and local lib_a referenced above: - -```rust -use dep::ecrecover; -use dep::lib_a; -``` - -You can also import only the specific parts of dependency that you want to use, like so: - -```rust -use dep::std::hash::sha256; -use dep::std::scalar_mul::fixed_base_embedded_curve; -``` - -Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you -can import multiple items in the same line by enclosing them in curly braces: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; -``` - -We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. - -Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. - -## Dependencies of Dependencies - -Note that when you import a dependency, you also get access to all of the dependencies of that package. - -For example, the [phy_vector](https://github.com/resurgencelabs/phy_vector) library imports an [fraction](https://github.com/resurgencelabs/fraction) library. If you're importing the phy_vector library, then you can access the functions in fractions library like so: - -```rust -use dep::phy_vector; - -fn main(x : Field, y : pub Field) { - //... - let f = phy_vector::fraction::toFraction(true, 2, 1); - //... -} -``` - -## Available Libraries - -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). - -Some libraries that are available today include: - -- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library -- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) -- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers -- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address -- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees -- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir -- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/modules_packages_crates/modules.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/modules_packages_crates/modules.md deleted file mode 100644 index 11e60cbf35e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/modules_packages_crates/modules.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: Modules -description: - Learn how to organize your files using modules in Noir, following the same convention as Rust's - module system. Examples included. -keywords: [Noir, Rust, modules, organizing files, sub-modules] ---- - -Noir's module system follows the same convention as the _newer_ version of Rust's module system. - -## Purpose of Modules - -Modules are used to organize files. Without modules all of your code would need to live in a single -file. In Noir, the compiler does not automatically scan all of your files to detect modules. This -must be done explicitly by the developer. - -## Examples - -### Importing a module in the crate root - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::hello_world(); -} -``` - -Filename : `src/foo.nr` - -```rust -fn from_foo() {} -``` - -In the above snippet, the crate root is the `src/main.nr` file. The compiler sees the module -declaration `mod foo` which prompts it to look for a foo.nr file. - -Visually this module hierarchy looks like the following : - -``` -crate - ├── main - │ - └── foo - └── from_foo - -``` - -### Importing a module throughout the tree - -All modules are accessible from the `crate::` namespace. - -``` -crate - ├── bar - ├── foo - └── main - -``` - -In the above snippet, if `bar` would like to use functions in `foo`, it can do so by `use crate::foo::function_name`. - -### Sub-modules - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::from_foo(); -} -``` - -Filename : `src/foo.nr` - -```rust -mod bar; -fn from_foo() {} -``` - -Filename : `src/foo/bar.nr` - -```rust -fn from_bar() {} -``` - -In the above snippet, we have added an extra module to the module tree; `bar`. `bar` is a submodule -of `foo` hence we declare bar in `foo.nr` with `mod bar`. Since `foo` is not the crate root, the -compiler looks for the file associated with the `bar` module in `src/foo/bar.nr` - -Visually the module hierarchy looks as follows: - -``` -crate - ├── main - │ - └── foo - ├── from_foo - └── bar - └── from_bar -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/modules_packages_crates/workspaces.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/modules_packages_crates/workspaces.md deleted file mode 100644 index 8168793fc80..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/modules_packages_crates/workspaces.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -title: Workspaces ---- - -Workspaces are a feature of nargo that allow you to manage multiple related Noir packages in a single repository. A workspace is essentially a group of related projects that share common build output directories and configurations. - -Each Noir project (with it's own Nargo.toml file) can be thought of as a package. Each package is expected to contain exactly one "named circuit", being the "name" defined in Nargo.toml with the program logic defined in `./src/main.nr`. - -For a project with the following structure: - -```tree -├── crates -│ ├── a -│ │ ├── Nargo.toml -│ │ └── Prover.toml -│ │ └── src -│ │ └── main.nr -│ └── b -│ ├── Nargo.toml -│ └── Prover.toml -│ └── src -│ └── main.nr -│ -└── Nargo.toml -``` - -You can define a workspace in Nargo.toml like so: - -```toml -[workspace] -members = ["crates/a", "crates/b"] -default-member = "crates/a" -``` - -`members` indicates which packages are included in the workspace. As such, all member packages of a workspace will be processed when the `--workspace` flag is used with various commands or if a `default-member` is not specified. - -`default-member` indicates which package various commands process by default. - -Libraries can be defined in a workspace. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. - -Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/nargo/01_commands.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/nargo/01_commands.md deleted file mode 100644 index e2b0af522f4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/nargo/01_commands.md +++ /dev/null @@ -1,250 +0,0 @@ ---- -title: Commands -description: - Noir CLI Commands for Noir Prover and Verifier to create, execute, prove and verify programs, - generate Solidity verifier smart contract and compile into JSON file containing ACIR - representation and ABI of circuit. -keywords: - [ - Nargo, - Noir CLI, - Noir Prover, - Noir Verifier, - generate Solidity verifier, - compile JSON file, - ACIR representation, - ABI of circuit, - TypeScript, - ] ---- - -## General options - -| Option | Description | -| -------------------- | -------------------------------------------------- | -| `--show-ssa` | Emit debug information for the intermediate SSA IR | -| `--deny-warnings` | Quit execution when warnings are emitted | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo help [subcommand]` - -Prints the list of available commands or specific information of a subcommand. - -_Arguments_ - -| Argument | Description | -| -------------- | -------------------------------------------- | -| `` | The subcommand whose help message to display | - -## `nargo backend` - -Installs and selects custom backends used to generate and verify proofs. - -### Commands - -| Command | Description | -| ----------- | --------------------------------------------------------- | -| `current` | Prints the name of the currently active backend | -| `ls` | Prints the list of currently installed backends | -| `use` | Select the backend to use | -| `install` | Install a new backend from a URL | -| `uninstall` | Uninstalls a backend | -| `help` | Print this message or the help of the given subcommand(s) | - -### Options - -| Option | Description | -| ------------ | ----------- | -| `-h, --help` | Print help | - -## `nargo check` - -Generate the `Prover.toml` and `Verifier.toml` files for specifying prover and verifier in/output -values of the Noir program respectively. - -### Options - -| Option | Description | -| --------------------- | ------------------------------------- | -| `--package ` | The name of the package to check | -| `--workspace` | Check all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -### `nargo codegen-verifier` - -Generate a Solidity verifier smart contract for the program. - -### Options - -| Option | Description | -| --------------------- | ------------------------------------- | -| `--package ` | The name of the package to codegen | -| `--workspace` | Codegen all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo compile` - -Compile the program into a JSON build artifact file containing the ACIR representation and the ABI -of the circuit. This build artifact can then be used to generate and verify proofs. - -You can also use "build" as an alias for compile (e.g. `nargo build`). - -### Options - -| Option | Description | -| --------------------- | ------------------------------------------------------------ | -| `--include-keys` | Include Proving and Verification keys in the build artifacts | -| `--package ` | The name of the package to compile | -| `--workspace` | Compile all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo new ` - -Creates a new Noir project in a new folder. - -**Arguments** - -| Argument | Description | -| -------- | -------------------------------- | -| `` | The path to save the new project | - -### Options - -| Option | Description | -| --------------- | ----------------------------------------------------- | -| `--name ` | Name of the package [default: package directory name] | -| `--lib` | Use a library template | -| `--bin` | Use a binary template [default] | -| `--contract` | Use a contract template | -| `-h, --help` | Print help | - -## `nargo init` - -Creates a new Noir project in the current directory. - -### Options - -| Option | Description | -| --------------- | ----------------------------------------------------- | -| `--name ` | Name of the package [default: current directory name] | -| `--lib` | Use a library template | -| `--bin` | Use a binary template [default] | -| `--contract` | Use a contract template | -| `-h, --help` | Print help | - -## `nargo execute [WITNESS_NAME]` - -Runs the Noir program and prints its return value. - -**Arguments** - -| Argument | Description | -| ---------------- | ----------------------------------------- | -| `[WITNESS_NAME]` | Write the execution witness to named file | - -### Options - -| Option | Description | -| --------------------------------- | ------------------------------------------------------------------------------------ | -| `-p, --prover-name ` | The name of the toml file which contains the inputs for the prover [default: Prover] | -| `--package ` | The name of the package to execute | -| `--workspace` | Execute all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -_Usage_ - -The inputs to the circuit are read from the `Prover.toml` file generated by `nargo check`, which -must be filled in. - -To save the witness to file, run the command with a value for the `WITNESS_NAME` argument. A -`.tr` file will then be saved in the `./target` folder. - -## `nargo prove` - -Creates a proof for the program. - -### Options - -| Option | Description | -| ------------------------------------- | ---------------------------------------------------------------------------------------- | -| `-p, --prover-name ` | The name of the toml file which contains the inputs for the prover [default: Prover] | -| `-v, --verifier-name ` | The name of the toml file which contains the inputs for the verifier [default: Verifier] | -| `--verify` | Verify proof after proving | -| `--package ` | The name of the package to prove | -| `--workspace` | Prove all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo verify` - -Given a proof and a program, verify whether the proof is valid. - -### Options - -| Option | Description | -| ------------------------------------- | ---------------------------------------------------------------------------------------- | -| `-v, --verifier-name ` | The name of the toml file which contains the inputs for the verifier [default: Verifier] | -| `--package ` | The name of the package to verify | -| `--workspace` | Verify all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo test [TEST_NAME]` - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. To print `println` statements in tests, use the `--show-output` flag. - -Takes an optional `--exact` flag which allows you to select tests based on an exact name. - -See an example on the [testing page](./testing.md). - -### Options - -| Option | Description | -| --------------------- | -------------------------------------- | -| `--show-output` | Display output of `println` statements | -| `--exact` | Only run tests that match exactly | -| `--package ` | The name of the package to test | -| `--workspace` | Test all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo info` - -Prints a table containing the information of the package. - -Currently the table provide - -1. The number of ACIR opcodes -2. The final number gates in the circuit used by a backend - -If the file contains a contract the table will provide the -above information about each function of the contract. - -## `nargo lsp` - -Start a long-running Language Server process that communicates over stdin/stdout. -Usually this command is not run by a user, but instead will be run by a Language Client, such as [vscode-noir](https://github.com/noir-lang/vscode-noir). - -## `nargo fmt` - -Automatically formats your Noir source code based on the default formatting settings. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/nargo/02_testing.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/nargo/02_testing.md deleted file mode 100644 index 5c57ef92705..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/nargo/02_testing.md +++ /dev/null @@ -1,61 +0,0 @@ ---- -title: Testing in Noir -description: Learn how to use Nargo to test your Noir program in a quick and easy way -keywords: [Nargo, testing, Noir, compile, test] ---- - -You can test your Noir programs using Noir circuits. - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. - -For example if you have a program like: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test] -fn test_add() { - assert(add(2,2) == 4); - assert(add(0,1) == 1); - assert(add(1,0) == 1); -} -``` - -Running `nargo test` will test that the `test_add` function can be executed while satisfying all -the constraints which allows you to test that add returns the expected values. Test functions can't -have any arguments currently. - -### Test fail - -You can write tests that are expected to fail by using the decorator `#[test(should_fail)]`. For example: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test(should_fail)] -fn test_add() { - assert(add(2,2) == 5); -} -``` - -You can be more specific and make it fail with a specific reason by using `should_fail_with = "`: - -```rust -fn main(african_swallow_avg_speed : Field) { - assert(african_swallow_avg_speed == 65, "What is the airspeed velocity of an unladen swallow"); -} - -#[test] -fn test_king_arthur() { - main(65); -} - -#[test(should_fail_with = "What is the airspeed velocity of an unladen swallow")] -fn test_bridgekeeper() { - main(32); -} - -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/nargo/03_solidity_verifier.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/nargo/03_solidity_verifier.md deleted file mode 100644 index 9ac60cb0ba7..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/nargo/03_solidity_verifier.md +++ /dev/null @@ -1,129 +0,0 @@ ---- -title: Solidity Verifier -description: - Learn how to run the verifier as a smart contract on the blockchain. Compile a Solidity verifier - contract for your Noir program and deploy it on any EVM blockchain acting as a verifier smart - contract. Read more to find out! -keywords: - [ - solidity verifier, - smart contract, - blockchain, - compiler, - plonk_vk.sol, - EVM blockchain, - verifying Noir programs, - proving backend, - Barretenberg, - ] ---- - -For certain applications, it may be desirable to run the verifier as a smart contract instead of on -a local machine. - -Compile a Solidity verifier contract for your Noir program by running: - -```sh -nargo codegen-verifier -``` - -A new `contract` folder would then be generated in your project directory, containing the Solidity -file `plonk_vk.sol`. It can be deployed on any EVM blockchain acting as a verifier smart contract. - -> **Note:** It is possible to compile verifier contracts of Noir programs for other smart contract -> platforms as long as the proving backend supplies an implementation. -> -> Barretenberg, the default proving backend for Nargo, supports compilation of verifier contracts in -> Solidity only for the time being. - -## Verify - -To verify a proof using the Solidity verifier contract, call the `verify` function with the -following signature: - -```solidity -function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) -``` - -You can see an example of how the `verify` function is called in the example zk voting application [here](https://github.com/noir-lang/noir-examples/blob/33e598c257e2402ea3a6b68dd4c5ad492bce1b0a/foundry-voting/src/zkVote.sol#L35): - -```solidity -function castVote(bytes calldata proof, uint proposalId, uint vote, bytes32 nullifierHash) public returns (bool) { - // ... - bytes32[] memory publicInputs = new bytes32[](4); - publicInputs[0] = merkleRoot; - publicInputs[1] = bytes32(proposalId); - publicInputs[2] = bytes32(vote); - publicInputs[3] = nullifierHash; - require(verifier.verify(proof, publicInputs), "Invalid proof"); -``` - -### Public Inputs - -:::tip - -A circuit doesn't have the concept of a return value. Return values are just syntactic sugar in -Noir. - -Under the hood, the return value is passed as an input to the circuit and is checked at the end of -the circuit program. - -::: - -The verifier contract uses the output (return) value of a Noir program as a public input. So if you -have the following function - -```rust -fn main( - // Public inputs - pubkey_x: pub Field, - pubkey_y: pub Field, - // Private inputs - priv_key: Field, -) -> pub Field -``` - -then `verify` in `plonk_vk.sol` will expect 3 public inputs. Passing two inputs will result in an -error like `Reason: PUBLIC_INPUT_COUNT_INVALID(3, 2)`. - -In this case the 3 inputs to `verify` would be ordered as `[pubkey_x, pubkey_y, return]`. - -#### Struct inputs - -Consider the following program: - -```rust -struct Type1 { - val1: Field, - val2: Field, -} - -struct Nested { - t1: Type1, - is_true: bool, -} - -fn main(x: pub Field, nested: pub Nested, y: pub Field) { - //... -} -``` - -Structs will be flattened so that the array of inputs is 1-dimensional array. The order of these inputs would be flattened to: `[x, nested.t1.val1, nested.t1.val2, nested.is_true, y]` - -## Noir for EVM chains - -You can currently deploy the Solidity verifier contracts to most EVM compatible chains. EVM chains that have been tested and are known to work include: - -- Optimism -- Arbitrum -- Polygon PoS -- Scroll -- Celo - -Other EVM chains should work, but have not been tested directly by our team. If you test any other chains, please open a PR on this page to update the list. See [this doc](https://github.com/noir-lang/noir-starter/tree/main/with-foundry#testing-on-chain) for more info about testing verifier contracts on different EVM chains. - -### Unsupported chains - -Unfortunately not all "EVM" chains are supported. - -**zkSync** and the **Polygon zkEVM** do _not_ currently support proof verification via Solidity verifier contracts. They are missing the bn256 precompile contract that the verifier contract requires. Once these chains support this precompile, they may work. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/nargo/04_language_server.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/nargo/04_language_server.md deleted file mode 100644 index 48c01465f6e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/nargo/04_language_server.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Language Server -description: Learn about the Noir Language Server, how to install the components, and configuration that may be required. -keywords: [Nargo, Language Server, LSP, VSCode, Visual Studio Code] ---- - -This section helps you install and configure the Noir Language Server. - -The Language Server Protocol (LSP) has two components, the [Server](#language-server) and the [Client](#language-client). Below we describe each in the context of Noir. - -## Language Server - -The Server component is provided by the Nargo command line tool that you installed at the beginning of this guide. -As long as Nargo is installed and you've used it to run other commands in this guide, it should be good to go! - -If you'd like to verify that the `nargo lsp` command is available, you can run `nargo --help` and look for `lsp` in the list of commands. If you see it, you're using a version of Noir with LSP support. - -## Language Client - -The Client component is usually an editor plugin that launches the Server. It communicates LSP messages between the editor and the Server. For example, when you save a file, the Client will alert the Server, so it can try to compile the project and report any errors. - -Currently, Noir provides a Language Client for Visual Studio Code via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). - -> **Note:** Noir's Language Server Protocol support currently assumes users' VSCode workspace root to be the same as users' Noir project root (i.e. where Nargo.toml lies). -> -> If LSP features seem to be missing / malfunctioning, make sure you are opening your Noir project directly (instead of as a sub-folder) in your VSCode instance. - -When your language server is running correctly and the VSCode plugin is installed, you should see handy codelens buttons for compilation, measuring circuit size, execution, and tests: - -![Compile and Execute](@site/static/img/codelens_compile_execute.png) -![Run test](@site/static/img/codelens_run_test.png) - -You should also see your tests in the `testing` panel: - -![Testing panel](@site/static/img/codelens_testing_panel.png) - -### Configuration - -- **Noir: Enable LSP** - If checked, the extension will launch the Language Server via `nargo lsp` and communicate with it. -- **Noir: Nargo Flags** - Additional flags may be specified if you require them to be added when the extension calls `nargo lsp`. -- **Noir: Nargo Path** - An absolute path to a Nargo binary with the `lsp` command. This may be useful if Nargo is not within the `PATH` of your editor. -- **Noir > Trace: Server** - Setting this to `"messages"` or `"verbose"` will log LSP messages between the Client and Server. Useful for debugging. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/noir_js/getting_started/01_tiny_noir_app.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/noir_js/getting_started/01_tiny_noir_app.md deleted file mode 100644 index b3f1d6df747..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/noir_js/getting_started/01_tiny_noir_app.md +++ /dev/null @@ -1,256 +0,0 @@ ---- -title: End-to-end -description: Learn how to setup a new app that uses Noir to generate and verify zero-knowledge SNARK proofs in a typescript or javascript environment -keywords: [how to, guide, javascript, typescript, noir, barretenberg, zero-knowledge, proofs] ---- - -NoirJS works both on the browser and on the server, and works for both ESM and CJS module systems. In this page, we will learn how can we write a simple test and a simple web app to verify the standard Noir example. - -## Before we start - -:::note - -Feel free to use whatever versions, just keep in mind that Nargo and the NoirJS packages are meant to be in sync. For example, Nargo 0.18.x matches `noir_js@0.18.x`, etc. - -In this guide, we will be pinned to 0.17.0. - -::: - -Make sure you have Node installed on your machine by opening a terminal and executing `node --version`. If you don't see a version, you should install [node](https://github.com/nvm-sh/nvm). You can also use `yarn` if you prefer that package manager over npm (which comes with node). - -First of all, follow the [Nargo guide](../../getting_started/00_nargo_installation.md) to install nargo version 0.17.0 and create a new project with `nargo new circuit`. Once there, `cd` into the `circuit` folder. You should then be able to compile your circuit into `json` format and see it inside the `target` folder: - -```bash -nargo compile -``` - -Your folder structure should look like: - -```tree -. -└── circuit - ├── Nargo.toml - ├── src - │ └── main.nr - └── target - └── circuit.json -``` - -## Starting a new project - -Go back to the previous folder and start a new project by running run `npm init`. You can configure your project or just leave the defaults, and see a `package.json` appear in your root folder. - -## Installing dependencies - -We'll need two `npm` packages. These packages will provide us the methods we need to run and verify proofs: - -```bash -npm i @noir-lang/backend_barretenberg@^0.17.0 @noir-lang/noir_js@^0.17.0 -``` - -To serve our page, we can use a build tool such as `vite`. Because we're gonna use some `wasm` files, we need to install a plugin as well. Run: - -```bash -npm i --save-dev vite rollup-plugin-copy -``` - -Since we're on the dependency world, we may as well define a nice starting script. Vite makes it easy. Just open `package.json`, find the block "scripts" and add this just below the line with `"test" : "echo......."`: - -```json - "start": "vite --open" -``` - -If you want do build a static website, you can also add some build and preview scripts: - -```json - "build": "vite build", - "preview": "vite preview" -``` - -## Vite plugins - -Vite is great, but support from `wasm` doesn't work out-of-the-box. We're gonna write a quick plugin and use another one. Just copy and paste this into a file named `vite.config.js`. You don't need to understand it, just trust me bro. - -```js -import { defineConfig } from 'vite'; -import copy from 'rollup-plugin-copy'; -import fs from 'fs'; -import path from 'path'; - -const wasmContentTypePlugin = { - name: 'wasm-content-type-plugin', - configureServer(server) { - server.middlewares.use(async (req, res, next) => { - if (req.url.endsWith('.wasm')) { - res.setHeader('Content-Type', 'application/wasm'); - const newPath = req.url.replace('deps', 'dist'); - const targetPath = path.join(__dirname, newPath); - const wasmContent = fs.readFileSync(targetPath); - return res.end(wasmContent); - } - next(); - }); - }, -}; - -export default defineConfig(({ command }) => { - if (command === 'serve') { - return { - plugins: [ - copy({ - targets: [{ src: 'node_modules/**/*.wasm', dest: 'node_modules/.vite/dist' }], - copySync: true, - hook: 'buildStart', - }), - command === 'serve' ? wasmContentTypePlugin : [], - ], - }; - } - - return {}; -}); -``` - -## HTML - -Here's the simplest HTML with some terrible UI. Create a file called `index.html` and paste this: - -```html - - - - - - -

Very basic Noir app

-
-

Logs

-

Proof

-
- - -``` - -## Some good old vanilla Javascript - -Create a new file `app.js`, which is where our javascript code will live. Let's start with this code inside: - -```js -document.addEventListener('DOMContentLoaded', async () => { - // here's where the magic happens -}); - -function display(container, msg) { - const c = document.getElementById(container); - const p = document.createElement('p'); - p.textContent = msg; - c.appendChild(p); -} -``` - -We can manipulate our website with this little function, so we can see our website working. - -## Adding Noir - -If you come from the previous page, your folder structure should look like this: - -```tree -├── app.js -├── circuit -│ ├── Nargo.toml -│ ├── src -│ │ └── main.nr -│ └── target -│ └── circuit.json -├── index.html -├── package.json -└── vite.config.js -``` - -You'll see other files and folders showing up (like `package-lock.json`, `yarn.lock`, `node_modules`) but you shouldn't have to care about those. - -## Importing our dependencies - -We're starting with the good stuff now. At the top of the new javascript file, import the packages: - -```ts -import { BarretenbergBackend } from '@noir-lang/backend_barretenberg'; -import { Noir } from '@noir-lang/noir_js'; -``` - -We also need to import the `circuit` JSON file we created. If you have the suggested folder structure, you can add this line: - -```ts -import circuit from './circuit/target/circuit.json'; -``` - -## Write code - -:::note - -We're gonna be adding code inside the `document.addEventListener...etc` block: - -```js -// forget stuff here -document.addEventListener('DOMContentLoaded', async () => { - // here's where the magic happens -}); -// forget stuff here -``` - -::: - -Our dependencies exported two classes: `BarretenbergBackend` and `Noir`. Let's `init` them and add some logs, just to flex: - -```ts -const backend = new BarretenbergBackend(circuit); -const noir = new Noir(circuit, backend); -``` - -## Proving - -Now we're ready to prove stuff! Let's feed some inputs to our circuit and calculate the proof: - -```js -const input = { x: 1, y: 2 }; -display('logs', 'Generating proof... ⌛'); -const proof = await noir.generateFinalProof(input); -display('logs', 'Generating proof... ✅'); -display('results', proof.proof); -``` - -You're probably eager to see stuff happening, so go and run your app now! - -From your terminal, run `npm start` (or `yarn start`). If it doesn't open a browser for you, just visit `localhost:5173`. On a modern laptop, proof will generate in less than 100ms, and you'll see this: - -![Getting Started 0](@site/static/img/noir_getting_started_1.png) - -If you're human, you shouldn't be able to understand anything on the "proof" box. That's OK. We like you, human. - -In any case, this means your proof was generated! But you shouldn't trust me just yet. Add these lines to see it being verified: - -```js -display('logs', 'Verifying proof... ⌛'); -const verification = await noir.verifyFinalProof(proof); -if (verification) display('logs', 'Verifying proof... ✅'); -``` - -By saving, your app will refresh and here's our complete Tiny Noir App! - -## Further Reading - -You can see how noirjs is used in a full stack Next.js hardhat application in the [noir-starter repo here](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat). The example shows how to calculate a proof in the browser and verify it with a deployed Solidity verifier contract from noirjs. - -You should also check out the more advanced examples in the [noir-examples repo](https://github.com/noir-lang/noir-examples), where you'll find reference usage for some cool apps. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/noir_js/noir_js.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/noir_js/noir_js.md deleted file mode 100644 index 23ea550e156..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/noir_js/noir_js.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: NoirJS -description: Interact with Noir in Typescript or Javascript -keywords: [Noir project, javascript, typescript, node.js, browser, react] ---- - -NoirJS is a TypeScript library that make it easy to use Noir on your dapp, webapp, Node.js server, website, etc. - -A typical workflow would be composed of two major elements: - -- NoirJS -- Proving backend of choice's JavaScript package - - - -To install NoirJS, install Node.js if you have not already and run this in your JavaScript project: - -```bash -npm i @noir-lang/noir_js -``` - -## Proving backend - -Since Noir is backend agnostic, you can instantiate NoirJS without any backend (i.e. to execute a function). But for proving, you would have to instantiate NoirJS with any of the supported backends through their own `js` interface. - -### Barretenberg - -Aztec Labs maintains the `barretenberg` proving backend, which you can instantiate and make use of alongside NoirJS. It is also the default proving backend installed and used with Nargo, the Noir CLI tool. - -To install its JavaScript library, run this in your project: - -```bash -npm i @noir-lang/backend_barretenberg -``` - -For more details on how to instantiate and use the libraries, refer to the [Full Noir App Guide](./getting_started/01_tiny_noir_app.md) and [Reference](./reference/01_noirjs.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/noir_js/reference/01_noirjs.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/noir_js/reference/01_noirjs.md deleted file mode 100644 index 3480fbfedad..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/noir_js/reference/01_noirjs.md +++ /dev/null @@ -1,143 +0,0 @@ ---- -title: Noir -description: Reference to noir_js library and the Noir class -keywords: [Noir project, javascript, typescript, node.js, browser, react, class, reference] ---- - -## Table of Contents - -- [constructor](#constructor) -- [init](#init) -- [generateFinalProof](#generatefinalproof) -- [verifyFinalProof](#verifyfinalproof) - -## `constructor` - -The `constructor` is a method used to create and initialize objects created within the `Noir` class. In the `Noir` class constructor, you need to pass two parameters: `circuit` and `backend`. - -### Syntax - -```js -constructor(circuit, backend); -``` - -### Parameters - -| Parameter | Type | Description | -| --------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `circuit` | Object | A circuit represented in a `json` format, containing the ABI and bytecode. Typically obtained by running [`nargo compile`](../../nargo/01_commands.md) | -| `backend` | Object | A backend instance, before initialization. | - -### Usage - -```js -const noir = new Noir(circuit, backend); -``` - -## `init` - -This async method should be called after class instantiation. It will run processes on the ACVM, instantiate your backend, etc. - -### Syntax - -```js -async init() -``` - -### Parameters - -This method takes no parameters - -### Usage - -```js -await noirInstance.init(); -``` - -## `execute` - -This async method allows to execute a circuit to get its witness and return value. [`generateFinalProof`](#generatefinalproof) calls it for you, but you can call it directly (i.e. to feed directly to a backend, or to get the return value). - -### Syntax - -```js -async execute(inputs) -``` - -### Parameters - -| Parameter | Type | Description | -| --------- | ------ | ------------------------------------------------ | -| `inputs` | Object | An object containing the inputs to your circuit. | - -### Returns - -| Return value | Type | Description | -| ------------ | --------------------- | --------------------------------------------------- | -| `witness` | Promise \ | The witness | -| `returnValue` | Promise \ | The return value | - -### Usage - -```js -const { witness, returnValue } = await noir.execute(inputs) -``` - -## `generateFinalProof` - -This async method generates a witness and a proof given an object as input. - -### Syntax - -```js -async generateFinalProof(input) -``` - -### Parameters - -| Parameter | Type | Description | -| --------- | ------ | ------------------------------------------------ | -| `input` | Object | An object containing the inputs to your circuit. | - -### Returns - -| Return value | Type | Description | -| ------------ | --------------------- | --------------------------------------------------- | -| `proof` | Promise \ | An array with the byte representation of the proof. | - -### Usage - -```js -// consider the Standard Noir Example given with nargo init -const input = { x: 1, y: 2 }; -noirInstance.generateProof(input); -``` - -## `verifyFinalProof` - -This async method instantiates the verification key and verifies your proof. - -### Syntax - -```js -async verifyFinalProof(proof) -``` - -### Parameters - -| Parameter | Type | Description | -| --------- | ---------- | --------------------------------------------------------------------------------------------- | -| `proof` | Uint8Array | The Uint8Array representation of your proof, usually obtained by calling `generateFinalProof` | - -### Returns - -| Return value | Type | Description | -| ------------ | ------------------ | -------------------------------------------- | -| `verified` | Promise \ | A boolean for whether the proof was verified | - -### Usage - -```js -const proof = noirInstance.generateProof(input); -noirInstance.verifyFinalProof(proof); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/noir_js/reference/02_bb_backend.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/noir_js/reference/02_bb_backend.md deleted file mode 100644 index 958cabd6289..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/noir_js/reference/02_bb_backend.md +++ /dev/null @@ -1,272 +0,0 @@ ---- -title: BarretenbergBackend -description: Reference documentation for the barretenberg_backend library and the BarretenbergBackend class -keywords: - [ - BarretenbergBackend, - Barretenberg, - javascript, - typescript, - node.js, - browser, - class, - reference, - noir_js, - ] ---- - -## Table of Contents - -- [constructor](#constructor) -- [generateFinalProof](#generatefinalproof) -- [generateIntermediateProof](#generateintermediateproof) -- [generateProof](#generateproof) -- [generateIntermediateProofArtifacts](#generateintermediateproofartifacts) -- [verifyFinalProof](#verifyfinalproof) -- [verifyIntermediateProof](#verifyintermediateproof) -- [verifyProof](#verifyproof) -- [destroy](#destroy) - -## `constructor` - -The `constructor` is a method used to create and initialize objects created within the `BarretenbergBackend` class. In this class, you should pass at least one argument for the `circuit`. - -### Syntax - -```js -constructor(acirCircuit, (numberOfThreads = 1)); -``` - -### Parameters - -| Parameter | Type | Description | -| ----------------- | ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `acirCircuit` | Object | A circuit represented in a `json` format, containing the ABI and bytecode typically obtained by running [`nargo compile`](../../nargo/01_commands.md). This is the same circuit expected to be passed to [the Noir class](01_noirjs.md) | -| `numberOfThreads` | Number (optional) | The number of threads to be used by the backend. Defaults to 1. | - -### Usage - -```js -const backend = new BarretenbergBackend(acirCircuit); -``` - -## `generateFinalProof` - -An async wrapper around the [generateProof](#generateproof) method that passes a `false` flag. Usually called by the Noir class. - -### Syntax - -```js -async generateFinalProof(decompressedWitness) -``` - -### Parameters - -| Parameter | Type | Description | -| --------------------- | ------ | -------------------------------------------------------- | -| `decompressedWitness` | Object | The decompressed witness for generating the final proof. | - -### Returns - -| Return value | Type | Description | -| ------------ | -------------------- | --------------------------------------------------------- | -| `proof` | Promise\ | An array with the byte representation of the final proof. | - -### Usage - -```js -const finalProof = await backend.generateFinalProof(decompressedWitness); -``` - -## `generateIntermediateProof` - -An async wrapper around the [generateProof](#generateproof) method that passes a `true` flag. It's not currently being used by the Noir class, but developers can call this method directly to use Noir's recursive features. - -### Syntax - -```js -async generateIntermediateProof(witness) -``` - -### Parameters - -| Parameter | Type | Description | -| --------- | ------ | -------------------------------------------------- | -| `witness` | Object | The witness for generating the intermediate proof. | - -### Returns - -| Return value | Type | Description | -| ------------ | -------------------- | --------------------------------------------------------------- | -| `proof` | Promise\ | An array with the byte representation of the intermediate proof | - -### Usage - -```js -const intermediateProof = await backend.generateIntermediateProof(witness); -``` - -## `generateProof` - -This async method generates a proof. Takes the witness generated by ACVM, and a boolean that evaluates to `true` when the proof _is_ meant to be verified in another circuit. Not currently used by the Noir class. - -### Syntax - -```js -async generateProof(decompressedWitness, makeEasyToVerifyInCircuit) -``` - -### Parameters - -| Parameter | Type | Description | -| --------------------------- | ------- | ---------------------------------------------------------------------------------------------- | -| `decompressedWitness` | Object | The decompressed witness for generating the proof. | -| `makeEasyToVerifyInCircuit` | Boolean | A flag indicating whether to generate proof components for easy verification within a circuit. | - -### Returns - -| Return value | Type | Description | -| ------------ | -------------------- | -------------------------------------------------- | -| `proof` | Promise\ | An array with the byte representation of the proof | - -### Usage - -```js -const proof = await backend.generateProof(decompressedWitness, makeEasyToVerifyInCircuit); -``` - -## `generateIntermediateProofArtifacts` - -This async method returns the artifacts needed to verify the intermediate proof in another circuit. It's not currently being used by the Noir class, but developers can call this method directly to use Noir's recursive features. - -### Syntax - -```js -async generateIntermediateProofArtifacts(proof, numOfPublicInputs = 0) -``` - -### Parameters - -| Parameter | Type | Description | -| ------------------- | ----------------- | ---------------------------------------------------------------- | -| `proof` | Object | The proof object. | -| `numOfPublicInputs` | Number (optional) | The number of public inputs in the inner proof, defaulting to 0. | - -### Returns - -| Return value | Type | Description | -| --------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `proofAsFields` | string[] | An array of strings with the hexadecimal representation of the [Fields](../../language_concepts/data_types/00_fields.md) that make up a proof | -| `vkAsFields` | string[] | An array of strings with the hexadecimal representation of the [Fields](../../language_concepts/data_types/00_fields.md) that make up the verification key | -| `vkHash` | string | A pedersen hash of the verification key | - -### Usage - -```js -const artifacts = await backend.generateIntermediateProofArtifacts(proof, numOfPublicInputs); -``` - -## `verifyFinalProof` - -An async wrapper around [verifyProof](#verifyproof) that sets the `false` flag. Usually called by the Noir class. - -### Syntax - -```js -async verifyFinalProof(proof) -``` - -### Parameters - -| Parameter | Type | Description | -| --------- | ------ | --------------------------- | -| `proof` | Object | The proof object to verify. | - -### Returns - -| Return value | Type | Description | -| ------------ | ------------------ | -------------------------------------------- | -| `verified` | Promise \ | A boolean for whether the proof was verified | - -### Usage - -```js -const isValidFinal = await backend.verifyFinalProof(proof); -``` - -## `verifyIntermediateProof` - -An async wrapper around [verifyProof](#verifyproof) that sets the `true` flag. It's not currently being used by the Noir class, but developers can call this method directly to use Noir's recursive features. - -### Syntax - -```js -async verifyIntermediateProof(proof) -``` - -### Parameters - -| Parameter | Type | Description | -| --------- | ------ | ---------------------------------------- | -| `proof` | Object | The intermediate proof object to verify. | - -### Returns - -| Return value | Type | Description | -| ------------ | ------------------ | -------------------------------------------- | -| `verified` | Promise \ | A boolean for whether the proof was verified | - -### Usage - -```js -const isValidIntermediate = await backend.verifyIntermediateProof(proof); -``` - -## `verifyProof` - -This async method verifies a proof. Takes the proof, and a boolean that evaluates to `true` when the proof is intermediate. - -### Syntax - -```js -async verifyProof(proof, makeEasyToVerifyInCircuit) -``` - -### Parameters - -| Parameter | Type | Description | -| --------------------------- | ------- | ------------------------------------------------------------ | -| `proof` | Object | The proof object to verify | -| `makeEasyToVerifyInCircuit` | Boolean | A flag indicating whether the proof is intermediate or final | - -### Returns - -| Parameter | Type | Description | -| ---------- | ------------------ | -------------------------------------------- | -| `verified` | Promise\ | A boolean for whether the proof was verified | - -### Usage - -```js -const isValid = await backend.verifyProof(proof, makeEasyToVerifyInCircuit); -``` - -## `destroy` - -This method destroys the resources allocated in the [instantiate](#instantiate) method. Noir doesn't currently call this method, but it's highly recommended that developers do so in order to save resources. - -### Syntax - -```js -async destroy() -``` - -### Parameters - -This method takes no parameters. - -### Usage - -```js -await backend.destroy(); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/black_box_fns.md deleted file mode 100644 index b4dedefe4c9..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/black_box_fns.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Black Box Functions -description: Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. -keywords: [noir, black box functions] ---- - -Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. This makes certain zk-snark unfriendly computations cheaper than if they were implemented in Noir. - -:::warning - -It is likely that not all backends will support a particular black box function. - -::: - -Because it is not guaranteed that all backends will support black box functions, it is possible that certain Noir programs won't compile against a particular backend if they use an unsupported black box function. It is possible to fallback to less efficient implementations written in Noir/ACIR in some cases. - -Black box functions are specified with the `#[foreign(black_box_fn)]` attribute. For example, the SHA256 function in the Noir [source code](https://github.com/noir-lang/noir/blob/v0.5.1/noir_stdlib/src/hash.nr) looks like: - -```rust -#[foreign(sha256)] -fn sha256(_input : [u8; N]) -> [u8; 32] {} -``` - -## Function list - -Here is a list of the current black box functions that are supported by UltraPlonk: - -- AES -- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) -- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) -- [Pedersen](./cryptographic_primitives/hashes.mdx#pedersen) -- [HashToField128Security](./cryptographic_primitives/hashes.mdx#hash_to_field) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx) -- [Compute merkle root](./merkle_trees.md#compute_merkle_root) -- AND -- XOR -- RANGE -- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion.md) - -Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. - -You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/noir/blob/master/acvm-repo/acir/src/circuit/black_box_functions.rs). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives.md deleted file mode 100644 index 2df4f929474..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Cryptographic primitives in Noir -description: - Learn about the cryptographic primitives ready to use for any Noir project -keywords: - [ - cryptographic primitives, - Noir project, - ] ---- - -The Noir team is progressively adding new cryptographic primitives to the standard library. Reach out for news or if you would be interested in adding more of these calculations in Noir. - -Some methods are available thanks to the Aztec backend, not being performed using Noir. When using other backends, these methods may or may not be supplied. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives/00_hashes.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives/00_hashes.mdx deleted file mode 100644 index 2cc3cd81e4e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives/00_hashes.mdx +++ /dev/null @@ -1,146 +0,0 @@ ---- -title: Hash methods -description: - Learn about the cryptographic primitives ready to use for any Noir project, including sha256, - blake2s, pedersen, mimc_bn254 and mimc -keywords: - [cryptographic primitives, Noir project, sha256, blake2s, pedersen, mimc_bn254, mimc, hash] ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## sha256 - -Given an array of bytes, returns the resulting sha256 hash. - -```rust -fn sha256(_input : [u8]) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::sha256(x); -} -``` - - - -## blake2s - -Given an array of bytes, returns an array with the Blake2 hash - -```rust -fn blake2s(_input : [u8]) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::blake2s(x); -} -``` - - - -## pedersen - -Given an array of Fields, returns the Pedersen hash. - -```rust -fn pedersen(_input : [Field]) -> [Field; 2] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::pedersen(x); -} -``` - - - -## keccak256 - -Given an array of bytes (`u8`), returns the resulting keccak hash as an array of 32 bytes -(`[u8; 32]`). Specify a message_size to hash only the first `message_size` bytes -of the input. - -```rust -fn keccak256(_input : [u8; N], _message_size: u32) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let message_size = 4; - let hash = std::hash::keccak256(x, message_size); -} -``` - - - -## poseidon - -Given an array of Fields, returns a new Field with the Poseidon Hash. Mind that you need to specify -how many inputs are there to your Poseidon function. - -```rust -// example for hash_1, hash_2 accepts an array of length 2, etc -fn hash_1(input: [Field; 1]) -> Field -``` - -example: - -```rust -fn main() -{ - let hash1 = std::hash::poseidon::bn254::hash_2([1, 2]); - assert(hash1 == 0x115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189a); -} -``` - -## mimc_bn254 and mimc - -`mimc_bn254` is `mimc`, but with hardcoded parameters for the BN254 curve. You can use it by -providing an array of Fields, and it returns a Field with the hash. You can use the `mimc` method if -you're willing to input your own constants: - -```rust -fn mimc(x: Field, k: Field, constants: [Field; N], exp : Field) -> Field -``` - -otherwise, use the `mimc_bn254` method: - -```rust -fn mimc_bn254(array: [Field; N]) -> Field -``` - -example: - -```rust - -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::mimc_bn254(x); -} -``` - -## hash_to_field - -```rust -fn hash_to_field(_input : [Field; N]) -> Field {} -``` - -Calculates the `blake2s` hash of the inputs and returns the hash modulo the field modulus to return -a value which can be represented as a `Field`. - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives/01_scalar.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives/01_scalar.mdx deleted file mode 100644 index c7eed820a80..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives/01_scalar.mdx +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: Scalar multiplication -description: See how you can perform scalar multiplications over a fixed base in Noir -keywords: [cryptographic primitives, Noir project, scalar multiplication] ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## scalar_mul::fixed_base_embedded_curve - -Performs scalar multiplication over the embedded curve whose coordinates are defined by the -configured noir field. For the BN254 scalar field, this is BabyJubJub or Grumpkin. - -```rust -fn fixed_base_embedded_curve(_input : Field) -> [Field; 2] -``` - -example - -```rust -fn main(x : Field) { - let scal = std::scalar_mul::fixed_base_embedded_curve(x); - std::println(scal); -} -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives/02_schnorr.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives/02_schnorr.mdx deleted file mode 100644 index c184ce28120..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives/02_schnorr.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: Schnorr Signatures -description: Learn how you can verify Schnorr signatures using Noir -keywords: [cryptographic primitives, Noir project, schnorr, signatures] ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## schnorr::verify_signature - -Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin). - -```rust -fn verify_signature(_public_key_x: Field, _public_key_y: Field, _signature: [u8; 64], _message: [u8]) -> bool -``` - -where `_signature` can be generated like so using the npm package -[@noir-lang/barretenberg](https://www.npmjs.com/package/@noir-lang/barretenberg) - -```js -const { BarretenbergWasm } = require('@noir-lang/barretenberg/dest/wasm'); -const { Schnorr } = require('@noir-lang/barretenberg/dest/crypto/schnorr'); - -... - -const barretenberg = await BarretenbergWasm.new(); -const schnorr = new Schnorr(barretenberg); -const pubKey = schnorr.computePublicKey(privateKey); -const message = ... -const signature = Array.from( - schnorr.constructSignature(hash, privateKey).toBuffer() -); - -... -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx deleted file mode 100644 index 72bce984821..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: ECDSA Signature Verification -description: Learn about the cryptographic primitives regarding ECDSA over the secp256k1 and secp256r1 curves -keywords: [cryptographic primitives, Noir project, ecdsa, secp256k1, secp256r1, signatures] ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -Noir supports ECDSA signatures verification over the secp256k1 and secp256r1 curves. - -## ecdsa_secp256k1::verify_signature - -Verifier for ECDSA Secp256k1 signatures - -```rust -fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message: [u8]) -> bool -``` - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - -## ecdsa_secp256r1::verify_signature - -Verifier for ECDSA Secp256r1 signatures - -```rust -fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message: [u8]) -> bool -``` - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives/04_ec_primitives.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives/04_ec_primitives.md deleted file mode 100644 index 0f431e40056..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives/04_ec_primitives.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -title: Elliptic Curve Primitives -keywords: [cryptographic primitives, Noir project] ---- - -Data structures and methods on them that allow you to carry out computations involving elliptic -curves over the (mathematical) field corresponding to `Field`. For the field currently at our -disposal, applications would involve a curve embedded in BN254, e.g. the -[Baby Jubjub curve](https://eips.ethereum.org/EIPS/eip-2494). - -## Data structures - -### Elliptic curve configurations - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Curve`), i.e. the specific elliptic -curve you want to use, which would be specified using any one of the methods -`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::new` which take the coefficients in the -defining equation together with a generator point as parameters. You can find more detail in the -comments in -[`noir_stdlib/src/ec.nr`](https://github.com/noir-lang/noir/blob/v0.17.0/noir_stdlib/src/ec.nr), but -the gist of it is that the elliptic curves of interest are usually expressed in one of the standard -forms implemented here (Twisted Edwards, Montgomery and Short Weierstraß), and in addition to that, -you could choose to use `affine` coordinates (Cartesian coordinates - the usual (x,y) - possibly -together with a point at infinity) or `curvegroup` coordinates (some form of projective coordinates -requiring more coordinates but allowing for more efficient implementations of elliptic curve -operations). Conversions between all of these forms are provided, and under the hood these -conversions are done whenever an operation is more efficient in a different representation (or a -mixed coordinate representation is employed). - -### Points - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Point`), i.e. points lying on the -elliptic curve. For a curve configuration `c` and a point `p`, it may be checked that `p` -does indeed lie on `c` by calling `c.contains(p1)`. - -## Methods - -(given a choice of curve representation, e.g. use `std::ec::tecurve::affine::Curve` and use -`std::ec::tecurve::affine::Point`) - -- The **zero element** is given by `Point::zero()`, and we can verify whether a point `p: Point` is - zero by calling `p.is_zero()`. -- **Equality**: Points `p1: Point` and `p2: Point` may be checked for equality by calling - `p1.eq(p2)`. -- **Addition**: For `c: Curve` and points `p1: Point` and `p2: Point` on the curve, adding these two - points is accomplished by calling `c.add(p1,p2)`. -- **Negation**: For a point `p: Point`, `p.negate()` is its negation. -- **Subtraction**: For `c` and `p1`, `p2` as above, subtracting `p2` from `p1` is accomplished by - calling `c.subtract(p1,p2)`. -- **Scalar multiplication**: For `c` as above, `p: Point` a point on the curve and `n: Field`, - scalar multiplication is given by `c.mul(n,p)`. If instead `n :: [u1; N]`, i.e. `n` is a bit - array, the `bit_mul` method may be used instead: `c.bit_mul(n,p)` -- **Multi-scalar multiplication**: For `c` as above and arrays `n: [Field; N]` and `p: [Point; N]`, - multi-scalar multiplication is given by `c.msm(n,p)`. -- **Coordinate representation conversions**: The `into_group` method converts a point or curve - configuration in the affine representation to one in the CurveGroup representation, and - `into_affine` goes in the other direction. -- **Curve representation conversions**: `tecurve` and `montcurve` curves and points are equivalent - and may be converted between one another by calling `into_montcurve` or `into_tecurve` on their - configurations or points. `swcurve` is more general and a curve c of one of the other two types - may be converted to this representation by calling `c.into_swcurve()`, whereas a point `p` lying - on the curve given by `c` may be mapped to its corresponding `swcurve` point by calling - `c.map_into_swcurve(p)`. -- **Map-to-curve methods**: The Elligator 2 method of mapping a field element `n: Field` into a - `tecurve` or `montcurve` with configuration `c` may be called as `c.elligator2_map(n)`. For all of - the curve configurations, the SWU map-to-curve method may be called as `c.swu_map(z,n)`, where - `z: Field` depends on `Field` and `c` and must be chosen by the user (the conditions it needs to - satisfy are specified in the comments - [here](https://github.com/noir-lang/noir/blob/v0.17.0/noir_stdlib/src/ec.nr). - -## Examples - -The -[ec_baby_jubjub test](https://github.com/noir-lang/noir/blob/master/test_programs/compile_success_empty/ec_baby_jubjub/src/main.nr) -illustrates all of the above primitives on various forms of the Baby Jubjub curve. A couple of more -interesting examples in Noir would be: - -Public-key cryptography: Given an elliptic curve and a 'base point' on it, determine the public key -from the private key. This is a matter of using scalar multiplication. In the case of Baby Jubjub, -for example, this code would do: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; - -fn bjj_pub_key(priv_key: Field) -> Point -{ - - let bjj = Curve::new(168700, 168696, G::new(995203441582195749578291179787384436505546430278305826713579947235728471134,5472060717959818805561601436314318772137091100104008585924551046643952123905)); - - let base_pt = Point::new(5299619240641551281634865583518297030282874472190772894086521144482721001553, 16950150798460657717958625567821834550301663161624707787222815936182638968203); - - bjj.mul(priv_key,base_pt) -} -``` - -This would come in handy in a Merkle proof. - -- EdDSA signature verification: This is a matter of combining these primitives with a suitable hash - function. See - [feat(stdlib): EdDSA sig verification noir#1136](https://github.com/noir-lang/noir/pull/1136) for - the case of Baby Jubjub and the Poseidon hash function. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives/05_eddsa.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives/05_eddsa.mdx deleted file mode 100644 index 9a5beb55ee9..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives/05_eddsa.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: EdDSA Verification -description: Learn about the cryptographic primitives regarding EdDSA -keywords: [cryptographic primitives, Noir project, eddsa, signatures] ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## eddsa::eddsa_poseidon_verify - -Verifier for EdDSA signatures - -```rust -fn eddsa_poseidon_verify(public_key_x : Field, public_key_y : Field, signature_s: Field, signature_r8_x: Field, signature_r8_y: Field, message: Field) -> bool -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/logging.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/logging.md deleted file mode 100644 index 4ba0fe0e656..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/logging.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -title: Logging -description: - Learn how to use the println statement for debugging in Noir with this tutorial. Understand the - basics of logging in Noir and how to implement it in your code. -keywords: - [ - noir logging, - println statement, - debugging in noir, - noir std library, - logging tutorial, - basic logging in noir, - noir logging implementation, - noir debugging techniques, - rust, - ] ---- - -The standard library provides a familiar `println` statement you can use. Despite being a limited -implementation of rust's `println!` macro, this construct can be useful for debugging. - -You can print the output of println statements in your Noir code by using the `nargo execute` command or the `--show-output` flag when using `nargo test` (provided there are println statements in your tests). - -It is recommended to use `nargo execute` if you want to debug failing constraints with `println` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). `println` will not work for failed constraints caught at compile time. - -The `println` statement is unconstrained, so it works for outputting integers, fields, strings, and even structs or expressions. For example: - -```rust -use dep::std; - -struct Person { - age : Field, - height : Field, -} - -fn main(age : Field, height : Field) { - let person = Person { age : age, height : height }; - std::println(person); - std::println(age + height); - std::println("Hello world!"); -} - -``` - -You can print multiple different types in the same statement and string as well as a new "fmtstr" type. A `fmtstr` can be specified in the same way as a normal string it just should be prepended with an "f" character: - -```rust - let fmt_str = f"i: {i}, j: {j}"; - std::println(fmt_str); - - let s = myStruct { y: x, x: y }; - std::println(s); - - std::println(f"i: {i}, s: {s}"); - - std::println(x); - std::println([x, y]); - - let foo = fooStruct { my_struct: s, foo: 15 }; - std::println(f"s: {s}, foo: {foo}"); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/merkle_trees.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/merkle_trees.md deleted file mode 100644 index 9761105f4f2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/merkle_trees.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: Merkle Trees -description: Learn about Merkle Trees in Noir with this tutorial. Explore the basics of computing a merkle root using a proof, with examples. -keywords: - [ - Merkle trees in Noir, - Noir programming language, - check membership, - computing root from leaf, - Noir Merkle tree implementation, - Merkle tree tutorial, - Merkle tree code examples, - Noir libraries, - pedersen hash., - ] ---- - -## compute_merkle_root - -Returns the root of the tree from the provided leaf and its hash path, using a [Pedersen hash](cryptographic_primitives/00_hashes.mdx#pedersen). - -```rust -fn compute_merkle_root(leaf : Field, index : Field, hash_path: [Field]) -> Field -``` - -example: - -```rust -/** - // these values are for this example only - index = "0" - priv_key = "0x000000000000000000000000000000000000000000000000000000616c696365" - secret = "0x1929ea3ab8d9106a899386883d9428f8256cfedb3c4f6b66bf4aa4d28a79988f" - note_hash_path = [ - "0x1e61bdae0f027b1b2159e1f9d3f8d00fa668a952dddd822fda80dc745d6f65cc", - "0x0e4223f3925f98934393c74975142bd73079ab0621f4ee133cee050a3c194f1a", - "0x2fd7bb412155bf8693a3bd2a3e7581a679c95c68a052f835dddca85fa1569a40" - ] - */ -fn main(index: Field, priv_key: Field, secret: Field, note_hash_path: [Field; 3]) { - - let pubkey = std::scalar_mul::fixed_base_embedded_curve(priv_key); - let pubkey_x = pubkey[0]; - let pubkey_y = pubkey[1]; - let note_commitment = std::hash::pedersen([pubkey_x, pubkey_y, secret]); - - let root = std::merkle::compute_merkle_root(note_commitment[0], index, note_hash_path); - std::println(root); -} -``` - -To check merkle tree membership: - -1. Include a merkle root as a program input. -2. Compute the merkle root of a given leaf, index and hash path. -3. Assert the merkle roots are equal. - -For more info about merkle trees, see the Wikipedia [page](https://en.wikipedia.org/wiki/Merkle_tree). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/options.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/options.md deleted file mode 100644 index 3d3139fb98b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/options.md +++ /dev/null @@ -1,99 +0,0 @@ ---- -title: Option Type ---- - -The `Option` type is a way to express that a value might be present (`Some(T))` or absent (`None`). It's a safer way to handle potential absence of values, compared to using nulls in many other languages. - -```rust -struct Option { - None, - Some(T), -} -``` - -You can import the Option type into your Noir program like so: - -```rust -use dep::std::option::Option; - -fn main() { - let none = Option::none(); - let some = Option::some(3); -} -``` - -See [this test](https://github.com/noir-lang/noir/blob/5cbfb9c4a06c8865c98ff2b594464b037d821a5c/crates/nargo_cli/tests/test_data/option/src/main.nr) for a more comprehensive set of examples of each of the methods described below. - -## Methods - -### none - -Constructs a none value. - -### some - -Constructs a some wrapper around a given value. - -### is_none - -Returns true if the Option is None. - -### is_some - -Returns true of the Option is Some. - -### unwrap - -Asserts `self.is_some()` and returns the wrapped value. - -### unwrap_unchecked - -Returns the inner value without asserting `self.is_some()`. This method can be useful within an if condition when we already know that `option.is_some()`. If the option is None, there is no guarantee what value will be returned, only that it will be of type T for an `Option`. - -### unwrap_or - -Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value. - -### unwrap_or_else - -Returns the wrapped value if `self.is_some()`. Otherwise, calls the given function to return a default value. - -### map - -If self is `Some(x)`, this returns `Some(f(x))`. Otherwise, this returns `None`. - -### map_or - -If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns the given default value. - -### map_or_else - -If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns `default()`. - -### and - -Returns None if self is None. Otherwise, this returns `other`. - -### and_then - -If self is None, this returns None. Otherwise, this calls the given function with the Some value contained within self, and returns the result of that call. In some languages this function is called `flat_map` or `bind`. - -### or - -If self is Some, return self. Otherwise, return `other`. - -### or_else - -If self is Some, return self. Otherwise, return `default()`. - -### xor - -If only one of the two Options is Some, return that option. Otherwise, if both options are Some or both are None, None is returned. - -### filter - -Returns `Some(x)` if self is `Some(x)` and `predicate(x)` is true. Otherwise, this returns `None`. - -### flatten - -Flattens an `Option>` into a `Option`. This returns `None` if the outer Option is None. Otherwise, this returns the inner Option. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/recursion.md deleted file mode 100644 index 5e592a2fd89..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/recursion.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: Recursive Proofs -description: Learn about how to write recursive proofs in Noir. -keywords: [recursion, recursive proofs, verification_key, aggregation object, verify_proof] ---- - -Noir supports recursively verifying proofs, meaning you verify the proof of a Noir program in another Noir program. This enables creating proofs of arbitrary size by doing step-wise verification of smaller components of a large proof. - -The `verify_proof` function takes a verification key, proof and public inputs for a zk program, as well as a key hash and an input aggregation object. The key hash is used to check the validity of the verification key and the input aggregation object is required by some proving systems. The `verify_proof` function returns an output aggregation object that can then be fed into future iterations of the proof verification if required. - -```rust -#[foreign(verify_proof)] -fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : Field, _key_hash : Field, _input_aggregation_object : [Field]) -> [Field] {} -``` - -:::info - -This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. - -::: - -## Aggregation Object - -The purpose of the input aggregation object is a little less clear though (and the output aggregation object that is returned from the `std::verify_proof` method). Recursive zkSNARK schemes do not necessarily "verify a proof" in the sense that you expect a true or false to be spit out by the verifier. Rather an aggregation object is built over the public inputs. In the case of PLONK the recursive aggregation object is two G1 points (expressed as 16 witness values). The final verifier (in our case this is most often the smart contract verifier) has to be aware of this aggregation object to execute a pairing and check the validity of these points (thus completing the recursive verification). - -So for example in this circuit: - -```rust -use dep::std; - -fn main( - verification_key : [Field; 114], - proof : [Field; 94], - public_inputs : [Field; 1], - key_hash : Field, - input_aggregation_object : [Field; 16], - proof_b : [Field; 94], -) -> pub [Field; 16] { - let output_aggregation_object_a = std::verify_proof( - verification_key, - proof, - public_inputs, - key_hash, - input_aggregation_object - ); - - let output_aggregation_object = std::verify_proof( - verification_key, - proof_b, - public_inputs, - key_hash, - output_aggregation_object_a - ); - - let mut output = [0; 16]; - for i in 0..16 { - output[i] = output_aggregation_object[i]; - } - output -} -``` - -In this example we have a circuit, that generates proofs A and B, that is being verified in circuit C. Assuming that the proof being passed in is not already a recursive proof, the `input_aggregation_object` will be all zeros. It will then generate an `output_aggregation_object`. This blob of data then becomes the `input_aggregation_object` of the next recursive aggregation we wish to compute. We can see here as the same public inputs, verification key, and key hash are used that we are verifying two proofs generated from the same circuit in this single circuit. `std::verify_proof` returns a `[Field]` because the size of an aggregation object is proof system dependent--in barretenberg, aggregation objects are two G1 points, while in Halo2, the aggregation object is a list of G1 points that is log the circuit size. So for the final step we convert the slice into an array of size 16 because we are generating proofs using UltraPlonk. - -## Parameters - -### `verification_key` - -The verification key for the zk program that is being verified. - -### `proof` - -The proof for the zk program that is being verified. - -### `public_inputs` - -These represent the public inputs of the proof we are verifying. They should be checked against in the circuit after construction of a new aggregation state. - -### `key_hash` - -A key hash is used to check the validity of the verification key. The circuit implementing this opcode can use this hash to ensure that the key provided to the circuit matches the key produced by the circuit creator. - -### `input_aggregation_object` - -An aggregation object is blob of data that the top-level verifier must run some proof system specific algorithm on to complete verification. The size is proof system specific and will be set by the backend integrating this opcode. The input aggregation object is only not `None` when we are verifying a previous recursive aggregation in the current circuit. If this is the first recursive aggregation there is no input aggregation object. It is left to the backend to determine how to handle when there is no input aggregation object. - -## Return value - -### `output_aggregation_object` - -This is the result of a recursive aggregation and is what will be fed into the next verifier. -The next verifier can either perform a final verification (returning true or false) or perform another recursive aggregation where this output aggregation object will be the input aggregation object of the next recursive aggregation. - -## Example - -You can see an example of how to do recursive proofs in [this example recursion demo repo](https://github.com/noir-lang/noir-examples/tree/master/recursion). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/zeroed.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/zeroed.md deleted file mode 100644 index 97dab02dac2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/zeroed.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: Zeroed Function -description: - The zeroed function returns a zeroed value of any type. -keywords: - [ - zeroed - ] ---- - -Implements `fn zeroed() -> T` to return a zeroed value of any type. This function is generally unsafe to use as the zeroed bit pattern is not guaranteed to be valid for all types. It can however, be useful in cases when the value is guaranteed not to be used such as in a BoundedVec library implementing a growable vector, up to a certain length, backed by an array. The array can be initialized with zeroed values which are guaranteed to be inaccessible until the vector is pushed to. Similarly, enumerations in noir can be implemented using this method by providing zeroed values for the unused variants. - -You can access the function at `std::unsafe::zeroed`. - -This function currently supports the following types: - -- Field -- Bool -- Uint -- Array -- String -- Tuple -- Function - -Using it on other types could result in unexpected behavior. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/examples/merkle-proof.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/examples/merkle-proof.mdx deleted file mode 100644 index 832fb4bb55e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/examples/merkle-proof.mdx +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Merkle Proof Membership -description: - Learn how to use merkle membership proof in Noir to prove that a given leaf is a member of a - merkle tree with a specified root, at a given index. -keywords: - [merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree] ---- - -Let's walk through an example of a merkle membership proof in Noir that proves that a given leaf is -in a merkle tree. - -```rust -use dep::std; - -fn main(message : [Field; 62], index : Field, hashpath : [Field; 40], root : Field) { - let leaf = std::hash::hash_to_field(message); - let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); - assert(merkle_root == root); -} - -``` - -The message is hashed using `hash_to_field`. The specific hash function that is being used is chosen -by the backend. The only requirement is that this hash function can heuristically be used as a -random oracle. If only collision resistance is needed, then one can call `std::hash::pedersen_hash` -instead. - -```rust -let leaf = std::hash::hash_to_field(message); -``` - -The leaf is then passed to a compute_merkle_root function with the root, index and hashpath. The returned root can then be asserted to be the same as the provided root. - -```rust -let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); -assert (merkle_root == root); -``` - -> **Note:** It is possible to re-implement the merkle tree implementation without standard library. -> However, for most usecases, it is enough. In general, the standard library will always opt to be -> as conservative as possible, while striking a balance with efficiency. - -An example, the merkle membership proof, only requires a hash function that has collision -resistance, hence a hash function like Pedersen is allowed, which in most cases is more efficient -than the even more conservative sha256. - -[View an example on the starter repo](https://github.com/noir-lang/noir-examples/blob/3ea09545cabfa464124ec2f3ea8e60c608abe6df/stealthdrop/circuits/src/main.nr#L20) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/getting_started/00_nargo_installation.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/getting_started/00_nargo_installation.md deleted file mode 100644 index 7d3c88c7693..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/getting_started/00_nargo_installation.md +++ /dev/null @@ -1,249 +0,0 @@ ---- -title: Nargo Installation -description: - nargo is a command line tool for interacting with Noir programs (e.g. compiling, proving, - verifying and more). Learn how to install and use Nargo for your projects with this comprehensive - guide. -keywords: [Nargo, command line tool, Noir programs, installation guide, how to use Nargo] ---- - -`nargo` is a command line tool for interacting with Noir programs (e.g. compiling, proving, -verifying and more). - -Alternatively, the interactions can also be performed in [NoirJS](../noir_js/noir_js.md). - -### UltraPlonk - -Nargo versions \<0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk -version of Aztec Backend, which lacks efficient implementations of useful primitives (e.g. Keccak256 in 18k constraints, ECDSA verification in 36k constraints) that the UltraPlonk version offers. - -## Installation - -There are four approaches for installing Nargo: - -- [Option 1: Noirup](#option-1-noirup) -- [Option 2: Binaries](#option-2-binaries) -- [Option 3: Compile from Source](#option-3-compile-from-source) -- [Option 4: WSL for Windows](#option-4-wsl-for-windows) - -Optionally you can also install [Noir VS Code extension] for syntax highlighting. - -### Option 1: Noirup - -If you're on OSX or Linux, the easiest way to start using Noir and Nargo is via noirup. Just open a -terminal and run: - -```bash -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -Close the terminal, open another one, and run - -```bash -noirup -``` - -Done, you should have the latest version working. You can check with `nargo --version`. - -You can also install nightlies, specific versions -or branches, check out the [noirup repository](https://github.com/noir-lang/noirup) for more -information. - -#### GitHub Actions - -You can use `noirup` with GitHub Actions for CI/CD and automated testing. It is as simple as -installing `noirup` and running tests in your GitHub Action `yml` file. - -See the -[config file](https://github.com/TomAFrench/noir-hashes/blob/master/.github/workflows/noir.yml) in -this repo containing hash functions in Noir for an example. - -#### Nightly versions - -To install the nightly version of Noir (updated daily) run: - -```bash -noirup -n -``` - -### Option 2: Binaries - -See [GitHub Releases](https://github.com/noir-lang/noir/releases) for the latest and previous -platform specific binaries. - -#### Step 1 - -Paste and run the following in the terminal to extract and install the binary: - -> **macOS / Linux:** If you are prompted with `Permission denied` when running commands, prepend -> `sudo` and re-run it. - -##### macOS (Apple Silicon) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-aarch64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### macOS (Intel) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### Linux (Bash) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-unknown-linux-gnu.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -C $HOME/.nargo/bin/ && \ -echo -e '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.bashrc && \ -source ~/.bashrc -``` - -#### Step 2 - -Check if the installation was successful by running `nargo --help`. - -> **macOS:** If you are prompted with an OS alert, right-click and open the _nargo_ executable from -> Finder. Close the new terminal popped up and `nargo` should now be accessible. - -For a successful installation, you should see something similar to the following after running the -command: - -```sh -$ nargo --help - -Noir's package manager - -Usage: nargo - -Commands: - check Checks the constraint system for errors - codegen-verifier Generates a Solidity verifier smart contract for the program - compile Compile the program and its secret execution trace into ACIR format - new Create a new binary project - execute Executes a circuit to calculate its return value - prove Create proof for this program. The proof is returned as a hex encoded string - verify Given a proof and a program, verify whether the proof is valid - test Run the tests for this program - gates Counts the occurrences of different gates in circuit - help Print this message or the help of the given subcommand(s) -``` - -### Option 3: Compile from Source - -Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. It helps mitigating issues commonly associated with dependency management, such as conflicts between required package versions for different projects (often referred to as "dependency hell"). - -Combined with direnv, which automatically sets or clears environment variables based on the directory, it further simplifies the development process by seamlessly integrating with the developer's shell, facilitating an efficient and reliable workflow for managing and deploying Noir projects with multiple dependencies. - -#### Setting up your environment - -For the best experience, please follow these instructions to setup your environment: - -1. Install Nix following [their guide](https://nixos.org/download.html) for your operating system. -2. Create the file `~/.config/nix/nix.conf` with the contents: - -```ini -experimental-features = nix-command -extra-experimental-features = flakes -``` - -3. Install direnv into your Nix profile by running: - -```sh -nix profile install nixpkgs#direnv -``` - -4. Add direnv to your shell following [their guide](https://direnv.net/docs/hook.html). - 1. For bash or zshell, add `eval "$(direnv hook bash)"` or `eval "$(direnv hook zsh)"` to your ~/.bashrc or ~/.zshrc file, respectively. -5. Restart your shell. - -#### Shell & editor experience - -Now that your environment is set up, you can get to work on the project. - -1. Clone the repository, such as: - -```sh -git clone git@github.com:noir-lang/noir -``` - -> Replacing `noir` with whichever repository you want to work on. - -2. Navigate to the directory: - -```sh -cd noir -``` - -> Replacing `noir` with whichever repository you cloned. - -3. You should see a **direnv error** because projects aren't allowed by default. Make sure you've reviewed and trust our `.envrc` file, then you need to run: - -```sh -direnv allow -``` - -4. Now, wait awhile for all the native dependencies to be built. This will take some time and direnv will warn you that it is taking a long time, but we just need to let it run. - -5. Once you are presented with your prompt again, you can start your editor within the project directory (we recommend [VSCode](https://code.visualstudio.com/)): - -```sh -code . -``` - -6. (Recommended) When launching VSCode for the first time, you should be prompted to install our recommended plugins. We highly recommend installing these for the best development experience. - -#### Building and testing - -Assuming you are using `direnv` to populate your environment, building and testing the project can be done -with the typical `cargo build`, `cargo test`, and `cargo clippy` commands. You'll notice that the `cargo` version matches the version we specify in `rust-toolchain.toml`, which is 1.71.1 at the time of this writing. - -If you want to build the entire project in an isolated sandbox, you can use Nix commands: - -1. `nix build .` (or `nix build . -L` for verbose output) to build the project in a Nix sandbox. -2. `nix flake check` (or `nix flake check -L` for verbose output) to run clippy and tests in a Nix sandbox. - -#### Without `direnv` - -If you have hesitations with using direnv, you can launch a subshell with `nix develop` and then launch your editor from within the subshell. However, if VSCode was already launched in the project directory, the environment won't be updated. - -Advanced: If you aren't using direnv nor launching your editor within the subshell, you can try to install Barretenberg and other global dependencies the package needs. This is an advanced workflow and likely won't receive support! - -### Option 4: WSL (for Windows) - -The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed natively. However, it is available by using Windows Subsystem for Linux (WSL). - -Step 1: Follow the instructions [here](https://learn.microsoft.com/en-us/windows/wsl/install) to install and run WSL. - -step 2: Follow the [Noirup instructions](#option-1-noirup). - -## Uninstalling Nargo - -### Noirup - -If you installed Noir with `noirup`, you can uninstall Noir by removing the files in `~/.nargo`, `~/nargo` and `~/noir_cache`. - -```bash -rm -r ~/.nargo -rm -r ~/nargo -rm -r ~/noir_cache -``` - -### Nix - -If you installed Noir with Nix or from source, you can remove the binary located at `~/.nix-profile/bin/nargo`. - -```bash -rm ~/.nix-profile/bin/nargo -``` - -[noir vs code extension]: https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/getting_started/01_hello_world.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/getting_started/01_hello_world.md deleted file mode 100644 index 34f8cd96fcd..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/getting_started/01_hello_world.md +++ /dev/null @@ -1,147 +0,0 @@ ---- -title: Create A Project -description: - Learn how to create and verify your first Noir program using Nargo, a programming language for - zero-knowledge proofs. -keywords: - [ - Nargo, - Noir, - zero-knowledge proofs, - programming language, - create Noir program, - verify Noir program, - step-by-step guide, - ] ---- - -Now that we have installed Nargo, it is time to make our first hello world program! - -## Create a Project Directory - -Noir code can live anywhere on your computer. Let us create a _projects_ folder in the home -directory to house our Noir programs. - -For Linux, macOS, and Windows PowerShell, create the directory and change directory into it by -running: - -```sh -mkdir ~/projects -cd ~/projects -``` - -For Windows CMD, run: - -```sh -> mkdir "%USERPROFILE%\projects" -> cd /d "%USERPROFILE%\projects" -``` - -## Create Our First Nargo Project - -Now that we are in the projects directory, create a new Nargo project by running: - -```sh -nargo new hello_world -``` - -> **Note:** `hello_world` can be any arbitrary project name, we are simply using `hello_world` for -> demonstration. -> -> In production, the common practice is to name the project folder as `circuits` for better -> identifiability when sitting alongside other folders in the codebase (e.g. `contracts`, `scripts`, -> `test`). - -A `hello_world` folder would be created. Similar to Rust, the folder houses _src/main.nr_ and -_Nargo.toml_ that contains the source code and environmental options of your Noir program -respectively. - -### Intro to Noir Syntax - -Let us take a closer look at _main.nr_. The default _main.nr_ generated should look like this: - -```rust -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` - -The first line of the program specifies the program's inputs: - -```rust -x : Field, y : pub Field -``` - -Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the -keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](../language_concepts/data_types.md) section. - -The next line of the program specifies its body: - -```rust -assert(x != y); -``` - -The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. - -For more Noir syntax, check the [Language Concepts](../language_concepts/comments.md) chapter. - -## Build In/Output Files - -Change directory into _hello_world_ and build in/output files for your Noir program by running: - -```sh -cd hello_world -nargo check -``` - -Two additional files would be generated in your project directory: - -_Prover.toml_ houses input values, and _Verifier.toml_ houses public values. - -## Prove Our Noir Program - -Now that the project is set up, we can create a proof of correct execution on our Noir program. - -Fill in input values for execution in the _Prover.toml_ file. For example: - -```toml -x = "1" -y = "2" -``` - -Prove the valid execution of your Noir program: - -```sh -nargo prove -``` - -A new folder _proofs_ would then be generated in your project directory, containing the proof file -`.proof`, where the project name is defined in Nargo.toml. - -The _Verifier.toml_ file would also be updated with the public values computed from program -execution (in this case the value of `y`): - -```toml -y = "0x0000000000000000000000000000000000000000000000000000000000000002" -``` - -> **Note:** Values in _Verifier.toml_ are computed as 32-byte hex values. - -## Verify Our Noir Program - -Once a proof is generated, we can verify correct execution of our Noir program by verifying the -proof file. - -Verify your proof by running: - -```sh -nargo verify -``` - -The verification will complete in silence if it is successful. If it fails, it will log the -corresponding error instead. - -Congratulations, you have now created and verified a proof for your very first Noir program! - -In the [next section](./02_breakdown.md), we will go into more detail on each step performed. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/getting_started/02_breakdown.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/getting_started/02_breakdown.md deleted file mode 100644 index f928370b2e8..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/getting_started/02_breakdown.md +++ /dev/null @@ -1,198 +0,0 @@ ---- -title: Project Breakdown -description: - Learn about the anatomy of a Nargo project, including the purpose of the Prover and Verifier TOML - files, and how to prove and verify your program. -keywords: - [Nargo, Nargo project, Prover.toml, Verifier.toml, proof verification, private asset transfer] ---- - -This section breaks down our hello world program in section _1.2_. We elaborate on the project -structure and what the `prove` and `verify` commands did in the previous section. - -## Anatomy of a Nargo Project - -Upon creating a new project with `nargo new` and building the in/output files with `nargo check` -commands, you would get a minimal Nargo project of the following structure: - - - src - - Prover.toml - - Verifier.toml - - Nargo.toml - -The source directory _src_ holds the source code for your Noir program. By default only a _main.nr_ -file will be generated within it. - -### Prover.toml - -_Prover.toml_ is used for specifying the input values for executing and proving the program. You can specify `toml` files with different names by using the `--prover-name` or `-p` flags, see the [Prover](#provertoml) section below. Optionally you may specify expected output values for prove-time checking as well. - -### Verifier.toml - -_Verifier.toml_ contains public in/output values computed when executing the Noir program. - -### Nargo.toml - -_Nargo.toml_ contains the environmental options of your project. It contains a "package" section and a "dependencies" section. - -Example Nargo.toml: - -```toml -[package] -name = "noir_starter" -type = "bin" -authors = ["Alice"] -compiler_version = "0.9.0" -description = "Getting started with Noir" -entry = "circuit/main.nr" -license = "MIT" - -[dependencies] -ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} -``` - -Nargo.toml for a [workspace](../modules_packages_crates/workspaces.md) will look a bit different. For example: - -```toml -[workspace] -members = ["crates/a", "crates/b"] -default-member = "crates/a" -``` - -#### Package section - -The package section requires a number of fields including: - -- `name` (**required**) - the name of the package -- `type` (**required**) - can be "bin", "lib", or "contract" to specify whether its a binary, library or Aztec contract -- `authors` (optional) - authors of the project -- `compiler_version` - specifies the version of the compiler to use. This is enforced by the compiler and follow's [Rust's versioning](https://doc.rust-lang.org/cargo/reference/manifest.html#the-version-field), so a `compiler_version = 0.18.0` will enforce Nargo version 0.18.0, `compiler_version = ^0.18.0` will enforce anything above 0.18.0 but below 0.19.0, etc. For more information, see how [Rust handles these operators](https://docs.rs/semver/latest/semver/enum.Op.html) -- `description` (optional) -- `entry` (optional) - a relative filepath to use as the entry point into your package (overrides the default of `src/lib.nr` or `src/main.nr`) -- `backend` (optional) -- `license` (optional) - -#### Dependencies section - -This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies.md)for more info. - -`./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or -verifier contract respectively. - -### main.nr - -The _main.nr_ file contains a `main` method, this method is the entry point into your Noir program. - -In our sample program, _main.nr_ looks like this: - -```rust -fn main(x : Field, y : Field) { - assert(x != y); -} -``` - -The parameters `x` and `y` can be seen as the API for the program and must be supplied by the -prover. Since neither `x` nor `y` is marked as public, the verifier does not supply any inputs, when -verifying the proof. - -The prover supplies the values for `x` and `y` in the _Prover.toml_ file. - -As for the program body, `assert` ensures the satisfaction of the condition (e.g. `x != y`) is -constrained by the proof of the execution of said program (i.e. if the condition was not met, the -verifier would reject the proof as an invalid proof). - -### Prover.toml - -The _Prover.toml_ file is a file which the prover uses to supply his witness values(both private and -public). - -In our hello world program the _Prover.toml_ file looks like this: - -```toml -x = "1" -y = "2" -``` - -When the command `nargo prove` is executed, two processes happen: - -1. Noir creates a proof that `x` which holds the value of `1` and `y` which holds the value of `2` - is not equal. This not equal constraint is due to the line `assert(x != y)`. - -2. Noir creates and stores the proof of this statement in the _proofs_ directory in a file called your-project.proof. So if your project is named "private_voting" (defined in the project Nargo.toml), the proof will be saved at `./proofs/private_voting.proof`. Opening this file will display the proof in hex format. - -#### Arrays of Structs - -The following code shows how to pass an array of structs to a Noir program to generate a proof. - -```rust -// main.nr -struct Foo { - bar: Field, - baz: Field, -} - -fn main(foos: [Foo; 3]) -> pub Field { - foos[2].bar + foos[2].baz -} -``` - -Prover.toml: - -```toml -[[foos]] # foos[0] -bar = 0 -baz = 0 - -[[foos]] # foos[1] -bar = 0 -baz = 0 - -[[foos]] # foos[2] -bar = 1 -baz = 2 -``` - -#### Custom toml files - -You can specify a `toml` file with a different name to use for proving by using the `--prover-name` or `-p` flags. - -This command looks for proof inputs in the default **Prover.toml** and generates the proof and saves it at `./proofs/.proof`: - -```bash -nargo prove -``` - -This command looks for proof inputs in the custom **OtherProver.toml** and generates proof and saves it at `./proofs/.proof`: - -```bash -nargo prove -p OtherProver -``` - -## Verifying a Proof - -When the command `nargo verify` is executed, two processes happen: - -1. Noir checks in the _proofs_ directory for a proof file with the project name (eg. test_project.proof) - -2. If that file is found, the proof's validity is checked - -> **Note:** The validity of the proof is linked to the current Noir program; if the program is -> changed and the verifier verifies the proof, it will fail because the proof is not valid for the -> _modified_ Noir program. - -In production, the prover and the verifier are usually two separate entities. A prover would -retrieve the necessary inputs, execute the Noir program, generate a proof and pass it to the -verifier. The verifier would then retrieve the public inputs from usually external sources and -verifies the validity of the proof against it. - -Take a private asset transfer as an example: - -A user on browser as the prover would retrieve private inputs (e.g. the user's private key) and -public inputs (e.g. the user's encrypted balance on-chain), compute the transfer, generate a proof -and submit it to the verifier smart contract. - -The verifier contract would then draw the user's encrypted balance directly from the blockchain and -verify the proof submitted against it. If the verification passes, additional functions in the -verifier contract could trigger (e.g. approve the asset transfer). - -Now that you understand the concepts, you'll probably want some editor feedback while you are writing more complex code. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/index.md deleted file mode 100644 index e8d86020a20..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/index.md +++ /dev/null @@ -1,100 +0,0 @@ ---- -title: Introducing Noir -description: - Learn about the public alpha release of Noir, a domain specific language heavily influenced by - Rust that compiles to an intermediate language which can be compiled to an arithmetic circuit or a - rank-1 constraint system. -keywords: - [ - Noir, - Domain Specific Language, - Rust, - Intermediate Language, - Arithmetic Circuit, - Rank-1 Constraint System, - Ethereum Developers, - Protocol Developers, - Blockchain Developers, - Proving System, - Smart Contract Language, - ] -slug: / ---- - -## What is Noir? - -Noir is a Domain Specific Language for SNARK proving systems. It has been designed to use any ACIR compatible proving system. - -Its design choices are influenced heavily by Rust and focuses on a simple, familiar syntax. - -## Who is Noir for? - -Noir can be used for a variety of purposes. - -### Solidity Developers - -Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will -be modularized in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier.md) command to create -a verifier contract. - -### Protocol Developers - -As a protocol developer, you may not want to use the Aztec backend due to it not being a fit for -your stack, or maybe you simply want to use a different proving system. Since Noir does not compile -to a specific proof system, it is possible for protocol developers to replace the PLONK-based -proving system with a different proving system altogether. - -### Blockchain developers - -As a blockchain developer, you will be constrained by parameters set by your blockchain (for example, the -proving system and smart contract language has been pre-defined). In order for you to use Noir in -your blockchain, a proving system backend and a smart contract interface -must be implemented for it. - -## What's new about Noir? - -Noir is simple and flexible in its design, as it does not compile immediately to a fixed -NP-complete language. Instead, Noir compiles to an intermediate language (ACIR), which itself can be compiled -to an arithmetic circuit (if choosing to target Aztec's barretenberg backend) or a rank-1 constraint system (if choosing to target an R1CS backend like Arkworks' Marlin backend, or others). - -This in itself brings up a few challenges within the design process, but allows one to decouple the programming language completely from the backend. This is similar in theory to LLVM. - -## Current Features - -Compiler: - -- Module System -- For expressions -- Arrays -- Bit Operations -- Binary operations (\<, \<=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] -- Unsigned integers -- If statements -- Structures and Tuples -- Generics - -ACIR Supported OPCODES: - -- Sha256 -- Blake2s -- Schnorr signature verification -- MerkleMembership -- Pedersen Commitment -- Pedersen Hash -- HashToField - -## Libraries - -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). - -Some libraries that are available today include: - -- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library -- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) -- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers -- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address -- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees -- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir -- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers - -See the section on [dependencies](./modules_packages_crates/dependencies.md) for more information. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/01_functions.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/01_functions.md deleted file mode 100644 index 5eb22170e54..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/01_functions.md +++ /dev/null @@ -1,225 +0,0 @@ ---- -title: Functions -description: - Learn how to declare functions and methods in Noir, a programming language with Rust semantics. - This guide covers parameter declaration, return types, call expressions, and more. -keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] ---- - -Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. - -To declare a function the `fn` keyword is used. - -```rust -fn foo() {} -``` - -By default, functions are visible only within the package they are defined. To make them visible outside of that package (for example, as part of a [library](../modules_packages_crates/crates_and_packages.md#libraries)), you should mark them as `pub`: - -```rust -pub fn foo() {} -``` - -You can also restrict the visibility of the function to only the crate it was defined in, by specifying `pub(crate)`: - -```rust -pub(crate) fn foo() {} //foo can only be called within its crate -``` - -All parameters in a function must have a type and all types are known at compile time. The parameter -is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. - -```rust -fn foo(x : Field, y : Field){} -``` - -The return type of a function can be stated by using the `->` arrow notation. The function below -states that the foo function must return a `Field`. If the function returns no value, then the arrow -is omitted. - -```rust -fn foo(x : Field, y : Field) -> Field { - x + y -} -``` - -Note that a `return` keyword is unneeded in this case - the last expression in a function's body is -returned. - -## Main function - -If you're writing a binary, the `main` function is the starting point of your program. You can pass all types of expressions to it, as long as they have a fixed size at compile time: - -```rust -fn main(x : Field) // this is fine: passing a Field -fn main(x : [Field; 2]) // this is also fine: passing a Field with known size at compile-time -fn main(x : (Field, bool)) // 👌: passing a (Field, bool) tuple means size 2 -fn main(x : str<5>) // this is fine, as long as you pass a string of size 5 - -fn main(x : Vec) // can't compile, has variable size -fn main(x : [Field]) // can't compile, has variable size -fn main(....// i think you got it by now -``` - -Keep in mind [tests](../nargo/02_testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: - -```rust -fn main(x : [Field]) { - assert(x[0] == 1); -} - -#[test] -fn test_one() { - main([1, 2]); -} -``` - -```bash -$ nargo test -[testing] Running 1 test functions -[testing] Testing test_one... ok -[testing] All tests passed - -$ nargo check -The application panicked (crashed). -Message: Cannot have variable sized arrays as a parameter to main -``` - -## Call Expressions - -Calling a function in Noir is executed by using the function name and passing in the necessary -arguments. - -Below we show how to call the `foo` function from the `main` function using a call expression: - -```rust -fn main(x : Field, y : Field) { - let z = foo(x); -} - -fn foo(x : Field) -> Field { - x + x -} -``` - -## Methods - -You can define methods in Noir on any struct type in scope. - -```rust -struct MyStruct { - foo: Field, - bar: Field, -} - -impl MyStruct { - fn new(foo: Field) -> MyStruct { - MyStruct { - foo, - bar: 2, - } - } - - fn sum(self) -> Field { - self.foo + self.bar - } -} - -fn main() { - let s = MyStruct::new(40); - assert(s.sum() == 42); -} -``` - -Methods are just syntactic sugar for functions, so if we wanted to we could also call `sum` as -follows: - -```rust -assert(MyStruct::sum(s) == 42); -``` - -It is also possible to specialize which method is chosen depending on the [generic](./06_generics.md) type that is used. In this example, the `foo` function returns different values depending on its type: - -```rust -struct Foo {} - -impl Foo { - fn foo(self) -> Field { 1 } -} - -impl Foo { - fn foo(self) -> Field { 2 } -} - -fn main() { - let f1: Foo = Foo{}; - let f2: Foo = Foo{}; - assert(f1.foo() + f2.foo() == 3); -} -``` - -Also note that impls with the same method name defined in them cannot overlap. For example, if we already have `foo` defined for `Foo` and `Foo` like we do above, we cannot also define `foo` in an `impl Foo` since it would be ambiguous which version of `foo` to choose. - -```rust -// Including this impl in the same project as the above snippet would -// cause an overlapping impls error -impl Foo { - fn foo(self) -> Field { 3 } -} -``` - -## Lambdas - -Lambdas are anonymous functions. They follow the syntax of Rust - `|arg1, arg2, ..., argN| return_expression`. - -```rust -let add_50 = |val| val + 50; -assert(add_50(100) == 150); -``` - -See [Lambdas](./08_lambdas.md) for more details. - -## Attributes - -Attributes are metadata that can be applied to a function, using the following syntax: `#[attribute(value)]`. - -Supported attributes include: - -- **builtin**: the function is implemented by the compiler, for efficiency purposes. -- **deprecated**: mark the function as _deprecated_. Calling the function will generate a warning: `warning: use of deprecated function` -- **field**: Used to enable conditional compilation of code depending on the field size. See below for more details -- **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./05_unconstrained.md) and [NoirJS](../noir_js/noir_js.md) for more details. -- **test**: mark the function as unit tests. See [Tests](../nargo/02_testing.md) for more details - -### Field Attribute - -The field attribute defines which field the function is compatible for. The function is conditionally compiled, under the condition that the field attribute matches the Noir native field. -The field can be defined implicitly, by using the name of the elliptic curve usually associated to it - for instance bn254, bls12_381 - or explicitly by using the field (prime) order, in decimal or hexadecimal form. -As a result, it is possible to define multiple versions of a function with each version specialized for a different field attribute. This can be useful when a function requires different parameters depending on the underlying elliptic curve. - -Example: we define the function `foo()` three times below. Once for the default Noir bn254 curve, once for the field $\mathbb F_{23}$, which will normally never be used by Noir, and once again for the bls12_381 curve. - -```rust -#[field(bn254)] -fn foo() -> u32 { - 1 -} - -#[field(23)] -fn foo() -> u32 { - 2 -} - -// This commented code would not compile as foo would be defined twice because it is the same field as bn254 -// #[field(21888242871839275222246405745257275088548364400416034343698204186575808495617)] -// fn foo() -> u32 { -// 2 -// } - -#[field(bls12_381)] -fn foo() -> u32 { - 3 -} -``` - -If the field name is not known to Noir, it will discard the function. Field names are case insensitive. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/02_control_flow.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/02_control_flow.md deleted file mode 100644 index a7f85360197..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/02_control_flow.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Control Flow -description: - Learn how to use loops and if expressions in the Noir programming language. Discover the syntax - and examples for for loops and if-else statements. -keywords: [Noir programming language, loops, for loop, if-else statements, Rust syntax] ---- - -## Loops - -Noir has one kind of loop: the `for` loop. `for` loops allow you to repeat a block of code multiple -times. - -The following block of code between the braces is run 10 times. - -```rust -for i in 0..10 { - // do something -}; -``` - -The index for loops is of type `u64`. - -## If Expressions - -Noir supports `if-else` statements. The syntax is most similar to Rust's where it is not required -for the statement's conditional to be surrounded by parentheses. - -```rust -let a = 0; -let mut x: u32 = 0; - -if a == 0 { - if a != 0 { - x = 6; - } else { - x = 2; - } -} else { - x = 5; - assert(x == 5); -} -assert(x == 2); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/03_ops.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/03_ops.md deleted file mode 100644 index 0e35ef5e584..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/03_ops.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -title: Logical Operations -description: - Learn about the supported arithmetic and logical operations in the Noir programming language. - Discover how to perform operations on private input types, integers, and booleans. -keywords: - [ - Noir programming language, - supported operations, - arithmetic operations, - logical operations, - predicate operators, - bitwise operations, - short-circuiting, - backend, - ] ---- - -# Operations - -## Table of Supported Operations - -| Operation | Description | Requirements | -| :-------- | :------------------------------------------------------------: | -------------------------------------: | -| + | Adds two private input types together | Types must be private input | -| - | Subtracts two private input types together | Types must be private input | -| \* | Multiplies two private input types together | Types must be private input | -| / | Divides two private input types together | Types must be private input | -| ^ | XOR two private input types together | Types must be integer | -| & | AND two private input types together | Types must be integer | -| \| | OR two private input types together | Types must be integer | -| \<\< | Left shift an integer by another integer amount | Types must be integer | -| >> | Right shift an integer by another integer amount | Types must be integer | -| ! | Bitwise not of a value | Type must be integer or boolean | -| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | -| > | returns a bool if one value is more than the other | Upper bound must have a known bit size | -| >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | -| == | returns a bool if one value is equal to the other | Both types must not be constants | -| != | returns a bool if one value is not equal to the other | Both types must not be constants | - -### Predicate Operators - -`<,<=, !=, == , >, >=` are known as predicate/comparison operations because they compare two values. -This differs from the operations such as `+` where the operands are used in _computation_. - -### Bitwise Operations Example - -```rust -fn main(x : Field) { - let y = x as u32; - let z = y & y; -} -``` - -`z` is implicitly constrained to be the result of `y & y`. The `&` operand is used to denote bitwise -`&`. - -> `x & x` would not compile as `x` is a `Field` and not an integer type. - -### Logical Operators - -Noir has no support for the logical operators `||` and `&&`. This is because encoding the -short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can -use the bitwise operators `|` and `&` which operate identically for booleans, just without the -short-circuiting. - -```rust -let my_val = 5; - -let mut flag = 1; -if (my_val > 6) | (my_val == 0) { - flag = 0; -} -assert(flag == 1); - -if (my_val != 10) & (my_val < 50) { - flag = 0; -} -assert(flag == 0); -``` - -### Shorthand operators - -Noir shorthand operators for most of the above operators, namely `+=, -=, *=, /=, %=, &=, |=, ^=, <<=`, and `>>=`. These allow for more concise syntax. For example: - -```rust -let mut i = 0; -i = i + 1; -``` - -could be written as: - -```rust -let mut i = 0; -i += 1; -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/04_assert.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/04_assert.md deleted file mode 100644 index 7427ec6cc63..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/04_assert.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Assert Function -description: - Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or - comparison expression that follows to be true, and what happens if the expression is false at - runtime. -keywords: [Noir programming language, assert statement, predicate expression, comparison expression] ---- - -Noir includes a special `assert` function which will explicitly constrain the predicate/comparison -expression that follows to be true. If this expression is false at runtime, the program will fail to -be proven. Example: - -```rust -fn main(x : Field, y : Field) { - assert(x == y); -} -``` - -You can optionally provide a message to be logged when the assertion fails: - -```rust -assert(x == y, "x and y are not equal"); -``` - -> Assertions only work for predicate operations, such as `==`. If there's any ambiguity on the operation, the program will fail to compile. For example, it is unclear if `assert(x + y)` would check for `x + y == 0` or simply would return `true`. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/05_unconstrained.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/05_unconstrained.md deleted file mode 100644 index 097d6ee9894..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/05_unconstrained.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: Unconstrained Functions -description: "Learn about what unconstrained functions in Noir are, how to use them and when you'd want to." - -keywords: [Noir programming language, unconstrained, open] ---- - - - -Unconstrained functions are functions which do not constrain any of the included computation and allow for non-deterministic computation. - -## Why? - -Zero-knowledge (ZK) domain-specific languages (DSL) enable developers to generate ZK proofs from their programs by compiling code down to the constraints of an NP complete language (such as R1CS or PLONKish languages). However, the hard bounds of a constraint system can be very limiting to the functionality of a ZK DSL. - -Enabling a circuit language to perform unconstrained execution is a powerful tool. Said another way, unconstrained execution lets developers generate witnesses from code that does not generate any constraints. Being able to execute logic outside of a circuit is critical for both circuit performance and constructing proofs on information that is external to a circuit. - -Fetching information from somewhere external to a circuit can also be used to enable developers to improve circuit efficiency. - -A ZK DSL does not just prove computation, but proves that some computation was handled correctly. Thus, it is necessary that when we switch from performing some operation directly inside of a circuit to inside of an unconstrained environment that the appropriate constraints are still laid down elsewhere in the circuit. - -## Example - -An in depth example might help drive the point home. This example comes from the excellent [post](https://discord.com/channels/1113924620781883405/1124022445054111926/1128747641853972590) by Tom in the Noir Discord. - -Let's look at how we can optimize a function to turn a `u72` into an array of `u8`s. - -```rust -fn main(num: u72) -> pub [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8)) as u72 & 0xff) as u8; - } - - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 91 -Backend circuit size: 3619 -``` - -A lot of the operations in this function are optimized away by the compiler (all the bit-shifts turn into divisions by constants). However we can save a bunch of gates by casting to u8 a bit earlier. This automatically truncates the bit-shifted value to fit in a u8 which allows us to remove the XOR against 0xff. This saves us ~480 gates in total. - -```rust -fn main(num: u72) -> pub [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8)) as u8; - } - - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 75 -Backend circuit size: 3143 -``` - -Those are some nice savings already but we can do better. This code is all constrained so we're proving every step of calculating out using num, but we don't actually care about how we calculate this, just that it's correct. This is where brillig comes in. - -It turns out that truncating a u72 into a u8 is hard to do inside a snark, each time we do as u8 we lay down 4 ACIR opcodes which get converted into multiple gates. It's actually much easier to calculate num from out than the other way around. All we need to do is multiply each element of out by a constant and add them all together, both relatively easy operations inside a snark. - -We can then run u72_to_u8 as unconstrained brillig code in order to calculate out, then use that result in our constrained function and assert that if we were to do the reverse calculation we'd get back num. This looks a little like the below: - -```rust -fn main(num: u72) -> pub [u8; 8] { - let out = u72_to_u8(num); - - let mut reconstructed_num: u72 = 0; - for i in 0..8 { - reconstructed_num += (out[i] as u72 << (56 - (8 * i))); - } - assert(num == reconstructed_num); - out -} - -unconstrained fn u72_to_u8(num: u72) -> [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8))) as u8; - } - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 78 -Backend circuit size: 2902 -``` - -This ends up taking off another ~250 gates from our circuit! We've ended up with more ACIR opcodes than before but they're easier for the backend to prove (resulting in fewer gates). - -Generally we want to use brillig whenever there's something that's easy to verify but hard to compute within the circuit. For example, if you wanted to calculate a square root of a number it'll be a much better idea to calculate this in brillig and then assert that if you square the result you get back your number. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/06_generics.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/06_generics.md deleted file mode 100644 index a932d7b47c2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/06_generics.md +++ /dev/null @@ -1,109 +0,0 @@ ---- -title: Generics -description: Learn how to use Generics in Noir -keywords: [Noir, Rust, generics, functions, structs] ---- - -Generics allow you to use the same functions with multiple different concrete data types. You can -read more about the concept of generics in the Rust documentation -[here](https://doc.rust-lang.org/book/ch10-01-syntax.html). - -Here is a trivial example showing the identity function that supports any type. In Rust, it is -common to refer to the most general type as `T`. We follow the same convention in Noir. - -```rust -fn id(x: T) -> T { - x -} -``` - -## In Structs - -Generics are useful for specifying types in structs. For example, we can specify that a field in a -struct will be of a certain generic type. In this case `value` is of type `T`. - -```rust -struct RepeatedValue { - value: T, - count: Field, -} - -impl RepeatedValue { - fn new(value: T) -> Self { - Self { value, count: 1 } - } - - fn increment(mut repeated: Self) -> Self { - repeated.count += 1; - repeated - } - - fn print(self) { - for _i in 0 .. self.count { - dep::std::println(self.value); - } - } -} - -fn main() { - let mut repeated = RepeatedValue::new("Hello!"); - repeated = repeated.increment(); - repeated.print(); -} -``` - -The `print` function will print `Hello!` an arbitrary number of times, twice in this case. - -If we want to be generic over array lengths (which are type-level integers), we can use numeric -generics. Using these looks just like using regular generics, but these generics can resolve to -integers at compile-time, rather than resolving to types. Here's an example of a struct that is -generic over the size of the array it contains internally: - -```rust -struct BigInt { - limbs: [u32; N], -} - -impl BigInt { - // `N` is in scope of all methods in the impl - fn first(first: BigInt, second: BigInt) -> Self { - assert(first.limbs != second.limbs); - first - - fn second(first: BigInt, second: Self) -> Self { - assert(first.limbs != second.limbs); - second - } -} -``` - -## Calling functions on generic parameters - -Unlike Rust, Noir does not have traits, so how can one translate the equivalent of a trait bound in -Rust into Noir? That is, how can we write a function that is generic over some type `T`, while also -requiring there is a function like `eq: fn(T, T) -> bool` that works on the type? - -The answer is that we can translate this by passing in the function manually. Here's an example of -implementing array equality in Noir: - -```rust -fn array_eq(array1: [T; N], array2: [T; N], elem_eq: fn(T, T) -> bool) -> bool { - if array1.len() != array2.len() { - false - } else { - let mut result = true; - for i in 0 .. array1.len() { - result &= elem_eq(array1[i], array2[i]); - } - result - } -} - -fn main() { - assert(array_eq([1, 2, 3], [1, 2, 3], |a, b| a == b)); - - // We can use array_eq even for arrays of structs, as long as we have - // an equality function for these structs we can pass in - let array = [MyStruct::new(), MyStruct::new()]; - assert(array_eq(array, array, MyStruct::eq)); -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/07_mutability.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/07_mutability.md deleted file mode 100644 index ed3fed820ec..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/07_mutability.md +++ /dev/null @@ -1,92 +0,0 @@ ---- -title: Mutability -description: - Learn about mutable variables, constants, and globals in Noir programming language. Discover how - to declare, modify, and use them in your programs. -keywords: [noir programming language, mutability in noir, mutable variables, constants, globals] ---- - -Variables in noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned -to via an assignment expression. - -```rust -let x = 2; -x = 3; // error: x must be mutable to be assigned to - -let mut y = 3; -let y = 4; // OK -``` - -The `mut` modifier can also apply to patterns: - -```rust -let (a, mut b) = (1, 2); -a = 11; // error: a must be mutable to be assigned to -b = 12; // OK - -let mut (c, d) = (3, 4); -c = 13; // OK -d = 14; // OK - -// etc. -let MyStruct { x: mut y } = MyStruct { x: a }; -// y is now in scope -``` - -Note that mutability in noir is local and everything is passed by value, so if a called function -mutates its parameters then the parent function will keep the old value of the parameters. - -```rust -fn main() -> pub Field { - let x = 3; - helper(x); - x // x is still 3 -} - -fn helper(mut x: i32) { - x = 4; -} -``` - -## Comptime Values - -:::warning - -The 'comptime' keyword was removed in version 0.10. The comptime keyword and syntax are currently still kept and parsed for backwards compatibility, but are now deprecated and will issue a warning when used. `comptime` has been removed because it is no longer needed for accessing arrays. - -::: - -## Globals - -Noir also supports global variables. However, they must be known at compile-time. The global type can also be inferred by the compiler entirely. Globals can also be used to specify array -annotations for function parameters and can be imported from submodules. - -```rust -global N: Field = 5; // Same as `global N: Field = 5` - -fn main(x : Field, y : [Field; N]) { - let res = x * N; - - assert(res == y[0]); - - let res2 = x * my_submodule::N; - assert(res != res2); -} - -mod my_submodule { - use dep::std; - - global N: Field = 10; - - fn my_helper() -> Field { - let x = N; - x - } -} -``` - -## Why only local mutability? - -Witnesses in a proving system are immutable in nature. Noir aims to _closely_ mirror this setting -without applying additional overhead to the user. Modeling a mutable reference is not as -straightforward as on conventional architectures and would incur some possibly unexpected overhead. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/08_lambdas.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/08_lambdas.md deleted file mode 100644 index ae1e6aecab1..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/08_lambdas.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: Lambdas -description: Learn how to use anonymous functions in Noir programming language. -keywords: [Noir programming language, lambda, closure, function, anonymous function] ---- - -## Introduction - -Lambdas are anonymous functions. The syntax is `|arg1, arg2, ..., argN| return_expression`. - -```rust -let add_50 = |val| val + 50; -assert(add_50(100) == 150); -``` - -A block can be used as the body of a lambda, allowing you to declare local variables inside it: - -```rust -let cool = || { - let x = 100; - let y = 100; - x + y -} - -assert(cool() == 200); -``` - -## Closures - -Inside the body of a lambda, you can use variables defined in the enclosing function. Such lambdas are called **closures**. In this example `x` is defined inside `main` and is accessed from within the lambda: - -```rust -fn main() { - let x = 100; - let closure = || x + 150; - assert(closure() == 250); -} -``` - -## Passing closures to higher-order functions - -It may catch you by surprise that the following code fails to compile: - -```rust -fn foo(f: fn () -> Field) -> Field { - f() -} - -fn main() { - let (x, y) = (50, 50); - assert(foo(|| x + y) == 100); // error :( -} -``` - -The reason is that the closure's capture environment affects its type - we have a closure that captures two Fields and `foo` -expects a regular function as an argument - those are incompatible. -:::note - -Variables contained within the `||` are the closure's parameters, and the expression that follows it is the closure's body. The capture environment is comprised of any variables used in the closure's body that are not parameters. - -E.g. in |x| x + y, y would be a captured variable, but x would not be, since it is a parameter of the closure. - -::: -The syntax for the type of a closure is `fn[env](args) -> ret_type`, where `env` is the capture environment of the closure - -in this example that's `(Field, Field)`. - -The best solution in our case is to make `foo` generic over the environment type of its parameter, so that it can be called -with closures with any environment, as well as with regular functions: - -```rust -fn foo(f: fn[Env]() -> Field) -> Field { - f() -} - -fn main() { - let (x, y) = (50, 50); - assert(foo(|| x + y) == 100); // compiles fine - assert(foo(|| 60) == 60); // compiles fine -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/09_comments.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/09_comments.md deleted file mode 100644 index 3bb4d2f25a4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/09_comments.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: Comments -description: - Learn how to write comments in Noir programming language. A comment is a line of code that is - ignored by the compiler, but it can be read by programmers. Single-line and multi-line comments - are supported in Noir. -keywords: [Noir programming language, comments, single-line comments, multi-line comments] ---- - -A comment is a line in your codebase which the compiler ignores, however it can be read by -programmers. - -Here is a single line comment: - -```rust -// This is a comment and is ignored -``` - -`//` is used to tell the compiler to ignore the rest of the line. - -Noir also supports multi-line block comments. Start a block comment with `/*` and end the block with `*/`. - -Noir does not natively support doc comments. You may be able to use [Rust doc comments](https://doc.rust-lang.org/reference/comments.html) in your code to leverage some Rust documentation build tools with Noir code. - -```rust -/* - This is a block comment describing a complex function. -*/ -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/10_distinct.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/10_distinct.md deleted file mode 100644 index e7ff7f5017a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/10_distinct.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: Distinct Witnesses ---- - -The `distinct` keyword prevents repetitions of witness indices in the program's ABI. This ensures -that the witnesses being returned as public inputs are all unique. - -The `distinct` keyword is only used for return values on program entry points (usually the `main()` -function). - -When using `distinct` and `pub` simultaneously, `distinct` comes first. See the example below. - -You can read more about the problem this solves -[here](https://github.com/noir-lang/noir/issues/1183). - -## Example - -Without the `distinct` keyword, the following program - -```rust -fn main(x : pub Field, y : pub Field) -> pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - "return_witnesses": [3, 2, 4, 4] - } -} -``` - -Whereas (with the `distinct` keyword) - -```rust -fn main(x : pub Field, y : pub Field) -> distinct pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - //... - "return_witnesses": [3, 4, 5, 6] - } -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/11_shadowing.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/11_shadowing.md deleted file mode 100644 index efd743e764f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/11_shadowing.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Shadowing ---- - -Noir allows for inheriting variables' values and re-declaring them with the same name similar to Rust, known as shadowing. - -For example, the following function is valid in Noir: - -```rust -fn main() { - let x = 5; - - { - let x = x * 2; - assert (x == 10); - } - - assert (x == 5); -} -``` - -In this example, a variable x is first defined with the value 5. - -The local scope that follows shadows the original x, i.e. creates a local mutable x based on the value of the original x. It is given a value of 2 times the original x. - -When we return to the main scope, x once again refers to just the original x, which stays at the value of 5. - -## Temporal mutability - -One way that shadowing is useful, in addition to ergonomics across scopes, is for temporarily mutating variables. - -```rust -fn main() { - let age = 30; - // age = age + 5; // Would error as `age` is immutable by default. - - let mut age = age + 5; // Temporarily mutates `age` with a new value. - - let age = age; // Locks `age`'s mutability again. - - assert (age == 35); -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types.md deleted file mode 100644 index 74f573f7d3f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: Data Types -description: - Get a clear understanding of the two categories of Noir data types - primitive types and compound - types. Learn about their characteristics, differences, and how to use them in your Noir - programming. -keywords: - [ - noir, - data types, - primitive types, - compound types, - private types, - public types, - ] ---- - -Every value in Noir has a type, which determines which operations are valid for it. - -All values in Noir are fundamentally composed of `Field` elements. For a more approachable -developing experience, abstractions are added on top to introduce different data types in Noir. - -Noir has two category of data types: primitive types (e.g. `Field`, integers, `bool`) and compound -types that group primitive types (e.g. arrays, tuples, structs). Each value can either be private or -public. - -## Private & Public Types - -A **private value** is known only to the Prover, while a **public value** is known by both the -Prover and Verifier. Mark values as `private` when the value should only be known to the prover. All -primitive types (including individual fields of compound types) in Noir are private by default, and -can be marked public when certain values are intended to be revealed to the Verifier. - -> **Note:** For public values defined in Noir programs paired with smart contract verifiers, once -> the proofs are verified on-chain the values can be considered known to everyone that has access to -> that blockchain. - -Public data types are treated no differently to private types apart from the fact that their values -will be revealed in proofs generated. Simply changing the value of a public type will not change the -circuit (where the same goes for changing values of private types as well). - -_Private values_ are also referred to as _witnesses_ sometimes. - -> **Note:** The terms private and public when applied to a type (e.g. `pub Field`) have a different -> meaning than when applied to a function (e.g. `pub fn foo() {}`). -> -> The former is a visibility modifier for the Prover to interpret if a value should be made known to -> the Verifier, while the latter is a visibility modifier for the compiler to interpret if a -> function should be made accessible to external Noir programs like in other languages. - -### pub Modifier - -All data types in Noir are private by default. Types are explicitly declared as public using the -`pub` modifier: - -```rust -fn main(x : Field, y : pub Field) -> pub Field { - x + y -} -``` - -In this example, `x` is **private** while `y` and `x + y` (the return value) are **public**. Note -that visibility is handled **per variable**, so it is perfectly valid to have one input that is -private and another that is public. - -> **Note:** Public types can only be declared through parameters on `main`. - -## Type Aliases - -A type alias is a new name for an existing type. Type aliases are declared with the keyword `type`: - -```rust -type Id = u8; - -fn main() { - let id: Id = 1; - let zero: u8 = 0; - assert(zero + 1 == id); -} -``` - -Type aliases can also be used with [generics](./06_generics.md): - -```rust -type Id = Size; - -fn main() { - let id: Id = 1; - let zero: u32 = 0; - assert(zero + 1 == id); -} -``` - -### BigInt - -You can achieve BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/00_fields.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/00_fields.md deleted file mode 100644 index 78d3d2af166..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/00_fields.md +++ /dev/null @@ -1,165 +0,0 @@ ---- -title: Fields -description: - Dive deep into the Field data type in Noir. Understand its methods, practical examples, and best practices to effectively use Fields in your Noir programs. -keywords: - [ - noir, - field type, - methods, - examples, - best practices, - ] ---- - -The field type corresponds to the native field type of the proving backend. - -The size of a Noir field depends on the elliptic curve's finite field for the proving backend -adopted. For example, a field would be a 254-bit integer when paired with the default backend that -spans the Grumpkin curve. - -Fields support integer arithmetic and are often used as the default numeric type in Noir: - -```rust -fn main(x : Field, y : Field) { - let z = x + y; -} -``` - -`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new -private value `z` constrained to be equal to `x + y`. - -If proving efficiency is of priority, fields should be used as a default for solving problems. -Smaller integer types (e.g. `u64`) incur extra range constraints. - -## Methods - -After declaring a Field, you can use these common methods on it: - -### to_le_bits - -Transforms the field into an array of bits, Little Endian. - -```rust -fn to_le_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_le_bits(32); -} -``` - -### to_be_bits - -Transforms the field into an array of bits, Big Endian. - -```rust -fn to_be_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_be_bits(32); -} -``` - -### to_le_bytes - -Transforms into an array of bytes, Little Endian - -```rust -fn to_le_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_le_bytes(4); -} -``` - -### to_be_bytes - -Transforms into an array of bytes, Big Endian - -```rust -fn to_be_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_be_bytes(4); -} -``` - -### to_le_radix - -Decomposes into a vector over the specified base, Little Endian - -```rust -fn to_le_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_le_radix(256, 4); -} -``` - -### to_be_radix - -Decomposes into a vector over the specified base, Big Endian - -```rust -fn to_be_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_be_radix(256, 4); -} -``` - -### pow_32 - -Returns the value to the power of the specified exponent - -```rust -fn pow_32(self, exponent: Field) -> Field -``` - -example: - -```rust -fn main() { - let field = 2 - let pow = field.pow_32(4); - assert(pow == 16); -} -``` - -### sgn0 - -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. - -```rust -fn sgn0(self) -> u1 -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/01_integers.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/01_integers.md deleted file mode 100644 index 1814365800a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/01_integers.md +++ /dev/null @@ -1,112 +0,0 @@ ---- -title: Integers -description: Explore the Integer data type in Noir. Learn about its methods, see real-world examples, and grasp how to efficiently use Integers in your Noir code. -keywords: [noir, integer types, methods, examples, arithmetic] ---- - -An integer type is a range constrained field type. The Noir frontend supports arbitrarily-sized, both unsigned and signed integer types. - -:::info - -When an integer is defined in Noir without a specific type, it will default to `Field`. - -The one exception is for loop indices which default to `u64` since comparisons on `Field`s are not possible. - -::: - -## Unsigned Integers - -An unsigned integer type is specified first with the letter `u` (indicating its unsigned nature) followed by its bit size (e.g. `8`): - -```rust -fn main() { - let x: u8 = 1; - let y: u8 = 1; - let z = x + y; - assert (z == 2); -} -``` - -The bit size determines the maximum value the integer type can store. For example, a `u8` variable can store a value in the range of 0 to 255 (i.e. $\\2^{8}-1\\$). - -## Signed Integers - -A signed integer type is specified first with the letter `i` (which stands for integer) followed by its bit size (e.g. `8`): - -```rust -fn main() { - let x: i8 = -1; - let y: i8 = -1; - let z = x + y; - assert (z == -2); -} -``` - -The bit size determines the maximum and minimum range of value the integer type can store. For example, an `i8` variable can store a value in the range of -128 to 127 (i.e. $\\-2^{7}\\$ to $\\2^{7}-1\\$). - -:::tip - -If you are using the default proving backend with Noir, both even (e.g. _u2_, _i2_) and odd (e.g. _u3_, _i3_) arbitrarily-sized integer types up to 127 bits (i.e. _u127_ and _i127_) are supported. - -::: - -## Overflows - -Computations that exceed the type boundaries will result in overflow errors. This happens with both signed and unsigned integers. For example, attempting to prove: - -```rust -fn main(x: u8, y: u8) { - let z = x + y; -} -``` - -With: - -```toml -x = "255" -y = "1" -``` - -Would result in: - -``` -$ nargo prove -error: Assertion failed: 'attempt to add with overflow' -┌─ ~/src/main.nr:9:13 -│ -│ let z = x + y; -│ ----- -│ -= Call stack: - ... -``` - -A similar error would happen with signed integers: - -```rust -fn main() { - let x: i8 = -118; - let y: i8 = -11; - let z = x + y; -} -``` - -### Wrapping methods - -Although integer overflow is expected to error, some use-cases rely on wrapping. For these use-cases, the standard library provides `wrapping` variants of certain common operations: - -```rust -fn wrapping_add(x: T, y: T) -> T; -fn wrapping_sub(x: T, y: T) -> T; -fn wrapping_mul(x: T, y: T) -> T; -``` - -Example of how it is used: - -```rust -use dep::std; - -fn main(x: u8, y: u8) -> pub u8 { - std::wrapping_add(x, y) -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/02_booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/02_booleans.md deleted file mode 100644 index d353606210a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/02_booleans.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: Booleans -description: - Delve into the Boolean data type in Noir. Understand its methods, practical examples, and best practices for using Booleans in your Noir programs. -keywords: - [ - noir, - boolean type, - methods, - examples, - logical operations, - ] ---- - - -The `bool` type in Noir has two possible values: `true` and `false`: - -```rust -fn main() { - let t = true; - let f: bool = false; -} -``` - -> **Note:** When returning a boolean value, it will show up as a value of 1 for `true` and 0 for -> `false` in _Verifier.toml_. - -The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and -[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/03_strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/03_strings.md deleted file mode 100644 index 4360893e9a2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/03_strings.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: Strings -description: - Discover the String data type in Noir. Learn about its methods, see real-world examples, and understand how to effectively manipulate and use Strings in Noir. -keywords: - [ - noir, - string type, - methods, - examples, - concatenation, - ] ---- - - -The string type is a fixed length value defined with `str`. - -You can use strings in `assert()` functions or print them with -`std::println()`. See more about [Logging](../../standard_library/logging.md). - -```rust -use dep::std; - -fn main(message : pub str<11>, hex_as_string : str<4>) { - std::println(message); - assert(message == "hello world"); - assert(hex_as_string == "0x41"); -} -``` - -You can convert a `str` to a byte array by calling `as_bytes()` -or a vector by calling `as_bytes_vec()`. - -```rust -fn main() { - let message = "hello world"; - let message_bytes = message.as_bytes(); - let mut message_vec = message.as_bytes_vec(); - assert(message_bytes.len() == 11); - assert(message_bytes[0] == 104); - assert(message_bytes[0] == message_vec.get(0)); -} -``` - -## Escape characters - -You can use escape characters for your strings: - -| Escape Sequence | Description | -|-----------------|-----------------| -| `\r` | Carriage Return | -| `\n` | Newline | -| `\t` | Tab | -| `\0` | Null Character | -| `\"` | Double Quote | -| `\\` | Backslash | - -Example: - -```rust -let s = "Hello \"world" // prints "Hello "world" -let s = "hey \tyou"; // prints "hey you" -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/04_arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/04_arrays.md deleted file mode 100644 index 3c84da3f8ad..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/04_arrays.md +++ /dev/null @@ -1,244 +0,0 @@ ---- -title: Arrays -description: - Dive into the Array data type in Noir. Grasp its methods, practical examples, and best practices for efficiently using Arrays in your Noir code. -keywords: - [ - noir, - array type, - methods, - examples, - indexing, - ] ---- - -An array is one way of grouping together values into one compound type. Array types can be inferred -or explicitly specified via the syntax `[; ]`: - -```rust -fn main(x : Field, y : Field) { - let my_arr = [x, y]; - let your_arr: [Field; 2] = [x, y]; -} -``` - -Here, both `my_arr` and `your_arr` are instantiated as an array containing two `Field` elements. - -Array elements can be accessed using indexing: - -```rust -fn main() { - let a = [1, 2, 3, 4, 5]; - - let first = a[0]; - let second = a[1]; -} -``` - -All elements in an array must be of the same type (i.e. homogeneous). That is, an array cannot group -a `Field` value and a `u8` value together for example. - -You can write mutable arrays, like: - -```rust -fn main() { - let mut arr = [1, 2, 3, 4, 5]; - assert(arr[0] == 1); - - arr[0] = 42; - assert(arr[0] == 42); -} -``` - -You can instantiate a new array of a fixed size with the same value repeated for each element. The following example instantiates an array of length 32 where each element is of type Field and has the value 0. - -```rust -let array: [Field; 32] = [0; 32]; -``` - -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: - -```rust -let array: [Field; 32] = [0; 32]; -let sl = array.as_slice() -``` - -You can define multidimensional arrays: - -```rust -let array : [[Field; 2]; 2]; -let element = array[0][0]; -``` - -## Types - -You can create arrays of primitive types or structs. There is not yet support for nested arrays -(arrays of arrays) or arrays of structs that contain arrays. - -## Methods - -For convenience, the STD provides some ready-to-use, common methods for arrays: - -### len - -Returns the length of an array - -```rust -fn len(_array: [T; N]) -> comptime Field -``` - -example - -```rust -fn main() { - let array = [42, 42]; - assert(array.len() == 2); -} -``` - -### sort - -Returns a new sorted array. The original array remains untouched. Notice that this function will -only work for arrays of fields or integers, not for any arbitrary type. This is because the sorting -logic it uses internally is optimized specifically for these values. If you need a sort function to -sort any type, you should use the function `sort_via` described below. - -```rust -fn sort(_array: [T; N]) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32]; - let sorted = arr.sort(); - assert(sorted == [32, 42]); -} -``` - -### sort_via - -Sorts the array with a custom comparison function - -```rust -fn sort_via(mut a: [T; N], ordering: fn(T, T) -> bool) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32] - let sorted_ascending = arr.sort_via(|a, b| a <= b); - assert(sorted_ascending == [32, 42]); // verifies - - let sorted_descending = arr.sort_via(|a, b| a >= b); - assert(sorted_descending == [32, 42]); // does not verify -} -``` - -### map - -Applies a function to each element of the array, returning a new array containing the mapped elements. - -```rust -fn map(f: fn(T) -> U) -> [U; N] -``` - -example - -```rust -let a = [1, 2, 3]; -let b = a.map(|a| a * 2); // b is now [2, 4, 6] -``` - -### fold - -Applies a function to each element of the array, returning the final accumulated value. The first -parameter is the initial value. - -```rust -fn fold(mut accumulator: U, f: fn(U, T) -> U) -> U -``` - -This is a left fold, so the given function will be applied to the accumulator and first element of -the array, then the second, and so on. For a given call the expected result would be equivalent to: - -```rust -let a1 = [1]; -let a2 = [1, 2]; -let a3 = [1, 2, 3]; - -let f = |a, b| a - b; -a1.fold(10, f) //=> f(10, 1) -a2.fold(10, f) //=> f(f(10, 1), 2) -a3.fold(10, f) //=> f(f(f(10, 1), 2), 3) -``` - -example: - -```rust - -fn main() { - let arr = [2, 2, 2, 2, 2]; - let folded = arr.fold(0, |a, b| a + b); - assert(folded == 10); -} - -``` - -### reduce - -Same as fold, but uses the first element as starting element. - -```rust -fn reduce(f: fn(T, T) -> T) -> T -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let reduced = arr.reduce(|a, b| a + b); - assert(reduced == 10); -} -``` - -### all - -Returns true if all the elements satisfy the given predicate - -```rust -fn all(predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let all = arr.all(|a| a == 2); - assert(all); -} -``` - -### any - -Returns true if any of the elements satisfy the given predicate - -```rust -fn any(predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 5]; - let any = arr.any(|a| a == 5); - assert(any); -} - -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/05_slices.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/05_slices.mdx deleted file mode 100644 index 1be0ec4a137..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/05_slices.mdx +++ /dev/null @@ -1,146 +0,0 @@ ---- -title: Slices -description: Explore the Slice data type in Noir. Understand its methods, see real-world examples, and learn how to effectively use Slices in your Noir programs. -keywords: [noir, slice type, methods, examples, subarrays] ---- - -import Experimental from '@site/src/components/Notes/_experimental.mdx'; - - - -A slice is a dynamically-sized view into a sequence of elements. They can be resized at runtime, but because they don't own the data, they cannot be returned from a circuit. You can treat slices as arrays without a constrained size. - -```rust -use dep::std::slice; - -fn main() -> pub Field { - let mut slice: [Field] = [0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -View the corresponding test file [here][test-file]. - -[test-file]: https://github.com/noir-lang/noir/blob/f387ec1475129732f72ba294877efdf6857135ac/crates/nargo_cli/tests/test_data_ssa_refactor/slices/src/main.nr - -## Methods - -For convenience, the STD provides some ready-to-use, common methods for slices: - -### push_back - -Pushes a new element to the end of the slice, returning a new slice with a length one greater than the original unmodified slice. - -```rust -fn push_back(_self: [T], _elem: T) -> [T] -``` - -example: - -```rust -fn main() -> pub Field { - let mut slice: [Field] = [0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -View the corresponding test file [here][test-file]. - -### push_front - -Returns a new array with the specified element inserted at index 0. The existing elements indexes are incremented by 1. - -```rust -fn push_front(_self: Self, _elem: T) -> Self -``` - -Example: - -```rust -let mut new_slice: [Field] = []; -new_slice = new_slice.push_front(20); -assert(new_slice[0] == 20); // returns true -``` - -View the corresponding test file [here][test-file]. - -### pop_front - -Returns a tuple of two items, the first element of the array and the rest of the array. - -```rust -fn pop_front(_self: Self) -> (T, Self) -``` - -Example: - -```rust -let (first_elem, rest_of_slice) = slice.pop_front(); -``` - -View the corresponding test file [here][test-file]. - -### pop_back - -Returns a tuple of two items, the beginning of the array with the last element omitted and the last element. - -```rust -fn pop_back(_self: Self) -> (Self, T) -``` - -Example: - -```rust -let (popped_slice, last_elem) = slice.pop_back(); -``` - -View the corresponding test file [here][test-file]. - -### append - -Loops over a slice and adds it to the end of another. - -```rust -fn append(mut self, other: Self) -> Self -``` - -Example: - -```rust -let append = [1, 2].append([3, 4, 5]); -``` - -### insert - -Inserts an element at a specified index and shifts all following elements by 1. - -```rust -fn insert(_self: Self, _index: Field, _elem: T) -> Self -``` - -Example: - -```rust -new_slice = rest_of_slice.insert(2, 100); -assert(new_slice[2] == 100); -``` - -View the corresponding test file [here][test-file]. - -### remove - -Remove an element at a specified index, shifting all elements after it to the left, returning the altered slice and the removed element. - -```rust -fn remove(_self: Self, _index: Field) -> (Self, T) -``` - -Example: - -```rust -let (remove_slice, removed_elem) = slice.remove(3); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/06_vectors.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/06_vectors.mdx deleted file mode 100644 index 4617e90d038..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/06_vectors.mdx +++ /dev/null @@ -1,172 +0,0 @@ ---- -title: Vectors -description: Delve into the Vector data type in Noir. Learn about its methods, practical examples, and best practices for using Vectors in your Noir code. -keywords: [noir, vector type, methods, examples, dynamic arrays] ---- - -import Experimental from '@site/src/components/Notes/_experimental.mdx'; - - - -A vector is a collection type similar to Rust's Vector type. It's convenient way to use slices as mutable arrays. - -Example: - -```rust -use dep::std::collections::vec::Vec; - -let mut vector: Vec = Vec::new(); -for i in 0..5 { - vector.push(i); -} -assert(vector.len() == 5); -``` - -## Methods - -### new - -Creates a new, empty vector. - -```rust -pub fn new() -> Self { - Self { slice: [] } -} -``` - -Example: - -```rust -let empty_vector: Vec = Vec::new(); -assert(empty_vector.len() == 0); -``` - -### from_slice - -Creates a vector containing each element from a given slice. Mutations to the resulting vector will not affect the original slice. - -```rust -pub fn from_slice(slice: [T]) -> Self { - Self { slice } -} -``` - -Example: - -```rust -let arr: [Field] = [1, 2, 3]; -let vector_from_slice = Vec::from_slice(arr); -assert(vector_from_slice.len() == 3); -``` - -### get - -Retrieves an element from the vector at a given index. Panics if the index points beyond the vector's end. - -```rust -pub fn get(self, index: Field) -> T { - self.slice[index] -} -``` - -Example: - -```rust -let vector: Vec = Vec::from_slice([10, 20, 30]); -assert(vector.get(1) == 20); -``` - -### push - -Adds a new element to the vector's end, returning a new vector with a length one greater than the original unmodified vector. - -```rust -pub fn push(&mut self, elem: T) { - self.slice = self.slice.push_back(elem); -} -``` - -Example: - -```rust -let mut vector: Vec = Vec::new(); -vector.push(10); -assert(vector.len() == 1); -``` - -### pop - -Removes an element from the vector's end, returning a new vector with a length one less than the original vector, along with the removed element. Panics if the vector's length is zero. - -```rust -pub fn pop(&mut self) -> T { - let (popped_slice, last_elem) = self.slice.pop_back(); - self.slice = popped_slice; - last_elem -} -``` - -Example: - -```rust -let mut vector = Vec::from_slice([10, 20]); -let popped_elem = vector.pop(); -assert(popped_elem == 20); -assert(vector.len() == 1); -``` - -### insert - -Inserts an element at a specified index, shifting subsequent elements to the right. - -```rust -pub fn insert(&mut self, index: Field, elem: T) { - self.slice = self.slice.insert(index, elem); -} -``` - -Example: - -```rust -let mut vector = Vec::from_slice([10, 30]); -vector.insert(1, 20); -assert(vector.get(1) == 20); -``` - -### remove - -Removes an element at a specified index, shifting subsequent elements to the left, and returns the removed element. - -```rust -pub fn remove(&mut self, index: Field) -> T { - let (new_slice, elem) = self.slice.remove(index); - self.slice = new_slice; - elem -} -``` - -Example: - -```rust -let mut vector = Vec::from_slice([10, 20, 30]); -let removed_elem = vector.remove(1); -assert(removed_elem == 20); -assert(vector.len() == 2); -``` - -### len - -Returns the number of elements in the vector. - -```rust -pub fn len(self) -> Field { - self.slice.len() -} -``` - -Example: - -```rust -let empty_vector: Vec = Vec::new(); -assert(empty_vector.len() == 0); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/07_tuples.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/07_tuples.md deleted file mode 100644 index 5f6cab974a8..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/07_tuples.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: Tuples -description: - Dive into the Tuple data type in Noir. Understand its methods, practical examples, and best practices for efficiently using Tuples in your Noir code. -keywords: - [ - noir, - tuple type, - methods, - examples, - multi-value containers, - ] ---- - -A tuple collects multiple values like an array, but with the added ability to collect values of -different types: - -```rust -fn main() { - let tup: (u8, u64, Field) = (255, 500, 1000); -} -``` - -One way to access tuple elements is via destructuring using pattern matching: - -```rust -fn main() { - let tup = (1, 2); - - let (one, two) = tup; - - let three = one + two; -} -``` - -Another way to access tuple elements is via direct member access, using a period (`.`) followed by -the index of the element we want to access. Index `0` corresponds to the first tuple element, `1` to -the second and so on: - -```rust -fn main() { - let tup = (5, 6, 7, 8); - - let five = tup.0; - let eight = tup.3; -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/08_structs.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/08_structs.md deleted file mode 100644 index 85649dfb389..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/08_structs.md +++ /dev/null @@ -1,73 +0,0 @@ ---- -title: Structs -description: - Explore the Struct data type in Noir. Learn about its methods, see real-world examples, and grasp how to effectively define and use Structs in your Noir programs. -keywords: - [ - noir, - struct type, - methods, - examples, - data structures, - ] ---- - -A struct also allows for grouping multiple values of different types. Unlike tuples, we can also -name each field. - -> **Note:** The usage of _field_ here refers to each element of the struct and is unrelated to the -> field type of Noir. - -Defining a struct requires giving it a name and listing each field within as `: ` pairs: - -```rust -struct Animal { - hands: Field, - legs: Field, - eyes: u8, -} -``` - -An instance of a struct can then be created with actual values in `: ` pairs in any -order. Struct fields are accessible using their given names: - -```rust -fn main() { - let legs = 4; - - let dog = Animal { - eyes: 2, - hands: 0, - legs, - }; - - let zero = dog.hands; -} -``` - -Structs can also be destructured in a pattern, binding each field to a new variable: - -```rust -fn main() { - let Animal { hands, legs: feet, eyes } = get_octopus(); - - let ten = hands + feet + eyes as u8; -} - -fn get_octopus() -> Animal { - let octopus = Animal { - hands: 0, - legs: 8, - eyes: 2, - }; - - octopus -} -``` - -The new variables can be bound with names different from the original struct field names, as -showcased in the `legs --> feet` binding in the example above. - -:::note -You can use Structs as inputs to the `main` function, but you can't output them -::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/09_references.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/09_references.md deleted file mode 100644 index b0c35ce2cb9..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/09_references.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: References ---- - -Noir supports first-class references. References are a bit like pointers: they point to a specific address that can be followed to access the data stored at that address. You can use Rust-like syntax to use pointers in Noir: the `&` operator references the variable, the `*` operator dereferences it. - -Example: - -```rust -fn main() { - let mut x = 2; - - // you can reference x as &mut and pass it to multiplyBy2 - multiplyBy2(&mut x); -} - -// you can access &mut here -fn multiplyBy2(x: &mut Field) { - // and dereference it with * - *x = *x * 2; -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/10_function_types.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/10_function_types.md deleted file mode 100644 index 1ec92efd594..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/10_function_types.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: Function types ---- - -Noir supports higher-order functions. The syntax for a function type is as follows: - -```rust -fn(arg1_type, arg2_type, ...) -> return_type -``` - -Example: - -```rust -fn assert_returns_100(f: fn() -> Field) { // f takes no args and returns a Field - assert(f() == 100); -} - -fn main() { - assert_returns_100(|| 100); // ok - assert_returns_100(|| 150); // fails -} -``` - -A function type also has an optional capture environment - this is necessary to support closures. -See [Lambdas](../08_lambdas.md) for more details. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/migration_notes.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/migration_notes.md deleted file mode 100644 index 905bca3d30c..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/migration_notes.md +++ /dev/null @@ -1,91 +0,0 @@ ---- -title: Migration notes -description: Read about migration notes from previous versions, which could solve problems while updating -keywords: [Noir, notes, migration, updating, upgrading] ---- - -Noir is in full-speed development. Things break fast, wild, and often. This page attempts to leave some notes on errors you might encounter when upgrading and how to resolve them until proper patches are built. - -## ≥0.19 - -### Enforcing `compiler_version` - -From this version on, the compiler will check for the `compiler_version` field in `Nargo.toml`, and will error if it doesn't match the current Nargo version in use. - -To update, please make sure this field in `Nargo.toml` matches the output of `nargo --version`. - -## ≥0.14 - -The index of the [for loops](./language_concepts/02_control_flow.md#loops) is now of type `u64` instead of `Field`. An example refactor would be: - -```rust -for i in 0..10 { - let i = i as Field; -} -``` - -## ≥v0.11.0 and Nargo backend - -From this version onwards, Nargo starts managing backends through the `nargo backend` command. Upgrading to the versions per usual steps might lead to: - -### `backend encountered an error` - -This is likely due to the existing locally installed version of proving backend (e.g. barretenberg) is incompatible with the version of Nargo in use. - -To fix the issue: - -1. Uninstall the existing backend - -```bash -nargo backend uninstall acvm-backend-barretenberg -``` - -You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. - -2. Reinstall a compatible version of the proving backend. - -If you are using the default barretenberg backend, simply run: - -``` -nargo prove -``` - -with your Noir program. - -This will trigger the download and installation of the latest version of barretenberg compatible with your Nargo in use. - -### `backend encountered an error: illegal instruction` - -On certain Intel-based systems, an `illegal instruction` error may arise due to incompatibility of barretenberg with certain CPU instructions. - -To fix the issue: - -1. Uninstall the existing backend - -```bash -nargo backend uninstall acvm-backend-barretenberg -``` - -You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. - -2. Reinstall a compatible version of the proving backend. - -If you are using the default barretenberg backend, simply run: - -``` -nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/barretenberg-js-binary/raw/master/run-bb.tar.gz -``` - -This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. - -The gzipped file is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. - -Then run: - -``` -DESIRED_BINARY_VERSION=0.8.1 nargo info -``` - -This overrides the bb native binary with a bb.js node application instead, which should be compatible with most if not all hardware. This does come with the drawback of being generally slower than native binary. - -0.8.1 indicates bb.js version 0.8.1, so if you change that it will update to a different version or the default version in the script if none was supplied. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/modules_packages_crates/crates_and_packages.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/modules_packages_crates/crates_and_packages.md deleted file mode 100644 index 23f60855c30..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/modules_packages_crates/crates_and_packages.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Crates and Packages -description: Learn how to use Crates and Packages in your Noir project -keywords: [Nargo, dependencies, package management, crates, package] ---- - -## Crates - -A crate is the smallest amount of code that the Noir compiler considers at a time. -Crates can contain modules, and the modules may be defined in other files that get compiled with the crate, as we’ll see in the coming sections. - -### Crate Types - -A Noir crate can come in several forms: binaries, libraries or contracts. - -#### Binaries - -_Binary crates_ are programs which you can compile to an ACIR circuit which you can then create proofs against. Each must have a function called `main` that defines the ACIR circuit which is to be proved. - -#### Libraries - -_Library crates_ don't have a `main` function and they don't compile down to ACIR. Instead they define functionality intended to be shared with multiple projects, and eventually included in a binary crate. - -#### Contracts - -Contract crates are similar to binary crates in that they compile to ACIR which you can create proofs against. They are different in that they do not have a single `main` function, but are a collection of functions to be deployed to the [Aztec network](https://aztec.network). You can learn more about the technical details of Aztec in the [monorepo](https://github.com/AztecProtocol/aztec-packages) or contract [examples](https://github.com/AztecProtocol/aztec-packages/tree/master/noir-projects/noir-contracts/contracts). - -### Crate Root - -Every crate has a root, which is the source file that the compiler starts, this is also known as the root module. The Noir compiler does not enforce any conditions on the name of the file which is the crate root, however if you are compiling via Nargo the crate root must be called `lib.nr` or `main.nr` for library or binary crates respectively. - -## Packages - -A Nargo _package_ is a collection of one of more crates that provides a set of functionality. A package must include a Nargo.toml file. - -A package _must_ contain either a library or a binary crate, but not both. - -### Differences from Cargo Packages - -One notable difference between Rust's Cargo and Noir's Nargo is that while Cargo allows a package to contain an unlimited number of binary crates and a single library crate, Nargo currently only allows a package to contain a single crate. - -In future this restriction may be lifted to allow a Nargo package to contain both a binary and library crate or multiple binary crates. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/modules_packages_crates/dependencies.md deleted file mode 100644 index 87a09293ea8..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/modules_packages_crates/dependencies.md +++ /dev/null @@ -1,123 +0,0 @@ ---- -title: Dependencies -description: - Learn how to specify and manage dependencies in Nargo, allowing you to upload packages to GitHub - and use them easily in your project. -keywords: [Nargo, dependencies, GitHub, package management, versioning] ---- - -Nargo allows you to upload packages to GitHub and use them as dependencies. - -## Specifying a dependency - -Specifying a dependency requires a tag to a specific commit and the git url to the url containing -the package. - -Currently, there are no requirements on the tag contents. If requirements are added, it would follow -semver 2.0 guidelines. - -> Note: Without a `tag` , there would be no versioning and dependencies would change each time you -> compile your project. - -For example, to add the [ecrecover-noir library](https://github.com/colinnielsen/ecrecover-noir) to your project, add it to `Nargo.toml`: - -```toml -# Nargo.toml - -[dependencies] -ecrecover = {tag = "v0.8.0", git = "https://github.com/colinnielsen/ecrecover-noir"} -``` - -If the module is in a subdirectory, you can define a subdirectory in your git repository, for example: - -```toml -# Nargo.toml - -[dependencies] -easy_private_token_contract = {tag ="v0.1.0-alpha62", git = "https://github.com/AztecProtocol/aztec-packages", directory = "yarn-project/noir-contracts/contracts/easy_private_token_contract"} -``` - -## Specifying a local dependency - -You can also specify dependencies that are local to your machine. - -For example, this file structure has a library and binary crate - -```tree -├── binary_crate -│   ├── Nargo.toml -│   └── src -│   └── main.nr -└── lib_a - ├── Nargo.toml - └── src - └── lib.nr -``` - -Inside of the binary crate, you can specify: - -```toml -# Nargo.toml - -[dependencies] -lib_a = { path = "../lib_a" } -``` - -## Importing dependencies - -You can import a dependency to a Noir file using the following syntax. For example, to import the -ecrecover-noir library and local lib_a referenced above: - -```rust -use dep::ecrecover; -use dep::lib_a; -``` - -You can also import only the specific parts of dependency that you want to use, like so: - -```rust -use dep::std::hash::sha256; -use dep::std::scalar_mul::fixed_base_embedded_curve; -``` - -Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you -can import multiple items in the same line by enclosing them in curly braces: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; -``` - -We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. - -Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. - -## Dependencies of Dependencies - -Note that when you import a dependency, you also get access to all of the dependencies of that package. - -For example, the [phy_vector](https://github.com/resurgencelabs/phy_vector) library imports an [fraction](https://github.com/resurgencelabs/fraction) library. If you're importing the phy_vector library, then you can access the functions in fractions library like so: - -```rust -use dep::phy_vector; - -fn main(x : Field, y : pub Field) { - //... - let f = phy_vector::fraction::toFraction(true, 2, 1); - //... -} -``` - -## Available Libraries - -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). - -Some libraries that are available today include: - -- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library -- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) -- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers -- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address -- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees -- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir -- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/modules_packages_crates/modules.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/modules_packages_crates/modules.md deleted file mode 100644 index 11e60cbf35e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/modules_packages_crates/modules.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: Modules -description: - Learn how to organize your files using modules in Noir, following the same convention as Rust's - module system. Examples included. -keywords: [Noir, Rust, modules, organizing files, sub-modules] ---- - -Noir's module system follows the same convention as the _newer_ version of Rust's module system. - -## Purpose of Modules - -Modules are used to organize files. Without modules all of your code would need to live in a single -file. In Noir, the compiler does not automatically scan all of your files to detect modules. This -must be done explicitly by the developer. - -## Examples - -### Importing a module in the crate root - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::hello_world(); -} -``` - -Filename : `src/foo.nr` - -```rust -fn from_foo() {} -``` - -In the above snippet, the crate root is the `src/main.nr` file. The compiler sees the module -declaration `mod foo` which prompts it to look for a foo.nr file. - -Visually this module hierarchy looks like the following : - -``` -crate - ├── main - │ - └── foo - └── from_foo - -``` - -### Importing a module throughout the tree - -All modules are accessible from the `crate::` namespace. - -``` -crate - ├── bar - ├── foo - └── main - -``` - -In the above snippet, if `bar` would like to use functions in `foo`, it can do so by `use crate::foo::function_name`. - -### Sub-modules - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::from_foo(); -} -``` - -Filename : `src/foo.nr` - -```rust -mod bar; -fn from_foo() {} -``` - -Filename : `src/foo/bar.nr` - -```rust -fn from_bar() {} -``` - -In the above snippet, we have added an extra module to the module tree; `bar`. `bar` is a submodule -of `foo` hence we declare bar in `foo.nr` with `mod bar`. Since `foo` is not the crate root, the -compiler looks for the file associated with the `bar` module in `src/foo/bar.nr` - -Visually the module hierarchy looks as follows: - -``` -crate - ├── main - │ - └── foo - ├── from_foo - └── bar - └── from_bar -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/modules_packages_crates/workspaces.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/modules_packages_crates/workspaces.md deleted file mode 100644 index 8168793fc80..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/modules_packages_crates/workspaces.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -title: Workspaces ---- - -Workspaces are a feature of nargo that allow you to manage multiple related Noir packages in a single repository. A workspace is essentially a group of related projects that share common build output directories and configurations. - -Each Noir project (with it's own Nargo.toml file) can be thought of as a package. Each package is expected to contain exactly one "named circuit", being the "name" defined in Nargo.toml with the program logic defined in `./src/main.nr`. - -For a project with the following structure: - -```tree -├── crates -│ ├── a -│ │ ├── Nargo.toml -│ │ └── Prover.toml -│ │ └── src -│ │ └── main.nr -│ └── b -│ ├── Nargo.toml -│ └── Prover.toml -│ └── src -│ └── main.nr -│ -└── Nargo.toml -``` - -You can define a workspace in Nargo.toml like so: - -```toml -[workspace] -members = ["crates/a", "crates/b"] -default-member = "crates/a" -``` - -`members` indicates which packages are included in the workspace. As such, all member packages of a workspace will be processed when the `--workspace` flag is used with various commands or if a `default-member` is not specified. - -`default-member` indicates which package various commands process by default. - -Libraries can be defined in a workspace. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. - -Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/nargo/01_commands.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/nargo/01_commands.md deleted file mode 100644 index e2b0af522f4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/nargo/01_commands.md +++ /dev/null @@ -1,250 +0,0 @@ ---- -title: Commands -description: - Noir CLI Commands for Noir Prover and Verifier to create, execute, prove and verify programs, - generate Solidity verifier smart contract and compile into JSON file containing ACIR - representation and ABI of circuit. -keywords: - [ - Nargo, - Noir CLI, - Noir Prover, - Noir Verifier, - generate Solidity verifier, - compile JSON file, - ACIR representation, - ABI of circuit, - TypeScript, - ] ---- - -## General options - -| Option | Description | -| -------------------- | -------------------------------------------------- | -| `--show-ssa` | Emit debug information for the intermediate SSA IR | -| `--deny-warnings` | Quit execution when warnings are emitted | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo help [subcommand]` - -Prints the list of available commands or specific information of a subcommand. - -_Arguments_ - -| Argument | Description | -| -------------- | -------------------------------------------- | -| `` | The subcommand whose help message to display | - -## `nargo backend` - -Installs and selects custom backends used to generate and verify proofs. - -### Commands - -| Command | Description | -| ----------- | --------------------------------------------------------- | -| `current` | Prints the name of the currently active backend | -| `ls` | Prints the list of currently installed backends | -| `use` | Select the backend to use | -| `install` | Install a new backend from a URL | -| `uninstall` | Uninstalls a backend | -| `help` | Print this message or the help of the given subcommand(s) | - -### Options - -| Option | Description | -| ------------ | ----------- | -| `-h, --help` | Print help | - -## `nargo check` - -Generate the `Prover.toml` and `Verifier.toml` files for specifying prover and verifier in/output -values of the Noir program respectively. - -### Options - -| Option | Description | -| --------------------- | ------------------------------------- | -| `--package ` | The name of the package to check | -| `--workspace` | Check all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -### `nargo codegen-verifier` - -Generate a Solidity verifier smart contract for the program. - -### Options - -| Option | Description | -| --------------------- | ------------------------------------- | -| `--package ` | The name of the package to codegen | -| `--workspace` | Codegen all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo compile` - -Compile the program into a JSON build artifact file containing the ACIR representation and the ABI -of the circuit. This build artifact can then be used to generate and verify proofs. - -You can also use "build" as an alias for compile (e.g. `nargo build`). - -### Options - -| Option | Description | -| --------------------- | ------------------------------------------------------------ | -| `--include-keys` | Include Proving and Verification keys in the build artifacts | -| `--package ` | The name of the package to compile | -| `--workspace` | Compile all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo new ` - -Creates a new Noir project in a new folder. - -**Arguments** - -| Argument | Description | -| -------- | -------------------------------- | -| `` | The path to save the new project | - -### Options - -| Option | Description | -| --------------- | ----------------------------------------------------- | -| `--name ` | Name of the package [default: package directory name] | -| `--lib` | Use a library template | -| `--bin` | Use a binary template [default] | -| `--contract` | Use a contract template | -| `-h, --help` | Print help | - -## `nargo init` - -Creates a new Noir project in the current directory. - -### Options - -| Option | Description | -| --------------- | ----------------------------------------------------- | -| `--name ` | Name of the package [default: current directory name] | -| `--lib` | Use a library template | -| `--bin` | Use a binary template [default] | -| `--contract` | Use a contract template | -| `-h, --help` | Print help | - -## `nargo execute [WITNESS_NAME]` - -Runs the Noir program and prints its return value. - -**Arguments** - -| Argument | Description | -| ---------------- | ----------------------------------------- | -| `[WITNESS_NAME]` | Write the execution witness to named file | - -### Options - -| Option | Description | -| --------------------------------- | ------------------------------------------------------------------------------------ | -| `-p, --prover-name ` | The name of the toml file which contains the inputs for the prover [default: Prover] | -| `--package ` | The name of the package to execute | -| `--workspace` | Execute all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -_Usage_ - -The inputs to the circuit are read from the `Prover.toml` file generated by `nargo check`, which -must be filled in. - -To save the witness to file, run the command with a value for the `WITNESS_NAME` argument. A -`.tr` file will then be saved in the `./target` folder. - -## `nargo prove` - -Creates a proof for the program. - -### Options - -| Option | Description | -| ------------------------------------- | ---------------------------------------------------------------------------------------- | -| `-p, --prover-name ` | The name of the toml file which contains the inputs for the prover [default: Prover] | -| `-v, --verifier-name ` | The name of the toml file which contains the inputs for the verifier [default: Verifier] | -| `--verify` | Verify proof after proving | -| `--package ` | The name of the package to prove | -| `--workspace` | Prove all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo verify` - -Given a proof and a program, verify whether the proof is valid. - -### Options - -| Option | Description | -| ------------------------------------- | ---------------------------------------------------------------------------------------- | -| `-v, --verifier-name ` | The name of the toml file which contains the inputs for the verifier [default: Verifier] | -| `--package ` | The name of the package to verify | -| `--workspace` | Verify all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo test [TEST_NAME]` - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. To print `println` statements in tests, use the `--show-output` flag. - -Takes an optional `--exact` flag which allows you to select tests based on an exact name. - -See an example on the [testing page](./testing.md). - -### Options - -| Option | Description | -| --------------------- | -------------------------------------- | -| `--show-output` | Display output of `println` statements | -| `--exact` | Only run tests that match exactly | -| `--package ` | The name of the package to test | -| `--workspace` | Test all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo info` - -Prints a table containing the information of the package. - -Currently the table provide - -1. The number of ACIR opcodes -2. The final number gates in the circuit used by a backend - -If the file contains a contract the table will provide the -above information about each function of the contract. - -## `nargo lsp` - -Start a long-running Language Server process that communicates over stdin/stdout. -Usually this command is not run by a user, but instead will be run by a Language Client, such as [vscode-noir](https://github.com/noir-lang/vscode-noir). - -## `nargo fmt` - -Automatically formats your Noir source code based on the default formatting settings. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/nargo/02_testing.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/nargo/02_testing.md deleted file mode 100644 index 5c57ef92705..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/nargo/02_testing.md +++ /dev/null @@ -1,61 +0,0 @@ ---- -title: Testing in Noir -description: Learn how to use Nargo to test your Noir program in a quick and easy way -keywords: [Nargo, testing, Noir, compile, test] ---- - -You can test your Noir programs using Noir circuits. - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. - -For example if you have a program like: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test] -fn test_add() { - assert(add(2,2) == 4); - assert(add(0,1) == 1); - assert(add(1,0) == 1); -} -``` - -Running `nargo test` will test that the `test_add` function can be executed while satisfying all -the constraints which allows you to test that add returns the expected values. Test functions can't -have any arguments currently. - -### Test fail - -You can write tests that are expected to fail by using the decorator `#[test(should_fail)]`. For example: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test(should_fail)] -fn test_add() { - assert(add(2,2) == 5); -} -``` - -You can be more specific and make it fail with a specific reason by using `should_fail_with = "`: - -```rust -fn main(african_swallow_avg_speed : Field) { - assert(african_swallow_avg_speed == 65, "What is the airspeed velocity of an unladen swallow"); -} - -#[test] -fn test_king_arthur() { - main(65); -} - -#[test(should_fail_with = "What is the airspeed velocity of an unladen swallow")] -fn test_bridgekeeper() { - main(32); -} - -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/nargo/03_solidity_verifier.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/nargo/03_solidity_verifier.md deleted file mode 100644 index 9ac60cb0ba7..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/nargo/03_solidity_verifier.md +++ /dev/null @@ -1,129 +0,0 @@ ---- -title: Solidity Verifier -description: - Learn how to run the verifier as a smart contract on the blockchain. Compile a Solidity verifier - contract for your Noir program and deploy it on any EVM blockchain acting as a verifier smart - contract. Read more to find out! -keywords: - [ - solidity verifier, - smart contract, - blockchain, - compiler, - plonk_vk.sol, - EVM blockchain, - verifying Noir programs, - proving backend, - Barretenberg, - ] ---- - -For certain applications, it may be desirable to run the verifier as a smart contract instead of on -a local machine. - -Compile a Solidity verifier contract for your Noir program by running: - -```sh -nargo codegen-verifier -``` - -A new `contract` folder would then be generated in your project directory, containing the Solidity -file `plonk_vk.sol`. It can be deployed on any EVM blockchain acting as a verifier smart contract. - -> **Note:** It is possible to compile verifier contracts of Noir programs for other smart contract -> platforms as long as the proving backend supplies an implementation. -> -> Barretenberg, the default proving backend for Nargo, supports compilation of verifier contracts in -> Solidity only for the time being. - -## Verify - -To verify a proof using the Solidity verifier contract, call the `verify` function with the -following signature: - -```solidity -function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) -``` - -You can see an example of how the `verify` function is called in the example zk voting application [here](https://github.com/noir-lang/noir-examples/blob/33e598c257e2402ea3a6b68dd4c5ad492bce1b0a/foundry-voting/src/zkVote.sol#L35): - -```solidity -function castVote(bytes calldata proof, uint proposalId, uint vote, bytes32 nullifierHash) public returns (bool) { - // ... - bytes32[] memory publicInputs = new bytes32[](4); - publicInputs[0] = merkleRoot; - publicInputs[1] = bytes32(proposalId); - publicInputs[2] = bytes32(vote); - publicInputs[3] = nullifierHash; - require(verifier.verify(proof, publicInputs), "Invalid proof"); -``` - -### Public Inputs - -:::tip - -A circuit doesn't have the concept of a return value. Return values are just syntactic sugar in -Noir. - -Under the hood, the return value is passed as an input to the circuit and is checked at the end of -the circuit program. - -::: - -The verifier contract uses the output (return) value of a Noir program as a public input. So if you -have the following function - -```rust -fn main( - // Public inputs - pubkey_x: pub Field, - pubkey_y: pub Field, - // Private inputs - priv_key: Field, -) -> pub Field -``` - -then `verify` in `plonk_vk.sol` will expect 3 public inputs. Passing two inputs will result in an -error like `Reason: PUBLIC_INPUT_COUNT_INVALID(3, 2)`. - -In this case the 3 inputs to `verify` would be ordered as `[pubkey_x, pubkey_y, return]`. - -#### Struct inputs - -Consider the following program: - -```rust -struct Type1 { - val1: Field, - val2: Field, -} - -struct Nested { - t1: Type1, - is_true: bool, -} - -fn main(x: pub Field, nested: pub Nested, y: pub Field) { - //... -} -``` - -Structs will be flattened so that the array of inputs is 1-dimensional array. The order of these inputs would be flattened to: `[x, nested.t1.val1, nested.t1.val2, nested.is_true, y]` - -## Noir for EVM chains - -You can currently deploy the Solidity verifier contracts to most EVM compatible chains. EVM chains that have been tested and are known to work include: - -- Optimism -- Arbitrum -- Polygon PoS -- Scroll -- Celo - -Other EVM chains should work, but have not been tested directly by our team. If you test any other chains, please open a PR on this page to update the list. See [this doc](https://github.com/noir-lang/noir-starter/tree/main/with-foundry#testing-on-chain) for more info about testing verifier contracts on different EVM chains. - -### Unsupported chains - -Unfortunately not all "EVM" chains are supported. - -**zkSync** and the **Polygon zkEVM** do _not_ currently support proof verification via Solidity verifier contracts. They are missing the bn256 precompile contract that the verifier contract requires. Once these chains support this precompile, they may work. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/nargo/04_language_server.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/nargo/04_language_server.md deleted file mode 100644 index 48c01465f6e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/nargo/04_language_server.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Language Server -description: Learn about the Noir Language Server, how to install the components, and configuration that may be required. -keywords: [Nargo, Language Server, LSP, VSCode, Visual Studio Code] ---- - -This section helps you install and configure the Noir Language Server. - -The Language Server Protocol (LSP) has two components, the [Server](#language-server) and the [Client](#language-client). Below we describe each in the context of Noir. - -## Language Server - -The Server component is provided by the Nargo command line tool that you installed at the beginning of this guide. -As long as Nargo is installed and you've used it to run other commands in this guide, it should be good to go! - -If you'd like to verify that the `nargo lsp` command is available, you can run `nargo --help` and look for `lsp` in the list of commands. If you see it, you're using a version of Noir with LSP support. - -## Language Client - -The Client component is usually an editor plugin that launches the Server. It communicates LSP messages between the editor and the Server. For example, when you save a file, the Client will alert the Server, so it can try to compile the project and report any errors. - -Currently, Noir provides a Language Client for Visual Studio Code via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). - -> **Note:** Noir's Language Server Protocol support currently assumes users' VSCode workspace root to be the same as users' Noir project root (i.e. where Nargo.toml lies). -> -> If LSP features seem to be missing / malfunctioning, make sure you are opening your Noir project directly (instead of as a sub-folder) in your VSCode instance. - -When your language server is running correctly and the VSCode plugin is installed, you should see handy codelens buttons for compilation, measuring circuit size, execution, and tests: - -![Compile and Execute](@site/static/img/codelens_compile_execute.png) -![Run test](@site/static/img/codelens_run_test.png) - -You should also see your tests in the `testing` panel: - -![Testing panel](@site/static/img/codelens_testing_panel.png) - -### Configuration - -- **Noir: Enable LSP** - If checked, the extension will launch the Language Server via `nargo lsp` and communicate with it. -- **Noir: Nargo Flags** - Additional flags may be specified if you require them to be added when the extension calls `nargo lsp`. -- **Noir: Nargo Path** - An absolute path to a Nargo binary with the `lsp` command. This may be useful if Nargo is not within the `PATH` of your editor. -- **Noir > Trace: Server** - Setting this to `"messages"` or `"verbose"` will log LSP messages between the Client and Server. Useful for debugging. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/getting_started/01_tiny_noir_app.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/getting_started/01_tiny_noir_app.md deleted file mode 100644 index 64ba4a2c44a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/getting_started/01_tiny_noir_app.md +++ /dev/null @@ -1,260 +0,0 @@ ---- -title: End-to-end -description: Learn how to setup a new app that uses Noir to generate and verify zero-knowledge SNARK proofs in a typescript or javascript environment -keywords: [how to, guide, javascript, typescript, noir, barretenberg, zero-knowledge, proofs] ---- - -NoirJS works both on the browser and on the server, and works for both ESM and CJS module systems. In this page, we will learn how can we write a simple test and a simple web app to verify the standard Noir example. - -You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). - -## Before we start - -:::note - -Feel free to use whatever versions, just keep in mind that Nargo and the NoirJS packages are meant to be in sync. For example, Nargo 0.18.x matches `noir_js@0.18.x`, etc. - -In this guide, we will be pinned to 0.17.0. - -::: - -Make sure you have Node installed on your machine by opening a terminal and executing `node --version`. If you don't see a version, you should install [node](https://github.com/nvm-sh/nvm). You can also use `yarn` if you prefer that package manager over npm (which comes with node). - -First of all, follow the [Nargo guide](../../getting_started/00_nargo_installation.md) to install nargo version 0.17.0 and create a new project with `nargo new circuit`. Once there, `cd` into the `circuit` folder. You should then be able to compile your circuit into `json` format and see it inside the `target` folder: - -```bash -nargo compile -``` - -Your folder structure should look like: - -```tree -. -└── circuit - ├── Nargo.toml - ├── src - │ └── main.nr - └── target - └── circuit.json -``` - -## Starting a new project - -Go back to the previous folder and start a new project by running run `npm init`. You can configure your project or just leave the defaults, and see a `package.json` appear in your root folder. - -## Installing dependencies - -We'll need two `npm` packages. These packages will provide us the methods we need to run and verify proofs: - -```bash -npm i @noir-lang/backend_barretenberg@^0.17.0 @noir-lang/noir_js@^0.17.0 -``` - -To serve our page, we can use a build tool such as `vite`. Because we're gonna use some `wasm` files, we need to install a plugin as well. Run: - -```bash -npm i --save-dev vite rollup-plugin-copy -``` - -Since we're on the dependency world, we may as well define a nice starting script. Vite makes it easy. Just open `package.json`, find the block "scripts" and add this just below the line with `"test" : "echo......."`: - -```json - "start": "vite --open" -``` - -If you want do build a static website, you can also add some build and preview scripts: - -```json - "build": "vite build", - "preview": "vite preview" -``` - -## Vite plugins - -Vite is great, but support from `wasm` doesn't work out-of-the-box. We're gonna write a quick plugin and use another one. Just copy and paste this into a file named `vite.config.js`. You don't need to understand it, just trust me bro. - -```js -import { defineConfig } from 'vite'; -import copy from 'rollup-plugin-copy'; -import fs from 'fs'; -import path from 'path'; - -const wasmContentTypePlugin = { - name: 'wasm-content-type-plugin', - configureServer(server) { - server.middlewares.use(async (req, res, next) => { - if (req.url.endsWith('.wasm')) { - res.setHeader('Content-Type', 'application/wasm'); - const newPath = req.url.replace('deps', 'dist'); - const targetPath = path.join(__dirname, newPath); - const wasmContent = fs.readFileSync(targetPath); - return res.end(wasmContent); - } - next(); - }); - }, -}; - -export default defineConfig(({ command }) => { - if (command === 'serve') { - return { - plugins: [ - copy({ - targets: [{ src: 'node_modules/**/*.wasm', dest: 'node_modules/.vite/dist' }], - copySync: true, - hook: 'buildStart', - }), - command === 'serve' ? wasmContentTypePlugin : [], - ], - }; - } - - return {}; -}); -``` - -## HTML - -Here's the simplest HTML with some terrible UI. Create a file called `index.html` and paste this: - -```html - - - - - - -

Very basic Noir app

-
-

Logs

-

Proof

-
- - -``` - -## Some good old vanilla Javascript - -Create a new file `app.js`, which is where our javascript code will live. Let's start with this code inside: - -```js -document.addEventListener('DOMContentLoaded', async () => { - // here's where the magic happens -}); - -function display(container, msg) { - const c = document.getElementById(container); - const p = document.createElement('p'); - p.textContent = msg; - c.appendChild(p); -} -``` - -We can manipulate our website with this little function, so we can see our website working. - -## Adding Noir - -If you come from the previous page, your folder structure should look like this: - -```tree -├── app.js -├── circuit -│ ├── Nargo.toml -│ ├── src -│ │ └── main.nr -│ └── target -│ └── circuit.json -├── index.html -├── package.json -└── vite.config.js -``` - -You'll see other files and folders showing up (like `package-lock.json`, `yarn.lock`, `node_modules`) but you shouldn't have to care about those. - -## Importing our dependencies - -We're starting with the good stuff now. At the top of the new javascript file, import the packages: - -```ts -import { BarretenbergBackend } from '@noir-lang/backend_barretenberg'; -import { Noir } from '@noir-lang/noir_js'; -``` - -We also need to import the `circuit` JSON file we created. If you have the suggested folder structure, you can add this line: - -```ts -import circuit from './circuit/target/circuit.json'; -``` - -## Write code - -:::note - -We're gonna be adding code inside the `document.addEventListener...etc` block: - -```js -// forget stuff here -document.addEventListener('DOMContentLoaded', async () => { - // here's where the magic happens -}); -// forget stuff here -``` - -::: - -Our dependencies exported two classes: `BarretenbergBackend` and `Noir`. Let's `init` them and add some logs, just to flex: - -```ts -const backend = new BarretenbergBackend(circuit); -const noir = new Noir(circuit, backend); -``` - -## Proving - -Now we're ready to prove stuff! Let's feed some inputs to our circuit and calculate the proof: - -```js -const input = { x: 1, y: 2 }; -display('logs', 'Generating proof... ⌛'); -const proof = await noir.generateFinalProof(input); -display('logs', 'Generating proof... ✅'); -display('results', proof.proof); -``` - -You're probably eager to see stuff happening, so go and run your app now! - -From your terminal, run `npm start` (or `yarn start`). If it doesn't open a browser for you, just visit `localhost:5173`. On a modern laptop, proof will generate in less than 100ms, and you'll see this: - -![Getting Started 0](@site/static/img/noir_getting_started_1.png) - -If you're human, you shouldn't be able to understand anything on the "proof" box. That's OK. We like you, human. - -In any case, this means your proof was generated! But you shouldn't trust me just yet. Add these lines to see it being verified: - -```js -display('logs', 'Verifying proof... ⌛'); -const verification = await noir.verifyFinalProof(proof); -if (verification) display('logs', 'Verifying proof... ✅'); -``` - -By saving, your app will refresh and here's our complete Tiny Noir App! - -You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). - -## Further Reading - -You can see how noirjs is used in a full stack Next.js hardhat application in the [noir-starter repo here](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat). The example shows how to calculate a proof in the browser and verify it with a deployed Solidity verifier contract from noirjs. - -You should also check out the more advanced examples in the [noir-examples repo](https://github.com/noir-lang/noir-examples), where you'll find reference usage for some cool apps. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/noir_js.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/noir_js.md deleted file mode 100644 index 23ea550e156..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/noir_js.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: NoirJS -description: Interact with Noir in Typescript or Javascript -keywords: [Noir project, javascript, typescript, node.js, browser, react] ---- - -NoirJS is a TypeScript library that make it easy to use Noir on your dapp, webapp, Node.js server, website, etc. - -A typical workflow would be composed of two major elements: - -- NoirJS -- Proving backend of choice's JavaScript package - - - -To install NoirJS, install Node.js if you have not already and run this in your JavaScript project: - -```bash -npm i @noir-lang/noir_js -``` - -## Proving backend - -Since Noir is backend agnostic, you can instantiate NoirJS without any backend (i.e. to execute a function). But for proving, you would have to instantiate NoirJS with any of the supported backends through their own `js` interface. - -### Barretenberg - -Aztec Labs maintains the `barretenberg` proving backend, which you can instantiate and make use of alongside NoirJS. It is also the default proving backend installed and used with Nargo, the Noir CLI tool. - -To install its JavaScript library, run this in your project: - -```bash -npm i @noir-lang/backend_barretenberg -``` - -For more details on how to instantiate and use the libraries, refer to the [Full Noir App Guide](./getting_started/01_tiny_noir_app.md) and [Reference](./reference/01_noirjs.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/01_noirjs.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/01_noirjs.md deleted file mode 100644 index 2e90779ceab..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/01_noirjs.md +++ /dev/null @@ -1,147 +0,0 @@ ---- -title: Noir -description: Reference to noir_js library and the Noir class -keywords: [Noir project, javascript, typescript, node.js, browser, react, class, reference] ---- - -## Table of Contents - -- [constructor](#constructor) -- [init](#init) -- [generateFinalProof](#generatefinalproof) -- [verifyFinalProof](#verifyfinalproof) - -## `constructor` - -The `constructor` is a method used to create and initialize objects created within the `Noir` class. In the `Noir` class constructor, you need to pass two parameters: `circuit` and `backend`. - -### Syntax - -```js -constructor(circuit, backend); -``` - -### Parameters - -| Parameter | Type | Description | -| --------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `circuit` | Object | A circuit represented in a `json` format, containing the ABI and bytecode. Typically obtained by running [`nargo compile`](../../nargo/01_commands.md) | -| `backend` | Object | A backend instance, before initialization. | - -### Usage - -```js -const noir = new Noir(circuit, backend); -``` - -## `init` - -This async method should be called after class instantiation. It will run processes on the ACVM, instantiate your backend, etc. - -### Syntax - -```js -async init() -``` - -### Parameters - -This method takes no parameters - -### Usage - -```js -await noirInstance.init(); -``` - -## `execute` - -This async method allows to execute a circuit to get its witness and return value. [`generateFinalProof`](#generatefinalproof) calls it for you, but you can call it directly (i.e. to feed directly to a backend, or to get the return value). - -You can optionally provide a foreignCallHandler, to handle functions that should run outside of the prover (e.g. `std::println`) - -### Syntax - -```js -async execute(inputs, foreignCallHandler) -``` - -### Parameters - -| Parameter | Type | Description | -| --------- | ------ | ------------------------------------------------ | -| `inputs` | Object | An object containing the inputs to your circuit. | -| `foreignCallHandler` (optional) | Function | A function handling the foreign call from your circuit | - -### Returns - -| Return value | Type | Description | -| ------------ | --------------------- | --------------------------------------------------- | -| `witness` | Promise \ | The witness | -| `returnValue` | Promise \ | The return value | - -### Usage - -```js -const { witness, returnValue } = await noir.execute(inputs) -const { witness, returnValue } = await noir.execute(inputs, (name, args) => console.log(`Received foreign call ${name} with arguments ${args}`)) -``` - -## `generateFinalProof` - -This async method generates a witness and a proof given an object as input. - -### Syntax - -```js -async generateFinalProof(input) -``` - -### Parameters - -| Parameter | Type | Description | -| --------- | ------ | ------------------------------------------------ | -| `input` | Object | An object containing the inputs to your circuit. | - -### Returns - -| Return value | Type | Description | -| ------------ | --------------------- | --------------------------------------------------- | -| `proof` | Promise \ | An array with the byte representation of the proof. | - -### Usage - -```js -// consider the Standard Noir Example given with nargo init -const input = { x: 1, y: 2 }; -noirInstance.generateProof(input); -``` - -## `verifyFinalProof` - -This async method instantiates the verification key and verifies your proof. - -### Syntax - -```js -async verifyFinalProof(proof) -``` - -### Parameters - -| Parameter | Type | Description | -| --------- | ---------- | --------------------------------------------------------------------------------------------- | -| `proof` | Uint8Array | The Uint8Array representation of your proof, usually obtained by calling `generateFinalProof` | - -### Returns - -| Return value | Type | Description | -| ------------ | ------------------ | -------------------------------------------- | -| `verified` | Promise \ | A boolean for whether the proof was verified | - -### Usage - -```js -const proof = noirInstance.generateProof(input); -noirInstance.verifyFinalProof(proof); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/02_bb_backend.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/02_bb_backend.md deleted file mode 100644 index 958cabd6289..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/02_bb_backend.md +++ /dev/null @@ -1,272 +0,0 @@ ---- -title: BarretenbergBackend -description: Reference documentation for the barretenberg_backend library and the BarretenbergBackend class -keywords: - [ - BarretenbergBackend, - Barretenberg, - javascript, - typescript, - node.js, - browser, - class, - reference, - noir_js, - ] ---- - -## Table of Contents - -- [constructor](#constructor) -- [generateFinalProof](#generatefinalproof) -- [generateIntermediateProof](#generateintermediateproof) -- [generateProof](#generateproof) -- [generateIntermediateProofArtifacts](#generateintermediateproofartifacts) -- [verifyFinalProof](#verifyfinalproof) -- [verifyIntermediateProof](#verifyintermediateproof) -- [verifyProof](#verifyproof) -- [destroy](#destroy) - -## `constructor` - -The `constructor` is a method used to create and initialize objects created within the `BarretenbergBackend` class. In this class, you should pass at least one argument for the `circuit`. - -### Syntax - -```js -constructor(acirCircuit, (numberOfThreads = 1)); -``` - -### Parameters - -| Parameter | Type | Description | -| ----------------- | ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `acirCircuit` | Object | A circuit represented in a `json` format, containing the ABI and bytecode typically obtained by running [`nargo compile`](../../nargo/01_commands.md). This is the same circuit expected to be passed to [the Noir class](01_noirjs.md) | -| `numberOfThreads` | Number (optional) | The number of threads to be used by the backend. Defaults to 1. | - -### Usage - -```js -const backend = new BarretenbergBackend(acirCircuit); -``` - -## `generateFinalProof` - -An async wrapper around the [generateProof](#generateproof) method that passes a `false` flag. Usually called by the Noir class. - -### Syntax - -```js -async generateFinalProof(decompressedWitness) -``` - -### Parameters - -| Parameter | Type | Description | -| --------------------- | ------ | -------------------------------------------------------- | -| `decompressedWitness` | Object | The decompressed witness for generating the final proof. | - -### Returns - -| Return value | Type | Description | -| ------------ | -------------------- | --------------------------------------------------------- | -| `proof` | Promise\ | An array with the byte representation of the final proof. | - -### Usage - -```js -const finalProof = await backend.generateFinalProof(decompressedWitness); -``` - -## `generateIntermediateProof` - -An async wrapper around the [generateProof](#generateproof) method that passes a `true` flag. It's not currently being used by the Noir class, but developers can call this method directly to use Noir's recursive features. - -### Syntax - -```js -async generateIntermediateProof(witness) -``` - -### Parameters - -| Parameter | Type | Description | -| --------- | ------ | -------------------------------------------------- | -| `witness` | Object | The witness for generating the intermediate proof. | - -### Returns - -| Return value | Type | Description | -| ------------ | -------------------- | --------------------------------------------------------------- | -| `proof` | Promise\ | An array with the byte representation of the intermediate proof | - -### Usage - -```js -const intermediateProof = await backend.generateIntermediateProof(witness); -``` - -## `generateProof` - -This async method generates a proof. Takes the witness generated by ACVM, and a boolean that evaluates to `true` when the proof _is_ meant to be verified in another circuit. Not currently used by the Noir class. - -### Syntax - -```js -async generateProof(decompressedWitness, makeEasyToVerifyInCircuit) -``` - -### Parameters - -| Parameter | Type | Description | -| --------------------------- | ------- | ---------------------------------------------------------------------------------------------- | -| `decompressedWitness` | Object | The decompressed witness for generating the proof. | -| `makeEasyToVerifyInCircuit` | Boolean | A flag indicating whether to generate proof components for easy verification within a circuit. | - -### Returns - -| Return value | Type | Description | -| ------------ | -------------------- | -------------------------------------------------- | -| `proof` | Promise\ | An array with the byte representation of the proof | - -### Usage - -```js -const proof = await backend.generateProof(decompressedWitness, makeEasyToVerifyInCircuit); -``` - -## `generateIntermediateProofArtifacts` - -This async method returns the artifacts needed to verify the intermediate proof in another circuit. It's not currently being used by the Noir class, but developers can call this method directly to use Noir's recursive features. - -### Syntax - -```js -async generateIntermediateProofArtifacts(proof, numOfPublicInputs = 0) -``` - -### Parameters - -| Parameter | Type | Description | -| ------------------- | ----------------- | ---------------------------------------------------------------- | -| `proof` | Object | The proof object. | -| `numOfPublicInputs` | Number (optional) | The number of public inputs in the inner proof, defaulting to 0. | - -### Returns - -| Return value | Type | Description | -| --------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `proofAsFields` | string[] | An array of strings with the hexadecimal representation of the [Fields](../../language_concepts/data_types/00_fields.md) that make up a proof | -| `vkAsFields` | string[] | An array of strings with the hexadecimal representation of the [Fields](../../language_concepts/data_types/00_fields.md) that make up the verification key | -| `vkHash` | string | A pedersen hash of the verification key | - -### Usage - -```js -const artifacts = await backend.generateIntermediateProofArtifacts(proof, numOfPublicInputs); -``` - -## `verifyFinalProof` - -An async wrapper around [verifyProof](#verifyproof) that sets the `false` flag. Usually called by the Noir class. - -### Syntax - -```js -async verifyFinalProof(proof) -``` - -### Parameters - -| Parameter | Type | Description | -| --------- | ------ | --------------------------- | -| `proof` | Object | The proof object to verify. | - -### Returns - -| Return value | Type | Description | -| ------------ | ------------------ | -------------------------------------------- | -| `verified` | Promise \ | A boolean for whether the proof was verified | - -### Usage - -```js -const isValidFinal = await backend.verifyFinalProof(proof); -``` - -## `verifyIntermediateProof` - -An async wrapper around [verifyProof](#verifyproof) that sets the `true` flag. It's not currently being used by the Noir class, but developers can call this method directly to use Noir's recursive features. - -### Syntax - -```js -async verifyIntermediateProof(proof) -``` - -### Parameters - -| Parameter | Type | Description | -| --------- | ------ | ---------------------------------------- | -| `proof` | Object | The intermediate proof object to verify. | - -### Returns - -| Return value | Type | Description | -| ------------ | ------------------ | -------------------------------------------- | -| `verified` | Promise \ | A boolean for whether the proof was verified | - -### Usage - -```js -const isValidIntermediate = await backend.verifyIntermediateProof(proof); -``` - -## `verifyProof` - -This async method verifies a proof. Takes the proof, and a boolean that evaluates to `true` when the proof is intermediate. - -### Syntax - -```js -async verifyProof(proof, makeEasyToVerifyInCircuit) -``` - -### Parameters - -| Parameter | Type | Description | -| --------------------------- | ------- | ------------------------------------------------------------ | -| `proof` | Object | The proof object to verify | -| `makeEasyToVerifyInCircuit` | Boolean | A flag indicating whether the proof is intermediate or final | - -### Returns - -| Parameter | Type | Description | -| ---------- | ------------------ | -------------------------------------------- | -| `verified` | Promise\ | A boolean for whether the proof was verified | - -### Usage - -```js -const isValid = await backend.verifyProof(proof, makeEasyToVerifyInCircuit); -``` - -## `destroy` - -This method destroys the resources allocated in the [instantiate](#instantiate) method. Noir doesn't currently call this method, but it's highly recommended that developers do so in order to save resources. - -### Syntax - -```js -async destroy() -``` - -### Parameters - -This method takes no parameters. - -### Usage - -```js -await backend.destroy(); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/classes/BarretenbergBackend.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/classes/BarretenbergBackend.md deleted file mode 100644 index 5cbe9421b92..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/classes/BarretenbergBackend.md +++ /dev/null @@ -1,185 +0,0 @@ -# BarretenbergBackend - -## Implements - -- [`Backend`](../interfaces/Backend.md) - -## Constructors - -### new BarretenbergBackend(acirCircuit, options) - -```ts -new BarretenbergBackend(acirCircuit, options): BarretenbergBackend -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `acirCircuit` | [`CompiledCircuit`](../type-aliases/CompiledCircuit.md) | -| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | - -#### Returns - -[`BarretenbergBackend`](BarretenbergBackend.md) - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`destroy`](../interfaces/Backend.md#destroy) - -#### Description - -Destroys the backend - -*** - -### generateFinalProof() - -```ts -generateFinalProof(decompressedWitness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `decompressedWitness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`generateFinalProof`](../interfaces/Backend.md#generatefinalproof) - -#### Description - -Generates a final proof (not meant to be verified in another circuit) - -*** - -### generateIntermediateProof() - -```ts -generateIntermediateProof(witness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `witness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`generateIntermediateProof`](../interfaces/Backend.md#generateintermediateproof) - -#### Example - -```typescript -const intermediateProof = await backend.generateIntermediateProof(witness); -``` - -*** - -### generateIntermediateProofArtifacts() - -```ts -generateIntermediateProofArtifacts(proofData, numOfPublicInputs): Promise -``` - -#### Parameters - -| Parameter | Type | Default value | -| :------ | :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | `undefined` | -| `numOfPublicInputs` | `number` | `0` | - -#### Returns - -`Promise`\<`object`\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`generateIntermediateProofArtifacts`](../interfaces/Backend.md#generateintermediateproofartifacts) - -#### Example - -```typescript -const artifacts = await backend.generateIntermediateProofArtifacts(proof, numOfPublicInputs); -``` - -*** - -### verifyFinalProof() - -```ts -verifyFinalProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`verifyFinalProof`](../interfaces/Backend.md#verifyfinalproof) - -#### Description - -Verifies a final proof - -*** - -### verifyIntermediateProof() - -```ts -verifyIntermediateProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`verifyIntermediateProof`](../interfaces/Backend.md#verifyintermediateproof) - -#### Example - -```typescript -const isValidIntermediate = await backend.verifyIntermediateProof(proof); -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/index.md deleted file mode 100644 index 3680ba3ca77..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/index.md +++ /dev/null @@ -1,27 +0,0 @@ -# Backend Barretenberg - -## Exports - -### Classes - -| Class | Description | -| :------ | :------ | -| [BarretenbergBackend](classes/BarretenbergBackend.md) | - | - -### Interfaces - -| Interface | Description | -| :------ | :------ | -| [Backend](interfaces/Backend.md) | - | - -### Type Aliases - -| Type alias | Description | -| :------ | :------ | -| [BackendOptions](type-aliases/BackendOptions.md) | - | -| [CompiledCircuit](type-aliases/CompiledCircuit.md) | - | -| [ProofData](type-aliases/ProofData.md) | - | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/interfaces/Backend.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/interfaces/Backend.md deleted file mode 100644 index 3eb9645c8d2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/interfaces/Backend.md +++ /dev/null @@ -1,132 +0,0 @@ -# Backend - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Description - -Destroys the backend - -*** - -### generateFinalProof() - -```ts -generateFinalProof(decompressedWitness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `decompressedWitness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Description - -Generates a final proof (not meant to be verified in another circuit) - -*** - -### generateIntermediateProof() - -```ts -generateIntermediateProof(decompressedWitness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `decompressedWitness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Description - -Generates an intermediate proof (meant to be verified in another circuit) - -*** - -### generateIntermediateProofArtifacts() - -```ts -generateIntermediateProofArtifacts(proofData, numOfPublicInputs): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | -| `numOfPublicInputs` | `number` | - -#### Returns - -`Promise`\<`object`\> - -#### Description - -Retrieves the artifacts from a proof in the Field format - -*** - -### verifyFinalProof() - -```ts -verifyFinalProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Verifies a final proof - -*** - -### verifyIntermediateProof() - -```ts -verifyIntermediateProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Verifies an intermediate proof - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/type-aliases/BackendOptions.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/type-aliases/BackendOptions.md deleted file mode 100644 index 266ade75d17..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/type-aliases/BackendOptions.md +++ /dev/null @@ -1,19 +0,0 @@ -# BackendOptions - -```ts -type BackendOptions: object; -``` - -## Description - -An options object, currently only used to specify the number of threads to use. - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `threads` | `number` | **Description**

Number of threads | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit.md deleted file mode 100644 index 34e0dd04205..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit.md +++ /dev/null @@ -1,20 +0,0 @@ -# CompiledCircuit - -```ts -type CompiledCircuit: object; -``` - -## Description - -The representation of a compiled circuit - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `abi` | `Abi` | **Description**

ABI representation of the circuit | -| `bytecode` | `string` | **Description**

The bytecode of the circuit | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/type-aliases/ProofData.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/type-aliases/ProofData.md deleted file mode 100644 index 4aeff73d3e4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/type-aliases/ProofData.md +++ /dev/null @@ -1,20 +0,0 @@ -# ProofData - -```ts -type ProofData: object; -``` - -## Description - -The representation of a proof - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `proof` | `Uint8Array` | **Description**

An byte array representing the proof | -| `publicInputs` | `Uint8Array`[] | **Description**

Public inputs of a proof | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs deleted file mode 100644 index 04e662c845f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"noir_js/reference/backend_barretenberg/classes/BarretenbergBackend","label":"BarretenbergBackend"}]},{"type":"category","label":"Interfaces","items":[{"type":"doc","id":"noir_js/reference/backend_barretenberg/interfaces/Backend","label":"Backend"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"noir_js/reference/backend_barretenberg/type-aliases/BackendOptions","label":"BackendOptions"},{"type":"doc","id":"noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit","label":"CompiledCircuit"},{"type":"doc","id":"noir_js/reference/backend_barretenberg/type-aliases/ProofData","label":"ProofData"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/classes/Noir.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/classes/Noir.md deleted file mode 100644 index 1d7b54a9dca..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/classes/Noir.md +++ /dev/null @@ -1,131 +0,0 @@ -# Noir - -## Constructors - -### new Noir(circuit, backend) - -```ts -new Noir(circuit, backend?): Noir -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `circuit` | [`CompiledCircuit`](../type-aliases/CompiledCircuit.md) | -| `backend`? | `Backend` | - -#### Returns - -[`Noir`](Noir.md) - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Description - -Destroys the underlying backend instance. - -#### Example - -```typescript -await noir.destroy(); -``` - -*** - -### execute() - -```ts -execute(inputs, foreignCallHandler?): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `inputs` | `InputMap` | -| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | - -#### Returns - -`Promise`\<`object`\> - -#### Description - -Allows to execute a circuit to get its witness and return value. - -#### Example - -```typescript -async execute(inputs) -``` - -*** - -### generateFinalProof() - -```ts -generateFinalProof(inputs): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `inputs` | `InputMap` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Description - -Generates a witness and a proof given an object as input. - -#### Example - -```typescript -async generateFinalProof(input) -``` - -*** - -### verifyFinalProof() - -```ts -verifyFinalProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Instantiates the verification key and verifies a proof. - -#### Example - -```typescript -async verifyFinalProof(proof) -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify.md deleted file mode 100644 index 0ba5783f0d5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify.md +++ /dev/null @@ -1,29 +0,0 @@ -# ecdsa\_secp256k1\_verify() - -```ts -ecdsa_secp256k1_verify( - hashed_msg, - public_key_x_bytes, - public_key_y_bytes, - signature): boolean -``` - -Calculates the Blake2s256 hash of the input bytes and represents these as a single field element. -Verifies a ECDSA signature over the secp256k1 curve. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `hashed_msg` | `Uint8Array` | | -| `public_key_x_bytes` | `Uint8Array` | | -| `public_key_y_bytes` | `Uint8Array` | | -| `signature` | `Uint8Array` | | - -## Returns - -`boolean` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/index.md deleted file mode 100644 index 58902c17b99..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/index.md +++ /dev/null @@ -1,36 +0,0 @@ -# Noir JS - -## Exports - -### Classes - -| Class | Description | -| :------ | :------ | -| [Noir](classes/Noir.md) | - | - -### Type Aliases - -| Type alias | Description | -| :------ | :------ | -| [CompiledCircuit](type-aliases/CompiledCircuit.md) | - | -| [ForeignCallHandler](type-aliases/ForeignCallHandler.md) | A callback which performs an foreign call and returns the response. | -| [ForeignCallInput](type-aliases/ForeignCallInput.md) | - | -| [ForeignCallOutput](type-aliases/ForeignCallOutput.md) | - | -| [ProofData](type-aliases/ProofData.md) | - | -| [WitnessMap](type-aliases/WitnessMap.md) | - | - -### Functions - -| Function | Description | -| :------ | :------ | -| [and](functions/and.md) | Performs a bitwise AND operation between `lhs` and `rhs` | -| [blake2s256](functions/blake2s256.md) | Calculates the Blake2s256 hash of the input bytes | -| [ecdsa\_secp256k1\_verify](functions/ecdsa_secp256k1_verify.md) | Calculates the Blake2s256 hash of the input bytes and represents these as a single field element. | -| [ecdsa\_secp256r1\_verify](functions/ecdsa_secp256r1_verify.md) | Verifies a ECDSA signature over the secp256r1 curve. | -| [keccak256](functions/keccak256.md) | Calculates the Keccak256 hash of the input bytes | -| [sha256](functions/sha256.md) | Calculates the SHA256 hash of the input bytes | -| [xor](functions/xor.md) | Performs a bitwise XOR operation between `lhs` and `rhs` | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/type-aliases/CompiledCircuit.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/type-aliases/CompiledCircuit.md deleted file mode 100644 index 34e0dd04205..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/type-aliases/CompiledCircuit.md +++ /dev/null @@ -1,20 +0,0 @@ -# CompiledCircuit - -```ts -type CompiledCircuit: object; -``` - -## Description - -The representation of a compiled circuit - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `abi` | `Abi` | **Description**

ABI representation of the circuit | -| `bytecode` | `string` | **Description**

The bytecode of the circuit | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/type-aliases/ProofData.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/type-aliases/ProofData.md deleted file mode 100644 index 4aeff73d3e4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/type-aliases/ProofData.md +++ /dev/null @@ -1,20 +0,0 @@ -# ProofData - -```ts -type ProofData: object; -``` - -## Description - -The representation of a proof - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `proof` | `Uint8Array` | **Description**

An byte array representing the proof | -| `publicInputs` | `Uint8Array`[] | **Description**

Public inputs of a proof | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/typedoc-sidebar.cjs deleted file mode 100644 index c18318850d0..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"noir_js/reference/noir_js/classes/Noir","label":"Noir"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/CompiledCircuit","label":"CompiledCircuit"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/ForeignCallHandler","label":"ForeignCallHandler"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/ForeignCallInput","label":"ForeignCallInput"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/ForeignCallOutput","label":"ForeignCallOutput"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/ProofData","label":"ProofData"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/WitnessMap","label":"WitnessMap"}]},{"type":"category","label":"Functions","items":[{"type":"doc","id":"noir_js/reference/noir_js/functions/and","label":"and"},{"type":"doc","id":"noir_js/reference/noir_js/functions/blake2s256","label":"blake2s256"},{"type":"doc","id":"noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify","label":"ecdsa_secp256k1_verify"},{"type":"doc","id":"noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify","label":"ecdsa_secp256r1_verify"},{"type":"doc","id":"noir_js/reference/noir_js/functions/keccak256","label":"keccak256"},{"type":"doc","id":"noir_js/reference/noir_js/functions/sha256","label":"sha256"},{"type":"doc","id":"noir_js/reference/noir_js/functions/xor","label":"xor"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/black_box_fns.md deleted file mode 100644 index 985bb7c879d..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/black_box_fns.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: Black Box Functions -description: Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. -keywords: [noir, black box functions] ---- - -Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. This makes certain zk-snark unfriendly computations cheaper than if they were implemented in Noir. - -:::warning - -It is likely that not all backends will support a particular black box function. - -::: - -Because it is not guaranteed that all backends will support black box functions, it is possible that certain Noir programs won't compile against a particular backend if they use an unsupported black box function. It is possible to fallback to less efficient implementations written in Noir/ACIR in some cases. - -Black box functions are specified with the `#[foreign(black_box_fn)]` attribute. For example, the SHA256 function in the Noir [source code](https://github.com/noir-lang/noir/blob/v0.5.1/noir_stdlib/src/hash.nr) looks like: - -```rust -#[foreign(sha256)] -fn sha256(_input : [u8; N]) -> [u8; 32] {} -``` - -## Function list - -Here is a list of the current black box functions that are supported by UltraPlonk: - -- AES -- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) -- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) -- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash) -- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment) -- [HashToField128Security](./cryptographic_primitives/hashes.mdx#hash_to_field) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx) -- [Compute merkle root](./merkle_trees.md#compute_merkle_root) -- AND -- XOR -- RANGE -- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion.md) - -Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. - -You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/noir/blob/master/acvm-repo/acir/src/circuit/black_box_functions.rs). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives.md deleted file mode 100644 index 2df4f929474..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Cryptographic primitives in Noir -description: - Learn about the cryptographic primitives ready to use for any Noir project -keywords: - [ - cryptographic primitives, - Noir project, - ] ---- - -The Noir team is progressively adding new cryptographic primitives to the standard library. Reach out for news or if you would be interested in adding more of these calculations in Noir. - -Some methods are available thanks to the Aztec backend, not being performed using Noir. When using other backends, these methods may or may not be supplied. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives/00_hashes.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives/00_hashes.mdx deleted file mode 100644 index 76745196681..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives/00_hashes.mdx +++ /dev/null @@ -1,167 +0,0 @@ ---- -title: Hash methods -description: - Learn about the cryptographic primitives ready to use for any Noir project, including sha256, - blake2s, pedersen, mimc_bn254 and mimc -keywords: - [cryptographic primitives, Noir project, sha256, blake2s, pedersen, mimc_bn254, mimc, hash] ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## sha256 - -Given an array of bytes, returns the resulting sha256 hash. - -```rust -fn sha256(_input : [u8]) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::sha256(x); -} -``` - - - -## blake2s - -Given an array of bytes, returns an array with the Blake2 hash - -```rust -fn blake2s(_input : [u8]) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::blake2s(x); -} -``` - - - -## pedersen_hash - -Given an array of Fields, returns the Pedersen hash. - -```rust -fn pedersen_hash(_input : [Field]) -> Field -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::pedersen_hash(x); -} -``` - - - - - -## pedersen_commitment - -Given an array of Fields, returns the Pedersen commitment. - -```rust -fn pedersen_commitment(_input : [Field]) -> [Field; 2] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let commitment = std::hash::pedersen_commitment(x); -} -``` - - - -## keccak256 - -Given an array of bytes (`u8`), returns the resulting keccak hash as an array of 32 bytes -(`[u8; 32]`). Specify a message_size to hash only the first `message_size` bytes -of the input. - -```rust -fn keccak256(_input : [u8; N], _message_size: u32) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let message_size = 4; - let hash = std::hash::keccak256(x, message_size); -} -``` - - - -## poseidon - -Given an array of Fields, returns a new Field with the Poseidon Hash. Mind that you need to specify -how many inputs are there to your Poseidon function. - -```rust -// example for hash_1, hash_2 accepts an array of length 2, etc -fn hash_1(input: [Field; 1]) -> Field -``` - -example: - -```rust -fn main() -{ - let hash1 = std::hash::poseidon::bn254::hash_2([1, 2]); - assert(hash1 == 0x115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189a); -} -``` - -## mimc_bn254 and mimc - -`mimc_bn254` is `mimc`, but with hardcoded parameters for the BN254 curve. You can use it by -providing an array of Fields, and it returns a Field with the hash. You can use the `mimc` method if -you're willing to input your own constants: - -```rust -fn mimc(x: Field, k: Field, constants: [Field; N], exp : Field) -> Field -``` - -otherwise, use the `mimc_bn254` method: - -```rust -fn mimc_bn254(array: [Field; N]) -> Field -``` - -example: - -```rust - -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::mimc::mimc_bn254(x); -} -``` - -## hash_to_field - -```rust -fn hash_to_field(_input : [Field; N]) -> Field {} -``` - -Calculates the `blake2s` hash of the inputs and returns the hash modulo the field modulus to return -a value which can be represented as a `Field`. - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives/01_scalar.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives/01_scalar.mdx deleted file mode 100644 index c7eed820a80..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives/01_scalar.mdx +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: Scalar multiplication -description: See how you can perform scalar multiplications over a fixed base in Noir -keywords: [cryptographic primitives, Noir project, scalar multiplication] ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## scalar_mul::fixed_base_embedded_curve - -Performs scalar multiplication over the embedded curve whose coordinates are defined by the -configured noir field. For the BN254 scalar field, this is BabyJubJub or Grumpkin. - -```rust -fn fixed_base_embedded_curve(_input : Field) -> [Field; 2] -``` - -example - -```rust -fn main(x : Field) { - let scal = std::scalar_mul::fixed_base_embedded_curve(x); - std::println(scal); -} -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives/02_schnorr.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives/02_schnorr.mdx deleted file mode 100644 index c184ce28120..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives/02_schnorr.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: Schnorr Signatures -description: Learn how you can verify Schnorr signatures using Noir -keywords: [cryptographic primitives, Noir project, schnorr, signatures] ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## schnorr::verify_signature - -Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin). - -```rust -fn verify_signature(_public_key_x: Field, _public_key_y: Field, _signature: [u8; 64], _message: [u8]) -> bool -``` - -where `_signature` can be generated like so using the npm package -[@noir-lang/barretenberg](https://www.npmjs.com/package/@noir-lang/barretenberg) - -```js -const { BarretenbergWasm } = require('@noir-lang/barretenberg/dest/wasm'); -const { Schnorr } = require('@noir-lang/barretenberg/dest/crypto/schnorr'); - -... - -const barretenberg = await BarretenbergWasm.new(); -const schnorr = new Schnorr(barretenberg); -const pubKey = schnorr.computePublicKey(privateKey); -const message = ... -const signature = Array.from( - schnorr.constructSignature(hash, privateKey).toBuffer() -); - -... -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx deleted file mode 100644 index 72bce984821..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: ECDSA Signature Verification -description: Learn about the cryptographic primitives regarding ECDSA over the secp256k1 and secp256r1 curves -keywords: [cryptographic primitives, Noir project, ecdsa, secp256k1, secp256r1, signatures] ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -Noir supports ECDSA signatures verification over the secp256k1 and secp256r1 curves. - -## ecdsa_secp256k1::verify_signature - -Verifier for ECDSA Secp256k1 signatures - -```rust -fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message: [u8]) -> bool -``` - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - -## ecdsa_secp256r1::verify_signature - -Verifier for ECDSA Secp256r1 signatures - -```rust -fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message: [u8]) -> bool -``` - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives/04_ec_primitives.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives/04_ec_primitives.md deleted file mode 100644 index a3780552682..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives/04_ec_primitives.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -title: Elliptic Curve Primitives -keywords: [cryptographic primitives, Noir project] ---- - -Data structures and methods on them that allow you to carry out computations involving elliptic -curves over the (mathematical) field corresponding to `Field`. For the field currently at our -disposal, applications would involve a curve embedded in BN254, e.g. the -[Baby Jubjub curve](https://eips.ethereum.org/EIPS/eip-2494). - -## Data structures - -### Elliptic curve configurations - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Curve`), i.e. the specific elliptic -curve you want to use, which would be specified using any one of the methods -`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::new` which take the coefficients in the -defining equation together with a generator point as parameters. You can find more detail in the -comments in -[`noir_stdlib/src/ec.nr`](https://github.com/noir-lang/noir/blob/v0.19.0/noir_stdlib/src/ec.nr), but -the gist of it is that the elliptic curves of interest are usually expressed in one of the standard -forms implemented here (Twisted Edwards, Montgomery and Short Weierstraß), and in addition to that, -you could choose to use `affine` coordinates (Cartesian coordinates - the usual (x,y) - possibly -together with a point at infinity) or `curvegroup` coordinates (some form of projective coordinates -requiring more coordinates but allowing for more efficient implementations of elliptic curve -operations). Conversions between all of these forms are provided, and under the hood these -conversions are done whenever an operation is more efficient in a different representation (or a -mixed coordinate representation is employed). - -### Points - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Point`), i.e. points lying on the -elliptic curve. For a curve configuration `c` and a point `p`, it may be checked that `p` -does indeed lie on `c` by calling `c.contains(p1)`. - -## Methods - -(given a choice of curve representation, e.g. use `std::ec::tecurve::affine::Curve` and use -`std::ec::tecurve::affine::Point`) - -- The **zero element** is given by `Point::zero()`, and we can verify whether a point `p: Point` is - zero by calling `p.is_zero()`. -- **Equality**: Points `p1: Point` and `p2: Point` may be checked for equality by calling - `p1.eq(p2)`. -- **Addition**: For `c: Curve` and points `p1: Point` and `p2: Point` on the curve, adding these two - points is accomplished by calling `c.add(p1,p2)`. -- **Negation**: For a point `p: Point`, `p.negate()` is its negation. -- **Subtraction**: For `c` and `p1`, `p2` as above, subtracting `p2` from `p1` is accomplished by - calling `c.subtract(p1,p2)`. -- **Scalar multiplication**: For `c` as above, `p: Point` a point on the curve and `n: Field`, - scalar multiplication is given by `c.mul(n,p)`. If instead `n :: [u1; N]`, i.e. `n` is a bit - array, the `bit_mul` method may be used instead: `c.bit_mul(n,p)` -- **Multi-scalar multiplication**: For `c` as above and arrays `n: [Field; N]` and `p: [Point; N]`, - multi-scalar multiplication is given by `c.msm(n,p)`. -- **Coordinate representation conversions**: The `into_group` method converts a point or curve - configuration in the affine representation to one in the CurveGroup representation, and - `into_affine` goes in the other direction. -- **Curve representation conversions**: `tecurve` and `montcurve` curves and points are equivalent - and may be converted between one another by calling `into_montcurve` or `into_tecurve` on their - configurations or points. `swcurve` is more general and a curve c of one of the other two types - may be converted to this representation by calling `c.into_swcurve()`, whereas a point `p` lying - on the curve given by `c` may be mapped to its corresponding `swcurve` point by calling - `c.map_into_swcurve(p)`. -- **Map-to-curve methods**: The Elligator 2 method of mapping a field element `n: Field` into a - `tecurve` or `montcurve` with configuration `c` may be called as `c.elligator2_map(n)`. For all of - the curve configurations, the SWU map-to-curve method may be called as `c.swu_map(z,n)`, where - `z: Field` depends on `Field` and `c` and must be chosen by the user (the conditions it needs to - satisfy are specified in the comments - [here](https://github.com/noir-lang/noir/blob/v0.19.0/noir_stdlib/src/ec.nr). - -## Examples - -The -[ec_baby_jubjub test](https://github.com/noir-lang/noir/blob/master/test_programs/compile_success_empty/ec_baby_jubjub/src/main.nr) -illustrates all of the above primitives on various forms of the Baby Jubjub curve. A couple of more -interesting examples in Noir would be: - -Public-key cryptography: Given an elliptic curve and a 'base point' on it, determine the public key -from the private key. This is a matter of using scalar multiplication. In the case of Baby Jubjub, -for example, this code would do: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; - -fn bjj_pub_key(priv_key: Field) -> Point -{ - - let bjj = Curve::new(168700, 168696, G::new(995203441582195749578291179787384436505546430278305826713579947235728471134,5472060717959818805561601436314318772137091100104008585924551046643952123905)); - - let base_pt = Point::new(5299619240641551281634865583518297030282874472190772894086521144482721001553, 16950150798460657717958625567821834550301663161624707787222815936182638968203); - - bjj.mul(priv_key,base_pt) -} -``` - -This would come in handy in a Merkle proof. - -- EdDSA signature verification: This is a matter of combining these primitives with a suitable hash - function. See - [feat(stdlib): EdDSA sig verification noir#1136](https://github.com/noir-lang/noir/pull/1136) for - the case of Baby Jubjub and the Poseidon hash function. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives/05_eddsa.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives/05_eddsa.mdx deleted file mode 100644 index 9a5beb55ee9..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives/05_eddsa.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: EdDSA Verification -description: Learn about the cryptographic primitives regarding EdDSA -keywords: [cryptographic primitives, Noir project, eddsa, signatures] ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## eddsa::eddsa_poseidon_verify - -Verifier for EdDSA signatures - -```rust -fn eddsa_poseidon_verify(public_key_x : Field, public_key_y : Field, signature_s: Field, signature_r8_x: Field, signature_r8_y: Field, message: Field) -> bool -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/logging.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/logging.md deleted file mode 100644 index 4ba0fe0e656..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/logging.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -title: Logging -description: - Learn how to use the println statement for debugging in Noir with this tutorial. Understand the - basics of logging in Noir and how to implement it in your code. -keywords: - [ - noir logging, - println statement, - debugging in noir, - noir std library, - logging tutorial, - basic logging in noir, - noir logging implementation, - noir debugging techniques, - rust, - ] ---- - -The standard library provides a familiar `println` statement you can use. Despite being a limited -implementation of rust's `println!` macro, this construct can be useful for debugging. - -You can print the output of println statements in your Noir code by using the `nargo execute` command or the `--show-output` flag when using `nargo test` (provided there are println statements in your tests). - -It is recommended to use `nargo execute` if you want to debug failing constraints with `println` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). `println` will not work for failed constraints caught at compile time. - -The `println` statement is unconstrained, so it works for outputting integers, fields, strings, and even structs or expressions. For example: - -```rust -use dep::std; - -struct Person { - age : Field, - height : Field, -} - -fn main(age : Field, height : Field) { - let person = Person { age : age, height : height }; - std::println(person); - std::println(age + height); - std::println("Hello world!"); -} - -``` - -You can print multiple different types in the same statement and string as well as a new "fmtstr" type. A `fmtstr` can be specified in the same way as a normal string it just should be prepended with an "f" character: - -```rust - let fmt_str = f"i: {i}, j: {j}"; - std::println(fmt_str); - - let s = myStruct { y: x, x: y }; - std::println(s); - - std::println(f"i: {i}, s: {s}"); - - std::println(x); - std::println([x, y]); - - let foo = fooStruct { my_struct: s, foo: 15 }; - std::println(f"s: {s}, foo: {foo}"); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/merkle_trees.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/merkle_trees.md deleted file mode 100644 index dc383a1426b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/merkle_trees.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: Merkle Trees -description: Learn about Merkle Trees in Noir with this tutorial. Explore the basics of computing a merkle root using a proof, with examples. -keywords: - [ - Merkle trees in Noir, - Noir programming language, - check membership, - computing root from leaf, - Noir Merkle tree implementation, - Merkle tree tutorial, - Merkle tree code examples, - Noir libraries, - pedersen hash., - ] ---- - -## compute_merkle_root - -Returns the root of the tree from the provided leaf and its hash path, using a [Pedersen hash](cryptographic_primitives/00_hashes.mdx#pedersen_hash). - -```rust -fn compute_merkle_root(leaf : Field, index : Field, hash_path: [Field]) -> Field -``` - -example: - -```rust -/** - // these values are for this example only - index = "0" - priv_key = "0x000000000000000000000000000000000000000000000000000000616c696365" - secret = "0x1929ea3ab8d9106a899386883d9428f8256cfedb3c4f6b66bf4aa4d28a79988f" - note_hash_path = [ - "0x1e61bdae0f027b1b2159e1f9d3f8d00fa668a952dddd822fda80dc745d6f65cc", - "0x0e4223f3925f98934393c74975142bd73079ab0621f4ee133cee050a3c194f1a", - "0x2fd7bb412155bf8693a3bd2a3e7581a679c95c68a052f835dddca85fa1569a40" - ] - */ -fn main(index: Field, priv_key: Field, secret: Field, note_hash_path: [Field; 3]) { - - let pubkey = std::scalar_mul::fixed_base_embedded_curve(priv_key); - let pubkey_x = pubkey[0]; - let pubkey_y = pubkey[1]; - let note_commitment = std::hash::pedersen([pubkey_x, pubkey_y, secret]); - - let root = std::merkle::compute_merkle_root(note_commitment[0], index, note_hash_path); - std::println(root); -} -``` - -To check merkle tree membership: - -1. Include a merkle root as a program input. -2. Compute the merkle root of a given leaf, index and hash path. -3. Assert the merkle roots are equal. - -For more info about merkle trees, see the Wikipedia [page](https://en.wikipedia.org/wiki/Merkle_tree). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/options.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/options.md deleted file mode 100644 index 3d3139fb98b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/options.md +++ /dev/null @@ -1,99 +0,0 @@ ---- -title: Option Type ---- - -The `Option` type is a way to express that a value might be present (`Some(T))` or absent (`None`). It's a safer way to handle potential absence of values, compared to using nulls in many other languages. - -```rust -struct Option { - None, - Some(T), -} -``` - -You can import the Option type into your Noir program like so: - -```rust -use dep::std::option::Option; - -fn main() { - let none = Option::none(); - let some = Option::some(3); -} -``` - -See [this test](https://github.com/noir-lang/noir/blob/5cbfb9c4a06c8865c98ff2b594464b037d821a5c/crates/nargo_cli/tests/test_data/option/src/main.nr) for a more comprehensive set of examples of each of the methods described below. - -## Methods - -### none - -Constructs a none value. - -### some - -Constructs a some wrapper around a given value. - -### is_none - -Returns true if the Option is None. - -### is_some - -Returns true of the Option is Some. - -### unwrap - -Asserts `self.is_some()` and returns the wrapped value. - -### unwrap_unchecked - -Returns the inner value without asserting `self.is_some()`. This method can be useful within an if condition when we already know that `option.is_some()`. If the option is None, there is no guarantee what value will be returned, only that it will be of type T for an `Option`. - -### unwrap_or - -Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value. - -### unwrap_or_else - -Returns the wrapped value if `self.is_some()`. Otherwise, calls the given function to return a default value. - -### map - -If self is `Some(x)`, this returns `Some(f(x))`. Otherwise, this returns `None`. - -### map_or - -If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns the given default value. - -### map_or_else - -If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns `default()`. - -### and - -Returns None if self is None. Otherwise, this returns `other`. - -### and_then - -If self is None, this returns None. Otherwise, this calls the given function with the Some value contained within self, and returns the result of that call. In some languages this function is called `flat_map` or `bind`. - -### or - -If self is Some, return self. Otherwise, return `other`. - -### or_else - -If self is Some, return self. Otherwise, return `default()`. - -### xor - -If only one of the two Options is Some, return that option. Otherwise, if both options are Some or both are None, None is returned. - -### filter - -Returns `Some(x)` if self is `Some(x)` and `predicate(x)` is true. Otherwise, this returns `None`. - -### flatten - -Flattens an `Option>` into a `Option`. This returns `None` if the outer Option is None. Otherwise, this returns the inner Option. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/recursion.md deleted file mode 100644 index 5e592a2fd89..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/recursion.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: Recursive Proofs -description: Learn about how to write recursive proofs in Noir. -keywords: [recursion, recursive proofs, verification_key, aggregation object, verify_proof] ---- - -Noir supports recursively verifying proofs, meaning you verify the proof of a Noir program in another Noir program. This enables creating proofs of arbitrary size by doing step-wise verification of smaller components of a large proof. - -The `verify_proof` function takes a verification key, proof and public inputs for a zk program, as well as a key hash and an input aggregation object. The key hash is used to check the validity of the verification key and the input aggregation object is required by some proving systems. The `verify_proof` function returns an output aggregation object that can then be fed into future iterations of the proof verification if required. - -```rust -#[foreign(verify_proof)] -fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : Field, _key_hash : Field, _input_aggregation_object : [Field]) -> [Field] {} -``` - -:::info - -This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. - -::: - -## Aggregation Object - -The purpose of the input aggregation object is a little less clear though (and the output aggregation object that is returned from the `std::verify_proof` method). Recursive zkSNARK schemes do not necessarily "verify a proof" in the sense that you expect a true or false to be spit out by the verifier. Rather an aggregation object is built over the public inputs. In the case of PLONK the recursive aggregation object is two G1 points (expressed as 16 witness values). The final verifier (in our case this is most often the smart contract verifier) has to be aware of this aggregation object to execute a pairing and check the validity of these points (thus completing the recursive verification). - -So for example in this circuit: - -```rust -use dep::std; - -fn main( - verification_key : [Field; 114], - proof : [Field; 94], - public_inputs : [Field; 1], - key_hash : Field, - input_aggregation_object : [Field; 16], - proof_b : [Field; 94], -) -> pub [Field; 16] { - let output_aggregation_object_a = std::verify_proof( - verification_key, - proof, - public_inputs, - key_hash, - input_aggregation_object - ); - - let output_aggregation_object = std::verify_proof( - verification_key, - proof_b, - public_inputs, - key_hash, - output_aggregation_object_a - ); - - let mut output = [0; 16]; - for i in 0..16 { - output[i] = output_aggregation_object[i]; - } - output -} -``` - -In this example we have a circuit, that generates proofs A and B, that is being verified in circuit C. Assuming that the proof being passed in is not already a recursive proof, the `input_aggregation_object` will be all zeros. It will then generate an `output_aggregation_object`. This blob of data then becomes the `input_aggregation_object` of the next recursive aggregation we wish to compute. We can see here as the same public inputs, verification key, and key hash are used that we are verifying two proofs generated from the same circuit in this single circuit. `std::verify_proof` returns a `[Field]` because the size of an aggregation object is proof system dependent--in barretenberg, aggregation objects are two G1 points, while in Halo2, the aggregation object is a list of G1 points that is log the circuit size. So for the final step we convert the slice into an array of size 16 because we are generating proofs using UltraPlonk. - -## Parameters - -### `verification_key` - -The verification key for the zk program that is being verified. - -### `proof` - -The proof for the zk program that is being verified. - -### `public_inputs` - -These represent the public inputs of the proof we are verifying. They should be checked against in the circuit after construction of a new aggregation state. - -### `key_hash` - -A key hash is used to check the validity of the verification key. The circuit implementing this opcode can use this hash to ensure that the key provided to the circuit matches the key produced by the circuit creator. - -### `input_aggregation_object` - -An aggregation object is blob of data that the top-level verifier must run some proof system specific algorithm on to complete verification. The size is proof system specific and will be set by the backend integrating this opcode. The input aggregation object is only not `None` when we are verifying a previous recursive aggregation in the current circuit. If this is the first recursive aggregation there is no input aggregation object. It is left to the backend to determine how to handle when there is no input aggregation object. - -## Return value - -### `output_aggregation_object` - -This is the result of a recursive aggregation and is what will be fed into the next verifier. -The next verifier can either perform a final verification (returning true or false) or perform another recursive aggregation where this output aggregation object will be the input aggregation object of the next recursive aggregation. - -## Example - -You can see an example of how to do recursive proofs in [this example recursion demo repo](https://github.com/noir-lang/noir-examples/tree/master/recursion). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/zeroed.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/zeroed.md deleted file mode 100644 index 97dab02dac2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/zeroed.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: Zeroed Function -description: - The zeroed function returns a zeroed value of any type. -keywords: - [ - zeroed - ] ---- - -Implements `fn zeroed() -> T` to return a zeroed value of any type. This function is generally unsafe to use as the zeroed bit pattern is not guaranteed to be valid for all types. It can however, be useful in cases when the value is guaranteed not to be used such as in a BoundedVec library implementing a growable vector, up to a certain length, backed by an array. The array can be initialized with zeroed values which are guaranteed to be inaccessible until the vector is pushed to. Similarly, enumerations in noir can be implemented using this method by providing zeroed values for the unused variants. - -You can access the function at `std::unsafe::zeroed`. - -This function currently supports the following types: - -- Field -- Bool -- Uint -- Array -- String -- Tuple -- Function - -Using it on other types could result in unexpected behavior. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/examples/merkle-proof.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/examples/merkle-proof.mdx deleted file mode 100644 index 832fb4bb55e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/examples/merkle-proof.mdx +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Merkle Proof Membership -description: - Learn how to use merkle membership proof in Noir to prove that a given leaf is a member of a - merkle tree with a specified root, at a given index. -keywords: - [merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree] ---- - -Let's walk through an example of a merkle membership proof in Noir that proves that a given leaf is -in a merkle tree. - -```rust -use dep::std; - -fn main(message : [Field; 62], index : Field, hashpath : [Field; 40], root : Field) { - let leaf = std::hash::hash_to_field(message); - let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); - assert(merkle_root == root); -} - -``` - -The message is hashed using `hash_to_field`. The specific hash function that is being used is chosen -by the backend. The only requirement is that this hash function can heuristically be used as a -random oracle. If only collision resistance is needed, then one can call `std::hash::pedersen_hash` -instead. - -```rust -let leaf = std::hash::hash_to_field(message); -``` - -The leaf is then passed to a compute_merkle_root function with the root, index and hashpath. The returned root can then be asserted to be the same as the provided root. - -```rust -let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); -assert (merkle_root == root); -``` - -> **Note:** It is possible to re-implement the merkle tree implementation without standard library. -> However, for most usecases, it is enough. In general, the standard library will always opt to be -> as conservative as possible, while striking a balance with efficiency. - -An example, the merkle membership proof, only requires a hash function that has collision -resistance, hence a hash function like Pedersen is allowed, which in most cases is more efficient -than the even more conservative sha256. - -[View an example on the starter repo](https://github.com/noir-lang/noir-examples/blob/3ea09545cabfa464124ec2f3ea8e60c608abe6df/stealthdrop/circuits/src/main.nr#L20) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/getting_started/00_nargo_installation.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/getting_started/00_nargo_installation.md deleted file mode 100644 index 7d3c88c7693..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/getting_started/00_nargo_installation.md +++ /dev/null @@ -1,249 +0,0 @@ ---- -title: Nargo Installation -description: - nargo is a command line tool for interacting with Noir programs (e.g. compiling, proving, - verifying and more). Learn how to install and use Nargo for your projects with this comprehensive - guide. -keywords: [Nargo, command line tool, Noir programs, installation guide, how to use Nargo] ---- - -`nargo` is a command line tool for interacting with Noir programs (e.g. compiling, proving, -verifying and more). - -Alternatively, the interactions can also be performed in [NoirJS](../noir_js/noir_js.md). - -### UltraPlonk - -Nargo versions \<0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk -version of Aztec Backend, which lacks efficient implementations of useful primitives (e.g. Keccak256 in 18k constraints, ECDSA verification in 36k constraints) that the UltraPlonk version offers. - -## Installation - -There are four approaches for installing Nargo: - -- [Option 1: Noirup](#option-1-noirup) -- [Option 2: Binaries](#option-2-binaries) -- [Option 3: Compile from Source](#option-3-compile-from-source) -- [Option 4: WSL for Windows](#option-4-wsl-for-windows) - -Optionally you can also install [Noir VS Code extension] for syntax highlighting. - -### Option 1: Noirup - -If you're on OSX or Linux, the easiest way to start using Noir and Nargo is via noirup. Just open a -terminal and run: - -```bash -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -Close the terminal, open another one, and run - -```bash -noirup -``` - -Done, you should have the latest version working. You can check with `nargo --version`. - -You can also install nightlies, specific versions -or branches, check out the [noirup repository](https://github.com/noir-lang/noirup) for more -information. - -#### GitHub Actions - -You can use `noirup` with GitHub Actions for CI/CD and automated testing. It is as simple as -installing `noirup` and running tests in your GitHub Action `yml` file. - -See the -[config file](https://github.com/TomAFrench/noir-hashes/blob/master/.github/workflows/noir.yml) in -this repo containing hash functions in Noir for an example. - -#### Nightly versions - -To install the nightly version of Noir (updated daily) run: - -```bash -noirup -n -``` - -### Option 2: Binaries - -See [GitHub Releases](https://github.com/noir-lang/noir/releases) for the latest and previous -platform specific binaries. - -#### Step 1 - -Paste and run the following in the terminal to extract and install the binary: - -> **macOS / Linux:** If you are prompted with `Permission denied` when running commands, prepend -> `sudo` and re-run it. - -##### macOS (Apple Silicon) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-aarch64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### macOS (Intel) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### Linux (Bash) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-unknown-linux-gnu.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -C $HOME/.nargo/bin/ && \ -echo -e '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.bashrc && \ -source ~/.bashrc -``` - -#### Step 2 - -Check if the installation was successful by running `nargo --help`. - -> **macOS:** If you are prompted with an OS alert, right-click and open the _nargo_ executable from -> Finder. Close the new terminal popped up and `nargo` should now be accessible. - -For a successful installation, you should see something similar to the following after running the -command: - -```sh -$ nargo --help - -Noir's package manager - -Usage: nargo - -Commands: - check Checks the constraint system for errors - codegen-verifier Generates a Solidity verifier smart contract for the program - compile Compile the program and its secret execution trace into ACIR format - new Create a new binary project - execute Executes a circuit to calculate its return value - prove Create proof for this program. The proof is returned as a hex encoded string - verify Given a proof and a program, verify whether the proof is valid - test Run the tests for this program - gates Counts the occurrences of different gates in circuit - help Print this message or the help of the given subcommand(s) -``` - -### Option 3: Compile from Source - -Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. It helps mitigating issues commonly associated with dependency management, such as conflicts between required package versions for different projects (often referred to as "dependency hell"). - -Combined with direnv, which automatically sets or clears environment variables based on the directory, it further simplifies the development process by seamlessly integrating with the developer's shell, facilitating an efficient and reliable workflow for managing and deploying Noir projects with multiple dependencies. - -#### Setting up your environment - -For the best experience, please follow these instructions to setup your environment: - -1. Install Nix following [their guide](https://nixos.org/download.html) for your operating system. -2. Create the file `~/.config/nix/nix.conf` with the contents: - -```ini -experimental-features = nix-command -extra-experimental-features = flakes -``` - -3. Install direnv into your Nix profile by running: - -```sh -nix profile install nixpkgs#direnv -``` - -4. Add direnv to your shell following [their guide](https://direnv.net/docs/hook.html). - 1. For bash or zshell, add `eval "$(direnv hook bash)"` or `eval "$(direnv hook zsh)"` to your ~/.bashrc or ~/.zshrc file, respectively. -5. Restart your shell. - -#### Shell & editor experience - -Now that your environment is set up, you can get to work on the project. - -1. Clone the repository, such as: - -```sh -git clone git@github.com:noir-lang/noir -``` - -> Replacing `noir` with whichever repository you want to work on. - -2. Navigate to the directory: - -```sh -cd noir -``` - -> Replacing `noir` with whichever repository you cloned. - -3. You should see a **direnv error** because projects aren't allowed by default. Make sure you've reviewed and trust our `.envrc` file, then you need to run: - -```sh -direnv allow -``` - -4. Now, wait awhile for all the native dependencies to be built. This will take some time and direnv will warn you that it is taking a long time, but we just need to let it run. - -5. Once you are presented with your prompt again, you can start your editor within the project directory (we recommend [VSCode](https://code.visualstudio.com/)): - -```sh -code . -``` - -6. (Recommended) When launching VSCode for the first time, you should be prompted to install our recommended plugins. We highly recommend installing these for the best development experience. - -#### Building and testing - -Assuming you are using `direnv` to populate your environment, building and testing the project can be done -with the typical `cargo build`, `cargo test`, and `cargo clippy` commands. You'll notice that the `cargo` version matches the version we specify in `rust-toolchain.toml`, which is 1.71.1 at the time of this writing. - -If you want to build the entire project in an isolated sandbox, you can use Nix commands: - -1. `nix build .` (or `nix build . -L` for verbose output) to build the project in a Nix sandbox. -2. `nix flake check` (or `nix flake check -L` for verbose output) to run clippy and tests in a Nix sandbox. - -#### Without `direnv` - -If you have hesitations with using direnv, you can launch a subshell with `nix develop` and then launch your editor from within the subshell. However, if VSCode was already launched in the project directory, the environment won't be updated. - -Advanced: If you aren't using direnv nor launching your editor within the subshell, you can try to install Barretenberg and other global dependencies the package needs. This is an advanced workflow and likely won't receive support! - -### Option 4: WSL (for Windows) - -The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed natively. However, it is available by using Windows Subsystem for Linux (WSL). - -Step 1: Follow the instructions [here](https://learn.microsoft.com/en-us/windows/wsl/install) to install and run WSL. - -step 2: Follow the [Noirup instructions](#option-1-noirup). - -## Uninstalling Nargo - -### Noirup - -If you installed Noir with `noirup`, you can uninstall Noir by removing the files in `~/.nargo`, `~/nargo` and `~/noir_cache`. - -```bash -rm -r ~/.nargo -rm -r ~/nargo -rm -r ~/noir_cache -``` - -### Nix - -If you installed Noir with Nix or from source, you can remove the binary located at `~/.nix-profile/bin/nargo`. - -```bash -rm ~/.nix-profile/bin/nargo -``` - -[noir vs code extension]: https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/getting_started/01_hello_world.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/getting_started/01_hello_world.md deleted file mode 100644 index 34f8cd96fcd..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/getting_started/01_hello_world.md +++ /dev/null @@ -1,147 +0,0 @@ ---- -title: Create A Project -description: - Learn how to create and verify your first Noir program using Nargo, a programming language for - zero-knowledge proofs. -keywords: - [ - Nargo, - Noir, - zero-knowledge proofs, - programming language, - create Noir program, - verify Noir program, - step-by-step guide, - ] ---- - -Now that we have installed Nargo, it is time to make our first hello world program! - -## Create a Project Directory - -Noir code can live anywhere on your computer. Let us create a _projects_ folder in the home -directory to house our Noir programs. - -For Linux, macOS, and Windows PowerShell, create the directory and change directory into it by -running: - -```sh -mkdir ~/projects -cd ~/projects -``` - -For Windows CMD, run: - -```sh -> mkdir "%USERPROFILE%\projects" -> cd /d "%USERPROFILE%\projects" -``` - -## Create Our First Nargo Project - -Now that we are in the projects directory, create a new Nargo project by running: - -```sh -nargo new hello_world -``` - -> **Note:** `hello_world` can be any arbitrary project name, we are simply using `hello_world` for -> demonstration. -> -> In production, the common practice is to name the project folder as `circuits` for better -> identifiability when sitting alongside other folders in the codebase (e.g. `contracts`, `scripts`, -> `test`). - -A `hello_world` folder would be created. Similar to Rust, the folder houses _src/main.nr_ and -_Nargo.toml_ that contains the source code and environmental options of your Noir program -respectively. - -### Intro to Noir Syntax - -Let us take a closer look at _main.nr_. The default _main.nr_ generated should look like this: - -```rust -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` - -The first line of the program specifies the program's inputs: - -```rust -x : Field, y : pub Field -``` - -Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the -keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](../language_concepts/data_types.md) section. - -The next line of the program specifies its body: - -```rust -assert(x != y); -``` - -The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. - -For more Noir syntax, check the [Language Concepts](../language_concepts/comments.md) chapter. - -## Build In/Output Files - -Change directory into _hello_world_ and build in/output files for your Noir program by running: - -```sh -cd hello_world -nargo check -``` - -Two additional files would be generated in your project directory: - -_Prover.toml_ houses input values, and _Verifier.toml_ houses public values. - -## Prove Our Noir Program - -Now that the project is set up, we can create a proof of correct execution on our Noir program. - -Fill in input values for execution in the _Prover.toml_ file. For example: - -```toml -x = "1" -y = "2" -``` - -Prove the valid execution of your Noir program: - -```sh -nargo prove -``` - -A new folder _proofs_ would then be generated in your project directory, containing the proof file -`.proof`, where the project name is defined in Nargo.toml. - -The _Verifier.toml_ file would also be updated with the public values computed from program -execution (in this case the value of `y`): - -```toml -y = "0x0000000000000000000000000000000000000000000000000000000000000002" -``` - -> **Note:** Values in _Verifier.toml_ are computed as 32-byte hex values. - -## Verify Our Noir Program - -Once a proof is generated, we can verify correct execution of our Noir program by verifying the -proof file. - -Verify your proof by running: - -```sh -nargo verify -``` - -The verification will complete in silence if it is successful. If it fails, it will log the -corresponding error instead. - -Congratulations, you have now created and verified a proof for your very first Noir program! - -In the [next section](./02_breakdown.md), we will go into more detail on each step performed. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/getting_started/02_breakdown.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/getting_started/02_breakdown.md deleted file mode 100644 index f928370b2e8..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/getting_started/02_breakdown.md +++ /dev/null @@ -1,198 +0,0 @@ ---- -title: Project Breakdown -description: - Learn about the anatomy of a Nargo project, including the purpose of the Prover and Verifier TOML - files, and how to prove and verify your program. -keywords: - [Nargo, Nargo project, Prover.toml, Verifier.toml, proof verification, private asset transfer] ---- - -This section breaks down our hello world program in section _1.2_. We elaborate on the project -structure and what the `prove` and `verify` commands did in the previous section. - -## Anatomy of a Nargo Project - -Upon creating a new project with `nargo new` and building the in/output files with `nargo check` -commands, you would get a minimal Nargo project of the following structure: - - - src - - Prover.toml - - Verifier.toml - - Nargo.toml - -The source directory _src_ holds the source code for your Noir program. By default only a _main.nr_ -file will be generated within it. - -### Prover.toml - -_Prover.toml_ is used for specifying the input values for executing and proving the program. You can specify `toml` files with different names by using the `--prover-name` or `-p` flags, see the [Prover](#provertoml) section below. Optionally you may specify expected output values for prove-time checking as well. - -### Verifier.toml - -_Verifier.toml_ contains public in/output values computed when executing the Noir program. - -### Nargo.toml - -_Nargo.toml_ contains the environmental options of your project. It contains a "package" section and a "dependencies" section. - -Example Nargo.toml: - -```toml -[package] -name = "noir_starter" -type = "bin" -authors = ["Alice"] -compiler_version = "0.9.0" -description = "Getting started with Noir" -entry = "circuit/main.nr" -license = "MIT" - -[dependencies] -ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} -``` - -Nargo.toml for a [workspace](../modules_packages_crates/workspaces.md) will look a bit different. For example: - -```toml -[workspace] -members = ["crates/a", "crates/b"] -default-member = "crates/a" -``` - -#### Package section - -The package section requires a number of fields including: - -- `name` (**required**) - the name of the package -- `type` (**required**) - can be "bin", "lib", or "contract" to specify whether its a binary, library or Aztec contract -- `authors` (optional) - authors of the project -- `compiler_version` - specifies the version of the compiler to use. This is enforced by the compiler and follow's [Rust's versioning](https://doc.rust-lang.org/cargo/reference/manifest.html#the-version-field), so a `compiler_version = 0.18.0` will enforce Nargo version 0.18.0, `compiler_version = ^0.18.0` will enforce anything above 0.18.0 but below 0.19.0, etc. For more information, see how [Rust handles these operators](https://docs.rs/semver/latest/semver/enum.Op.html) -- `description` (optional) -- `entry` (optional) - a relative filepath to use as the entry point into your package (overrides the default of `src/lib.nr` or `src/main.nr`) -- `backend` (optional) -- `license` (optional) - -#### Dependencies section - -This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies.md)for more info. - -`./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or -verifier contract respectively. - -### main.nr - -The _main.nr_ file contains a `main` method, this method is the entry point into your Noir program. - -In our sample program, _main.nr_ looks like this: - -```rust -fn main(x : Field, y : Field) { - assert(x != y); -} -``` - -The parameters `x` and `y` can be seen as the API for the program and must be supplied by the -prover. Since neither `x` nor `y` is marked as public, the verifier does not supply any inputs, when -verifying the proof. - -The prover supplies the values for `x` and `y` in the _Prover.toml_ file. - -As for the program body, `assert` ensures the satisfaction of the condition (e.g. `x != y`) is -constrained by the proof of the execution of said program (i.e. if the condition was not met, the -verifier would reject the proof as an invalid proof). - -### Prover.toml - -The _Prover.toml_ file is a file which the prover uses to supply his witness values(both private and -public). - -In our hello world program the _Prover.toml_ file looks like this: - -```toml -x = "1" -y = "2" -``` - -When the command `nargo prove` is executed, two processes happen: - -1. Noir creates a proof that `x` which holds the value of `1` and `y` which holds the value of `2` - is not equal. This not equal constraint is due to the line `assert(x != y)`. - -2. Noir creates and stores the proof of this statement in the _proofs_ directory in a file called your-project.proof. So if your project is named "private_voting" (defined in the project Nargo.toml), the proof will be saved at `./proofs/private_voting.proof`. Opening this file will display the proof in hex format. - -#### Arrays of Structs - -The following code shows how to pass an array of structs to a Noir program to generate a proof. - -```rust -// main.nr -struct Foo { - bar: Field, - baz: Field, -} - -fn main(foos: [Foo; 3]) -> pub Field { - foos[2].bar + foos[2].baz -} -``` - -Prover.toml: - -```toml -[[foos]] # foos[0] -bar = 0 -baz = 0 - -[[foos]] # foos[1] -bar = 0 -baz = 0 - -[[foos]] # foos[2] -bar = 1 -baz = 2 -``` - -#### Custom toml files - -You can specify a `toml` file with a different name to use for proving by using the `--prover-name` or `-p` flags. - -This command looks for proof inputs in the default **Prover.toml** and generates the proof and saves it at `./proofs/.proof`: - -```bash -nargo prove -``` - -This command looks for proof inputs in the custom **OtherProver.toml** and generates proof and saves it at `./proofs/.proof`: - -```bash -nargo prove -p OtherProver -``` - -## Verifying a Proof - -When the command `nargo verify` is executed, two processes happen: - -1. Noir checks in the _proofs_ directory for a proof file with the project name (eg. test_project.proof) - -2. If that file is found, the proof's validity is checked - -> **Note:** The validity of the proof is linked to the current Noir program; if the program is -> changed and the verifier verifies the proof, it will fail because the proof is not valid for the -> _modified_ Noir program. - -In production, the prover and the verifier are usually two separate entities. A prover would -retrieve the necessary inputs, execute the Noir program, generate a proof and pass it to the -verifier. The verifier would then retrieve the public inputs from usually external sources and -verifies the validity of the proof against it. - -Take a private asset transfer as an example: - -A user on browser as the prover would retrieve private inputs (e.g. the user's private key) and -public inputs (e.g. the user's encrypted balance on-chain), compute the transfer, generate a proof -and submit it to the verifier smart contract. - -The verifier contract would then draw the user's encrypted balance directly from the blockchain and -verify the proof submitted against it. If the verification passes, additional functions in the -verifier contract could trigger (e.g. approve the asset transfer). - -Now that you understand the concepts, you'll probably want some editor feedback while you are writing more complex code. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/index.md deleted file mode 100644 index e8d86020a20..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/index.md +++ /dev/null @@ -1,100 +0,0 @@ ---- -title: Introducing Noir -description: - Learn about the public alpha release of Noir, a domain specific language heavily influenced by - Rust that compiles to an intermediate language which can be compiled to an arithmetic circuit or a - rank-1 constraint system. -keywords: - [ - Noir, - Domain Specific Language, - Rust, - Intermediate Language, - Arithmetic Circuit, - Rank-1 Constraint System, - Ethereum Developers, - Protocol Developers, - Blockchain Developers, - Proving System, - Smart Contract Language, - ] -slug: / ---- - -## What is Noir? - -Noir is a Domain Specific Language for SNARK proving systems. It has been designed to use any ACIR compatible proving system. - -Its design choices are influenced heavily by Rust and focuses on a simple, familiar syntax. - -## Who is Noir for? - -Noir can be used for a variety of purposes. - -### Solidity Developers - -Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will -be modularized in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier.md) command to create -a verifier contract. - -### Protocol Developers - -As a protocol developer, you may not want to use the Aztec backend due to it not being a fit for -your stack, or maybe you simply want to use a different proving system. Since Noir does not compile -to a specific proof system, it is possible for protocol developers to replace the PLONK-based -proving system with a different proving system altogether. - -### Blockchain developers - -As a blockchain developer, you will be constrained by parameters set by your blockchain (for example, the -proving system and smart contract language has been pre-defined). In order for you to use Noir in -your blockchain, a proving system backend and a smart contract interface -must be implemented for it. - -## What's new about Noir? - -Noir is simple and flexible in its design, as it does not compile immediately to a fixed -NP-complete language. Instead, Noir compiles to an intermediate language (ACIR), which itself can be compiled -to an arithmetic circuit (if choosing to target Aztec's barretenberg backend) or a rank-1 constraint system (if choosing to target an R1CS backend like Arkworks' Marlin backend, or others). - -This in itself brings up a few challenges within the design process, but allows one to decouple the programming language completely from the backend. This is similar in theory to LLVM. - -## Current Features - -Compiler: - -- Module System -- For expressions -- Arrays -- Bit Operations -- Binary operations (\<, \<=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] -- Unsigned integers -- If statements -- Structures and Tuples -- Generics - -ACIR Supported OPCODES: - -- Sha256 -- Blake2s -- Schnorr signature verification -- MerkleMembership -- Pedersen Commitment -- Pedersen Hash -- HashToField - -## Libraries - -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). - -Some libraries that are available today include: - -- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library -- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) -- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers -- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address -- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees -- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir -- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers - -See the section on [dependencies](./modules_packages_crates/dependencies.md) for more information. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/01_functions.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/01_functions.md deleted file mode 100644 index 5eb22170e54..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/01_functions.md +++ /dev/null @@ -1,225 +0,0 @@ ---- -title: Functions -description: - Learn how to declare functions and methods in Noir, a programming language with Rust semantics. - This guide covers parameter declaration, return types, call expressions, and more. -keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] ---- - -Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. - -To declare a function the `fn` keyword is used. - -```rust -fn foo() {} -``` - -By default, functions are visible only within the package they are defined. To make them visible outside of that package (for example, as part of a [library](../modules_packages_crates/crates_and_packages.md#libraries)), you should mark them as `pub`: - -```rust -pub fn foo() {} -``` - -You can also restrict the visibility of the function to only the crate it was defined in, by specifying `pub(crate)`: - -```rust -pub(crate) fn foo() {} //foo can only be called within its crate -``` - -All parameters in a function must have a type and all types are known at compile time. The parameter -is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. - -```rust -fn foo(x : Field, y : Field){} -``` - -The return type of a function can be stated by using the `->` arrow notation. The function below -states that the foo function must return a `Field`. If the function returns no value, then the arrow -is omitted. - -```rust -fn foo(x : Field, y : Field) -> Field { - x + y -} -``` - -Note that a `return` keyword is unneeded in this case - the last expression in a function's body is -returned. - -## Main function - -If you're writing a binary, the `main` function is the starting point of your program. You can pass all types of expressions to it, as long as they have a fixed size at compile time: - -```rust -fn main(x : Field) // this is fine: passing a Field -fn main(x : [Field; 2]) // this is also fine: passing a Field with known size at compile-time -fn main(x : (Field, bool)) // 👌: passing a (Field, bool) tuple means size 2 -fn main(x : str<5>) // this is fine, as long as you pass a string of size 5 - -fn main(x : Vec) // can't compile, has variable size -fn main(x : [Field]) // can't compile, has variable size -fn main(....// i think you got it by now -``` - -Keep in mind [tests](../nargo/02_testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: - -```rust -fn main(x : [Field]) { - assert(x[0] == 1); -} - -#[test] -fn test_one() { - main([1, 2]); -} -``` - -```bash -$ nargo test -[testing] Running 1 test functions -[testing] Testing test_one... ok -[testing] All tests passed - -$ nargo check -The application panicked (crashed). -Message: Cannot have variable sized arrays as a parameter to main -``` - -## Call Expressions - -Calling a function in Noir is executed by using the function name and passing in the necessary -arguments. - -Below we show how to call the `foo` function from the `main` function using a call expression: - -```rust -fn main(x : Field, y : Field) { - let z = foo(x); -} - -fn foo(x : Field) -> Field { - x + x -} -``` - -## Methods - -You can define methods in Noir on any struct type in scope. - -```rust -struct MyStruct { - foo: Field, - bar: Field, -} - -impl MyStruct { - fn new(foo: Field) -> MyStruct { - MyStruct { - foo, - bar: 2, - } - } - - fn sum(self) -> Field { - self.foo + self.bar - } -} - -fn main() { - let s = MyStruct::new(40); - assert(s.sum() == 42); -} -``` - -Methods are just syntactic sugar for functions, so if we wanted to we could also call `sum` as -follows: - -```rust -assert(MyStruct::sum(s) == 42); -``` - -It is also possible to specialize which method is chosen depending on the [generic](./06_generics.md) type that is used. In this example, the `foo` function returns different values depending on its type: - -```rust -struct Foo {} - -impl Foo { - fn foo(self) -> Field { 1 } -} - -impl Foo { - fn foo(self) -> Field { 2 } -} - -fn main() { - let f1: Foo = Foo{}; - let f2: Foo = Foo{}; - assert(f1.foo() + f2.foo() == 3); -} -``` - -Also note that impls with the same method name defined in them cannot overlap. For example, if we already have `foo` defined for `Foo` and `Foo` like we do above, we cannot also define `foo` in an `impl Foo` since it would be ambiguous which version of `foo` to choose. - -```rust -// Including this impl in the same project as the above snippet would -// cause an overlapping impls error -impl Foo { - fn foo(self) -> Field { 3 } -} -``` - -## Lambdas - -Lambdas are anonymous functions. They follow the syntax of Rust - `|arg1, arg2, ..., argN| return_expression`. - -```rust -let add_50 = |val| val + 50; -assert(add_50(100) == 150); -``` - -See [Lambdas](./08_lambdas.md) for more details. - -## Attributes - -Attributes are metadata that can be applied to a function, using the following syntax: `#[attribute(value)]`. - -Supported attributes include: - -- **builtin**: the function is implemented by the compiler, for efficiency purposes. -- **deprecated**: mark the function as _deprecated_. Calling the function will generate a warning: `warning: use of deprecated function` -- **field**: Used to enable conditional compilation of code depending on the field size. See below for more details -- **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./05_unconstrained.md) and [NoirJS](../noir_js/noir_js.md) for more details. -- **test**: mark the function as unit tests. See [Tests](../nargo/02_testing.md) for more details - -### Field Attribute - -The field attribute defines which field the function is compatible for. The function is conditionally compiled, under the condition that the field attribute matches the Noir native field. -The field can be defined implicitly, by using the name of the elliptic curve usually associated to it - for instance bn254, bls12_381 - or explicitly by using the field (prime) order, in decimal or hexadecimal form. -As a result, it is possible to define multiple versions of a function with each version specialized for a different field attribute. This can be useful when a function requires different parameters depending on the underlying elliptic curve. - -Example: we define the function `foo()` three times below. Once for the default Noir bn254 curve, once for the field $\mathbb F_{23}$, which will normally never be used by Noir, and once again for the bls12_381 curve. - -```rust -#[field(bn254)] -fn foo() -> u32 { - 1 -} - -#[field(23)] -fn foo() -> u32 { - 2 -} - -// This commented code would not compile as foo would be defined twice because it is the same field as bn254 -// #[field(21888242871839275222246405745257275088548364400416034343698204186575808495617)] -// fn foo() -> u32 { -// 2 -// } - -#[field(bls12_381)] -fn foo() -> u32 { - 3 -} -``` - -If the field name is not known to Noir, it will discard the function. Field names are case insensitive. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/02_control_flow.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/02_control_flow.md deleted file mode 100644 index a7f85360197..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/02_control_flow.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Control Flow -description: - Learn how to use loops and if expressions in the Noir programming language. Discover the syntax - and examples for for loops and if-else statements. -keywords: [Noir programming language, loops, for loop, if-else statements, Rust syntax] ---- - -## Loops - -Noir has one kind of loop: the `for` loop. `for` loops allow you to repeat a block of code multiple -times. - -The following block of code between the braces is run 10 times. - -```rust -for i in 0..10 { - // do something -}; -``` - -The index for loops is of type `u64`. - -## If Expressions - -Noir supports `if-else` statements. The syntax is most similar to Rust's where it is not required -for the statement's conditional to be surrounded by parentheses. - -```rust -let a = 0; -let mut x: u32 = 0; - -if a == 0 { - if a != 0 { - x = 6; - } else { - x = 2; - } -} else { - x = 5; - assert(x == 5); -} -assert(x == 2); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/03_ops.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/03_ops.md deleted file mode 100644 index 0e35ef5e584..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/03_ops.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -title: Logical Operations -description: - Learn about the supported arithmetic and logical operations in the Noir programming language. - Discover how to perform operations on private input types, integers, and booleans. -keywords: - [ - Noir programming language, - supported operations, - arithmetic operations, - logical operations, - predicate operators, - bitwise operations, - short-circuiting, - backend, - ] ---- - -# Operations - -## Table of Supported Operations - -| Operation | Description | Requirements | -| :-------- | :------------------------------------------------------------: | -------------------------------------: | -| + | Adds two private input types together | Types must be private input | -| - | Subtracts two private input types together | Types must be private input | -| \* | Multiplies two private input types together | Types must be private input | -| / | Divides two private input types together | Types must be private input | -| ^ | XOR two private input types together | Types must be integer | -| & | AND two private input types together | Types must be integer | -| \| | OR two private input types together | Types must be integer | -| \<\< | Left shift an integer by another integer amount | Types must be integer | -| >> | Right shift an integer by another integer amount | Types must be integer | -| ! | Bitwise not of a value | Type must be integer or boolean | -| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | -| > | returns a bool if one value is more than the other | Upper bound must have a known bit size | -| >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | -| == | returns a bool if one value is equal to the other | Both types must not be constants | -| != | returns a bool if one value is not equal to the other | Both types must not be constants | - -### Predicate Operators - -`<,<=, !=, == , >, >=` are known as predicate/comparison operations because they compare two values. -This differs from the operations such as `+` where the operands are used in _computation_. - -### Bitwise Operations Example - -```rust -fn main(x : Field) { - let y = x as u32; - let z = y & y; -} -``` - -`z` is implicitly constrained to be the result of `y & y`. The `&` operand is used to denote bitwise -`&`. - -> `x & x` would not compile as `x` is a `Field` and not an integer type. - -### Logical Operators - -Noir has no support for the logical operators `||` and `&&`. This is because encoding the -short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can -use the bitwise operators `|` and `&` which operate identically for booleans, just without the -short-circuiting. - -```rust -let my_val = 5; - -let mut flag = 1; -if (my_val > 6) | (my_val == 0) { - flag = 0; -} -assert(flag == 1); - -if (my_val != 10) & (my_val < 50) { - flag = 0; -} -assert(flag == 0); -``` - -### Shorthand operators - -Noir shorthand operators for most of the above operators, namely `+=, -=, *=, /=, %=, &=, |=, ^=, <<=`, and `>>=`. These allow for more concise syntax. For example: - -```rust -let mut i = 0; -i = i + 1; -``` - -could be written as: - -```rust -let mut i = 0; -i += 1; -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/04_assert.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/04_assert.md deleted file mode 100644 index 7427ec6cc63..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/04_assert.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Assert Function -description: - Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or - comparison expression that follows to be true, and what happens if the expression is false at - runtime. -keywords: [Noir programming language, assert statement, predicate expression, comparison expression] ---- - -Noir includes a special `assert` function which will explicitly constrain the predicate/comparison -expression that follows to be true. If this expression is false at runtime, the program will fail to -be proven. Example: - -```rust -fn main(x : Field, y : Field) { - assert(x == y); -} -``` - -You can optionally provide a message to be logged when the assertion fails: - -```rust -assert(x == y, "x and y are not equal"); -``` - -> Assertions only work for predicate operations, such as `==`. If there's any ambiguity on the operation, the program will fail to compile. For example, it is unclear if `assert(x + y)` would check for `x + y == 0` or simply would return `true`. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/05_unconstrained.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/05_unconstrained.md deleted file mode 100644 index 097d6ee9894..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/05_unconstrained.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: Unconstrained Functions -description: "Learn about what unconstrained functions in Noir are, how to use them and when you'd want to." - -keywords: [Noir programming language, unconstrained, open] ---- - - - -Unconstrained functions are functions which do not constrain any of the included computation and allow for non-deterministic computation. - -## Why? - -Zero-knowledge (ZK) domain-specific languages (DSL) enable developers to generate ZK proofs from their programs by compiling code down to the constraints of an NP complete language (such as R1CS or PLONKish languages). However, the hard bounds of a constraint system can be very limiting to the functionality of a ZK DSL. - -Enabling a circuit language to perform unconstrained execution is a powerful tool. Said another way, unconstrained execution lets developers generate witnesses from code that does not generate any constraints. Being able to execute logic outside of a circuit is critical for both circuit performance and constructing proofs on information that is external to a circuit. - -Fetching information from somewhere external to a circuit can also be used to enable developers to improve circuit efficiency. - -A ZK DSL does not just prove computation, but proves that some computation was handled correctly. Thus, it is necessary that when we switch from performing some operation directly inside of a circuit to inside of an unconstrained environment that the appropriate constraints are still laid down elsewhere in the circuit. - -## Example - -An in depth example might help drive the point home. This example comes from the excellent [post](https://discord.com/channels/1113924620781883405/1124022445054111926/1128747641853972590) by Tom in the Noir Discord. - -Let's look at how we can optimize a function to turn a `u72` into an array of `u8`s. - -```rust -fn main(num: u72) -> pub [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8)) as u72 & 0xff) as u8; - } - - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 91 -Backend circuit size: 3619 -``` - -A lot of the operations in this function are optimized away by the compiler (all the bit-shifts turn into divisions by constants). However we can save a bunch of gates by casting to u8 a bit earlier. This automatically truncates the bit-shifted value to fit in a u8 which allows us to remove the XOR against 0xff. This saves us ~480 gates in total. - -```rust -fn main(num: u72) -> pub [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8)) as u8; - } - - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 75 -Backend circuit size: 3143 -``` - -Those are some nice savings already but we can do better. This code is all constrained so we're proving every step of calculating out using num, but we don't actually care about how we calculate this, just that it's correct. This is where brillig comes in. - -It turns out that truncating a u72 into a u8 is hard to do inside a snark, each time we do as u8 we lay down 4 ACIR opcodes which get converted into multiple gates. It's actually much easier to calculate num from out than the other way around. All we need to do is multiply each element of out by a constant and add them all together, both relatively easy operations inside a snark. - -We can then run u72_to_u8 as unconstrained brillig code in order to calculate out, then use that result in our constrained function and assert that if we were to do the reverse calculation we'd get back num. This looks a little like the below: - -```rust -fn main(num: u72) -> pub [u8; 8] { - let out = u72_to_u8(num); - - let mut reconstructed_num: u72 = 0; - for i in 0..8 { - reconstructed_num += (out[i] as u72 << (56 - (8 * i))); - } - assert(num == reconstructed_num); - out -} - -unconstrained fn u72_to_u8(num: u72) -> [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8))) as u8; - } - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 78 -Backend circuit size: 2902 -``` - -This ends up taking off another ~250 gates from our circuit! We've ended up with more ACIR opcodes than before but they're easier for the backend to prove (resulting in fewer gates). - -Generally we want to use brillig whenever there's something that's easy to verify but hard to compute within the circuit. For example, if you wanted to calculate a square root of a number it'll be a much better idea to calculate this in brillig and then assert that if you square the result you get back your number. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/06_generics.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/06_generics.md deleted file mode 100644 index 36c2b593fcd..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/06_generics.md +++ /dev/null @@ -1,113 +0,0 @@ ---- -title: Generics -description: Learn how to use Generics in Noir -keywords: [Noir, Rust, generics, functions, structs] ---- - -Generics allow you to use the same functions with multiple different concrete data types. You can -read more about the concept of generics in the Rust documentation -[here](https://doc.rust-lang.org/book/ch10-01-syntax.html). - -Here is a trivial example showing the identity function that supports any type. In Rust, it is -common to refer to the most general type as `T`. We follow the same convention in Noir. - -```rust -fn id(x: T) -> T { - x -} -``` - -## In Structs - -Generics are useful for specifying types in structs. For example, we can specify that a field in a -struct will be of a certain generic type. In this case `value` is of type `T`. - -```rust -struct RepeatedValue { - value: T, - count: Field, -} - -impl RepeatedValue { - fn new(value: T) -> Self { - Self { value, count: 1 } - } - - fn increment(mut repeated: Self) -> Self { - repeated.count += 1; - repeated - } - - fn print(self) { - for _i in 0 .. self.count { - dep::std::println(self.value); - } - } -} - -fn main() { - let mut repeated = RepeatedValue::new("Hello!"); - repeated = repeated.increment(); - repeated.print(); -} -``` - -The `print` function will print `Hello!` an arbitrary number of times, twice in this case. - -If we want to be generic over array lengths (which are type-level integers), we can use numeric -generics. Using these looks just like using regular generics, but these generics can resolve to -integers at compile-time, rather than resolving to types. Here's an example of a struct that is -generic over the size of the array it contains internally: - -```rust -struct BigInt { - limbs: [u32; N], -} - -impl BigInt { - // `N` is in scope of all methods in the impl - fn first(first: BigInt, second: BigInt) -> Self { - assert(first.limbs != second.limbs); - first - - fn second(first: BigInt, second: Self) -> Self { - assert(first.limbs != second.limbs); - second - } -} -``` - -## Calling functions on generic parameters - -Unlike Rust, Noir does not have traits, so how can one translate the equivalent of a trait bound in -Rust into Noir? That is, how can we write a function that is generic over some type `T`, while also -requiring there is a function like `eq: fn(T, T) -> bool` that works on the type? - -The answer is that we can translate this by passing in the function manually. Here's an example of -implementing array equality in Noir: - -```rust -fn array_eq(array1: [T; N], array2: [T; N], elem_eq: fn(T, T) -> bool) -> bool { - if array1.len() != array2.len() { - false - } else { - let mut result = true; - for i in 0 .. array1.len() { - result &= elem_eq(array1[i], array2[i]); - } - result - } -} - -fn main() { - assert(array_eq([1, 2, 3], [1, 2, 3], |a, b| a == b)); - - // We can use array_eq even for arrays of structs, as long as we have - // an equality function for these structs we can pass in - let array = [MyStruct::new(), MyStruct::new()]; - assert(array_eq(array, array, MyStruct::eq)); -} -``` - -You can see an example of generics in the tests -[here](https://github.com/noir-lang/noir/blob/master/test_programs/execution_success/generics/src/main.nr). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/07_mutability.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/07_mutability.md deleted file mode 100644 index ed3fed820ec..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/07_mutability.md +++ /dev/null @@ -1,92 +0,0 @@ ---- -title: Mutability -description: - Learn about mutable variables, constants, and globals in Noir programming language. Discover how - to declare, modify, and use them in your programs. -keywords: [noir programming language, mutability in noir, mutable variables, constants, globals] ---- - -Variables in noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned -to via an assignment expression. - -```rust -let x = 2; -x = 3; // error: x must be mutable to be assigned to - -let mut y = 3; -let y = 4; // OK -``` - -The `mut` modifier can also apply to patterns: - -```rust -let (a, mut b) = (1, 2); -a = 11; // error: a must be mutable to be assigned to -b = 12; // OK - -let mut (c, d) = (3, 4); -c = 13; // OK -d = 14; // OK - -// etc. -let MyStruct { x: mut y } = MyStruct { x: a }; -// y is now in scope -``` - -Note that mutability in noir is local and everything is passed by value, so if a called function -mutates its parameters then the parent function will keep the old value of the parameters. - -```rust -fn main() -> pub Field { - let x = 3; - helper(x); - x // x is still 3 -} - -fn helper(mut x: i32) { - x = 4; -} -``` - -## Comptime Values - -:::warning - -The 'comptime' keyword was removed in version 0.10. The comptime keyword and syntax are currently still kept and parsed for backwards compatibility, but are now deprecated and will issue a warning when used. `comptime` has been removed because it is no longer needed for accessing arrays. - -::: - -## Globals - -Noir also supports global variables. However, they must be known at compile-time. The global type can also be inferred by the compiler entirely. Globals can also be used to specify array -annotations for function parameters and can be imported from submodules. - -```rust -global N: Field = 5; // Same as `global N: Field = 5` - -fn main(x : Field, y : [Field; N]) { - let res = x * N; - - assert(res == y[0]); - - let res2 = x * my_submodule::N; - assert(res != res2); -} - -mod my_submodule { - use dep::std; - - global N: Field = 10; - - fn my_helper() -> Field { - let x = N; - x - } -} -``` - -## Why only local mutability? - -Witnesses in a proving system are immutable in nature. Noir aims to _closely_ mirror this setting -without applying additional overhead to the user. Modeling a mutable reference is not as -straightforward as on conventional architectures and would incur some possibly unexpected overhead. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/08_lambdas.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/08_lambdas.md deleted file mode 100644 index ae1e6aecab1..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/08_lambdas.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: Lambdas -description: Learn how to use anonymous functions in Noir programming language. -keywords: [Noir programming language, lambda, closure, function, anonymous function] ---- - -## Introduction - -Lambdas are anonymous functions. The syntax is `|arg1, arg2, ..., argN| return_expression`. - -```rust -let add_50 = |val| val + 50; -assert(add_50(100) == 150); -``` - -A block can be used as the body of a lambda, allowing you to declare local variables inside it: - -```rust -let cool = || { - let x = 100; - let y = 100; - x + y -} - -assert(cool() == 200); -``` - -## Closures - -Inside the body of a lambda, you can use variables defined in the enclosing function. Such lambdas are called **closures**. In this example `x` is defined inside `main` and is accessed from within the lambda: - -```rust -fn main() { - let x = 100; - let closure = || x + 150; - assert(closure() == 250); -} -``` - -## Passing closures to higher-order functions - -It may catch you by surprise that the following code fails to compile: - -```rust -fn foo(f: fn () -> Field) -> Field { - f() -} - -fn main() { - let (x, y) = (50, 50); - assert(foo(|| x + y) == 100); // error :( -} -``` - -The reason is that the closure's capture environment affects its type - we have a closure that captures two Fields and `foo` -expects a regular function as an argument - those are incompatible. -:::note - -Variables contained within the `||` are the closure's parameters, and the expression that follows it is the closure's body. The capture environment is comprised of any variables used in the closure's body that are not parameters. - -E.g. in |x| x + y, y would be a captured variable, but x would not be, since it is a parameter of the closure. - -::: -The syntax for the type of a closure is `fn[env](args) -> ret_type`, where `env` is the capture environment of the closure - -in this example that's `(Field, Field)`. - -The best solution in our case is to make `foo` generic over the environment type of its parameter, so that it can be called -with closures with any environment, as well as with regular functions: - -```rust -fn foo(f: fn[Env]() -> Field) -> Field { - f() -} - -fn main() { - let (x, y) = (50, 50); - assert(foo(|| x + y) == 100); // compiles fine - assert(foo(|| 60) == 60); // compiles fine -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/09_comments.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/09_comments.md deleted file mode 100644 index 3bb4d2f25a4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/09_comments.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: Comments -description: - Learn how to write comments in Noir programming language. A comment is a line of code that is - ignored by the compiler, but it can be read by programmers. Single-line and multi-line comments - are supported in Noir. -keywords: [Noir programming language, comments, single-line comments, multi-line comments] ---- - -A comment is a line in your codebase which the compiler ignores, however it can be read by -programmers. - -Here is a single line comment: - -```rust -// This is a comment and is ignored -``` - -`//` is used to tell the compiler to ignore the rest of the line. - -Noir also supports multi-line block comments. Start a block comment with `/*` and end the block with `*/`. - -Noir does not natively support doc comments. You may be able to use [Rust doc comments](https://doc.rust-lang.org/reference/comments.html) in your code to leverage some Rust documentation build tools with Noir code. - -```rust -/* - This is a block comment describing a complex function. -*/ -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/10_distinct.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/10_distinct.md deleted file mode 100644 index e7ff7f5017a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/10_distinct.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: Distinct Witnesses ---- - -The `distinct` keyword prevents repetitions of witness indices in the program's ABI. This ensures -that the witnesses being returned as public inputs are all unique. - -The `distinct` keyword is only used for return values on program entry points (usually the `main()` -function). - -When using `distinct` and `pub` simultaneously, `distinct` comes first. See the example below. - -You can read more about the problem this solves -[here](https://github.com/noir-lang/noir/issues/1183). - -## Example - -Without the `distinct` keyword, the following program - -```rust -fn main(x : pub Field, y : pub Field) -> pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - "return_witnesses": [3, 2, 4, 4] - } -} -``` - -Whereas (with the `distinct` keyword) - -```rust -fn main(x : pub Field, y : pub Field) -> distinct pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - //... - "return_witnesses": [3, 4, 5, 6] - } -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/11_shadowing.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/11_shadowing.md deleted file mode 100644 index efd743e764f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/11_shadowing.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Shadowing ---- - -Noir allows for inheriting variables' values and re-declaring them with the same name similar to Rust, known as shadowing. - -For example, the following function is valid in Noir: - -```rust -fn main() { - let x = 5; - - { - let x = x * 2; - assert (x == 10); - } - - assert (x == 5); -} -``` - -In this example, a variable x is first defined with the value 5. - -The local scope that follows shadows the original x, i.e. creates a local mutable x based on the value of the original x. It is given a value of 2 times the original x. - -When we return to the main scope, x once again refers to just the original x, which stays at the value of 5. - -## Temporal mutability - -One way that shadowing is useful, in addition to ergonomics across scopes, is for temporarily mutating variables. - -```rust -fn main() { - let age = 30; - // age = age + 5; // Would error as `age` is immutable by default. - - let mut age = age + 5; // Temporarily mutates `age` with a new value. - - let age = age; // Locks `age`'s mutability again. - - assert (age == 35); -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types.md deleted file mode 100644 index 74f573f7d3f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: Data Types -description: - Get a clear understanding of the two categories of Noir data types - primitive types and compound - types. Learn about their characteristics, differences, and how to use them in your Noir - programming. -keywords: - [ - noir, - data types, - primitive types, - compound types, - private types, - public types, - ] ---- - -Every value in Noir has a type, which determines which operations are valid for it. - -All values in Noir are fundamentally composed of `Field` elements. For a more approachable -developing experience, abstractions are added on top to introduce different data types in Noir. - -Noir has two category of data types: primitive types (e.g. `Field`, integers, `bool`) and compound -types that group primitive types (e.g. arrays, tuples, structs). Each value can either be private or -public. - -## Private & Public Types - -A **private value** is known only to the Prover, while a **public value** is known by both the -Prover and Verifier. Mark values as `private` when the value should only be known to the prover. All -primitive types (including individual fields of compound types) in Noir are private by default, and -can be marked public when certain values are intended to be revealed to the Verifier. - -> **Note:** For public values defined in Noir programs paired with smart contract verifiers, once -> the proofs are verified on-chain the values can be considered known to everyone that has access to -> that blockchain. - -Public data types are treated no differently to private types apart from the fact that their values -will be revealed in proofs generated. Simply changing the value of a public type will not change the -circuit (where the same goes for changing values of private types as well). - -_Private values_ are also referred to as _witnesses_ sometimes. - -> **Note:** The terms private and public when applied to a type (e.g. `pub Field`) have a different -> meaning than when applied to a function (e.g. `pub fn foo() {}`). -> -> The former is a visibility modifier for the Prover to interpret if a value should be made known to -> the Verifier, while the latter is a visibility modifier for the compiler to interpret if a -> function should be made accessible to external Noir programs like in other languages. - -### pub Modifier - -All data types in Noir are private by default. Types are explicitly declared as public using the -`pub` modifier: - -```rust -fn main(x : Field, y : pub Field) -> pub Field { - x + y -} -``` - -In this example, `x` is **private** while `y` and `x + y` (the return value) are **public**. Note -that visibility is handled **per variable**, so it is perfectly valid to have one input that is -private and another that is public. - -> **Note:** Public types can only be declared through parameters on `main`. - -## Type Aliases - -A type alias is a new name for an existing type. Type aliases are declared with the keyword `type`: - -```rust -type Id = u8; - -fn main() { - let id: Id = 1; - let zero: u8 = 0; - assert(zero + 1 == id); -} -``` - -Type aliases can also be used with [generics](./06_generics.md): - -```rust -type Id = Size; - -fn main() { - let id: Id = 1; - let zero: u32 = 0; - assert(zero + 1 == id); -} -``` - -### BigInt - -You can achieve BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/00_fields.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/00_fields.md deleted file mode 100644 index 78d3d2af166..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/00_fields.md +++ /dev/null @@ -1,165 +0,0 @@ ---- -title: Fields -description: - Dive deep into the Field data type in Noir. Understand its methods, practical examples, and best practices to effectively use Fields in your Noir programs. -keywords: - [ - noir, - field type, - methods, - examples, - best practices, - ] ---- - -The field type corresponds to the native field type of the proving backend. - -The size of a Noir field depends on the elliptic curve's finite field for the proving backend -adopted. For example, a field would be a 254-bit integer when paired with the default backend that -spans the Grumpkin curve. - -Fields support integer arithmetic and are often used as the default numeric type in Noir: - -```rust -fn main(x : Field, y : Field) { - let z = x + y; -} -``` - -`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new -private value `z` constrained to be equal to `x + y`. - -If proving efficiency is of priority, fields should be used as a default for solving problems. -Smaller integer types (e.g. `u64`) incur extra range constraints. - -## Methods - -After declaring a Field, you can use these common methods on it: - -### to_le_bits - -Transforms the field into an array of bits, Little Endian. - -```rust -fn to_le_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_le_bits(32); -} -``` - -### to_be_bits - -Transforms the field into an array of bits, Big Endian. - -```rust -fn to_be_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_be_bits(32); -} -``` - -### to_le_bytes - -Transforms into an array of bytes, Little Endian - -```rust -fn to_le_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_le_bytes(4); -} -``` - -### to_be_bytes - -Transforms into an array of bytes, Big Endian - -```rust -fn to_be_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_be_bytes(4); -} -``` - -### to_le_radix - -Decomposes into a vector over the specified base, Little Endian - -```rust -fn to_le_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_le_radix(256, 4); -} -``` - -### to_be_radix - -Decomposes into a vector over the specified base, Big Endian - -```rust -fn to_be_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_be_radix(256, 4); -} -``` - -### pow_32 - -Returns the value to the power of the specified exponent - -```rust -fn pow_32(self, exponent: Field) -> Field -``` - -example: - -```rust -fn main() { - let field = 2 - let pow = field.pow_32(4); - assert(pow == 16); -} -``` - -### sgn0 - -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. - -```rust -fn sgn0(self) -> u1 -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/01_integers.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/01_integers.md deleted file mode 100644 index 1814365800a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/01_integers.md +++ /dev/null @@ -1,112 +0,0 @@ ---- -title: Integers -description: Explore the Integer data type in Noir. Learn about its methods, see real-world examples, and grasp how to efficiently use Integers in your Noir code. -keywords: [noir, integer types, methods, examples, arithmetic] ---- - -An integer type is a range constrained field type. The Noir frontend supports arbitrarily-sized, both unsigned and signed integer types. - -:::info - -When an integer is defined in Noir without a specific type, it will default to `Field`. - -The one exception is for loop indices which default to `u64` since comparisons on `Field`s are not possible. - -::: - -## Unsigned Integers - -An unsigned integer type is specified first with the letter `u` (indicating its unsigned nature) followed by its bit size (e.g. `8`): - -```rust -fn main() { - let x: u8 = 1; - let y: u8 = 1; - let z = x + y; - assert (z == 2); -} -``` - -The bit size determines the maximum value the integer type can store. For example, a `u8` variable can store a value in the range of 0 to 255 (i.e. $\\2^{8}-1\\$). - -## Signed Integers - -A signed integer type is specified first with the letter `i` (which stands for integer) followed by its bit size (e.g. `8`): - -```rust -fn main() { - let x: i8 = -1; - let y: i8 = -1; - let z = x + y; - assert (z == -2); -} -``` - -The bit size determines the maximum and minimum range of value the integer type can store. For example, an `i8` variable can store a value in the range of -128 to 127 (i.e. $\\-2^{7}\\$ to $\\2^{7}-1\\$). - -:::tip - -If you are using the default proving backend with Noir, both even (e.g. _u2_, _i2_) and odd (e.g. _u3_, _i3_) arbitrarily-sized integer types up to 127 bits (i.e. _u127_ and _i127_) are supported. - -::: - -## Overflows - -Computations that exceed the type boundaries will result in overflow errors. This happens with both signed and unsigned integers. For example, attempting to prove: - -```rust -fn main(x: u8, y: u8) { - let z = x + y; -} -``` - -With: - -```toml -x = "255" -y = "1" -``` - -Would result in: - -``` -$ nargo prove -error: Assertion failed: 'attempt to add with overflow' -┌─ ~/src/main.nr:9:13 -│ -│ let z = x + y; -│ ----- -│ -= Call stack: - ... -``` - -A similar error would happen with signed integers: - -```rust -fn main() { - let x: i8 = -118; - let y: i8 = -11; - let z = x + y; -} -``` - -### Wrapping methods - -Although integer overflow is expected to error, some use-cases rely on wrapping. For these use-cases, the standard library provides `wrapping` variants of certain common operations: - -```rust -fn wrapping_add(x: T, y: T) -> T; -fn wrapping_sub(x: T, y: T) -> T; -fn wrapping_mul(x: T, y: T) -> T; -``` - -Example of how it is used: - -```rust -use dep::std; - -fn main(x: u8, y: u8) -> pub u8 { - std::wrapping_add(x, y) -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/02_booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/02_booleans.md deleted file mode 100644 index d353606210a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/02_booleans.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: Booleans -description: - Delve into the Boolean data type in Noir. Understand its methods, practical examples, and best practices for using Booleans in your Noir programs. -keywords: - [ - noir, - boolean type, - methods, - examples, - logical operations, - ] ---- - - -The `bool` type in Noir has two possible values: `true` and `false`: - -```rust -fn main() { - let t = true; - let f: bool = false; -} -``` - -> **Note:** When returning a boolean value, it will show up as a value of 1 for `true` and 0 for -> `false` in _Verifier.toml_. - -The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and -[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/03_strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/03_strings.md deleted file mode 100644 index 4360893e9a2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/03_strings.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: Strings -description: - Discover the String data type in Noir. Learn about its methods, see real-world examples, and understand how to effectively manipulate and use Strings in Noir. -keywords: - [ - noir, - string type, - methods, - examples, - concatenation, - ] ---- - - -The string type is a fixed length value defined with `str`. - -You can use strings in `assert()` functions or print them with -`std::println()`. See more about [Logging](../../standard_library/logging.md). - -```rust -use dep::std; - -fn main(message : pub str<11>, hex_as_string : str<4>) { - std::println(message); - assert(message == "hello world"); - assert(hex_as_string == "0x41"); -} -``` - -You can convert a `str` to a byte array by calling `as_bytes()` -or a vector by calling `as_bytes_vec()`. - -```rust -fn main() { - let message = "hello world"; - let message_bytes = message.as_bytes(); - let mut message_vec = message.as_bytes_vec(); - assert(message_bytes.len() == 11); - assert(message_bytes[0] == 104); - assert(message_bytes[0] == message_vec.get(0)); -} -``` - -## Escape characters - -You can use escape characters for your strings: - -| Escape Sequence | Description | -|-----------------|-----------------| -| `\r` | Carriage Return | -| `\n` | Newline | -| `\t` | Tab | -| `\0` | Null Character | -| `\"` | Double Quote | -| `\\` | Backslash | - -Example: - -```rust -let s = "Hello \"world" // prints "Hello "world" -let s = "hey \tyou"; // prints "hey you" -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/04_arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/04_arrays.md deleted file mode 100644 index 3c84da3f8ad..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/04_arrays.md +++ /dev/null @@ -1,244 +0,0 @@ ---- -title: Arrays -description: - Dive into the Array data type in Noir. Grasp its methods, practical examples, and best practices for efficiently using Arrays in your Noir code. -keywords: - [ - noir, - array type, - methods, - examples, - indexing, - ] ---- - -An array is one way of grouping together values into one compound type. Array types can be inferred -or explicitly specified via the syntax `[; ]`: - -```rust -fn main(x : Field, y : Field) { - let my_arr = [x, y]; - let your_arr: [Field; 2] = [x, y]; -} -``` - -Here, both `my_arr` and `your_arr` are instantiated as an array containing two `Field` elements. - -Array elements can be accessed using indexing: - -```rust -fn main() { - let a = [1, 2, 3, 4, 5]; - - let first = a[0]; - let second = a[1]; -} -``` - -All elements in an array must be of the same type (i.e. homogeneous). That is, an array cannot group -a `Field` value and a `u8` value together for example. - -You can write mutable arrays, like: - -```rust -fn main() { - let mut arr = [1, 2, 3, 4, 5]; - assert(arr[0] == 1); - - arr[0] = 42; - assert(arr[0] == 42); -} -``` - -You can instantiate a new array of a fixed size with the same value repeated for each element. The following example instantiates an array of length 32 where each element is of type Field and has the value 0. - -```rust -let array: [Field; 32] = [0; 32]; -``` - -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: - -```rust -let array: [Field; 32] = [0; 32]; -let sl = array.as_slice() -``` - -You can define multidimensional arrays: - -```rust -let array : [[Field; 2]; 2]; -let element = array[0][0]; -``` - -## Types - -You can create arrays of primitive types or structs. There is not yet support for nested arrays -(arrays of arrays) or arrays of structs that contain arrays. - -## Methods - -For convenience, the STD provides some ready-to-use, common methods for arrays: - -### len - -Returns the length of an array - -```rust -fn len(_array: [T; N]) -> comptime Field -``` - -example - -```rust -fn main() { - let array = [42, 42]; - assert(array.len() == 2); -} -``` - -### sort - -Returns a new sorted array. The original array remains untouched. Notice that this function will -only work for arrays of fields or integers, not for any arbitrary type. This is because the sorting -logic it uses internally is optimized specifically for these values. If you need a sort function to -sort any type, you should use the function `sort_via` described below. - -```rust -fn sort(_array: [T; N]) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32]; - let sorted = arr.sort(); - assert(sorted == [32, 42]); -} -``` - -### sort_via - -Sorts the array with a custom comparison function - -```rust -fn sort_via(mut a: [T; N], ordering: fn(T, T) -> bool) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32] - let sorted_ascending = arr.sort_via(|a, b| a <= b); - assert(sorted_ascending == [32, 42]); // verifies - - let sorted_descending = arr.sort_via(|a, b| a >= b); - assert(sorted_descending == [32, 42]); // does not verify -} -``` - -### map - -Applies a function to each element of the array, returning a new array containing the mapped elements. - -```rust -fn map(f: fn(T) -> U) -> [U; N] -``` - -example - -```rust -let a = [1, 2, 3]; -let b = a.map(|a| a * 2); // b is now [2, 4, 6] -``` - -### fold - -Applies a function to each element of the array, returning the final accumulated value. The first -parameter is the initial value. - -```rust -fn fold(mut accumulator: U, f: fn(U, T) -> U) -> U -``` - -This is a left fold, so the given function will be applied to the accumulator and first element of -the array, then the second, and so on. For a given call the expected result would be equivalent to: - -```rust -let a1 = [1]; -let a2 = [1, 2]; -let a3 = [1, 2, 3]; - -let f = |a, b| a - b; -a1.fold(10, f) //=> f(10, 1) -a2.fold(10, f) //=> f(f(10, 1), 2) -a3.fold(10, f) //=> f(f(f(10, 1), 2), 3) -``` - -example: - -```rust - -fn main() { - let arr = [2, 2, 2, 2, 2]; - let folded = arr.fold(0, |a, b| a + b); - assert(folded == 10); -} - -``` - -### reduce - -Same as fold, but uses the first element as starting element. - -```rust -fn reduce(f: fn(T, T) -> T) -> T -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let reduced = arr.reduce(|a, b| a + b); - assert(reduced == 10); -} -``` - -### all - -Returns true if all the elements satisfy the given predicate - -```rust -fn all(predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let all = arr.all(|a| a == 2); - assert(all); -} -``` - -### any - -Returns true if any of the elements satisfy the given predicate - -```rust -fn any(predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 5]; - let any = arr.any(|a| a == 5); - assert(any); -} - -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/05_slices.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/05_slices.mdx deleted file mode 100644 index 1be0ec4a137..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/05_slices.mdx +++ /dev/null @@ -1,146 +0,0 @@ ---- -title: Slices -description: Explore the Slice data type in Noir. Understand its methods, see real-world examples, and learn how to effectively use Slices in your Noir programs. -keywords: [noir, slice type, methods, examples, subarrays] ---- - -import Experimental from '@site/src/components/Notes/_experimental.mdx'; - - - -A slice is a dynamically-sized view into a sequence of elements. They can be resized at runtime, but because they don't own the data, they cannot be returned from a circuit. You can treat slices as arrays without a constrained size. - -```rust -use dep::std::slice; - -fn main() -> pub Field { - let mut slice: [Field] = [0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -View the corresponding test file [here][test-file]. - -[test-file]: https://github.com/noir-lang/noir/blob/f387ec1475129732f72ba294877efdf6857135ac/crates/nargo_cli/tests/test_data_ssa_refactor/slices/src/main.nr - -## Methods - -For convenience, the STD provides some ready-to-use, common methods for slices: - -### push_back - -Pushes a new element to the end of the slice, returning a new slice with a length one greater than the original unmodified slice. - -```rust -fn push_back(_self: [T], _elem: T) -> [T] -``` - -example: - -```rust -fn main() -> pub Field { - let mut slice: [Field] = [0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -View the corresponding test file [here][test-file]. - -### push_front - -Returns a new array with the specified element inserted at index 0. The existing elements indexes are incremented by 1. - -```rust -fn push_front(_self: Self, _elem: T) -> Self -``` - -Example: - -```rust -let mut new_slice: [Field] = []; -new_slice = new_slice.push_front(20); -assert(new_slice[0] == 20); // returns true -``` - -View the corresponding test file [here][test-file]. - -### pop_front - -Returns a tuple of two items, the first element of the array and the rest of the array. - -```rust -fn pop_front(_self: Self) -> (T, Self) -``` - -Example: - -```rust -let (first_elem, rest_of_slice) = slice.pop_front(); -``` - -View the corresponding test file [here][test-file]. - -### pop_back - -Returns a tuple of two items, the beginning of the array with the last element omitted and the last element. - -```rust -fn pop_back(_self: Self) -> (Self, T) -``` - -Example: - -```rust -let (popped_slice, last_elem) = slice.pop_back(); -``` - -View the corresponding test file [here][test-file]. - -### append - -Loops over a slice and adds it to the end of another. - -```rust -fn append(mut self, other: Self) -> Self -``` - -Example: - -```rust -let append = [1, 2].append([3, 4, 5]); -``` - -### insert - -Inserts an element at a specified index and shifts all following elements by 1. - -```rust -fn insert(_self: Self, _index: Field, _elem: T) -> Self -``` - -Example: - -```rust -new_slice = rest_of_slice.insert(2, 100); -assert(new_slice[2] == 100); -``` - -View the corresponding test file [here][test-file]. - -### remove - -Remove an element at a specified index, shifting all elements after it to the left, returning the altered slice and the removed element. - -```rust -fn remove(_self: Self, _index: Field) -> (Self, T) -``` - -Example: - -```rust -let (remove_slice, removed_elem) = slice.remove(3); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/06_vectors.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/06_vectors.mdx deleted file mode 100644 index 4617e90d038..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/06_vectors.mdx +++ /dev/null @@ -1,172 +0,0 @@ ---- -title: Vectors -description: Delve into the Vector data type in Noir. Learn about its methods, practical examples, and best practices for using Vectors in your Noir code. -keywords: [noir, vector type, methods, examples, dynamic arrays] ---- - -import Experimental from '@site/src/components/Notes/_experimental.mdx'; - - - -A vector is a collection type similar to Rust's Vector type. It's convenient way to use slices as mutable arrays. - -Example: - -```rust -use dep::std::collections::vec::Vec; - -let mut vector: Vec = Vec::new(); -for i in 0..5 { - vector.push(i); -} -assert(vector.len() == 5); -``` - -## Methods - -### new - -Creates a new, empty vector. - -```rust -pub fn new() -> Self { - Self { slice: [] } -} -``` - -Example: - -```rust -let empty_vector: Vec = Vec::new(); -assert(empty_vector.len() == 0); -``` - -### from_slice - -Creates a vector containing each element from a given slice. Mutations to the resulting vector will not affect the original slice. - -```rust -pub fn from_slice(slice: [T]) -> Self { - Self { slice } -} -``` - -Example: - -```rust -let arr: [Field] = [1, 2, 3]; -let vector_from_slice = Vec::from_slice(arr); -assert(vector_from_slice.len() == 3); -``` - -### get - -Retrieves an element from the vector at a given index. Panics if the index points beyond the vector's end. - -```rust -pub fn get(self, index: Field) -> T { - self.slice[index] -} -``` - -Example: - -```rust -let vector: Vec = Vec::from_slice([10, 20, 30]); -assert(vector.get(1) == 20); -``` - -### push - -Adds a new element to the vector's end, returning a new vector with a length one greater than the original unmodified vector. - -```rust -pub fn push(&mut self, elem: T) { - self.slice = self.slice.push_back(elem); -} -``` - -Example: - -```rust -let mut vector: Vec = Vec::new(); -vector.push(10); -assert(vector.len() == 1); -``` - -### pop - -Removes an element from the vector's end, returning a new vector with a length one less than the original vector, along with the removed element. Panics if the vector's length is zero. - -```rust -pub fn pop(&mut self) -> T { - let (popped_slice, last_elem) = self.slice.pop_back(); - self.slice = popped_slice; - last_elem -} -``` - -Example: - -```rust -let mut vector = Vec::from_slice([10, 20]); -let popped_elem = vector.pop(); -assert(popped_elem == 20); -assert(vector.len() == 1); -``` - -### insert - -Inserts an element at a specified index, shifting subsequent elements to the right. - -```rust -pub fn insert(&mut self, index: Field, elem: T) { - self.slice = self.slice.insert(index, elem); -} -``` - -Example: - -```rust -let mut vector = Vec::from_slice([10, 30]); -vector.insert(1, 20); -assert(vector.get(1) == 20); -``` - -### remove - -Removes an element at a specified index, shifting subsequent elements to the left, and returns the removed element. - -```rust -pub fn remove(&mut self, index: Field) -> T { - let (new_slice, elem) = self.slice.remove(index); - self.slice = new_slice; - elem -} -``` - -Example: - -```rust -let mut vector = Vec::from_slice([10, 20, 30]); -let removed_elem = vector.remove(1); -assert(removed_elem == 20); -assert(vector.len() == 2); -``` - -### len - -Returns the number of elements in the vector. - -```rust -pub fn len(self) -> Field { - self.slice.len() -} -``` - -Example: - -```rust -let empty_vector: Vec = Vec::new(); -assert(empty_vector.len() == 0); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/07_tuples.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/07_tuples.md deleted file mode 100644 index 5f6cab974a8..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/07_tuples.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: Tuples -description: - Dive into the Tuple data type in Noir. Understand its methods, practical examples, and best practices for efficiently using Tuples in your Noir code. -keywords: - [ - noir, - tuple type, - methods, - examples, - multi-value containers, - ] ---- - -A tuple collects multiple values like an array, but with the added ability to collect values of -different types: - -```rust -fn main() { - let tup: (u8, u64, Field) = (255, 500, 1000); -} -``` - -One way to access tuple elements is via destructuring using pattern matching: - -```rust -fn main() { - let tup = (1, 2); - - let (one, two) = tup; - - let three = one + two; -} -``` - -Another way to access tuple elements is via direct member access, using a period (`.`) followed by -the index of the element we want to access. Index `0` corresponds to the first tuple element, `1` to -the second and so on: - -```rust -fn main() { - let tup = (5, 6, 7, 8); - - let five = tup.0; - let eight = tup.3; -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/08_structs.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/08_structs.md deleted file mode 100644 index 35421734639..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/08_structs.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -title: Structs -description: - Explore the Struct data type in Noir. Learn about its methods, see real-world examples, and grasp how to effectively define and use Structs in your Noir programs. -keywords: - [ - noir, - struct type, - methods, - examples, - data structures, - ] ---- - -A struct also allows for grouping multiple values of different types. Unlike tuples, we can also -name each field. - -> **Note:** The usage of _field_ here refers to each element of the struct and is unrelated to the -> field type of Noir. - -Defining a struct requires giving it a name and listing each field within as `: ` pairs: - -```rust -struct Animal { - hands: Field, - legs: Field, - eyes: u8, -} -``` - -An instance of a struct can then be created with actual values in `: ` pairs in any -order. Struct fields are accessible using their given names: - -```rust -fn main() { - let legs = 4; - - let dog = Animal { - eyes: 2, - hands: 0, - legs, - }; - - let zero = dog.hands; -} -``` - -Structs can also be destructured in a pattern, binding each field to a new variable: - -```rust -fn main() { - let Animal { hands, legs: feet, eyes } = get_octopus(); - - let ten = hands + feet + eyes as u8; -} - -fn get_octopus() -> Animal { - let octopus = Animal { - hands: 0, - legs: 8, - eyes: 2, - }; - - octopus -} -``` - -The new variables can be bound with names different from the original struct field names, as -showcased in the `legs --> feet` binding in the example above. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/09_references.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/09_references.md deleted file mode 100644 index b0c35ce2cb9..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/09_references.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: References ---- - -Noir supports first-class references. References are a bit like pointers: they point to a specific address that can be followed to access the data stored at that address. You can use Rust-like syntax to use pointers in Noir: the `&` operator references the variable, the `*` operator dereferences it. - -Example: - -```rust -fn main() { - let mut x = 2; - - // you can reference x as &mut and pass it to multiplyBy2 - multiplyBy2(&mut x); -} - -// you can access &mut here -fn multiplyBy2(x: &mut Field) { - // and dereference it with * - *x = *x * 2; -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/10_function_types.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/10_function_types.md deleted file mode 100644 index 1ec92efd594..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/10_function_types.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: Function types ---- - -Noir supports higher-order functions. The syntax for a function type is as follows: - -```rust -fn(arg1_type, arg2_type, ...) -> return_type -``` - -Example: - -```rust -fn assert_returns_100(f: fn() -> Field) { // f takes no args and returns a Field - assert(f() == 100); -} - -fn main() { - assert_returns_100(|| 100); // ok - assert_returns_100(|| 150); // fails -} -``` - -A function type also has an optional capture environment - this is necessary to support closures. -See [Lambdas](../08_lambdas.md) for more details. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/migration_notes.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/migration_notes.md deleted file mode 100644 index 905bca3d30c..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/migration_notes.md +++ /dev/null @@ -1,91 +0,0 @@ ---- -title: Migration notes -description: Read about migration notes from previous versions, which could solve problems while updating -keywords: [Noir, notes, migration, updating, upgrading] ---- - -Noir is in full-speed development. Things break fast, wild, and often. This page attempts to leave some notes on errors you might encounter when upgrading and how to resolve them until proper patches are built. - -## ≥0.19 - -### Enforcing `compiler_version` - -From this version on, the compiler will check for the `compiler_version` field in `Nargo.toml`, and will error if it doesn't match the current Nargo version in use. - -To update, please make sure this field in `Nargo.toml` matches the output of `nargo --version`. - -## ≥0.14 - -The index of the [for loops](./language_concepts/02_control_flow.md#loops) is now of type `u64` instead of `Field`. An example refactor would be: - -```rust -for i in 0..10 { - let i = i as Field; -} -``` - -## ≥v0.11.0 and Nargo backend - -From this version onwards, Nargo starts managing backends through the `nargo backend` command. Upgrading to the versions per usual steps might lead to: - -### `backend encountered an error` - -This is likely due to the existing locally installed version of proving backend (e.g. barretenberg) is incompatible with the version of Nargo in use. - -To fix the issue: - -1. Uninstall the existing backend - -```bash -nargo backend uninstall acvm-backend-barretenberg -``` - -You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. - -2. Reinstall a compatible version of the proving backend. - -If you are using the default barretenberg backend, simply run: - -``` -nargo prove -``` - -with your Noir program. - -This will trigger the download and installation of the latest version of barretenberg compatible with your Nargo in use. - -### `backend encountered an error: illegal instruction` - -On certain Intel-based systems, an `illegal instruction` error may arise due to incompatibility of barretenberg with certain CPU instructions. - -To fix the issue: - -1. Uninstall the existing backend - -```bash -nargo backend uninstall acvm-backend-barretenberg -``` - -You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. - -2. Reinstall a compatible version of the proving backend. - -If you are using the default barretenberg backend, simply run: - -``` -nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/barretenberg-js-binary/raw/master/run-bb.tar.gz -``` - -This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. - -The gzipped file is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. - -Then run: - -``` -DESIRED_BINARY_VERSION=0.8.1 nargo info -``` - -This overrides the bb native binary with a bb.js node application instead, which should be compatible with most if not all hardware. This does come with the drawback of being generally slower than native binary. - -0.8.1 indicates bb.js version 0.8.1, so if you change that it will update to a different version or the default version in the script if none was supplied. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/modules_packages_crates/crates_and_packages.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/modules_packages_crates/crates_and_packages.md deleted file mode 100644 index 23f60855c30..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/modules_packages_crates/crates_and_packages.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Crates and Packages -description: Learn how to use Crates and Packages in your Noir project -keywords: [Nargo, dependencies, package management, crates, package] ---- - -## Crates - -A crate is the smallest amount of code that the Noir compiler considers at a time. -Crates can contain modules, and the modules may be defined in other files that get compiled with the crate, as we’ll see in the coming sections. - -### Crate Types - -A Noir crate can come in several forms: binaries, libraries or contracts. - -#### Binaries - -_Binary crates_ are programs which you can compile to an ACIR circuit which you can then create proofs against. Each must have a function called `main` that defines the ACIR circuit which is to be proved. - -#### Libraries - -_Library crates_ don't have a `main` function and they don't compile down to ACIR. Instead they define functionality intended to be shared with multiple projects, and eventually included in a binary crate. - -#### Contracts - -Contract crates are similar to binary crates in that they compile to ACIR which you can create proofs against. They are different in that they do not have a single `main` function, but are a collection of functions to be deployed to the [Aztec network](https://aztec.network). You can learn more about the technical details of Aztec in the [monorepo](https://github.com/AztecProtocol/aztec-packages) or contract [examples](https://github.com/AztecProtocol/aztec-packages/tree/master/noir-projects/noir-contracts/contracts). - -### Crate Root - -Every crate has a root, which is the source file that the compiler starts, this is also known as the root module. The Noir compiler does not enforce any conditions on the name of the file which is the crate root, however if you are compiling via Nargo the crate root must be called `lib.nr` or `main.nr` for library or binary crates respectively. - -## Packages - -A Nargo _package_ is a collection of one of more crates that provides a set of functionality. A package must include a Nargo.toml file. - -A package _must_ contain either a library or a binary crate, but not both. - -### Differences from Cargo Packages - -One notable difference between Rust's Cargo and Noir's Nargo is that while Cargo allows a package to contain an unlimited number of binary crates and a single library crate, Nargo currently only allows a package to contain a single crate. - -In future this restriction may be lifted to allow a Nargo package to contain both a binary and library crate or multiple binary crates. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/modules_packages_crates/dependencies.md deleted file mode 100644 index 87a09293ea8..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/modules_packages_crates/dependencies.md +++ /dev/null @@ -1,123 +0,0 @@ ---- -title: Dependencies -description: - Learn how to specify and manage dependencies in Nargo, allowing you to upload packages to GitHub - and use them easily in your project. -keywords: [Nargo, dependencies, GitHub, package management, versioning] ---- - -Nargo allows you to upload packages to GitHub and use them as dependencies. - -## Specifying a dependency - -Specifying a dependency requires a tag to a specific commit and the git url to the url containing -the package. - -Currently, there are no requirements on the tag contents. If requirements are added, it would follow -semver 2.0 guidelines. - -> Note: Without a `tag` , there would be no versioning and dependencies would change each time you -> compile your project. - -For example, to add the [ecrecover-noir library](https://github.com/colinnielsen/ecrecover-noir) to your project, add it to `Nargo.toml`: - -```toml -# Nargo.toml - -[dependencies] -ecrecover = {tag = "v0.8.0", git = "https://github.com/colinnielsen/ecrecover-noir"} -``` - -If the module is in a subdirectory, you can define a subdirectory in your git repository, for example: - -```toml -# Nargo.toml - -[dependencies] -easy_private_token_contract = {tag ="v0.1.0-alpha62", git = "https://github.com/AztecProtocol/aztec-packages", directory = "yarn-project/noir-contracts/contracts/easy_private_token_contract"} -``` - -## Specifying a local dependency - -You can also specify dependencies that are local to your machine. - -For example, this file structure has a library and binary crate - -```tree -├── binary_crate -│   ├── Nargo.toml -│   └── src -│   └── main.nr -└── lib_a - ├── Nargo.toml - └── src - └── lib.nr -``` - -Inside of the binary crate, you can specify: - -```toml -# Nargo.toml - -[dependencies] -lib_a = { path = "../lib_a" } -``` - -## Importing dependencies - -You can import a dependency to a Noir file using the following syntax. For example, to import the -ecrecover-noir library and local lib_a referenced above: - -```rust -use dep::ecrecover; -use dep::lib_a; -``` - -You can also import only the specific parts of dependency that you want to use, like so: - -```rust -use dep::std::hash::sha256; -use dep::std::scalar_mul::fixed_base_embedded_curve; -``` - -Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you -can import multiple items in the same line by enclosing them in curly braces: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; -``` - -We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. - -Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. - -## Dependencies of Dependencies - -Note that when you import a dependency, you also get access to all of the dependencies of that package. - -For example, the [phy_vector](https://github.com/resurgencelabs/phy_vector) library imports an [fraction](https://github.com/resurgencelabs/fraction) library. If you're importing the phy_vector library, then you can access the functions in fractions library like so: - -```rust -use dep::phy_vector; - -fn main(x : Field, y : pub Field) { - //... - let f = phy_vector::fraction::toFraction(true, 2, 1); - //... -} -``` - -## Available Libraries - -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). - -Some libraries that are available today include: - -- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library -- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) -- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers -- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address -- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees -- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir -- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/modules_packages_crates/modules.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/modules_packages_crates/modules.md deleted file mode 100644 index 11e60cbf35e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/modules_packages_crates/modules.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: Modules -description: - Learn how to organize your files using modules in Noir, following the same convention as Rust's - module system. Examples included. -keywords: [Noir, Rust, modules, organizing files, sub-modules] ---- - -Noir's module system follows the same convention as the _newer_ version of Rust's module system. - -## Purpose of Modules - -Modules are used to organize files. Without modules all of your code would need to live in a single -file. In Noir, the compiler does not automatically scan all of your files to detect modules. This -must be done explicitly by the developer. - -## Examples - -### Importing a module in the crate root - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::hello_world(); -} -``` - -Filename : `src/foo.nr` - -```rust -fn from_foo() {} -``` - -In the above snippet, the crate root is the `src/main.nr` file. The compiler sees the module -declaration `mod foo` which prompts it to look for a foo.nr file. - -Visually this module hierarchy looks like the following : - -``` -crate - ├── main - │ - └── foo - └── from_foo - -``` - -### Importing a module throughout the tree - -All modules are accessible from the `crate::` namespace. - -``` -crate - ├── bar - ├── foo - └── main - -``` - -In the above snippet, if `bar` would like to use functions in `foo`, it can do so by `use crate::foo::function_name`. - -### Sub-modules - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::from_foo(); -} -``` - -Filename : `src/foo.nr` - -```rust -mod bar; -fn from_foo() {} -``` - -Filename : `src/foo/bar.nr` - -```rust -fn from_bar() {} -``` - -In the above snippet, we have added an extra module to the module tree; `bar`. `bar` is a submodule -of `foo` hence we declare bar in `foo.nr` with `mod bar`. Since `foo` is not the crate root, the -compiler looks for the file associated with the `bar` module in `src/foo/bar.nr` - -Visually the module hierarchy looks as follows: - -``` -crate - ├── main - │ - └── foo - ├── from_foo - └── bar - └── from_bar -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/modules_packages_crates/workspaces.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/modules_packages_crates/workspaces.md deleted file mode 100644 index 8168793fc80..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/modules_packages_crates/workspaces.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -title: Workspaces ---- - -Workspaces are a feature of nargo that allow you to manage multiple related Noir packages in a single repository. A workspace is essentially a group of related projects that share common build output directories and configurations. - -Each Noir project (with it's own Nargo.toml file) can be thought of as a package. Each package is expected to contain exactly one "named circuit", being the "name" defined in Nargo.toml with the program logic defined in `./src/main.nr`. - -For a project with the following structure: - -```tree -├── crates -│ ├── a -│ │ ├── Nargo.toml -│ │ └── Prover.toml -│ │ └── src -│ │ └── main.nr -│ └── b -│ ├── Nargo.toml -│ └── Prover.toml -│ └── src -│ └── main.nr -│ -└── Nargo.toml -``` - -You can define a workspace in Nargo.toml like so: - -```toml -[workspace] -members = ["crates/a", "crates/b"] -default-member = "crates/a" -``` - -`members` indicates which packages are included in the workspace. As such, all member packages of a workspace will be processed when the `--workspace` flag is used with various commands or if a `default-member` is not specified. - -`default-member` indicates which package various commands process by default. - -Libraries can be defined in a workspace. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. - -Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/nargo/01_commands.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/nargo/01_commands.md deleted file mode 100644 index e2b0af522f4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/nargo/01_commands.md +++ /dev/null @@ -1,250 +0,0 @@ ---- -title: Commands -description: - Noir CLI Commands for Noir Prover and Verifier to create, execute, prove and verify programs, - generate Solidity verifier smart contract and compile into JSON file containing ACIR - representation and ABI of circuit. -keywords: - [ - Nargo, - Noir CLI, - Noir Prover, - Noir Verifier, - generate Solidity verifier, - compile JSON file, - ACIR representation, - ABI of circuit, - TypeScript, - ] ---- - -## General options - -| Option | Description | -| -------------------- | -------------------------------------------------- | -| `--show-ssa` | Emit debug information for the intermediate SSA IR | -| `--deny-warnings` | Quit execution when warnings are emitted | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo help [subcommand]` - -Prints the list of available commands or specific information of a subcommand. - -_Arguments_ - -| Argument | Description | -| -------------- | -------------------------------------------- | -| `` | The subcommand whose help message to display | - -## `nargo backend` - -Installs and selects custom backends used to generate and verify proofs. - -### Commands - -| Command | Description | -| ----------- | --------------------------------------------------------- | -| `current` | Prints the name of the currently active backend | -| `ls` | Prints the list of currently installed backends | -| `use` | Select the backend to use | -| `install` | Install a new backend from a URL | -| `uninstall` | Uninstalls a backend | -| `help` | Print this message or the help of the given subcommand(s) | - -### Options - -| Option | Description | -| ------------ | ----------- | -| `-h, --help` | Print help | - -## `nargo check` - -Generate the `Prover.toml` and `Verifier.toml` files for specifying prover and verifier in/output -values of the Noir program respectively. - -### Options - -| Option | Description | -| --------------------- | ------------------------------------- | -| `--package ` | The name of the package to check | -| `--workspace` | Check all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -### `nargo codegen-verifier` - -Generate a Solidity verifier smart contract for the program. - -### Options - -| Option | Description | -| --------------------- | ------------------------------------- | -| `--package ` | The name of the package to codegen | -| `--workspace` | Codegen all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo compile` - -Compile the program into a JSON build artifact file containing the ACIR representation and the ABI -of the circuit. This build artifact can then be used to generate and verify proofs. - -You can also use "build" as an alias for compile (e.g. `nargo build`). - -### Options - -| Option | Description | -| --------------------- | ------------------------------------------------------------ | -| `--include-keys` | Include Proving and Verification keys in the build artifacts | -| `--package ` | The name of the package to compile | -| `--workspace` | Compile all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo new ` - -Creates a new Noir project in a new folder. - -**Arguments** - -| Argument | Description | -| -------- | -------------------------------- | -| `` | The path to save the new project | - -### Options - -| Option | Description | -| --------------- | ----------------------------------------------------- | -| `--name ` | Name of the package [default: package directory name] | -| `--lib` | Use a library template | -| `--bin` | Use a binary template [default] | -| `--contract` | Use a contract template | -| `-h, --help` | Print help | - -## `nargo init` - -Creates a new Noir project in the current directory. - -### Options - -| Option | Description | -| --------------- | ----------------------------------------------------- | -| `--name ` | Name of the package [default: current directory name] | -| `--lib` | Use a library template | -| `--bin` | Use a binary template [default] | -| `--contract` | Use a contract template | -| `-h, --help` | Print help | - -## `nargo execute [WITNESS_NAME]` - -Runs the Noir program and prints its return value. - -**Arguments** - -| Argument | Description | -| ---------------- | ----------------------------------------- | -| `[WITNESS_NAME]` | Write the execution witness to named file | - -### Options - -| Option | Description | -| --------------------------------- | ------------------------------------------------------------------------------------ | -| `-p, --prover-name ` | The name of the toml file which contains the inputs for the prover [default: Prover] | -| `--package ` | The name of the package to execute | -| `--workspace` | Execute all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -_Usage_ - -The inputs to the circuit are read from the `Prover.toml` file generated by `nargo check`, which -must be filled in. - -To save the witness to file, run the command with a value for the `WITNESS_NAME` argument. A -`.tr` file will then be saved in the `./target` folder. - -## `nargo prove` - -Creates a proof for the program. - -### Options - -| Option | Description | -| ------------------------------------- | ---------------------------------------------------------------------------------------- | -| `-p, --prover-name ` | The name of the toml file which contains the inputs for the prover [default: Prover] | -| `-v, --verifier-name ` | The name of the toml file which contains the inputs for the verifier [default: Verifier] | -| `--verify` | Verify proof after proving | -| `--package ` | The name of the package to prove | -| `--workspace` | Prove all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo verify` - -Given a proof and a program, verify whether the proof is valid. - -### Options - -| Option | Description | -| ------------------------------------- | ---------------------------------------------------------------------------------------- | -| `-v, --verifier-name ` | The name of the toml file which contains the inputs for the verifier [default: Verifier] | -| `--package ` | The name of the package to verify | -| `--workspace` | Verify all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo test [TEST_NAME]` - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. To print `println` statements in tests, use the `--show-output` flag. - -Takes an optional `--exact` flag which allows you to select tests based on an exact name. - -See an example on the [testing page](./testing.md). - -### Options - -| Option | Description | -| --------------------- | -------------------------------------- | -| `--show-output` | Display output of `println` statements | -| `--exact` | Only run tests that match exactly | -| `--package ` | The name of the package to test | -| `--workspace` | Test all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo info` - -Prints a table containing the information of the package. - -Currently the table provide - -1. The number of ACIR opcodes -2. The final number gates in the circuit used by a backend - -If the file contains a contract the table will provide the -above information about each function of the contract. - -## `nargo lsp` - -Start a long-running Language Server process that communicates over stdin/stdout. -Usually this command is not run by a user, but instead will be run by a Language Client, such as [vscode-noir](https://github.com/noir-lang/vscode-noir). - -## `nargo fmt` - -Automatically formats your Noir source code based on the default formatting settings. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/nargo/02_testing.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/nargo/02_testing.md deleted file mode 100644 index 5c57ef92705..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/nargo/02_testing.md +++ /dev/null @@ -1,61 +0,0 @@ ---- -title: Testing in Noir -description: Learn how to use Nargo to test your Noir program in a quick and easy way -keywords: [Nargo, testing, Noir, compile, test] ---- - -You can test your Noir programs using Noir circuits. - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. - -For example if you have a program like: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test] -fn test_add() { - assert(add(2,2) == 4); - assert(add(0,1) == 1); - assert(add(1,0) == 1); -} -``` - -Running `nargo test` will test that the `test_add` function can be executed while satisfying all -the constraints which allows you to test that add returns the expected values. Test functions can't -have any arguments currently. - -### Test fail - -You can write tests that are expected to fail by using the decorator `#[test(should_fail)]`. For example: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test(should_fail)] -fn test_add() { - assert(add(2,2) == 5); -} -``` - -You can be more specific and make it fail with a specific reason by using `should_fail_with = "`: - -```rust -fn main(african_swallow_avg_speed : Field) { - assert(african_swallow_avg_speed == 65, "What is the airspeed velocity of an unladen swallow"); -} - -#[test] -fn test_king_arthur() { - main(65); -} - -#[test(should_fail_with = "What is the airspeed velocity of an unladen swallow")] -fn test_bridgekeeper() { - main(32); -} - -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/nargo/03_solidity_verifier.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/nargo/03_solidity_verifier.md deleted file mode 100644 index 9ac60cb0ba7..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/nargo/03_solidity_verifier.md +++ /dev/null @@ -1,129 +0,0 @@ ---- -title: Solidity Verifier -description: - Learn how to run the verifier as a smart contract on the blockchain. Compile a Solidity verifier - contract for your Noir program and deploy it on any EVM blockchain acting as a verifier smart - contract. Read more to find out! -keywords: - [ - solidity verifier, - smart contract, - blockchain, - compiler, - plonk_vk.sol, - EVM blockchain, - verifying Noir programs, - proving backend, - Barretenberg, - ] ---- - -For certain applications, it may be desirable to run the verifier as a smart contract instead of on -a local machine. - -Compile a Solidity verifier contract for your Noir program by running: - -```sh -nargo codegen-verifier -``` - -A new `contract` folder would then be generated in your project directory, containing the Solidity -file `plonk_vk.sol`. It can be deployed on any EVM blockchain acting as a verifier smart contract. - -> **Note:** It is possible to compile verifier contracts of Noir programs for other smart contract -> platforms as long as the proving backend supplies an implementation. -> -> Barretenberg, the default proving backend for Nargo, supports compilation of verifier contracts in -> Solidity only for the time being. - -## Verify - -To verify a proof using the Solidity verifier contract, call the `verify` function with the -following signature: - -```solidity -function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) -``` - -You can see an example of how the `verify` function is called in the example zk voting application [here](https://github.com/noir-lang/noir-examples/blob/33e598c257e2402ea3a6b68dd4c5ad492bce1b0a/foundry-voting/src/zkVote.sol#L35): - -```solidity -function castVote(bytes calldata proof, uint proposalId, uint vote, bytes32 nullifierHash) public returns (bool) { - // ... - bytes32[] memory publicInputs = new bytes32[](4); - publicInputs[0] = merkleRoot; - publicInputs[1] = bytes32(proposalId); - publicInputs[2] = bytes32(vote); - publicInputs[3] = nullifierHash; - require(verifier.verify(proof, publicInputs), "Invalid proof"); -``` - -### Public Inputs - -:::tip - -A circuit doesn't have the concept of a return value. Return values are just syntactic sugar in -Noir. - -Under the hood, the return value is passed as an input to the circuit and is checked at the end of -the circuit program. - -::: - -The verifier contract uses the output (return) value of a Noir program as a public input. So if you -have the following function - -```rust -fn main( - // Public inputs - pubkey_x: pub Field, - pubkey_y: pub Field, - // Private inputs - priv_key: Field, -) -> pub Field -``` - -then `verify` in `plonk_vk.sol` will expect 3 public inputs. Passing two inputs will result in an -error like `Reason: PUBLIC_INPUT_COUNT_INVALID(3, 2)`. - -In this case the 3 inputs to `verify` would be ordered as `[pubkey_x, pubkey_y, return]`. - -#### Struct inputs - -Consider the following program: - -```rust -struct Type1 { - val1: Field, - val2: Field, -} - -struct Nested { - t1: Type1, - is_true: bool, -} - -fn main(x: pub Field, nested: pub Nested, y: pub Field) { - //... -} -``` - -Structs will be flattened so that the array of inputs is 1-dimensional array. The order of these inputs would be flattened to: `[x, nested.t1.val1, nested.t1.val2, nested.is_true, y]` - -## Noir for EVM chains - -You can currently deploy the Solidity verifier contracts to most EVM compatible chains. EVM chains that have been tested and are known to work include: - -- Optimism -- Arbitrum -- Polygon PoS -- Scroll -- Celo - -Other EVM chains should work, but have not been tested directly by our team. If you test any other chains, please open a PR on this page to update the list. See [this doc](https://github.com/noir-lang/noir-starter/tree/main/with-foundry#testing-on-chain) for more info about testing verifier contracts on different EVM chains. - -### Unsupported chains - -Unfortunately not all "EVM" chains are supported. - -**zkSync** and the **Polygon zkEVM** do _not_ currently support proof verification via Solidity verifier contracts. They are missing the bn256 precompile contract that the verifier contract requires. Once these chains support this precompile, they may work. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/nargo/04_language_server.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/nargo/04_language_server.md deleted file mode 100644 index 48c01465f6e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/nargo/04_language_server.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Language Server -description: Learn about the Noir Language Server, how to install the components, and configuration that may be required. -keywords: [Nargo, Language Server, LSP, VSCode, Visual Studio Code] ---- - -This section helps you install and configure the Noir Language Server. - -The Language Server Protocol (LSP) has two components, the [Server](#language-server) and the [Client](#language-client). Below we describe each in the context of Noir. - -## Language Server - -The Server component is provided by the Nargo command line tool that you installed at the beginning of this guide. -As long as Nargo is installed and you've used it to run other commands in this guide, it should be good to go! - -If you'd like to verify that the `nargo lsp` command is available, you can run `nargo --help` and look for `lsp` in the list of commands. If you see it, you're using a version of Noir with LSP support. - -## Language Client - -The Client component is usually an editor plugin that launches the Server. It communicates LSP messages between the editor and the Server. For example, when you save a file, the Client will alert the Server, so it can try to compile the project and report any errors. - -Currently, Noir provides a Language Client for Visual Studio Code via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). - -> **Note:** Noir's Language Server Protocol support currently assumes users' VSCode workspace root to be the same as users' Noir project root (i.e. where Nargo.toml lies). -> -> If LSP features seem to be missing / malfunctioning, make sure you are opening your Noir project directly (instead of as a sub-folder) in your VSCode instance. - -When your language server is running correctly and the VSCode plugin is installed, you should see handy codelens buttons for compilation, measuring circuit size, execution, and tests: - -![Compile and Execute](@site/static/img/codelens_compile_execute.png) -![Run test](@site/static/img/codelens_run_test.png) - -You should also see your tests in the `testing` panel: - -![Testing panel](@site/static/img/codelens_testing_panel.png) - -### Configuration - -- **Noir: Enable LSP** - If checked, the extension will launch the Language Server via `nargo lsp` and communicate with it. -- **Noir: Nargo Flags** - Additional flags may be specified if you require them to be added when the extension calls `nargo lsp`. -- **Noir: Nargo Path** - An absolute path to a Nargo binary with the `lsp` command. This may be useful if Nargo is not within the `PATH` of your editor. -- **Noir > Trace: Server** - Setting this to `"messages"` or `"verbose"` will log LSP messages between the Client and Server. Useful for debugging. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/getting_started/01_tiny_noir_app.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/getting_started/01_tiny_noir_app.md deleted file mode 100644 index 64ba4a2c44a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/getting_started/01_tiny_noir_app.md +++ /dev/null @@ -1,260 +0,0 @@ ---- -title: End-to-end -description: Learn how to setup a new app that uses Noir to generate and verify zero-knowledge SNARK proofs in a typescript or javascript environment -keywords: [how to, guide, javascript, typescript, noir, barretenberg, zero-knowledge, proofs] ---- - -NoirJS works both on the browser and on the server, and works for both ESM and CJS module systems. In this page, we will learn how can we write a simple test and a simple web app to verify the standard Noir example. - -You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). - -## Before we start - -:::note - -Feel free to use whatever versions, just keep in mind that Nargo and the NoirJS packages are meant to be in sync. For example, Nargo 0.18.x matches `noir_js@0.18.x`, etc. - -In this guide, we will be pinned to 0.17.0. - -::: - -Make sure you have Node installed on your machine by opening a terminal and executing `node --version`. If you don't see a version, you should install [node](https://github.com/nvm-sh/nvm). You can also use `yarn` if you prefer that package manager over npm (which comes with node). - -First of all, follow the [Nargo guide](../../getting_started/00_nargo_installation.md) to install nargo version 0.17.0 and create a new project with `nargo new circuit`. Once there, `cd` into the `circuit` folder. You should then be able to compile your circuit into `json` format and see it inside the `target` folder: - -```bash -nargo compile -``` - -Your folder structure should look like: - -```tree -. -└── circuit - ├── Nargo.toml - ├── src - │ └── main.nr - └── target - └── circuit.json -``` - -## Starting a new project - -Go back to the previous folder and start a new project by running run `npm init`. You can configure your project or just leave the defaults, and see a `package.json` appear in your root folder. - -## Installing dependencies - -We'll need two `npm` packages. These packages will provide us the methods we need to run and verify proofs: - -```bash -npm i @noir-lang/backend_barretenberg@^0.17.0 @noir-lang/noir_js@^0.17.0 -``` - -To serve our page, we can use a build tool such as `vite`. Because we're gonna use some `wasm` files, we need to install a plugin as well. Run: - -```bash -npm i --save-dev vite rollup-plugin-copy -``` - -Since we're on the dependency world, we may as well define a nice starting script. Vite makes it easy. Just open `package.json`, find the block "scripts" and add this just below the line with `"test" : "echo......."`: - -```json - "start": "vite --open" -``` - -If you want do build a static website, you can also add some build and preview scripts: - -```json - "build": "vite build", - "preview": "vite preview" -``` - -## Vite plugins - -Vite is great, but support from `wasm` doesn't work out-of-the-box. We're gonna write a quick plugin and use another one. Just copy and paste this into a file named `vite.config.js`. You don't need to understand it, just trust me bro. - -```js -import { defineConfig } from 'vite'; -import copy from 'rollup-plugin-copy'; -import fs from 'fs'; -import path from 'path'; - -const wasmContentTypePlugin = { - name: 'wasm-content-type-plugin', - configureServer(server) { - server.middlewares.use(async (req, res, next) => { - if (req.url.endsWith('.wasm')) { - res.setHeader('Content-Type', 'application/wasm'); - const newPath = req.url.replace('deps', 'dist'); - const targetPath = path.join(__dirname, newPath); - const wasmContent = fs.readFileSync(targetPath); - return res.end(wasmContent); - } - next(); - }); - }, -}; - -export default defineConfig(({ command }) => { - if (command === 'serve') { - return { - plugins: [ - copy({ - targets: [{ src: 'node_modules/**/*.wasm', dest: 'node_modules/.vite/dist' }], - copySync: true, - hook: 'buildStart', - }), - command === 'serve' ? wasmContentTypePlugin : [], - ], - }; - } - - return {}; -}); -``` - -## HTML - -Here's the simplest HTML with some terrible UI. Create a file called `index.html` and paste this: - -```html - - - - - - -

Very basic Noir app

-
-

Logs

-

Proof

-
- - -``` - -## Some good old vanilla Javascript - -Create a new file `app.js`, which is where our javascript code will live. Let's start with this code inside: - -```js -document.addEventListener('DOMContentLoaded', async () => { - // here's where the magic happens -}); - -function display(container, msg) { - const c = document.getElementById(container); - const p = document.createElement('p'); - p.textContent = msg; - c.appendChild(p); -} -``` - -We can manipulate our website with this little function, so we can see our website working. - -## Adding Noir - -If you come from the previous page, your folder structure should look like this: - -```tree -├── app.js -├── circuit -│ ├── Nargo.toml -│ ├── src -│ │ └── main.nr -│ └── target -│ └── circuit.json -├── index.html -├── package.json -└── vite.config.js -``` - -You'll see other files and folders showing up (like `package-lock.json`, `yarn.lock`, `node_modules`) but you shouldn't have to care about those. - -## Importing our dependencies - -We're starting with the good stuff now. At the top of the new javascript file, import the packages: - -```ts -import { BarretenbergBackend } from '@noir-lang/backend_barretenberg'; -import { Noir } from '@noir-lang/noir_js'; -``` - -We also need to import the `circuit` JSON file we created. If you have the suggested folder structure, you can add this line: - -```ts -import circuit from './circuit/target/circuit.json'; -``` - -## Write code - -:::note - -We're gonna be adding code inside the `document.addEventListener...etc` block: - -```js -// forget stuff here -document.addEventListener('DOMContentLoaded', async () => { - // here's where the magic happens -}); -// forget stuff here -``` - -::: - -Our dependencies exported two classes: `BarretenbergBackend` and `Noir`. Let's `init` them and add some logs, just to flex: - -```ts -const backend = new BarretenbergBackend(circuit); -const noir = new Noir(circuit, backend); -``` - -## Proving - -Now we're ready to prove stuff! Let's feed some inputs to our circuit and calculate the proof: - -```js -const input = { x: 1, y: 2 }; -display('logs', 'Generating proof... ⌛'); -const proof = await noir.generateFinalProof(input); -display('logs', 'Generating proof... ✅'); -display('results', proof.proof); -``` - -You're probably eager to see stuff happening, so go and run your app now! - -From your terminal, run `npm start` (or `yarn start`). If it doesn't open a browser for you, just visit `localhost:5173`. On a modern laptop, proof will generate in less than 100ms, and you'll see this: - -![Getting Started 0](@site/static/img/noir_getting_started_1.png) - -If you're human, you shouldn't be able to understand anything on the "proof" box. That's OK. We like you, human. - -In any case, this means your proof was generated! But you shouldn't trust me just yet. Add these lines to see it being verified: - -```js -display('logs', 'Verifying proof... ⌛'); -const verification = await noir.verifyFinalProof(proof); -if (verification) display('logs', 'Verifying proof... ✅'); -``` - -By saving, your app will refresh and here's our complete Tiny Noir App! - -You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). - -## Further Reading - -You can see how noirjs is used in a full stack Next.js hardhat application in the [noir-starter repo here](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat). The example shows how to calculate a proof in the browser and verify it with a deployed Solidity verifier contract from noirjs. - -You should also check out the more advanced examples in the [noir-examples repo](https://github.com/noir-lang/noir-examples), where you'll find reference usage for some cool apps. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/noir_js.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/noir_js.md deleted file mode 100644 index f895b22eaf8..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/noir_js.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: NoirJS -description: Interact with Noir in Typescript or Javascript -keywords: [Noir project, javascript, typescript, node.js, browser, react] ---- - -NoirJS is a TypeScript library that make it easy to use Noir on your dapp, webapp, Node.js server, website, etc. - -A typical workflow would be composed of two major elements: - -- NoirJS -- Proving backend of choice's JavaScript package - - - -To install NoirJS, install Node.js if you have not already and run this in your JavaScript project: - -```bash -npm i @noir-lang/noir_js -``` - -## Proving backend - -Since Noir is backend agnostic, you can instantiate NoirJS without any backend (i.e. to execute a function). But for proving, you would have to instantiate NoirJS with any of the supported backends through their own `js` interface. - -### Barretenberg - -Aztec Labs maintains the `barretenberg` proving backend, which you can instantiate and make use of alongside NoirJS. It is also the default proving backend installed and used with Nargo, the Noir CLI tool. - -To install its JavaScript library, run this in your project: - -```bash -npm i @noir-lang/backend_barretenberg -``` - -For more details on how to instantiate and use the libraries, refer to the [Full Noir App Guide](./getting_started/01_tiny_noir_app.md) and [Reference](./reference/noir_js/classes/Noir.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/classes/BarretenbergBackend.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/classes/BarretenbergBackend.md deleted file mode 100644 index 5cbe9421b92..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/classes/BarretenbergBackend.md +++ /dev/null @@ -1,185 +0,0 @@ -# BarretenbergBackend - -## Implements - -- [`Backend`](../interfaces/Backend.md) - -## Constructors - -### new BarretenbergBackend(acirCircuit, options) - -```ts -new BarretenbergBackend(acirCircuit, options): BarretenbergBackend -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `acirCircuit` | [`CompiledCircuit`](../type-aliases/CompiledCircuit.md) | -| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | - -#### Returns - -[`BarretenbergBackend`](BarretenbergBackend.md) - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`destroy`](../interfaces/Backend.md#destroy) - -#### Description - -Destroys the backend - -*** - -### generateFinalProof() - -```ts -generateFinalProof(decompressedWitness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `decompressedWitness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`generateFinalProof`](../interfaces/Backend.md#generatefinalproof) - -#### Description - -Generates a final proof (not meant to be verified in another circuit) - -*** - -### generateIntermediateProof() - -```ts -generateIntermediateProof(witness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `witness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`generateIntermediateProof`](../interfaces/Backend.md#generateintermediateproof) - -#### Example - -```typescript -const intermediateProof = await backend.generateIntermediateProof(witness); -``` - -*** - -### generateIntermediateProofArtifacts() - -```ts -generateIntermediateProofArtifacts(proofData, numOfPublicInputs): Promise -``` - -#### Parameters - -| Parameter | Type | Default value | -| :------ | :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | `undefined` | -| `numOfPublicInputs` | `number` | `0` | - -#### Returns - -`Promise`\<`object`\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`generateIntermediateProofArtifacts`](../interfaces/Backend.md#generateintermediateproofartifacts) - -#### Example - -```typescript -const artifacts = await backend.generateIntermediateProofArtifacts(proof, numOfPublicInputs); -``` - -*** - -### verifyFinalProof() - -```ts -verifyFinalProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`verifyFinalProof`](../interfaces/Backend.md#verifyfinalproof) - -#### Description - -Verifies a final proof - -*** - -### verifyIntermediateProof() - -```ts -verifyIntermediateProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`verifyIntermediateProof`](../interfaces/Backend.md#verifyintermediateproof) - -#### Example - -```typescript -const isValidIntermediate = await backend.verifyIntermediateProof(proof); -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/index.md deleted file mode 100644 index 3680ba3ca77..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/index.md +++ /dev/null @@ -1,27 +0,0 @@ -# Backend Barretenberg - -## Exports - -### Classes - -| Class | Description | -| :------ | :------ | -| [BarretenbergBackend](classes/BarretenbergBackend.md) | - | - -### Interfaces - -| Interface | Description | -| :------ | :------ | -| [Backend](interfaces/Backend.md) | - | - -### Type Aliases - -| Type alias | Description | -| :------ | :------ | -| [BackendOptions](type-aliases/BackendOptions.md) | - | -| [CompiledCircuit](type-aliases/CompiledCircuit.md) | - | -| [ProofData](type-aliases/ProofData.md) | - | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/interfaces/Backend.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/interfaces/Backend.md deleted file mode 100644 index 3eb9645c8d2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/interfaces/Backend.md +++ /dev/null @@ -1,132 +0,0 @@ -# Backend - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Description - -Destroys the backend - -*** - -### generateFinalProof() - -```ts -generateFinalProof(decompressedWitness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `decompressedWitness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Description - -Generates a final proof (not meant to be verified in another circuit) - -*** - -### generateIntermediateProof() - -```ts -generateIntermediateProof(decompressedWitness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `decompressedWitness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Description - -Generates an intermediate proof (meant to be verified in another circuit) - -*** - -### generateIntermediateProofArtifacts() - -```ts -generateIntermediateProofArtifacts(proofData, numOfPublicInputs): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | -| `numOfPublicInputs` | `number` | - -#### Returns - -`Promise`\<`object`\> - -#### Description - -Retrieves the artifacts from a proof in the Field format - -*** - -### verifyFinalProof() - -```ts -verifyFinalProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Verifies a final proof - -*** - -### verifyIntermediateProof() - -```ts -verifyIntermediateProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Verifies an intermediate proof - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/type-aliases/BackendOptions.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/type-aliases/BackendOptions.md deleted file mode 100644 index 266ade75d17..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/type-aliases/BackendOptions.md +++ /dev/null @@ -1,19 +0,0 @@ -# BackendOptions - -```ts -type BackendOptions: object; -``` - -## Description - -An options object, currently only used to specify the number of threads to use. - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `threads` | `number` | **Description**

Number of threads | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit.md deleted file mode 100644 index 34e0dd04205..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit.md +++ /dev/null @@ -1,20 +0,0 @@ -# CompiledCircuit - -```ts -type CompiledCircuit: object; -``` - -## Description - -The representation of a compiled circuit - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `abi` | `Abi` | **Description**

ABI representation of the circuit | -| `bytecode` | `string` | **Description**

The bytecode of the circuit | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/type-aliases/ProofData.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/type-aliases/ProofData.md deleted file mode 100644 index 4aeff73d3e4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/type-aliases/ProofData.md +++ /dev/null @@ -1,20 +0,0 @@ -# ProofData - -```ts -type ProofData: object; -``` - -## Description - -The representation of a proof - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `proof` | `Uint8Array` | **Description**

An byte array representing the proof | -| `publicInputs` | `Uint8Array`[] | **Description**

Public inputs of a proof | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs deleted file mode 100644 index 04e662c845f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"noir_js/reference/backend_barretenberg/classes/BarretenbergBackend","label":"BarretenbergBackend"}]},{"type":"category","label":"Interfaces","items":[{"type":"doc","id":"noir_js/reference/backend_barretenberg/interfaces/Backend","label":"Backend"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"noir_js/reference/backend_barretenberg/type-aliases/BackendOptions","label":"BackendOptions"},{"type":"doc","id":"noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit","label":"CompiledCircuit"},{"type":"doc","id":"noir_js/reference/backend_barretenberg/type-aliases/ProofData","label":"ProofData"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/.nojekyll deleted file mode 100644 index e2ac6616add..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/classes/Noir.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/classes/Noir.md deleted file mode 100644 index 1d7b54a9dca..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/classes/Noir.md +++ /dev/null @@ -1,131 +0,0 @@ -# Noir - -## Constructors - -### new Noir(circuit, backend) - -```ts -new Noir(circuit, backend?): Noir -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `circuit` | [`CompiledCircuit`](../type-aliases/CompiledCircuit.md) | -| `backend`? | `Backend` | - -#### Returns - -[`Noir`](Noir.md) - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Description - -Destroys the underlying backend instance. - -#### Example - -```typescript -await noir.destroy(); -``` - -*** - -### execute() - -```ts -execute(inputs, foreignCallHandler?): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `inputs` | `InputMap` | -| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | - -#### Returns - -`Promise`\<`object`\> - -#### Description - -Allows to execute a circuit to get its witness and return value. - -#### Example - -```typescript -async execute(inputs) -``` - -*** - -### generateFinalProof() - -```ts -generateFinalProof(inputs): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `inputs` | `InputMap` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Description - -Generates a witness and a proof given an object as input. - -#### Example - -```typescript -async generateFinalProof(input) -``` - -*** - -### verifyFinalProof() - -```ts -verifyFinalProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Instantiates the verification key and verifies a proof. - -#### Example - -```typescript -async verifyFinalProof(proof) -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/functions/and.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/functions/and.md deleted file mode 100644 index c783283e396..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/functions/and.md +++ /dev/null @@ -1,22 +0,0 @@ -# and() - -```ts -and(lhs, rhs): string -``` - -Performs a bitwise AND operation between `lhs` and `rhs` - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `lhs` | `string` | | -| `rhs` | `string` | | - -## Returns - -`string` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/functions/blake2s256.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/functions/blake2s256.md deleted file mode 100644 index 7882d0da8d5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/functions/blake2s256.md +++ /dev/null @@ -1,21 +0,0 @@ -# blake2s256() - -```ts -blake2s256(inputs): Uint8Array -``` - -Calculates the Blake2s256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify.md deleted file mode 100644 index 0ba5783f0d5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify.md +++ /dev/null @@ -1,29 +0,0 @@ -# ecdsa\_secp256k1\_verify() - -```ts -ecdsa_secp256k1_verify( - hashed_msg, - public_key_x_bytes, - public_key_y_bytes, - signature): boolean -``` - -Calculates the Blake2s256 hash of the input bytes and represents these as a single field element. -Verifies a ECDSA signature over the secp256k1 curve. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `hashed_msg` | `Uint8Array` | | -| `public_key_x_bytes` | `Uint8Array` | | -| `public_key_y_bytes` | `Uint8Array` | | -| `signature` | `Uint8Array` | | - -## Returns - -`boolean` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify.md deleted file mode 100644 index 0b20ff68957..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify.md +++ /dev/null @@ -1,28 +0,0 @@ -# ecdsa\_secp256r1\_verify() - -```ts -ecdsa_secp256r1_verify( - hashed_msg, - public_key_x_bytes, - public_key_y_bytes, - signature): boolean -``` - -Verifies a ECDSA signature over the secp256r1 curve. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `hashed_msg` | `Uint8Array` | | -| `public_key_x_bytes` | `Uint8Array` | | -| `public_key_y_bytes` | `Uint8Array` | | -| `signature` | `Uint8Array` | | - -## Returns - -`boolean` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/functions/keccak256.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/functions/keccak256.md deleted file mode 100644 index d10f155ce86..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/functions/keccak256.md +++ /dev/null @@ -1,21 +0,0 @@ -# keccak256() - -```ts -keccak256(inputs): Uint8Array -``` - -Calculates the Keccak256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/functions/sha256.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/functions/sha256.md deleted file mode 100644 index 6ba4ecac022..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/functions/sha256.md +++ /dev/null @@ -1,21 +0,0 @@ -# sha256() - -```ts -sha256(inputs): Uint8Array -``` - -Calculates the SHA256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/functions/xor.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/functions/xor.md deleted file mode 100644 index 8d762b895d3..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/functions/xor.md +++ /dev/null @@ -1,22 +0,0 @@ -# xor() - -```ts -xor(lhs, rhs): string -``` - -Performs a bitwise XOR operation between `lhs` and `rhs` - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `lhs` | `string` | | -| `rhs` | `string` | | - -## Returns - -`string` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/index.md deleted file mode 100644 index 58902c17b99..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/index.md +++ /dev/null @@ -1,36 +0,0 @@ -# Noir JS - -## Exports - -### Classes - -| Class | Description | -| :------ | :------ | -| [Noir](classes/Noir.md) | - | - -### Type Aliases - -| Type alias | Description | -| :------ | :------ | -| [CompiledCircuit](type-aliases/CompiledCircuit.md) | - | -| [ForeignCallHandler](type-aliases/ForeignCallHandler.md) | A callback which performs an foreign call and returns the response. | -| [ForeignCallInput](type-aliases/ForeignCallInput.md) | - | -| [ForeignCallOutput](type-aliases/ForeignCallOutput.md) | - | -| [ProofData](type-aliases/ProofData.md) | - | -| [WitnessMap](type-aliases/WitnessMap.md) | - | - -### Functions - -| Function | Description | -| :------ | :------ | -| [and](functions/and.md) | Performs a bitwise AND operation between `lhs` and `rhs` | -| [blake2s256](functions/blake2s256.md) | Calculates the Blake2s256 hash of the input bytes | -| [ecdsa\_secp256k1\_verify](functions/ecdsa_secp256k1_verify.md) | Calculates the Blake2s256 hash of the input bytes and represents these as a single field element. | -| [ecdsa\_secp256r1\_verify](functions/ecdsa_secp256r1_verify.md) | Verifies a ECDSA signature over the secp256r1 curve. | -| [keccak256](functions/keccak256.md) | Calculates the Keccak256 hash of the input bytes | -| [sha256](functions/sha256.md) | Calculates the SHA256 hash of the input bytes | -| [xor](functions/xor.md) | Performs a bitwise XOR operation between `lhs` and `rhs` | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/type-aliases/CompiledCircuit.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/type-aliases/CompiledCircuit.md deleted file mode 100644 index 34e0dd04205..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/type-aliases/CompiledCircuit.md +++ /dev/null @@ -1,20 +0,0 @@ -# CompiledCircuit - -```ts -type CompiledCircuit: object; -``` - -## Description - -The representation of a compiled circuit - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `abi` | `Abi` | **Description**

ABI representation of the circuit | -| `bytecode` | `string` | **Description**

The bytecode of the circuit | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/type-aliases/ForeignCallHandler.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/type-aliases/ForeignCallHandler.md deleted file mode 100644 index 812b8b16481..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/type-aliases/ForeignCallHandler.md +++ /dev/null @@ -1,24 +0,0 @@ -# ForeignCallHandler - -```ts -type ForeignCallHandler: (name, inputs) => Promise; -``` - -A callback which performs an foreign call and returns the response. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `name` | `string` | The identifier for the type of foreign call being performed. | -| `inputs` | [`ForeignCallInput`](ForeignCallInput.md)[] | An array of hex encoded inputs to the foreign call. | - -## Returns - -`Promise`\<[`ForeignCallOutput`](ForeignCallOutput.md)[]\> - -outputs - An array of hex encoded outputs containing the results of the foreign call. - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/type-aliases/ForeignCallInput.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/type-aliases/ForeignCallInput.md deleted file mode 100644 index dd95809186a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/type-aliases/ForeignCallInput.md +++ /dev/null @@ -1,9 +0,0 @@ -# ForeignCallInput - -```ts -type ForeignCallInput: string[]; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/type-aliases/ForeignCallOutput.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/type-aliases/ForeignCallOutput.md deleted file mode 100644 index b71fb78a946..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/type-aliases/ForeignCallOutput.md +++ /dev/null @@ -1,9 +0,0 @@ -# ForeignCallOutput - -```ts -type ForeignCallOutput: string | string[]; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/type-aliases/ProofData.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/type-aliases/ProofData.md deleted file mode 100644 index 4aeff73d3e4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/type-aliases/ProofData.md +++ /dev/null @@ -1,20 +0,0 @@ -# ProofData - -```ts -type ProofData: object; -``` - -## Description - -The representation of a proof - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `proof` | `Uint8Array` | **Description**

An byte array representing the proof | -| `publicInputs` | `Uint8Array`[] | **Description**

Public inputs of a proof | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/type-aliases/WitnessMap.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/type-aliases/WitnessMap.md deleted file mode 100644 index 258c46f9d0c..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/type-aliases/WitnessMap.md +++ /dev/null @@ -1,9 +0,0 @@ -# WitnessMap - -```ts -type WitnessMap: Map; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/typedoc-sidebar.cjs deleted file mode 100644 index c18318850d0..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"noir_js/reference/noir_js/classes/Noir","label":"Noir"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/CompiledCircuit","label":"CompiledCircuit"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/ForeignCallHandler","label":"ForeignCallHandler"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/ForeignCallInput","label":"ForeignCallInput"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/ForeignCallOutput","label":"ForeignCallOutput"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/ProofData","label":"ProofData"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/WitnessMap","label":"WitnessMap"}]},{"type":"category","label":"Functions","items":[{"type":"doc","id":"noir_js/reference/noir_js/functions/and","label":"and"},{"type":"doc","id":"noir_js/reference/noir_js/functions/blake2s256","label":"blake2s256"},{"type":"doc","id":"noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify","label":"ecdsa_secp256k1_verify"},{"type":"doc","id":"noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify","label":"ecdsa_secp256r1_verify"},{"type":"doc","id":"noir_js/reference/noir_js/functions/keccak256","label":"keccak256"},{"type":"doc","id":"noir_js/reference/noir_js/functions/sha256","label":"sha256"},{"type":"doc","id":"noir_js/reference/noir_js/functions/xor","label":"xor"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/black_box_fns.md deleted file mode 100644 index 985bb7c879d..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/black_box_fns.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: Black Box Functions -description: Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. -keywords: [noir, black box functions] ---- - -Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. This makes certain zk-snark unfriendly computations cheaper than if they were implemented in Noir. - -:::warning - -It is likely that not all backends will support a particular black box function. - -::: - -Because it is not guaranteed that all backends will support black box functions, it is possible that certain Noir programs won't compile against a particular backend if they use an unsupported black box function. It is possible to fallback to less efficient implementations written in Noir/ACIR in some cases. - -Black box functions are specified with the `#[foreign(black_box_fn)]` attribute. For example, the SHA256 function in the Noir [source code](https://github.com/noir-lang/noir/blob/v0.5.1/noir_stdlib/src/hash.nr) looks like: - -```rust -#[foreign(sha256)] -fn sha256(_input : [u8; N]) -> [u8; 32] {} -``` - -## Function list - -Here is a list of the current black box functions that are supported by UltraPlonk: - -- AES -- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) -- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) -- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash) -- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment) -- [HashToField128Security](./cryptographic_primitives/hashes.mdx#hash_to_field) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx) -- [Compute merkle root](./merkle_trees.md#compute_merkle_root) -- AND -- XOR -- RANGE -- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion.md) - -Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. - -You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/noir/blob/master/acvm-repo/acir/src/circuit/black_box_functions.rs). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives.md deleted file mode 100644 index 2df4f929474..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Cryptographic primitives in Noir -description: - Learn about the cryptographic primitives ready to use for any Noir project -keywords: - [ - cryptographic primitives, - Noir project, - ] ---- - -The Noir team is progressively adding new cryptographic primitives to the standard library. Reach out for news or if you would be interested in adding more of these calculations in Noir. - -Some methods are available thanks to the Aztec backend, not being performed using Noir. When using other backends, these methods may or may not be supplied. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives/00_hashes.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives/00_hashes.mdx deleted file mode 100644 index 76745196681..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives/00_hashes.mdx +++ /dev/null @@ -1,167 +0,0 @@ ---- -title: Hash methods -description: - Learn about the cryptographic primitives ready to use for any Noir project, including sha256, - blake2s, pedersen, mimc_bn254 and mimc -keywords: - [cryptographic primitives, Noir project, sha256, blake2s, pedersen, mimc_bn254, mimc, hash] ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## sha256 - -Given an array of bytes, returns the resulting sha256 hash. - -```rust -fn sha256(_input : [u8]) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::sha256(x); -} -``` - - - -## blake2s - -Given an array of bytes, returns an array with the Blake2 hash - -```rust -fn blake2s(_input : [u8]) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::blake2s(x); -} -``` - - - -## pedersen_hash - -Given an array of Fields, returns the Pedersen hash. - -```rust -fn pedersen_hash(_input : [Field]) -> Field -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::pedersen_hash(x); -} -``` - - - - - -## pedersen_commitment - -Given an array of Fields, returns the Pedersen commitment. - -```rust -fn pedersen_commitment(_input : [Field]) -> [Field; 2] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let commitment = std::hash::pedersen_commitment(x); -} -``` - - - -## keccak256 - -Given an array of bytes (`u8`), returns the resulting keccak hash as an array of 32 bytes -(`[u8; 32]`). Specify a message_size to hash only the first `message_size` bytes -of the input. - -```rust -fn keccak256(_input : [u8; N], _message_size: u32) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let message_size = 4; - let hash = std::hash::keccak256(x, message_size); -} -``` - - - -## poseidon - -Given an array of Fields, returns a new Field with the Poseidon Hash. Mind that you need to specify -how many inputs are there to your Poseidon function. - -```rust -// example for hash_1, hash_2 accepts an array of length 2, etc -fn hash_1(input: [Field; 1]) -> Field -``` - -example: - -```rust -fn main() -{ - let hash1 = std::hash::poseidon::bn254::hash_2([1, 2]); - assert(hash1 == 0x115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189a); -} -``` - -## mimc_bn254 and mimc - -`mimc_bn254` is `mimc`, but with hardcoded parameters for the BN254 curve. You can use it by -providing an array of Fields, and it returns a Field with the hash. You can use the `mimc` method if -you're willing to input your own constants: - -```rust -fn mimc(x: Field, k: Field, constants: [Field; N], exp : Field) -> Field -``` - -otherwise, use the `mimc_bn254` method: - -```rust -fn mimc_bn254(array: [Field; N]) -> Field -``` - -example: - -```rust - -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::mimc::mimc_bn254(x); -} -``` - -## hash_to_field - -```rust -fn hash_to_field(_input : [Field; N]) -> Field {} -``` - -Calculates the `blake2s` hash of the inputs and returns the hash modulo the field modulus to return -a value which can be represented as a `Field`. - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives/01_scalar.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives/01_scalar.mdx deleted file mode 100644 index c7eed820a80..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives/01_scalar.mdx +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: Scalar multiplication -description: See how you can perform scalar multiplications over a fixed base in Noir -keywords: [cryptographic primitives, Noir project, scalar multiplication] ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## scalar_mul::fixed_base_embedded_curve - -Performs scalar multiplication over the embedded curve whose coordinates are defined by the -configured noir field. For the BN254 scalar field, this is BabyJubJub or Grumpkin. - -```rust -fn fixed_base_embedded_curve(_input : Field) -> [Field; 2] -``` - -example - -```rust -fn main(x : Field) { - let scal = std::scalar_mul::fixed_base_embedded_curve(x); - std::println(scal); -} -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives/02_schnorr.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives/02_schnorr.mdx deleted file mode 100644 index c184ce28120..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives/02_schnorr.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: Schnorr Signatures -description: Learn how you can verify Schnorr signatures using Noir -keywords: [cryptographic primitives, Noir project, schnorr, signatures] ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## schnorr::verify_signature - -Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin). - -```rust -fn verify_signature(_public_key_x: Field, _public_key_y: Field, _signature: [u8; 64], _message: [u8]) -> bool -``` - -where `_signature` can be generated like so using the npm package -[@noir-lang/barretenberg](https://www.npmjs.com/package/@noir-lang/barretenberg) - -```js -const { BarretenbergWasm } = require('@noir-lang/barretenberg/dest/wasm'); -const { Schnorr } = require('@noir-lang/barretenberg/dest/crypto/schnorr'); - -... - -const barretenberg = await BarretenbergWasm.new(); -const schnorr = new Schnorr(barretenberg); -const pubKey = schnorr.computePublicKey(privateKey); -const message = ... -const signature = Array.from( - schnorr.constructSignature(hash, privateKey).toBuffer() -); - -... -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx deleted file mode 100644 index 72bce984821..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: ECDSA Signature Verification -description: Learn about the cryptographic primitives regarding ECDSA over the secp256k1 and secp256r1 curves -keywords: [cryptographic primitives, Noir project, ecdsa, secp256k1, secp256r1, signatures] ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -Noir supports ECDSA signatures verification over the secp256k1 and secp256r1 curves. - -## ecdsa_secp256k1::verify_signature - -Verifier for ECDSA Secp256k1 signatures - -```rust -fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message: [u8]) -> bool -``` - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - -## ecdsa_secp256r1::verify_signature - -Verifier for ECDSA Secp256r1 signatures - -```rust -fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message: [u8]) -> bool -``` - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives/04_ec_primitives.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives/04_ec_primitives.md deleted file mode 100644 index a493d52a083..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives/04_ec_primitives.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -title: Elliptic Curve Primitives -keywords: [cryptographic primitives, Noir project] ---- - -Data structures and methods on them that allow you to carry out computations involving elliptic -curves over the (mathematical) field corresponding to `Field`. For the field currently at our -disposal, applications would involve a curve embedded in BN254, e.g. the -[Baby Jubjub curve](https://eips.ethereum.org/EIPS/eip-2494). - -## Data structures - -### Elliptic curve configurations - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Curve`), i.e. the specific elliptic -curve you want to use, which would be specified using any one of the methods -`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::new` which take the coefficients in the -defining equation together with a generator point as parameters. You can find more detail in the -comments in -[`noir_stdlib/src/ec.nr`](https://github.com/noir-lang/noir/blob/v0.19.1/noir_stdlib/src/ec.nr), but -the gist of it is that the elliptic curves of interest are usually expressed in one of the standard -forms implemented here (Twisted Edwards, Montgomery and Short Weierstraß), and in addition to that, -you could choose to use `affine` coordinates (Cartesian coordinates - the usual (x,y) - possibly -together with a point at infinity) or `curvegroup` coordinates (some form of projective coordinates -requiring more coordinates but allowing for more efficient implementations of elliptic curve -operations). Conversions between all of these forms are provided, and under the hood these -conversions are done whenever an operation is more efficient in a different representation (or a -mixed coordinate representation is employed). - -### Points - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Point`), i.e. points lying on the -elliptic curve. For a curve configuration `c` and a point `p`, it may be checked that `p` -does indeed lie on `c` by calling `c.contains(p1)`. - -## Methods - -(given a choice of curve representation, e.g. use `std::ec::tecurve::affine::Curve` and use -`std::ec::tecurve::affine::Point`) - -- The **zero element** is given by `Point::zero()`, and we can verify whether a point `p: Point` is - zero by calling `p.is_zero()`. -- **Equality**: Points `p1: Point` and `p2: Point` may be checked for equality by calling - `p1.eq(p2)`. -- **Addition**: For `c: Curve` and points `p1: Point` and `p2: Point` on the curve, adding these two - points is accomplished by calling `c.add(p1,p2)`. -- **Negation**: For a point `p: Point`, `p.negate()` is its negation. -- **Subtraction**: For `c` and `p1`, `p2` as above, subtracting `p2` from `p1` is accomplished by - calling `c.subtract(p1,p2)`. -- **Scalar multiplication**: For `c` as above, `p: Point` a point on the curve and `n: Field`, - scalar multiplication is given by `c.mul(n,p)`. If instead `n :: [u1; N]`, i.e. `n` is a bit - array, the `bit_mul` method may be used instead: `c.bit_mul(n,p)` -- **Multi-scalar multiplication**: For `c` as above and arrays `n: [Field; N]` and `p: [Point; N]`, - multi-scalar multiplication is given by `c.msm(n,p)`. -- **Coordinate representation conversions**: The `into_group` method converts a point or curve - configuration in the affine representation to one in the CurveGroup representation, and - `into_affine` goes in the other direction. -- **Curve representation conversions**: `tecurve` and `montcurve` curves and points are equivalent - and may be converted between one another by calling `into_montcurve` or `into_tecurve` on their - configurations or points. `swcurve` is more general and a curve c of one of the other two types - may be converted to this representation by calling `c.into_swcurve()`, whereas a point `p` lying - on the curve given by `c` may be mapped to its corresponding `swcurve` point by calling - `c.map_into_swcurve(p)`. -- **Map-to-curve methods**: The Elligator 2 method of mapping a field element `n: Field` into a - `tecurve` or `montcurve` with configuration `c` may be called as `c.elligator2_map(n)`. For all of - the curve configurations, the SWU map-to-curve method may be called as `c.swu_map(z,n)`, where - `z: Field` depends on `Field` and `c` and must be chosen by the user (the conditions it needs to - satisfy are specified in the comments - [here](https://github.com/noir-lang/noir/blob/v0.19.1/noir_stdlib/src/ec.nr). - -## Examples - -The -[ec_baby_jubjub test](https://github.com/noir-lang/noir/blob/master/test_programs/compile_success_empty/ec_baby_jubjub/src/main.nr) -illustrates all of the above primitives on various forms of the Baby Jubjub curve. A couple of more -interesting examples in Noir would be: - -Public-key cryptography: Given an elliptic curve and a 'base point' on it, determine the public key -from the private key. This is a matter of using scalar multiplication. In the case of Baby Jubjub, -for example, this code would do: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; - -fn bjj_pub_key(priv_key: Field) -> Point -{ - - let bjj = Curve::new(168700, 168696, G::new(995203441582195749578291179787384436505546430278305826713579947235728471134,5472060717959818805561601436314318772137091100104008585924551046643952123905)); - - let base_pt = Point::new(5299619240641551281634865583518297030282874472190772894086521144482721001553, 16950150798460657717958625567821834550301663161624707787222815936182638968203); - - bjj.mul(priv_key,base_pt) -} -``` - -This would come in handy in a Merkle proof. - -- EdDSA signature verification: This is a matter of combining these primitives with a suitable hash - function. See - [feat(stdlib): EdDSA sig verification noir#1136](https://github.com/noir-lang/noir/pull/1136) for - the case of Baby Jubjub and the Poseidon hash function. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives/05_eddsa.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives/05_eddsa.mdx deleted file mode 100644 index 9a5beb55ee9..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives/05_eddsa.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: EdDSA Verification -description: Learn about the cryptographic primitives regarding EdDSA -keywords: [cryptographic primitives, Noir project, eddsa, signatures] ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## eddsa::eddsa_poseidon_verify - -Verifier for EdDSA signatures - -```rust -fn eddsa_poseidon_verify(public_key_x : Field, public_key_y : Field, signature_s: Field, signature_r8_x: Field, signature_r8_y: Field, message: Field) -> bool -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/logging.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/logging.md deleted file mode 100644 index 4ba0fe0e656..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/logging.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -title: Logging -description: - Learn how to use the println statement for debugging in Noir with this tutorial. Understand the - basics of logging in Noir and how to implement it in your code. -keywords: - [ - noir logging, - println statement, - debugging in noir, - noir std library, - logging tutorial, - basic logging in noir, - noir logging implementation, - noir debugging techniques, - rust, - ] ---- - -The standard library provides a familiar `println` statement you can use. Despite being a limited -implementation of rust's `println!` macro, this construct can be useful for debugging. - -You can print the output of println statements in your Noir code by using the `nargo execute` command or the `--show-output` flag when using `nargo test` (provided there are println statements in your tests). - -It is recommended to use `nargo execute` if you want to debug failing constraints with `println` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). `println` will not work for failed constraints caught at compile time. - -The `println` statement is unconstrained, so it works for outputting integers, fields, strings, and even structs or expressions. For example: - -```rust -use dep::std; - -struct Person { - age : Field, - height : Field, -} - -fn main(age : Field, height : Field) { - let person = Person { age : age, height : height }; - std::println(person); - std::println(age + height); - std::println("Hello world!"); -} - -``` - -You can print multiple different types in the same statement and string as well as a new "fmtstr" type. A `fmtstr` can be specified in the same way as a normal string it just should be prepended with an "f" character: - -```rust - let fmt_str = f"i: {i}, j: {j}"; - std::println(fmt_str); - - let s = myStruct { y: x, x: y }; - std::println(s); - - std::println(f"i: {i}, s: {s}"); - - std::println(x); - std::println([x, y]); - - let foo = fooStruct { my_struct: s, foo: 15 }; - std::println(f"s: {s}, foo: {foo}"); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/merkle_trees.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/merkle_trees.md deleted file mode 100644 index dc383a1426b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/merkle_trees.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: Merkle Trees -description: Learn about Merkle Trees in Noir with this tutorial. Explore the basics of computing a merkle root using a proof, with examples. -keywords: - [ - Merkle trees in Noir, - Noir programming language, - check membership, - computing root from leaf, - Noir Merkle tree implementation, - Merkle tree tutorial, - Merkle tree code examples, - Noir libraries, - pedersen hash., - ] ---- - -## compute_merkle_root - -Returns the root of the tree from the provided leaf and its hash path, using a [Pedersen hash](cryptographic_primitives/00_hashes.mdx#pedersen_hash). - -```rust -fn compute_merkle_root(leaf : Field, index : Field, hash_path: [Field]) -> Field -``` - -example: - -```rust -/** - // these values are for this example only - index = "0" - priv_key = "0x000000000000000000000000000000000000000000000000000000616c696365" - secret = "0x1929ea3ab8d9106a899386883d9428f8256cfedb3c4f6b66bf4aa4d28a79988f" - note_hash_path = [ - "0x1e61bdae0f027b1b2159e1f9d3f8d00fa668a952dddd822fda80dc745d6f65cc", - "0x0e4223f3925f98934393c74975142bd73079ab0621f4ee133cee050a3c194f1a", - "0x2fd7bb412155bf8693a3bd2a3e7581a679c95c68a052f835dddca85fa1569a40" - ] - */ -fn main(index: Field, priv_key: Field, secret: Field, note_hash_path: [Field; 3]) { - - let pubkey = std::scalar_mul::fixed_base_embedded_curve(priv_key); - let pubkey_x = pubkey[0]; - let pubkey_y = pubkey[1]; - let note_commitment = std::hash::pedersen([pubkey_x, pubkey_y, secret]); - - let root = std::merkle::compute_merkle_root(note_commitment[0], index, note_hash_path); - std::println(root); -} -``` - -To check merkle tree membership: - -1. Include a merkle root as a program input. -2. Compute the merkle root of a given leaf, index and hash path. -3. Assert the merkle roots are equal. - -For more info about merkle trees, see the Wikipedia [page](https://en.wikipedia.org/wiki/Merkle_tree). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/options.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/options.md deleted file mode 100644 index 3d3139fb98b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/options.md +++ /dev/null @@ -1,99 +0,0 @@ ---- -title: Option Type ---- - -The `Option` type is a way to express that a value might be present (`Some(T))` or absent (`None`). It's a safer way to handle potential absence of values, compared to using nulls in many other languages. - -```rust -struct Option { - None, - Some(T), -} -``` - -You can import the Option type into your Noir program like so: - -```rust -use dep::std::option::Option; - -fn main() { - let none = Option::none(); - let some = Option::some(3); -} -``` - -See [this test](https://github.com/noir-lang/noir/blob/5cbfb9c4a06c8865c98ff2b594464b037d821a5c/crates/nargo_cli/tests/test_data/option/src/main.nr) for a more comprehensive set of examples of each of the methods described below. - -## Methods - -### none - -Constructs a none value. - -### some - -Constructs a some wrapper around a given value. - -### is_none - -Returns true if the Option is None. - -### is_some - -Returns true of the Option is Some. - -### unwrap - -Asserts `self.is_some()` and returns the wrapped value. - -### unwrap_unchecked - -Returns the inner value without asserting `self.is_some()`. This method can be useful within an if condition when we already know that `option.is_some()`. If the option is None, there is no guarantee what value will be returned, only that it will be of type T for an `Option`. - -### unwrap_or - -Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value. - -### unwrap_or_else - -Returns the wrapped value if `self.is_some()`. Otherwise, calls the given function to return a default value. - -### map - -If self is `Some(x)`, this returns `Some(f(x))`. Otherwise, this returns `None`. - -### map_or - -If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns the given default value. - -### map_or_else - -If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns `default()`. - -### and - -Returns None if self is None. Otherwise, this returns `other`. - -### and_then - -If self is None, this returns None. Otherwise, this calls the given function with the Some value contained within self, and returns the result of that call. In some languages this function is called `flat_map` or `bind`. - -### or - -If self is Some, return self. Otherwise, return `other`. - -### or_else - -If self is Some, return self. Otherwise, return `default()`. - -### xor - -If only one of the two Options is Some, return that option. Otherwise, if both options are Some or both are None, None is returned. - -### filter - -Returns `Some(x)` if self is `Some(x)` and `predicate(x)` is true. Otherwise, this returns `None`. - -### flatten - -Flattens an `Option>` into a `Option`. This returns `None` if the outer Option is None. Otherwise, this returns the inner Option. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/recursion.md deleted file mode 100644 index 5e592a2fd89..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/recursion.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: Recursive Proofs -description: Learn about how to write recursive proofs in Noir. -keywords: [recursion, recursive proofs, verification_key, aggregation object, verify_proof] ---- - -Noir supports recursively verifying proofs, meaning you verify the proof of a Noir program in another Noir program. This enables creating proofs of arbitrary size by doing step-wise verification of smaller components of a large proof. - -The `verify_proof` function takes a verification key, proof and public inputs for a zk program, as well as a key hash and an input aggregation object. The key hash is used to check the validity of the verification key and the input aggregation object is required by some proving systems. The `verify_proof` function returns an output aggregation object that can then be fed into future iterations of the proof verification if required. - -```rust -#[foreign(verify_proof)] -fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : Field, _key_hash : Field, _input_aggregation_object : [Field]) -> [Field] {} -``` - -:::info - -This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. - -::: - -## Aggregation Object - -The purpose of the input aggregation object is a little less clear though (and the output aggregation object that is returned from the `std::verify_proof` method). Recursive zkSNARK schemes do not necessarily "verify a proof" in the sense that you expect a true or false to be spit out by the verifier. Rather an aggregation object is built over the public inputs. In the case of PLONK the recursive aggregation object is two G1 points (expressed as 16 witness values). The final verifier (in our case this is most often the smart contract verifier) has to be aware of this aggregation object to execute a pairing and check the validity of these points (thus completing the recursive verification). - -So for example in this circuit: - -```rust -use dep::std; - -fn main( - verification_key : [Field; 114], - proof : [Field; 94], - public_inputs : [Field; 1], - key_hash : Field, - input_aggregation_object : [Field; 16], - proof_b : [Field; 94], -) -> pub [Field; 16] { - let output_aggregation_object_a = std::verify_proof( - verification_key, - proof, - public_inputs, - key_hash, - input_aggregation_object - ); - - let output_aggregation_object = std::verify_proof( - verification_key, - proof_b, - public_inputs, - key_hash, - output_aggregation_object_a - ); - - let mut output = [0; 16]; - for i in 0..16 { - output[i] = output_aggregation_object[i]; - } - output -} -``` - -In this example we have a circuit, that generates proofs A and B, that is being verified in circuit C. Assuming that the proof being passed in is not already a recursive proof, the `input_aggregation_object` will be all zeros. It will then generate an `output_aggregation_object`. This blob of data then becomes the `input_aggregation_object` of the next recursive aggregation we wish to compute. We can see here as the same public inputs, verification key, and key hash are used that we are verifying two proofs generated from the same circuit in this single circuit. `std::verify_proof` returns a `[Field]` because the size of an aggregation object is proof system dependent--in barretenberg, aggregation objects are two G1 points, while in Halo2, the aggregation object is a list of G1 points that is log the circuit size. So for the final step we convert the slice into an array of size 16 because we are generating proofs using UltraPlonk. - -## Parameters - -### `verification_key` - -The verification key for the zk program that is being verified. - -### `proof` - -The proof for the zk program that is being verified. - -### `public_inputs` - -These represent the public inputs of the proof we are verifying. They should be checked against in the circuit after construction of a new aggregation state. - -### `key_hash` - -A key hash is used to check the validity of the verification key. The circuit implementing this opcode can use this hash to ensure that the key provided to the circuit matches the key produced by the circuit creator. - -### `input_aggregation_object` - -An aggregation object is blob of data that the top-level verifier must run some proof system specific algorithm on to complete verification. The size is proof system specific and will be set by the backend integrating this opcode. The input aggregation object is only not `None` when we are verifying a previous recursive aggregation in the current circuit. If this is the first recursive aggregation there is no input aggregation object. It is left to the backend to determine how to handle when there is no input aggregation object. - -## Return value - -### `output_aggregation_object` - -This is the result of a recursive aggregation and is what will be fed into the next verifier. -The next verifier can either perform a final verification (returning true or false) or perform another recursive aggregation where this output aggregation object will be the input aggregation object of the next recursive aggregation. - -## Example - -You can see an example of how to do recursive proofs in [this example recursion demo repo](https://github.com/noir-lang/noir-examples/tree/master/recursion). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/zeroed.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/zeroed.md deleted file mode 100644 index 97dab02dac2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/zeroed.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: Zeroed Function -description: - The zeroed function returns a zeroed value of any type. -keywords: - [ - zeroed - ] ---- - -Implements `fn zeroed() -> T` to return a zeroed value of any type. This function is generally unsafe to use as the zeroed bit pattern is not guaranteed to be valid for all types. It can however, be useful in cases when the value is guaranteed not to be used such as in a BoundedVec library implementing a growable vector, up to a certain length, backed by an array. The array can be initialized with zeroed values which are guaranteed to be inaccessible until the vector is pushed to. Similarly, enumerations in noir can be implemented using this method by providing zeroed values for the unused variants. - -You can access the function at `std::unsafe::zeroed`. - -This function currently supports the following types: - -- Field -- Bool -- Uint -- Array -- String -- Tuple -- Function - -Using it on other types could result in unexpected behavior. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/examples/merkle-proof.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/examples/merkle-proof.mdx deleted file mode 100644 index 832fb4bb55e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/examples/merkle-proof.mdx +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Merkle Proof Membership -description: - Learn how to use merkle membership proof in Noir to prove that a given leaf is a member of a - merkle tree with a specified root, at a given index. -keywords: - [merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree] ---- - -Let's walk through an example of a merkle membership proof in Noir that proves that a given leaf is -in a merkle tree. - -```rust -use dep::std; - -fn main(message : [Field; 62], index : Field, hashpath : [Field; 40], root : Field) { - let leaf = std::hash::hash_to_field(message); - let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); - assert(merkle_root == root); -} - -``` - -The message is hashed using `hash_to_field`. The specific hash function that is being used is chosen -by the backend. The only requirement is that this hash function can heuristically be used as a -random oracle. If only collision resistance is needed, then one can call `std::hash::pedersen_hash` -instead. - -```rust -let leaf = std::hash::hash_to_field(message); -``` - -The leaf is then passed to a compute_merkle_root function with the root, index and hashpath. The returned root can then be asserted to be the same as the provided root. - -```rust -let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); -assert (merkle_root == root); -``` - -> **Note:** It is possible to re-implement the merkle tree implementation without standard library. -> However, for most usecases, it is enough. In general, the standard library will always opt to be -> as conservative as possible, while striking a balance with efficiency. - -An example, the merkle membership proof, only requires a hash function that has collision -resistance, hence a hash function like Pedersen is allowed, which in most cases is more efficient -than the even more conservative sha256. - -[View an example on the starter repo](https://github.com/noir-lang/noir-examples/blob/3ea09545cabfa464124ec2f3ea8e60c608abe6df/stealthdrop/circuits/src/main.nr#L20) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/getting_started/00_nargo_installation.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/getting_started/00_nargo_installation.md deleted file mode 100644 index 7d3c88c7693..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/getting_started/00_nargo_installation.md +++ /dev/null @@ -1,249 +0,0 @@ ---- -title: Nargo Installation -description: - nargo is a command line tool for interacting with Noir programs (e.g. compiling, proving, - verifying and more). Learn how to install and use Nargo for your projects with this comprehensive - guide. -keywords: [Nargo, command line tool, Noir programs, installation guide, how to use Nargo] ---- - -`nargo` is a command line tool for interacting with Noir programs (e.g. compiling, proving, -verifying and more). - -Alternatively, the interactions can also be performed in [NoirJS](../noir_js/noir_js.md). - -### UltraPlonk - -Nargo versions \<0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk -version of Aztec Backend, which lacks efficient implementations of useful primitives (e.g. Keccak256 in 18k constraints, ECDSA verification in 36k constraints) that the UltraPlonk version offers. - -## Installation - -There are four approaches for installing Nargo: - -- [Option 1: Noirup](#option-1-noirup) -- [Option 2: Binaries](#option-2-binaries) -- [Option 3: Compile from Source](#option-3-compile-from-source) -- [Option 4: WSL for Windows](#option-4-wsl-for-windows) - -Optionally you can also install [Noir VS Code extension] for syntax highlighting. - -### Option 1: Noirup - -If you're on OSX or Linux, the easiest way to start using Noir and Nargo is via noirup. Just open a -terminal and run: - -```bash -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -Close the terminal, open another one, and run - -```bash -noirup -``` - -Done, you should have the latest version working. You can check with `nargo --version`. - -You can also install nightlies, specific versions -or branches, check out the [noirup repository](https://github.com/noir-lang/noirup) for more -information. - -#### GitHub Actions - -You can use `noirup` with GitHub Actions for CI/CD and automated testing. It is as simple as -installing `noirup` and running tests in your GitHub Action `yml` file. - -See the -[config file](https://github.com/TomAFrench/noir-hashes/blob/master/.github/workflows/noir.yml) in -this repo containing hash functions in Noir for an example. - -#### Nightly versions - -To install the nightly version of Noir (updated daily) run: - -```bash -noirup -n -``` - -### Option 2: Binaries - -See [GitHub Releases](https://github.com/noir-lang/noir/releases) for the latest and previous -platform specific binaries. - -#### Step 1 - -Paste and run the following in the terminal to extract and install the binary: - -> **macOS / Linux:** If you are prompted with `Permission denied` when running commands, prepend -> `sudo` and re-run it. - -##### macOS (Apple Silicon) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-aarch64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### macOS (Intel) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### Linux (Bash) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-unknown-linux-gnu.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -C $HOME/.nargo/bin/ && \ -echo -e '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.bashrc && \ -source ~/.bashrc -``` - -#### Step 2 - -Check if the installation was successful by running `nargo --help`. - -> **macOS:** If you are prompted with an OS alert, right-click and open the _nargo_ executable from -> Finder. Close the new terminal popped up and `nargo` should now be accessible. - -For a successful installation, you should see something similar to the following after running the -command: - -```sh -$ nargo --help - -Noir's package manager - -Usage: nargo - -Commands: - check Checks the constraint system for errors - codegen-verifier Generates a Solidity verifier smart contract for the program - compile Compile the program and its secret execution trace into ACIR format - new Create a new binary project - execute Executes a circuit to calculate its return value - prove Create proof for this program. The proof is returned as a hex encoded string - verify Given a proof and a program, verify whether the proof is valid - test Run the tests for this program - gates Counts the occurrences of different gates in circuit - help Print this message or the help of the given subcommand(s) -``` - -### Option 3: Compile from Source - -Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. It helps mitigating issues commonly associated with dependency management, such as conflicts between required package versions for different projects (often referred to as "dependency hell"). - -Combined with direnv, which automatically sets or clears environment variables based on the directory, it further simplifies the development process by seamlessly integrating with the developer's shell, facilitating an efficient and reliable workflow for managing and deploying Noir projects with multiple dependencies. - -#### Setting up your environment - -For the best experience, please follow these instructions to setup your environment: - -1. Install Nix following [their guide](https://nixos.org/download.html) for your operating system. -2. Create the file `~/.config/nix/nix.conf` with the contents: - -```ini -experimental-features = nix-command -extra-experimental-features = flakes -``` - -3. Install direnv into your Nix profile by running: - -```sh -nix profile install nixpkgs#direnv -``` - -4. Add direnv to your shell following [their guide](https://direnv.net/docs/hook.html). - 1. For bash or zshell, add `eval "$(direnv hook bash)"` or `eval "$(direnv hook zsh)"` to your ~/.bashrc or ~/.zshrc file, respectively. -5. Restart your shell. - -#### Shell & editor experience - -Now that your environment is set up, you can get to work on the project. - -1. Clone the repository, such as: - -```sh -git clone git@github.com:noir-lang/noir -``` - -> Replacing `noir` with whichever repository you want to work on. - -2. Navigate to the directory: - -```sh -cd noir -``` - -> Replacing `noir` with whichever repository you cloned. - -3. You should see a **direnv error** because projects aren't allowed by default. Make sure you've reviewed and trust our `.envrc` file, then you need to run: - -```sh -direnv allow -``` - -4. Now, wait awhile for all the native dependencies to be built. This will take some time and direnv will warn you that it is taking a long time, but we just need to let it run. - -5. Once you are presented with your prompt again, you can start your editor within the project directory (we recommend [VSCode](https://code.visualstudio.com/)): - -```sh -code . -``` - -6. (Recommended) When launching VSCode for the first time, you should be prompted to install our recommended plugins. We highly recommend installing these for the best development experience. - -#### Building and testing - -Assuming you are using `direnv` to populate your environment, building and testing the project can be done -with the typical `cargo build`, `cargo test`, and `cargo clippy` commands. You'll notice that the `cargo` version matches the version we specify in `rust-toolchain.toml`, which is 1.71.1 at the time of this writing. - -If you want to build the entire project in an isolated sandbox, you can use Nix commands: - -1. `nix build .` (or `nix build . -L` for verbose output) to build the project in a Nix sandbox. -2. `nix flake check` (or `nix flake check -L` for verbose output) to run clippy and tests in a Nix sandbox. - -#### Without `direnv` - -If you have hesitations with using direnv, you can launch a subshell with `nix develop` and then launch your editor from within the subshell. However, if VSCode was already launched in the project directory, the environment won't be updated. - -Advanced: If you aren't using direnv nor launching your editor within the subshell, you can try to install Barretenberg and other global dependencies the package needs. This is an advanced workflow and likely won't receive support! - -### Option 4: WSL (for Windows) - -The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed natively. However, it is available by using Windows Subsystem for Linux (WSL). - -Step 1: Follow the instructions [here](https://learn.microsoft.com/en-us/windows/wsl/install) to install and run WSL. - -step 2: Follow the [Noirup instructions](#option-1-noirup). - -## Uninstalling Nargo - -### Noirup - -If you installed Noir with `noirup`, you can uninstall Noir by removing the files in `~/.nargo`, `~/nargo` and `~/noir_cache`. - -```bash -rm -r ~/.nargo -rm -r ~/nargo -rm -r ~/noir_cache -``` - -### Nix - -If you installed Noir with Nix or from source, you can remove the binary located at `~/.nix-profile/bin/nargo`. - -```bash -rm ~/.nix-profile/bin/nargo -``` - -[noir vs code extension]: https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/getting_started/01_hello_world.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/getting_started/01_hello_world.md deleted file mode 100644 index 34f8cd96fcd..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/getting_started/01_hello_world.md +++ /dev/null @@ -1,147 +0,0 @@ ---- -title: Create A Project -description: - Learn how to create and verify your first Noir program using Nargo, a programming language for - zero-knowledge proofs. -keywords: - [ - Nargo, - Noir, - zero-knowledge proofs, - programming language, - create Noir program, - verify Noir program, - step-by-step guide, - ] ---- - -Now that we have installed Nargo, it is time to make our first hello world program! - -## Create a Project Directory - -Noir code can live anywhere on your computer. Let us create a _projects_ folder in the home -directory to house our Noir programs. - -For Linux, macOS, and Windows PowerShell, create the directory and change directory into it by -running: - -```sh -mkdir ~/projects -cd ~/projects -``` - -For Windows CMD, run: - -```sh -> mkdir "%USERPROFILE%\projects" -> cd /d "%USERPROFILE%\projects" -``` - -## Create Our First Nargo Project - -Now that we are in the projects directory, create a new Nargo project by running: - -```sh -nargo new hello_world -``` - -> **Note:** `hello_world` can be any arbitrary project name, we are simply using `hello_world` for -> demonstration. -> -> In production, the common practice is to name the project folder as `circuits` for better -> identifiability when sitting alongside other folders in the codebase (e.g. `contracts`, `scripts`, -> `test`). - -A `hello_world` folder would be created. Similar to Rust, the folder houses _src/main.nr_ and -_Nargo.toml_ that contains the source code and environmental options of your Noir program -respectively. - -### Intro to Noir Syntax - -Let us take a closer look at _main.nr_. The default _main.nr_ generated should look like this: - -```rust -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` - -The first line of the program specifies the program's inputs: - -```rust -x : Field, y : pub Field -``` - -Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the -keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](../language_concepts/data_types.md) section. - -The next line of the program specifies its body: - -```rust -assert(x != y); -``` - -The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. - -For more Noir syntax, check the [Language Concepts](../language_concepts/comments.md) chapter. - -## Build In/Output Files - -Change directory into _hello_world_ and build in/output files for your Noir program by running: - -```sh -cd hello_world -nargo check -``` - -Two additional files would be generated in your project directory: - -_Prover.toml_ houses input values, and _Verifier.toml_ houses public values. - -## Prove Our Noir Program - -Now that the project is set up, we can create a proof of correct execution on our Noir program. - -Fill in input values for execution in the _Prover.toml_ file. For example: - -```toml -x = "1" -y = "2" -``` - -Prove the valid execution of your Noir program: - -```sh -nargo prove -``` - -A new folder _proofs_ would then be generated in your project directory, containing the proof file -`.proof`, where the project name is defined in Nargo.toml. - -The _Verifier.toml_ file would also be updated with the public values computed from program -execution (in this case the value of `y`): - -```toml -y = "0x0000000000000000000000000000000000000000000000000000000000000002" -``` - -> **Note:** Values in _Verifier.toml_ are computed as 32-byte hex values. - -## Verify Our Noir Program - -Once a proof is generated, we can verify correct execution of our Noir program by verifying the -proof file. - -Verify your proof by running: - -```sh -nargo verify -``` - -The verification will complete in silence if it is successful. If it fails, it will log the -corresponding error instead. - -Congratulations, you have now created and verified a proof for your very first Noir program! - -In the [next section](./02_breakdown.md), we will go into more detail on each step performed. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/getting_started/02_breakdown.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/getting_started/02_breakdown.md deleted file mode 100644 index f928370b2e8..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/getting_started/02_breakdown.md +++ /dev/null @@ -1,198 +0,0 @@ ---- -title: Project Breakdown -description: - Learn about the anatomy of a Nargo project, including the purpose of the Prover and Verifier TOML - files, and how to prove and verify your program. -keywords: - [Nargo, Nargo project, Prover.toml, Verifier.toml, proof verification, private asset transfer] ---- - -This section breaks down our hello world program in section _1.2_. We elaborate on the project -structure and what the `prove` and `verify` commands did in the previous section. - -## Anatomy of a Nargo Project - -Upon creating a new project with `nargo new` and building the in/output files with `nargo check` -commands, you would get a minimal Nargo project of the following structure: - - - src - - Prover.toml - - Verifier.toml - - Nargo.toml - -The source directory _src_ holds the source code for your Noir program. By default only a _main.nr_ -file will be generated within it. - -### Prover.toml - -_Prover.toml_ is used for specifying the input values for executing and proving the program. You can specify `toml` files with different names by using the `--prover-name` or `-p` flags, see the [Prover](#provertoml) section below. Optionally you may specify expected output values for prove-time checking as well. - -### Verifier.toml - -_Verifier.toml_ contains public in/output values computed when executing the Noir program. - -### Nargo.toml - -_Nargo.toml_ contains the environmental options of your project. It contains a "package" section and a "dependencies" section. - -Example Nargo.toml: - -```toml -[package] -name = "noir_starter" -type = "bin" -authors = ["Alice"] -compiler_version = "0.9.0" -description = "Getting started with Noir" -entry = "circuit/main.nr" -license = "MIT" - -[dependencies] -ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} -``` - -Nargo.toml for a [workspace](../modules_packages_crates/workspaces.md) will look a bit different. For example: - -```toml -[workspace] -members = ["crates/a", "crates/b"] -default-member = "crates/a" -``` - -#### Package section - -The package section requires a number of fields including: - -- `name` (**required**) - the name of the package -- `type` (**required**) - can be "bin", "lib", or "contract" to specify whether its a binary, library or Aztec contract -- `authors` (optional) - authors of the project -- `compiler_version` - specifies the version of the compiler to use. This is enforced by the compiler and follow's [Rust's versioning](https://doc.rust-lang.org/cargo/reference/manifest.html#the-version-field), so a `compiler_version = 0.18.0` will enforce Nargo version 0.18.0, `compiler_version = ^0.18.0` will enforce anything above 0.18.0 but below 0.19.0, etc. For more information, see how [Rust handles these operators](https://docs.rs/semver/latest/semver/enum.Op.html) -- `description` (optional) -- `entry` (optional) - a relative filepath to use as the entry point into your package (overrides the default of `src/lib.nr` or `src/main.nr`) -- `backend` (optional) -- `license` (optional) - -#### Dependencies section - -This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies.md)for more info. - -`./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or -verifier contract respectively. - -### main.nr - -The _main.nr_ file contains a `main` method, this method is the entry point into your Noir program. - -In our sample program, _main.nr_ looks like this: - -```rust -fn main(x : Field, y : Field) { - assert(x != y); -} -``` - -The parameters `x` and `y` can be seen as the API for the program and must be supplied by the -prover. Since neither `x` nor `y` is marked as public, the verifier does not supply any inputs, when -verifying the proof. - -The prover supplies the values for `x` and `y` in the _Prover.toml_ file. - -As for the program body, `assert` ensures the satisfaction of the condition (e.g. `x != y`) is -constrained by the proof of the execution of said program (i.e. if the condition was not met, the -verifier would reject the proof as an invalid proof). - -### Prover.toml - -The _Prover.toml_ file is a file which the prover uses to supply his witness values(both private and -public). - -In our hello world program the _Prover.toml_ file looks like this: - -```toml -x = "1" -y = "2" -``` - -When the command `nargo prove` is executed, two processes happen: - -1. Noir creates a proof that `x` which holds the value of `1` and `y` which holds the value of `2` - is not equal. This not equal constraint is due to the line `assert(x != y)`. - -2. Noir creates and stores the proof of this statement in the _proofs_ directory in a file called your-project.proof. So if your project is named "private_voting" (defined in the project Nargo.toml), the proof will be saved at `./proofs/private_voting.proof`. Opening this file will display the proof in hex format. - -#### Arrays of Structs - -The following code shows how to pass an array of structs to a Noir program to generate a proof. - -```rust -// main.nr -struct Foo { - bar: Field, - baz: Field, -} - -fn main(foos: [Foo; 3]) -> pub Field { - foos[2].bar + foos[2].baz -} -``` - -Prover.toml: - -```toml -[[foos]] # foos[0] -bar = 0 -baz = 0 - -[[foos]] # foos[1] -bar = 0 -baz = 0 - -[[foos]] # foos[2] -bar = 1 -baz = 2 -``` - -#### Custom toml files - -You can specify a `toml` file with a different name to use for proving by using the `--prover-name` or `-p` flags. - -This command looks for proof inputs in the default **Prover.toml** and generates the proof and saves it at `./proofs/.proof`: - -```bash -nargo prove -``` - -This command looks for proof inputs in the custom **OtherProver.toml** and generates proof and saves it at `./proofs/.proof`: - -```bash -nargo prove -p OtherProver -``` - -## Verifying a Proof - -When the command `nargo verify` is executed, two processes happen: - -1. Noir checks in the _proofs_ directory for a proof file with the project name (eg. test_project.proof) - -2. If that file is found, the proof's validity is checked - -> **Note:** The validity of the proof is linked to the current Noir program; if the program is -> changed and the verifier verifies the proof, it will fail because the proof is not valid for the -> _modified_ Noir program. - -In production, the prover and the verifier are usually two separate entities. A prover would -retrieve the necessary inputs, execute the Noir program, generate a proof and pass it to the -verifier. The verifier would then retrieve the public inputs from usually external sources and -verifies the validity of the proof against it. - -Take a private asset transfer as an example: - -A user on browser as the prover would retrieve private inputs (e.g. the user's private key) and -public inputs (e.g. the user's encrypted balance on-chain), compute the transfer, generate a proof -and submit it to the verifier smart contract. - -The verifier contract would then draw the user's encrypted balance directly from the blockchain and -verify the proof submitted against it. If the verification passes, additional functions in the -verifier contract could trigger (e.g. approve the asset transfer). - -Now that you understand the concepts, you'll probably want some editor feedback while you are writing more complex code. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/index.md deleted file mode 100644 index e8d86020a20..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/index.md +++ /dev/null @@ -1,100 +0,0 @@ ---- -title: Introducing Noir -description: - Learn about the public alpha release of Noir, a domain specific language heavily influenced by - Rust that compiles to an intermediate language which can be compiled to an arithmetic circuit or a - rank-1 constraint system. -keywords: - [ - Noir, - Domain Specific Language, - Rust, - Intermediate Language, - Arithmetic Circuit, - Rank-1 Constraint System, - Ethereum Developers, - Protocol Developers, - Blockchain Developers, - Proving System, - Smart Contract Language, - ] -slug: / ---- - -## What is Noir? - -Noir is a Domain Specific Language for SNARK proving systems. It has been designed to use any ACIR compatible proving system. - -Its design choices are influenced heavily by Rust and focuses on a simple, familiar syntax. - -## Who is Noir for? - -Noir can be used for a variety of purposes. - -### Solidity Developers - -Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will -be modularized in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier.md) command to create -a verifier contract. - -### Protocol Developers - -As a protocol developer, you may not want to use the Aztec backend due to it not being a fit for -your stack, or maybe you simply want to use a different proving system. Since Noir does not compile -to a specific proof system, it is possible for protocol developers to replace the PLONK-based -proving system with a different proving system altogether. - -### Blockchain developers - -As a blockchain developer, you will be constrained by parameters set by your blockchain (for example, the -proving system and smart contract language has been pre-defined). In order for you to use Noir in -your blockchain, a proving system backend and a smart contract interface -must be implemented for it. - -## What's new about Noir? - -Noir is simple and flexible in its design, as it does not compile immediately to a fixed -NP-complete language. Instead, Noir compiles to an intermediate language (ACIR), which itself can be compiled -to an arithmetic circuit (if choosing to target Aztec's barretenberg backend) or a rank-1 constraint system (if choosing to target an R1CS backend like Arkworks' Marlin backend, or others). - -This in itself brings up a few challenges within the design process, but allows one to decouple the programming language completely from the backend. This is similar in theory to LLVM. - -## Current Features - -Compiler: - -- Module System -- For expressions -- Arrays -- Bit Operations -- Binary operations (\<, \<=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] -- Unsigned integers -- If statements -- Structures and Tuples -- Generics - -ACIR Supported OPCODES: - -- Sha256 -- Blake2s -- Schnorr signature verification -- MerkleMembership -- Pedersen Commitment -- Pedersen Hash -- HashToField - -## Libraries - -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). - -Some libraries that are available today include: - -- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library -- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) -- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers -- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address -- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees -- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir -- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers - -See the section on [dependencies](./modules_packages_crates/dependencies.md) for more information. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/01_functions.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/01_functions.md deleted file mode 100644 index 5eb22170e54..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/01_functions.md +++ /dev/null @@ -1,225 +0,0 @@ ---- -title: Functions -description: - Learn how to declare functions and methods in Noir, a programming language with Rust semantics. - This guide covers parameter declaration, return types, call expressions, and more. -keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] ---- - -Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. - -To declare a function the `fn` keyword is used. - -```rust -fn foo() {} -``` - -By default, functions are visible only within the package they are defined. To make them visible outside of that package (for example, as part of a [library](../modules_packages_crates/crates_and_packages.md#libraries)), you should mark them as `pub`: - -```rust -pub fn foo() {} -``` - -You can also restrict the visibility of the function to only the crate it was defined in, by specifying `pub(crate)`: - -```rust -pub(crate) fn foo() {} //foo can only be called within its crate -``` - -All parameters in a function must have a type and all types are known at compile time. The parameter -is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. - -```rust -fn foo(x : Field, y : Field){} -``` - -The return type of a function can be stated by using the `->` arrow notation. The function below -states that the foo function must return a `Field`. If the function returns no value, then the arrow -is omitted. - -```rust -fn foo(x : Field, y : Field) -> Field { - x + y -} -``` - -Note that a `return` keyword is unneeded in this case - the last expression in a function's body is -returned. - -## Main function - -If you're writing a binary, the `main` function is the starting point of your program. You can pass all types of expressions to it, as long as they have a fixed size at compile time: - -```rust -fn main(x : Field) // this is fine: passing a Field -fn main(x : [Field; 2]) // this is also fine: passing a Field with known size at compile-time -fn main(x : (Field, bool)) // 👌: passing a (Field, bool) tuple means size 2 -fn main(x : str<5>) // this is fine, as long as you pass a string of size 5 - -fn main(x : Vec) // can't compile, has variable size -fn main(x : [Field]) // can't compile, has variable size -fn main(....// i think you got it by now -``` - -Keep in mind [tests](../nargo/02_testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: - -```rust -fn main(x : [Field]) { - assert(x[0] == 1); -} - -#[test] -fn test_one() { - main([1, 2]); -} -``` - -```bash -$ nargo test -[testing] Running 1 test functions -[testing] Testing test_one... ok -[testing] All tests passed - -$ nargo check -The application panicked (crashed). -Message: Cannot have variable sized arrays as a parameter to main -``` - -## Call Expressions - -Calling a function in Noir is executed by using the function name and passing in the necessary -arguments. - -Below we show how to call the `foo` function from the `main` function using a call expression: - -```rust -fn main(x : Field, y : Field) { - let z = foo(x); -} - -fn foo(x : Field) -> Field { - x + x -} -``` - -## Methods - -You can define methods in Noir on any struct type in scope. - -```rust -struct MyStruct { - foo: Field, - bar: Field, -} - -impl MyStruct { - fn new(foo: Field) -> MyStruct { - MyStruct { - foo, - bar: 2, - } - } - - fn sum(self) -> Field { - self.foo + self.bar - } -} - -fn main() { - let s = MyStruct::new(40); - assert(s.sum() == 42); -} -``` - -Methods are just syntactic sugar for functions, so if we wanted to we could also call `sum` as -follows: - -```rust -assert(MyStruct::sum(s) == 42); -``` - -It is also possible to specialize which method is chosen depending on the [generic](./06_generics.md) type that is used. In this example, the `foo` function returns different values depending on its type: - -```rust -struct Foo {} - -impl Foo { - fn foo(self) -> Field { 1 } -} - -impl Foo { - fn foo(self) -> Field { 2 } -} - -fn main() { - let f1: Foo = Foo{}; - let f2: Foo = Foo{}; - assert(f1.foo() + f2.foo() == 3); -} -``` - -Also note that impls with the same method name defined in them cannot overlap. For example, if we already have `foo` defined for `Foo` and `Foo` like we do above, we cannot also define `foo` in an `impl Foo` since it would be ambiguous which version of `foo` to choose. - -```rust -// Including this impl in the same project as the above snippet would -// cause an overlapping impls error -impl Foo { - fn foo(self) -> Field { 3 } -} -``` - -## Lambdas - -Lambdas are anonymous functions. They follow the syntax of Rust - `|arg1, arg2, ..., argN| return_expression`. - -```rust -let add_50 = |val| val + 50; -assert(add_50(100) == 150); -``` - -See [Lambdas](./08_lambdas.md) for more details. - -## Attributes - -Attributes are metadata that can be applied to a function, using the following syntax: `#[attribute(value)]`. - -Supported attributes include: - -- **builtin**: the function is implemented by the compiler, for efficiency purposes. -- **deprecated**: mark the function as _deprecated_. Calling the function will generate a warning: `warning: use of deprecated function` -- **field**: Used to enable conditional compilation of code depending on the field size. See below for more details -- **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./05_unconstrained.md) and [NoirJS](../noir_js/noir_js.md) for more details. -- **test**: mark the function as unit tests. See [Tests](../nargo/02_testing.md) for more details - -### Field Attribute - -The field attribute defines which field the function is compatible for. The function is conditionally compiled, under the condition that the field attribute matches the Noir native field. -The field can be defined implicitly, by using the name of the elliptic curve usually associated to it - for instance bn254, bls12_381 - or explicitly by using the field (prime) order, in decimal or hexadecimal form. -As a result, it is possible to define multiple versions of a function with each version specialized for a different field attribute. This can be useful when a function requires different parameters depending on the underlying elliptic curve. - -Example: we define the function `foo()` three times below. Once for the default Noir bn254 curve, once for the field $\mathbb F_{23}$, which will normally never be used by Noir, and once again for the bls12_381 curve. - -```rust -#[field(bn254)] -fn foo() -> u32 { - 1 -} - -#[field(23)] -fn foo() -> u32 { - 2 -} - -// This commented code would not compile as foo would be defined twice because it is the same field as bn254 -// #[field(21888242871839275222246405745257275088548364400416034343698204186575808495617)] -// fn foo() -> u32 { -// 2 -// } - -#[field(bls12_381)] -fn foo() -> u32 { - 3 -} -``` - -If the field name is not known to Noir, it will discard the function. Field names are case insensitive. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/02_control_flow.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/02_control_flow.md deleted file mode 100644 index a7f85360197..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/02_control_flow.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Control Flow -description: - Learn how to use loops and if expressions in the Noir programming language. Discover the syntax - and examples for for loops and if-else statements. -keywords: [Noir programming language, loops, for loop, if-else statements, Rust syntax] ---- - -## Loops - -Noir has one kind of loop: the `for` loop. `for` loops allow you to repeat a block of code multiple -times. - -The following block of code between the braces is run 10 times. - -```rust -for i in 0..10 { - // do something -}; -``` - -The index for loops is of type `u64`. - -## If Expressions - -Noir supports `if-else` statements. The syntax is most similar to Rust's where it is not required -for the statement's conditional to be surrounded by parentheses. - -```rust -let a = 0; -let mut x: u32 = 0; - -if a == 0 { - if a != 0 { - x = 6; - } else { - x = 2; - } -} else { - x = 5; - assert(x == 5); -} -assert(x == 2); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/03_ops.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/03_ops.md deleted file mode 100644 index 0e35ef5e584..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/03_ops.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -title: Logical Operations -description: - Learn about the supported arithmetic and logical operations in the Noir programming language. - Discover how to perform operations on private input types, integers, and booleans. -keywords: - [ - Noir programming language, - supported operations, - arithmetic operations, - logical operations, - predicate operators, - bitwise operations, - short-circuiting, - backend, - ] ---- - -# Operations - -## Table of Supported Operations - -| Operation | Description | Requirements | -| :-------- | :------------------------------------------------------------: | -------------------------------------: | -| + | Adds two private input types together | Types must be private input | -| - | Subtracts two private input types together | Types must be private input | -| \* | Multiplies two private input types together | Types must be private input | -| / | Divides two private input types together | Types must be private input | -| ^ | XOR two private input types together | Types must be integer | -| & | AND two private input types together | Types must be integer | -| \| | OR two private input types together | Types must be integer | -| \<\< | Left shift an integer by another integer amount | Types must be integer | -| >> | Right shift an integer by another integer amount | Types must be integer | -| ! | Bitwise not of a value | Type must be integer or boolean | -| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | -| > | returns a bool if one value is more than the other | Upper bound must have a known bit size | -| >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | -| == | returns a bool if one value is equal to the other | Both types must not be constants | -| != | returns a bool if one value is not equal to the other | Both types must not be constants | - -### Predicate Operators - -`<,<=, !=, == , >, >=` are known as predicate/comparison operations because they compare two values. -This differs from the operations such as `+` where the operands are used in _computation_. - -### Bitwise Operations Example - -```rust -fn main(x : Field) { - let y = x as u32; - let z = y & y; -} -``` - -`z` is implicitly constrained to be the result of `y & y`. The `&` operand is used to denote bitwise -`&`. - -> `x & x` would not compile as `x` is a `Field` and not an integer type. - -### Logical Operators - -Noir has no support for the logical operators `||` and `&&`. This is because encoding the -short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can -use the bitwise operators `|` and `&` which operate identically for booleans, just without the -short-circuiting. - -```rust -let my_val = 5; - -let mut flag = 1; -if (my_val > 6) | (my_val == 0) { - flag = 0; -} -assert(flag == 1); - -if (my_val != 10) & (my_val < 50) { - flag = 0; -} -assert(flag == 0); -``` - -### Shorthand operators - -Noir shorthand operators for most of the above operators, namely `+=, -=, *=, /=, %=, &=, |=, ^=, <<=`, and `>>=`. These allow for more concise syntax. For example: - -```rust -let mut i = 0; -i = i + 1; -``` - -could be written as: - -```rust -let mut i = 0; -i += 1; -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/04_assert.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/04_assert.md deleted file mode 100644 index 7427ec6cc63..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/04_assert.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Assert Function -description: - Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or - comparison expression that follows to be true, and what happens if the expression is false at - runtime. -keywords: [Noir programming language, assert statement, predicate expression, comparison expression] ---- - -Noir includes a special `assert` function which will explicitly constrain the predicate/comparison -expression that follows to be true. If this expression is false at runtime, the program will fail to -be proven. Example: - -```rust -fn main(x : Field, y : Field) { - assert(x == y); -} -``` - -You can optionally provide a message to be logged when the assertion fails: - -```rust -assert(x == y, "x and y are not equal"); -``` - -> Assertions only work for predicate operations, such as `==`. If there's any ambiguity on the operation, the program will fail to compile. For example, it is unclear if `assert(x + y)` would check for `x + y == 0` or simply would return `true`. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/05_unconstrained.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/05_unconstrained.md deleted file mode 100644 index 097d6ee9894..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/05_unconstrained.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: Unconstrained Functions -description: "Learn about what unconstrained functions in Noir are, how to use them and when you'd want to." - -keywords: [Noir programming language, unconstrained, open] ---- - - - -Unconstrained functions are functions which do not constrain any of the included computation and allow for non-deterministic computation. - -## Why? - -Zero-knowledge (ZK) domain-specific languages (DSL) enable developers to generate ZK proofs from their programs by compiling code down to the constraints of an NP complete language (such as R1CS or PLONKish languages). However, the hard bounds of a constraint system can be very limiting to the functionality of a ZK DSL. - -Enabling a circuit language to perform unconstrained execution is a powerful tool. Said another way, unconstrained execution lets developers generate witnesses from code that does not generate any constraints. Being able to execute logic outside of a circuit is critical for both circuit performance and constructing proofs on information that is external to a circuit. - -Fetching information from somewhere external to a circuit can also be used to enable developers to improve circuit efficiency. - -A ZK DSL does not just prove computation, but proves that some computation was handled correctly. Thus, it is necessary that when we switch from performing some operation directly inside of a circuit to inside of an unconstrained environment that the appropriate constraints are still laid down elsewhere in the circuit. - -## Example - -An in depth example might help drive the point home. This example comes from the excellent [post](https://discord.com/channels/1113924620781883405/1124022445054111926/1128747641853972590) by Tom in the Noir Discord. - -Let's look at how we can optimize a function to turn a `u72` into an array of `u8`s. - -```rust -fn main(num: u72) -> pub [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8)) as u72 & 0xff) as u8; - } - - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 91 -Backend circuit size: 3619 -``` - -A lot of the operations in this function are optimized away by the compiler (all the bit-shifts turn into divisions by constants). However we can save a bunch of gates by casting to u8 a bit earlier. This automatically truncates the bit-shifted value to fit in a u8 which allows us to remove the XOR against 0xff. This saves us ~480 gates in total. - -```rust -fn main(num: u72) -> pub [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8)) as u8; - } - - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 75 -Backend circuit size: 3143 -``` - -Those are some nice savings already but we can do better. This code is all constrained so we're proving every step of calculating out using num, but we don't actually care about how we calculate this, just that it's correct. This is where brillig comes in. - -It turns out that truncating a u72 into a u8 is hard to do inside a snark, each time we do as u8 we lay down 4 ACIR opcodes which get converted into multiple gates. It's actually much easier to calculate num from out than the other way around. All we need to do is multiply each element of out by a constant and add them all together, both relatively easy operations inside a snark. - -We can then run u72_to_u8 as unconstrained brillig code in order to calculate out, then use that result in our constrained function and assert that if we were to do the reverse calculation we'd get back num. This looks a little like the below: - -```rust -fn main(num: u72) -> pub [u8; 8] { - let out = u72_to_u8(num); - - let mut reconstructed_num: u72 = 0; - for i in 0..8 { - reconstructed_num += (out[i] as u72 << (56 - (8 * i))); - } - assert(num == reconstructed_num); - out -} - -unconstrained fn u72_to_u8(num: u72) -> [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8))) as u8; - } - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 78 -Backend circuit size: 2902 -``` - -This ends up taking off another ~250 gates from our circuit! We've ended up with more ACIR opcodes than before but they're easier for the backend to prove (resulting in fewer gates). - -Generally we want to use brillig whenever there's something that's easy to verify but hard to compute within the circuit. For example, if you wanted to calculate a square root of a number it'll be a much better idea to calculate this in brillig and then assert that if you square the result you get back your number. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/06_generics.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/06_generics.md deleted file mode 100644 index 36c2b593fcd..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/06_generics.md +++ /dev/null @@ -1,113 +0,0 @@ ---- -title: Generics -description: Learn how to use Generics in Noir -keywords: [Noir, Rust, generics, functions, structs] ---- - -Generics allow you to use the same functions with multiple different concrete data types. You can -read more about the concept of generics in the Rust documentation -[here](https://doc.rust-lang.org/book/ch10-01-syntax.html). - -Here is a trivial example showing the identity function that supports any type. In Rust, it is -common to refer to the most general type as `T`. We follow the same convention in Noir. - -```rust -fn id(x: T) -> T { - x -} -``` - -## In Structs - -Generics are useful for specifying types in structs. For example, we can specify that a field in a -struct will be of a certain generic type. In this case `value` is of type `T`. - -```rust -struct RepeatedValue { - value: T, - count: Field, -} - -impl RepeatedValue { - fn new(value: T) -> Self { - Self { value, count: 1 } - } - - fn increment(mut repeated: Self) -> Self { - repeated.count += 1; - repeated - } - - fn print(self) { - for _i in 0 .. self.count { - dep::std::println(self.value); - } - } -} - -fn main() { - let mut repeated = RepeatedValue::new("Hello!"); - repeated = repeated.increment(); - repeated.print(); -} -``` - -The `print` function will print `Hello!` an arbitrary number of times, twice in this case. - -If we want to be generic over array lengths (which are type-level integers), we can use numeric -generics. Using these looks just like using regular generics, but these generics can resolve to -integers at compile-time, rather than resolving to types. Here's an example of a struct that is -generic over the size of the array it contains internally: - -```rust -struct BigInt { - limbs: [u32; N], -} - -impl BigInt { - // `N` is in scope of all methods in the impl - fn first(first: BigInt, second: BigInt) -> Self { - assert(first.limbs != second.limbs); - first - - fn second(first: BigInt, second: Self) -> Self { - assert(first.limbs != second.limbs); - second - } -} -``` - -## Calling functions on generic parameters - -Unlike Rust, Noir does not have traits, so how can one translate the equivalent of a trait bound in -Rust into Noir? That is, how can we write a function that is generic over some type `T`, while also -requiring there is a function like `eq: fn(T, T) -> bool` that works on the type? - -The answer is that we can translate this by passing in the function manually. Here's an example of -implementing array equality in Noir: - -```rust -fn array_eq(array1: [T; N], array2: [T; N], elem_eq: fn(T, T) -> bool) -> bool { - if array1.len() != array2.len() { - false - } else { - let mut result = true; - for i in 0 .. array1.len() { - result &= elem_eq(array1[i], array2[i]); - } - result - } -} - -fn main() { - assert(array_eq([1, 2, 3], [1, 2, 3], |a, b| a == b)); - - // We can use array_eq even for arrays of structs, as long as we have - // an equality function for these structs we can pass in - let array = [MyStruct::new(), MyStruct::new()]; - assert(array_eq(array, array, MyStruct::eq)); -} -``` - -You can see an example of generics in the tests -[here](https://github.com/noir-lang/noir/blob/master/test_programs/execution_success/generics/src/main.nr). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/07_mutability.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/07_mutability.md deleted file mode 100644 index ed3fed820ec..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/07_mutability.md +++ /dev/null @@ -1,92 +0,0 @@ ---- -title: Mutability -description: - Learn about mutable variables, constants, and globals in Noir programming language. Discover how - to declare, modify, and use them in your programs. -keywords: [noir programming language, mutability in noir, mutable variables, constants, globals] ---- - -Variables in noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned -to via an assignment expression. - -```rust -let x = 2; -x = 3; // error: x must be mutable to be assigned to - -let mut y = 3; -let y = 4; // OK -``` - -The `mut` modifier can also apply to patterns: - -```rust -let (a, mut b) = (1, 2); -a = 11; // error: a must be mutable to be assigned to -b = 12; // OK - -let mut (c, d) = (3, 4); -c = 13; // OK -d = 14; // OK - -// etc. -let MyStruct { x: mut y } = MyStruct { x: a }; -// y is now in scope -``` - -Note that mutability in noir is local and everything is passed by value, so if a called function -mutates its parameters then the parent function will keep the old value of the parameters. - -```rust -fn main() -> pub Field { - let x = 3; - helper(x); - x // x is still 3 -} - -fn helper(mut x: i32) { - x = 4; -} -``` - -## Comptime Values - -:::warning - -The 'comptime' keyword was removed in version 0.10. The comptime keyword and syntax are currently still kept and parsed for backwards compatibility, but are now deprecated and will issue a warning when used. `comptime` has been removed because it is no longer needed for accessing arrays. - -::: - -## Globals - -Noir also supports global variables. However, they must be known at compile-time. The global type can also be inferred by the compiler entirely. Globals can also be used to specify array -annotations for function parameters and can be imported from submodules. - -```rust -global N: Field = 5; // Same as `global N: Field = 5` - -fn main(x : Field, y : [Field; N]) { - let res = x * N; - - assert(res == y[0]); - - let res2 = x * my_submodule::N; - assert(res != res2); -} - -mod my_submodule { - use dep::std; - - global N: Field = 10; - - fn my_helper() -> Field { - let x = N; - x - } -} -``` - -## Why only local mutability? - -Witnesses in a proving system are immutable in nature. Noir aims to _closely_ mirror this setting -without applying additional overhead to the user. Modeling a mutable reference is not as -straightforward as on conventional architectures and would incur some possibly unexpected overhead. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/08_lambdas.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/08_lambdas.md deleted file mode 100644 index ae1e6aecab1..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/08_lambdas.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: Lambdas -description: Learn how to use anonymous functions in Noir programming language. -keywords: [Noir programming language, lambda, closure, function, anonymous function] ---- - -## Introduction - -Lambdas are anonymous functions. The syntax is `|arg1, arg2, ..., argN| return_expression`. - -```rust -let add_50 = |val| val + 50; -assert(add_50(100) == 150); -``` - -A block can be used as the body of a lambda, allowing you to declare local variables inside it: - -```rust -let cool = || { - let x = 100; - let y = 100; - x + y -} - -assert(cool() == 200); -``` - -## Closures - -Inside the body of a lambda, you can use variables defined in the enclosing function. Such lambdas are called **closures**. In this example `x` is defined inside `main` and is accessed from within the lambda: - -```rust -fn main() { - let x = 100; - let closure = || x + 150; - assert(closure() == 250); -} -``` - -## Passing closures to higher-order functions - -It may catch you by surprise that the following code fails to compile: - -```rust -fn foo(f: fn () -> Field) -> Field { - f() -} - -fn main() { - let (x, y) = (50, 50); - assert(foo(|| x + y) == 100); // error :( -} -``` - -The reason is that the closure's capture environment affects its type - we have a closure that captures two Fields and `foo` -expects a regular function as an argument - those are incompatible. -:::note - -Variables contained within the `||` are the closure's parameters, and the expression that follows it is the closure's body. The capture environment is comprised of any variables used in the closure's body that are not parameters. - -E.g. in |x| x + y, y would be a captured variable, but x would not be, since it is a parameter of the closure. - -::: -The syntax for the type of a closure is `fn[env](args) -> ret_type`, where `env` is the capture environment of the closure - -in this example that's `(Field, Field)`. - -The best solution in our case is to make `foo` generic over the environment type of its parameter, so that it can be called -with closures with any environment, as well as with regular functions: - -```rust -fn foo(f: fn[Env]() -> Field) -> Field { - f() -} - -fn main() { - let (x, y) = (50, 50); - assert(foo(|| x + y) == 100); // compiles fine - assert(foo(|| 60) == 60); // compiles fine -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/09_comments.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/09_comments.md deleted file mode 100644 index 3bb4d2f25a4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/09_comments.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: Comments -description: - Learn how to write comments in Noir programming language. A comment is a line of code that is - ignored by the compiler, but it can be read by programmers. Single-line and multi-line comments - are supported in Noir. -keywords: [Noir programming language, comments, single-line comments, multi-line comments] ---- - -A comment is a line in your codebase which the compiler ignores, however it can be read by -programmers. - -Here is a single line comment: - -```rust -// This is a comment and is ignored -``` - -`//` is used to tell the compiler to ignore the rest of the line. - -Noir also supports multi-line block comments. Start a block comment with `/*` and end the block with `*/`. - -Noir does not natively support doc comments. You may be able to use [Rust doc comments](https://doc.rust-lang.org/reference/comments.html) in your code to leverage some Rust documentation build tools with Noir code. - -```rust -/* - This is a block comment describing a complex function. -*/ -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/10_distinct.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/10_distinct.md deleted file mode 100644 index e7ff7f5017a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/10_distinct.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: Distinct Witnesses ---- - -The `distinct` keyword prevents repetitions of witness indices in the program's ABI. This ensures -that the witnesses being returned as public inputs are all unique. - -The `distinct` keyword is only used for return values on program entry points (usually the `main()` -function). - -When using `distinct` and `pub` simultaneously, `distinct` comes first. See the example below. - -You can read more about the problem this solves -[here](https://github.com/noir-lang/noir/issues/1183). - -## Example - -Without the `distinct` keyword, the following program - -```rust -fn main(x : pub Field, y : pub Field) -> pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - "return_witnesses": [3, 2, 4, 4] - } -} -``` - -Whereas (with the `distinct` keyword) - -```rust -fn main(x : pub Field, y : pub Field) -> distinct pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - //... - "return_witnesses": [3, 4, 5, 6] - } -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/11_shadowing.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/11_shadowing.md deleted file mode 100644 index efd743e764f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/11_shadowing.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Shadowing ---- - -Noir allows for inheriting variables' values and re-declaring them with the same name similar to Rust, known as shadowing. - -For example, the following function is valid in Noir: - -```rust -fn main() { - let x = 5; - - { - let x = x * 2; - assert (x == 10); - } - - assert (x == 5); -} -``` - -In this example, a variable x is first defined with the value 5. - -The local scope that follows shadows the original x, i.e. creates a local mutable x based on the value of the original x. It is given a value of 2 times the original x. - -When we return to the main scope, x once again refers to just the original x, which stays at the value of 5. - -## Temporal mutability - -One way that shadowing is useful, in addition to ergonomics across scopes, is for temporarily mutating variables. - -```rust -fn main() { - let age = 30; - // age = age + 5; // Would error as `age` is immutable by default. - - let mut age = age + 5; // Temporarily mutates `age` with a new value. - - let age = age; // Locks `age`'s mutability again. - - assert (age == 35); -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types.md deleted file mode 100644 index 74f573f7d3f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: Data Types -description: - Get a clear understanding of the two categories of Noir data types - primitive types and compound - types. Learn about their characteristics, differences, and how to use them in your Noir - programming. -keywords: - [ - noir, - data types, - primitive types, - compound types, - private types, - public types, - ] ---- - -Every value in Noir has a type, which determines which operations are valid for it. - -All values in Noir are fundamentally composed of `Field` elements. For a more approachable -developing experience, abstractions are added on top to introduce different data types in Noir. - -Noir has two category of data types: primitive types (e.g. `Field`, integers, `bool`) and compound -types that group primitive types (e.g. arrays, tuples, structs). Each value can either be private or -public. - -## Private & Public Types - -A **private value** is known only to the Prover, while a **public value** is known by both the -Prover and Verifier. Mark values as `private` when the value should only be known to the prover. All -primitive types (including individual fields of compound types) in Noir are private by default, and -can be marked public when certain values are intended to be revealed to the Verifier. - -> **Note:** For public values defined in Noir programs paired with smart contract verifiers, once -> the proofs are verified on-chain the values can be considered known to everyone that has access to -> that blockchain. - -Public data types are treated no differently to private types apart from the fact that their values -will be revealed in proofs generated. Simply changing the value of a public type will not change the -circuit (where the same goes for changing values of private types as well). - -_Private values_ are also referred to as _witnesses_ sometimes. - -> **Note:** The terms private and public when applied to a type (e.g. `pub Field`) have a different -> meaning than when applied to a function (e.g. `pub fn foo() {}`). -> -> The former is a visibility modifier for the Prover to interpret if a value should be made known to -> the Verifier, while the latter is a visibility modifier for the compiler to interpret if a -> function should be made accessible to external Noir programs like in other languages. - -### pub Modifier - -All data types in Noir are private by default. Types are explicitly declared as public using the -`pub` modifier: - -```rust -fn main(x : Field, y : pub Field) -> pub Field { - x + y -} -``` - -In this example, `x` is **private** while `y` and `x + y` (the return value) are **public**. Note -that visibility is handled **per variable**, so it is perfectly valid to have one input that is -private and another that is public. - -> **Note:** Public types can only be declared through parameters on `main`. - -## Type Aliases - -A type alias is a new name for an existing type. Type aliases are declared with the keyword `type`: - -```rust -type Id = u8; - -fn main() { - let id: Id = 1; - let zero: u8 = 0; - assert(zero + 1 == id); -} -``` - -Type aliases can also be used with [generics](./06_generics.md): - -```rust -type Id = Size; - -fn main() { - let id: Id = 1; - let zero: u32 = 0; - assert(zero + 1 == id); -} -``` - -### BigInt - -You can achieve BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/00_fields.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/00_fields.md deleted file mode 100644 index 78d3d2af166..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/00_fields.md +++ /dev/null @@ -1,165 +0,0 @@ ---- -title: Fields -description: - Dive deep into the Field data type in Noir. Understand its methods, practical examples, and best practices to effectively use Fields in your Noir programs. -keywords: - [ - noir, - field type, - methods, - examples, - best practices, - ] ---- - -The field type corresponds to the native field type of the proving backend. - -The size of a Noir field depends on the elliptic curve's finite field for the proving backend -adopted. For example, a field would be a 254-bit integer when paired with the default backend that -spans the Grumpkin curve. - -Fields support integer arithmetic and are often used as the default numeric type in Noir: - -```rust -fn main(x : Field, y : Field) { - let z = x + y; -} -``` - -`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new -private value `z` constrained to be equal to `x + y`. - -If proving efficiency is of priority, fields should be used as a default for solving problems. -Smaller integer types (e.g. `u64`) incur extra range constraints. - -## Methods - -After declaring a Field, you can use these common methods on it: - -### to_le_bits - -Transforms the field into an array of bits, Little Endian. - -```rust -fn to_le_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_le_bits(32); -} -``` - -### to_be_bits - -Transforms the field into an array of bits, Big Endian. - -```rust -fn to_be_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_be_bits(32); -} -``` - -### to_le_bytes - -Transforms into an array of bytes, Little Endian - -```rust -fn to_le_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_le_bytes(4); -} -``` - -### to_be_bytes - -Transforms into an array of bytes, Big Endian - -```rust -fn to_be_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_be_bytes(4); -} -``` - -### to_le_radix - -Decomposes into a vector over the specified base, Little Endian - -```rust -fn to_le_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_le_radix(256, 4); -} -``` - -### to_be_radix - -Decomposes into a vector over the specified base, Big Endian - -```rust -fn to_be_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_be_radix(256, 4); -} -``` - -### pow_32 - -Returns the value to the power of the specified exponent - -```rust -fn pow_32(self, exponent: Field) -> Field -``` - -example: - -```rust -fn main() { - let field = 2 - let pow = field.pow_32(4); - assert(pow == 16); -} -``` - -### sgn0 - -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. - -```rust -fn sgn0(self) -> u1 -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/01_integers.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/01_integers.md deleted file mode 100644 index 1814365800a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/01_integers.md +++ /dev/null @@ -1,112 +0,0 @@ ---- -title: Integers -description: Explore the Integer data type in Noir. Learn about its methods, see real-world examples, and grasp how to efficiently use Integers in your Noir code. -keywords: [noir, integer types, methods, examples, arithmetic] ---- - -An integer type is a range constrained field type. The Noir frontend supports arbitrarily-sized, both unsigned and signed integer types. - -:::info - -When an integer is defined in Noir without a specific type, it will default to `Field`. - -The one exception is for loop indices which default to `u64` since comparisons on `Field`s are not possible. - -::: - -## Unsigned Integers - -An unsigned integer type is specified first with the letter `u` (indicating its unsigned nature) followed by its bit size (e.g. `8`): - -```rust -fn main() { - let x: u8 = 1; - let y: u8 = 1; - let z = x + y; - assert (z == 2); -} -``` - -The bit size determines the maximum value the integer type can store. For example, a `u8` variable can store a value in the range of 0 to 255 (i.e. $\\2^{8}-1\\$). - -## Signed Integers - -A signed integer type is specified first with the letter `i` (which stands for integer) followed by its bit size (e.g. `8`): - -```rust -fn main() { - let x: i8 = -1; - let y: i8 = -1; - let z = x + y; - assert (z == -2); -} -``` - -The bit size determines the maximum and minimum range of value the integer type can store. For example, an `i8` variable can store a value in the range of -128 to 127 (i.e. $\\-2^{7}\\$ to $\\2^{7}-1\\$). - -:::tip - -If you are using the default proving backend with Noir, both even (e.g. _u2_, _i2_) and odd (e.g. _u3_, _i3_) arbitrarily-sized integer types up to 127 bits (i.e. _u127_ and _i127_) are supported. - -::: - -## Overflows - -Computations that exceed the type boundaries will result in overflow errors. This happens with both signed and unsigned integers. For example, attempting to prove: - -```rust -fn main(x: u8, y: u8) { - let z = x + y; -} -``` - -With: - -```toml -x = "255" -y = "1" -``` - -Would result in: - -``` -$ nargo prove -error: Assertion failed: 'attempt to add with overflow' -┌─ ~/src/main.nr:9:13 -│ -│ let z = x + y; -│ ----- -│ -= Call stack: - ... -``` - -A similar error would happen with signed integers: - -```rust -fn main() { - let x: i8 = -118; - let y: i8 = -11; - let z = x + y; -} -``` - -### Wrapping methods - -Although integer overflow is expected to error, some use-cases rely on wrapping. For these use-cases, the standard library provides `wrapping` variants of certain common operations: - -```rust -fn wrapping_add(x: T, y: T) -> T; -fn wrapping_sub(x: T, y: T) -> T; -fn wrapping_mul(x: T, y: T) -> T; -``` - -Example of how it is used: - -```rust -use dep::std; - -fn main(x: u8, y: u8) -> pub u8 { - std::wrapping_add(x, y) -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/02_booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/02_booleans.md deleted file mode 100644 index d353606210a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/02_booleans.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: Booleans -description: - Delve into the Boolean data type in Noir. Understand its methods, practical examples, and best practices for using Booleans in your Noir programs. -keywords: - [ - noir, - boolean type, - methods, - examples, - logical operations, - ] ---- - - -The `bool` type in Noir has two possible values: `true` and `false`: - -```rust -fn main() { - let t = true; - let f: bool = false; -} -``` - -> **Note:** When returning a boolean value, it will show up as a value of 1 for `true` and 0 for -> `false` in _Verifier.toml_. - -The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and -[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/03_strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/03_strings.md deleted file mode 100644 index 4360893e9a2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/03_strings.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: Strings -description: - Discover the String data type in Noir. Learn about its methods, see real-world examples, and understand how to effectively manipulate and use Strings in Noir. -keywords: - [ - noir, - string type, - methods, - examples, - concatenation, - ] ---- - - -The string type is a fixed length value defined with `str`. - -You can use strings in `assert()` functions or print them with -`std::println()`. See more about [Logging](../../standard_library/logging.md). - -```rust -use dep::std; - -fn main(message : pub str<11>, hex_as_string : str<4>) { - std::println(message); - assert(message == "hello world"); - assert(hex_as_string == "0x41"); -} -``` - -You can convert a `str` to a byte array by calling `as_bytes()` -or a vector by calling `as_bytes_vec()`. - -```rust -fn main() { - let message = "hello world"; - let message_bytes = message.as_bytes(); - let mut message_vec = message.as_bytes_vec(); - assert(message_bytes.len() == 11); - assert(message_bytes[0] == 104); - assert(message_bytes[0] == message_vec.get(0)); -} -``` - -## Escape characters - -You can use escape characters for your strings: - -| Escape Sequence | Description | -|-----------------|-----------------| -| `\r` | Carriage Return | -| `\n` | Newline | -| `\t` | Tab | -| `\0` | Null Character | -| `\"` | Double Quote | -| `\\` | Backslash | - -Example: - -```rust -let s = "Hello \"world" // prints "Hello "world" -let s = "hey \tyou"; // prints "hey you" -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/04_arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/04_arrays.md deleted file mode 100644 index 3c84da3f8ad..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/04_arrays.md +++ /dev/null @@ -1,244 +0,0 @@ ---- -title: Arrays -description: - Dive into the Array data type in Noir. Grasp its methods, practical examples, and best practices for efficiently using Arrays in your Noir code. -keywords: - [ - noir, - array type, - methods, - examples, - indexing, - ] ---- - -An array is one way of grouping together values into one compound type. Array types can be inferred -or explicitly specified via the syntax `[; ]`: - -```rust -fn main(x : Field, y : Field) { - let my_arr = [x, y]; - let your_arr: [Field; 2] = [x, y]; -} -``` - -Here, both `my_arr` and `your_arr` are instantiated as an array containing two `Field` elements. - -Array elements can be accessed using indexing: - -```rust -fn main() { - let a = [1, 2, 3, 4, 5]; - - let first = a[0]; - let second = a[1]; -} -``` - -All elements in an array must be of the same type (i.e. homogeneous). That is, an array cannot group -a `Field` value and a `u8` value together for example. - -You can write mutable arrays, like: - -```rust -fn main() { - let mut arr = [1, 2, 3, 4, 5]; - assert(arr[0] == 1); - - arr[0] = 42; - assert(arr[0] == 42); -} -``` - -You can instantiate a new array of a fixed size with the same value repeated for each element. The following example instantiates an array of length 32 where each element is of type Field and has the value 0. - -```rust -let array: [Field; 32] = [0; 32]; -``` - -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: - -```rust -let array: [Field; 32] = [0; 32]; -let sl = array.as_slice() -``` - -You can define multidimensional arrays: - -```rust -let array : [[Field; 2]; 2]; -let element = array[0][0]; -``` - -## Types - -You can create arrays of primitive types or structs. There is not yet support for nested arrays -(arrays of arrays) or arrays of structs that contain arrays. - -## Methods - -For convenience, the STD provides some ready-to-use, common methods for arrays: - -### len - -Returns the length of an array - -```rust -fn len(_array: [T; N]) -> comptime Field -``` - -example - -```rust -fn main() { - let array = [42, 42]; - assert(array.len() == 2); -} -``` - -### sort - -Returns a new sorted array. The original array remains untouched. Notice that this function will -only work for arrays of fields or integers, not for any arbitrary type. This is because the sorting -logic it uses internally is optimized specifically for these values. If you need a sort function to -sort any type, you should use the function `sort_via` described below. - -```rust -fn sort(_array: [T; N]) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32]; - let sorted = arr.sort(); - assert(sorted == [32, 42]); -} -``` - -### sort_via - -Sorts the array with a custom comparison function - -```rust -fn sort_via(mut a: [T; N], ordering: fn(T, T) -> bool) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32] - let sorted_ascending = arr.sort_via(|a, b| a <= b); - assert(sorted_ascending == [32, 42]); // verifies - - let sorted_descending = arr.sort_via(|a, b| a >= b); - assert(sorted_descending == [32, 42]); // does not verify -} -``` - -### map - -Applies a function to each element of the array, returning a new array containing the mapped elements. - -```rust -fn map(f: fn(T) -> U) -> [U; N] -``` - -example - -```rust -let a = [1, 2, 3]; -let b = a.map(|a| a * 2); // b is now [2, 4, 6] -``` - -### fold - -Applies a function to each element of the array, returning the final accumulated value. The first -parameter is the initial value. - -```rust -fn fold(mut accumulator: U, f: fn(U, T) -> U) -> U -``` - -This is a left fold, so the given function will be applied to the accumulator and first element of -the array, then the second, and so on. For a given call the expected result would be equivalent to: - -```rust -let a1 = [1]; -let a2 = [1, 2]; -let a3 = [1, 2, 3]; - -let f = |a, b| a - b; -a1.fold(10, f) //=> f(10, 1) -a2.fold(10, f) //=> f(f(10, 1), 2) -a3.fold(10, f) //=> f(f(f(10, 1), 2), 3) -``` - -example: - -```rust - -fn main() { - let arr = [2, 2, 2, 2, 2]; - let folded = arr.fold(0, |a, b| a + b); - assert(folded == 10); -} - -``` - -### reduce - -Same as fold, but uses the first element as starting element. - -```rust -fn reduce(f: fn(T, T) -> T) -> T -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let reduced = arr.reduce(|a, b| a + b); - assert(reduced == 10); -} -``` - -### all - -Returns true if all the elements satisfy the given predicate - -```rust -fn all(predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let all = arr.all(|a| a == 2); - assert(all); -} -``` - -### any - -Returns true if any of the elements satisfy the given predicate - -```rust -fn any(predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 5]; - let any = arr.any(|a| a == 5); - assert(any); -} - -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/05_slices.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/05_slices.mdx deleted file mode 100644 index 1be0ec4a137..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/05_slices.mdx +++ /dev/null @@ -1,146 +0,0 @@ ---- -title: Slices -description: Explore the Slice data type in Noir. Understand its methods, see real-world examples, and learn how to effectively use Slices in your Noir programs. -keywords: [noir, slice type, methods, examples, subarrays] ---- - -import Experimental from '@site/src/components/Notes/_experimental.mdx'; - - - -A slice is a dynamically-sized view into a sequence of elements. They can be resized at runtime, but because they don't own the data, they cannot be returned from a circuit. You can treat slices as arrays without a constrained size. - -```rust -use dep::std::slice; - -fn main() -> pub Field { - let mut slice: [Field] = [0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -View the corresponding test file [here][test-file]. - -[test-file]: https://github.com/noir-lang/noir/blob/f387ec1475129732f72ba294877efdf6857135ac/crates/nargo_cli/tests/test_data_ssa_refactor/slices/src/main.nr - -## Methods - -For convenience, the STD provides some ready-to-use, common methods for slices: - -### push_back - -Pushes a new element to the end of the slice, returning a new slice with a length one greater than the original unmodified slice. - -```rust -fn push_back(_self: [T], _elem: T) -> [T] -``` - -example: - -```rust -fn main() -> pub Field { - let mut slice: [Field] = [0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -View the corresponding test file [here][test-file]. - -### push_front - -Returns a new array with the specified element inserted at index 0. The existing elements indexes are incremented by 1. - -```rust -fn push_front(_self: Self, _elem: T) -> Self -``` - -Example: - -```rust -let mut new_slice: [Field] = []; -new_slice = new_slice.push_front(20); -assert(new_slice[0] == 20); // returns true -``` - -View the corresponding test file [here][test-file]. - -### pop_front - -Returns a tuple of two items, the first element of the array and the rest of the array. - -```rust -fn pop_front(_self: Self) -> (T, Self) -``` - -Example: - -```rust -let (first_elem, rest_of_slice) = slice.pop_front(); -``` - -View the corresponding test file [here][test-file]. - -### pop_back - -Returns a tuple of two items, the beginning of the array with the last element omitted and the last element. - -```rust -fn pop_back(_self: Self) -> (Self, T) -``` - -Example: - -```rust -let (popped_slice, last_elem) = slice.pop_back(); -``` - -View the corresponding test file [here][test-file]. - -### append - -Loops over a slice and adds it to the end of another. - -```rust -fn append(mut self, other: Self) -> Self -``` - -Example: - -```rust -let append = [1, 2].append([3, 4, 5]); -``` - -### insert - -Inserts an element at a specified index and shifts all following elements by 1. - -```rust -fn insert(_self: Self, _index: Field, _elem: T) -> Self -``` - -Example: - -```rust -new_slice = rest_of_slice.insert(2, 100); -assert(new_slice[2] == 100); -``` - -View the corresponding test file [here][test-file]. - -### remove - -Remove an element at a specified index, shifting all elements after it to the left, returning the altered slice and the removed element. - -```rust -fn remove(_self: Self, _index: Field) -> (Self, T) -``` - -Example: - -```rust -let (remove_slice, removed_elem) = slice.remove(3); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/06_vectors.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/06_vectors.mdx deleted file mode 100644 index 4617e90d038..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/06_vectors.mdx +++ /dev/null @@ -1,172 +0,0 @@ ---- -title: Vectors -description: Delve into the Vector data type in Noir. Learn about its methods, practical examples, and best practices for using Vectors in your Noir code. -keywords: [noir, vector type, methods, examples, dynamic arrays] ---- - -import Experimental from '@site/src/components/Notes/_experimental.mdx'; - - - -A vector is a collection type similar to Rust's Vector type. It's convenient way to use slices as mutable arrays. - -Example: - -```rust -use dep::std::collections::vec::Vec; - -let mut vector: Vec = Vec::new(); -for i in 0..5 { - vector.push(i); -} -assert(vector.len() == 5); -``` - -## Methods - -### new - -Creates a new, empty vector. - -```rust -pub fn new() -> Self { - Self { slice: [] } -} -``` - -Example: - -```rust -let empty_vector: Vec = Vec::new(); -assert(empty_vector.len() == 0); -``` - -### from_slice - -Creates a vector containing each element from a given slice. Mutations to the resulting vector will not affect the original slice. - -```rust -pub fn from_slice(slice: [T]) -> Self { - Self { slice } -} -``` - -Example: - -```rust -let arr: [Field] = [1, 2, 3]; -let vector_from_slice = Vec::from_slice(arr); -assert(vector_from_slice.len() == 3); -``` - -### get - -Retrieves an element from the vector at a given index. Panics if the index points beyond the vector's end. - -```rust -pub fn get(self, index: Field) -> T { - self.slice[index] -} -``` - -Example: - -```rust -let vector: Vec = Vec::from_slice([10, 20, 30]); -assert(vector.get(1) == 20); -``` - -### push - -Adds a new element to the vector's end, returning a new vector with a length one greater than the original unmodified vector. - -```rust -pub fn push(&mut self, elem: T) { - self.slice = self.slice.push_back(elem); -} -``` - -Example: - -```rust -let mut vector: Vec = Vec::new(); -vector.push(10); -assert(vector.len() == 1); -``` - -### pop - -Removes an element from the vector's end, returning a new vector with a length one less than the original vector, along with the removed element. Panics if the vector's length is zero. - -```rust -pub fn pop(&mut self) -> T { - let (popped_slice, last_elem) = self.slice.pop_back(); - self.slice = popped_slice; - last_elem -} -``` - -Example: - -```rust -let mut vector = Vec::from_slice([10, 20]); -let popped_elem = vector.pop(); -assert(popped_elem == 20); -assert(vector.len() == 1); -``` - -### insert - -Inserts an element at a specified index, shifting subsequent elements to the right. - -```rust -pub fn insert(&mut self, index: Field, elem: T) { - self.slice = self.slice.insert(index, elem); -} -``` - -Example: - -```rust -let mut vector = Vec::from_slice([10, 30]); -vector.insert(1, 20); -assert(vector.get(1) == 20); -``` - -### remove - -Removes an element at a specified index, shifting subsequent elements to the left, and returns the removed element. - -```rust -pub fn remove(&mut self, index: Field) -> T { - let (new_slice, elem) = self.slice.remove(index); - self.slice = new_slice; - elem -} -``` - -Example: - -```rust -let mut vector = Vec::from_slice([10, 20, 30]); -let removed_elem = vector.remove(1); -assert(removed_elem == 20); -assert(vector.len() == 2); -``` - -### len - -Returns the number of elements in the vector. - -```rust -pub fn len(self) -> Field { - self.slice.len() -} -``` - -Example: - -```rust -let empty_vector: Vec = Vec::new(); -assert(empty_vector.len() == 0); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/07_tuples.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/07_tuples.md deleted file mode 100644 index 5f6cab974a8..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/07_tuples.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: Tuples -description: - Dive into the Tuple data type in Noir. Understand its methods, practical examples, and best practices for efficiently using Tuples in your Noir code. -keywords: - [ - noir, - tuple type, - methods, - examples, - multi-value containers, - ] ---- - -A tuple collects multiple values like an array, but with the added ability to collect values of -different types: - -```rust -fn main() { - let tup: (u8, u64, Field) = (255, 500, 1000); -} -``` - -One way to access tuple elements is via destructuring using pattern matching: - -```rust -fn main() { - let tup = (1, 2); - - let (one, two) = tup; - - let three = one + two; -} -``` - -Another way to access tuple elements is via direct member access, using a period (`.`) followed by -the index of the element we want to access. Index `0` corresponds to the first tuple element, `1` to -the second and so on: - -```rust -fn main() { - let tup = (5, 6, 7, 8); - - let five = tup.0; - let eight = tup.3; -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/08_structs.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/08_structs.md deleted file mode 100644 index 9255455bdcb..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/08_structs.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -title: Structs -description: - Explore the Struct data type in Noir. Learn about its methods, see real-world examples, and grasp how to effectively define and use Structs in your Noir programs. -keywords: - [ - noir, - struct type, - methods, - examples, - data structures, - ] ---- - -A struct also allows for grouping multiple values of different types. Unlike tuples, we can also -name each field. - -> **Note:** The usage of _field_ here refers to each element of the struct and is unrelated to the -> field type of Noir. - -Defining a struct requires giving it a name and listing each field within as `: ` pairs: - -```rust -struct Animal { - hands: Field, - legs: Field, - eyes: u8, -} -``` - -An instance of a struct can then be created with actual values in `: ` pairs in any -order. Struct fields are accessible using their given names: - -```rust -fn main() { - let legs = 4; - - let dog = Animal { - eyes: 2, - hands: 0, - legs, - }; - - let zero = dog.hands; -} -``` - -Structs can also be destructured in a pattern, binding each field to a new variable: - -```rust -fn main() { - let Animal { hands, legs: feet, eyes } = get_octopus(); - - let ten = hands + feet + eyes as u8; -} - -fn get_octopus() -> Animal { - let octopus = Animal { - hands: 0, - legs: 8, - eyes: 2, - }; - - octopus -} -``` - -The new variables can be bound with names different from the original struct field names, as -showcased in the `legs --> feet` binding in the example above. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/09_references.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/09_references.md deleted file mode 100644 index b0c35ce2cb9..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/09_references.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: References ---- - -Noir supports first-class references. References are a bit like pointers: they point to a specific address that can be followed to access the data stored at that address. You can use Rust-like syntax to use pointers in Noir: the `&` operator references the variable, the `*` operator dereferences it. - -Example: - -```rust -fn main() { - let mut x = 2; - - // you can reference x as &mut and pass it to multiplyBy2 - multiplyBy2(&mut x); -} - -// you can access &mut here -fn multiplyBy2(x: &mut Field) { - // and dereference it with * - *x = *x * 2; -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/10_function_types.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/10_function_types.md deleted file mode 100644 index 1ec92efd594..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/10_function_types.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: Function types ---- - -Noir supports higher-order functions. The syntax for a function type is as follows: - -```rust -fn(arg1_type, arg2_type, ...) -> return_type -``` - -Example: - -```rust -fn assert_returns_100(f: fn() -> Field) { // f takes no args and returns a Field - assert(f() == 100); -} - -fn main() { - assert_returns_100(|| 100); // ok - assert_returns_100(|| 150); // fails -} -``` - -A function type also has an optional capture environment - this is necessary to support closures. -See [Lambdas](../08_lambdas.md) for more details. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/migration_notes.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/migration_notes.md deleted file mode 100644 index 905bca3d30c..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/migration_notes.md +++ /dev/null @@ -1,91 +0,0 @@ ---- -title: Migration notes -description: Read about migration notes from previous versions, which could solve problems while updating -keywords: [Noir, notes, migration, updating, upgrading] ---- - -Noir is in full-speed development. Things break fast, wild, and often. This page attempts to leave some notes on errors you might encounter when upgrading and how to resolve them until proper patches are built. - -## ≥0.19 - -### Enforcing `compiler_version` - -From this version on, the compiler will check for the `compiler_version` field in `Nargo.toml`, and will error if it doesn't match the current Nargo version in use. - -To update, please make sure this field in `Nargo.toml` matches the output of `nargo --version`. - -## ≥0.14 - -The index of the [for loops](./language_concepts/02_control_flow.md#loops) is now of type `u64` instead of `Field`. An example refactor would be: - -```rust -for i in 0..10 { - let i = i as Field; -} -``` - -## ≥v0.11.0 and Nargo backend - -From this version onwards, Nargo starts managing backends through the `nargo backend` command. Upgrading to the versions per usual steps might lead to: - -### `backend encountered an error` - -This is likely due to the existing locally installed version of proving backend (e.g. barretenberg) is incompatible with the version of Nargo in use. - -To fix the issue: - -1. Uninstall the existing backend - -```bash -nargo backend uninstall acvm-backend-barretenberg -``` - -You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. - -2. Reinstall a compatible version of the proving backend. - -If you are using the default barretenberg backend, simply run: - -``` -nargo prove -``` - -with your Noir program. - -This will trigger the download and installation of the latest version of barretenberg compatible with your Nargo in use. - -### `backend encountered an error: illegal instruction` - -On certain Intel-based systems, an `illegal instruction` error may arise due to incompatibility of barretenberg with certain CPU instructions. - -To fix the issue: - -1. Uninstall the existing backend - -```bash -nargo backend uninstall acvm-backend-barretenberg -``` - -You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. - -2. Reinstall a compatible version of the proving backend. - -If you are using the default barretenberg backend, simply run: - -``` -nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/barretenberg-js-binary/raw/master/run-bb.tar.gz -``` - -This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. - -The gzipped file is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. - -Then run: - -``` -DESIRED_BINARY_VERSION=0.8.1 nargo info -``` - -This overrides the bb native binary with a bb.js node application instead, which should be compatible with most if not all hardware. This does come with the drawback of being generally slower than native binary. - -0.8.1 indicates bb.js version 0.8.1, so if you change that it will update to a different version or the default version in the script if none was supplied. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/modules_packages_crates/crates_and_packages.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/modules_packages_crates/crates_and_packages.md deleted file mode 100644 index 23f60855c30..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/modules_packages_crates/crates_and_packages.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Crates and Packages -description: Learn how to use Crates and Packages in your Noir project -keywords: [Nargo, dependencies, package management, crates, package] ---- - -## Crates - -A crate is the smallest amount of code that the Noir compiler considers at a time. -Crates can contain modules, and the modules may be defined in other files that get compiled with the crate, as we’ll see in the coming sections. - -### Crate Types - -A Noir crate can come in several forms: binaries, libraries or contracts. - -#### Binaries - -_Binary crates_ are programs which you can compile to an ACIR circuit which you can then create proofs against. Each must have a function called `main` that defines the ACIR circuit which is to be proved. - -#### Libraries - -_Library crates_ don't have a `main` function and they don't compile down to ACIR. Instead they define functionality intended to be shared with multiple projects, and eventually included in a binary crate. - -#### Contracts - -Contract crates are similar to binary crates in that they compile to ACIR which you can create proofs against. They are different in that they do not have a single `main` function, but are a collection of functions to be deployed to the [Aztec network](https://aztec.network). You can learn more about the technical details of Aztec in the [monorepo](https://github.com/AztecProtocol/aztec-packages) or contract [examples](https://github.com/AztecProtocol/aztec-packages/tree/master/noir-projects/noir-contracts/contracts). - -### Crate Root - -Every crate has a root, which is the source file that the compiler starts, this is also known as the root module. The Noir compiler does not enforce any conditions on the name of the file which is the crate root, however if you are compiling via Nargo the crate root must be called `lib.nr` or `main.nr` for library or binary crates respectively. - -## Packages - -A Nargo _package_ is a collection of one of more crates that provides a set of functionality. A package must include a Nargo.toml file. - -A package _must_ contain either a library or a binary crate, but not both. - -### Differences from Cargo Packages - -One notable difference between Rust's Cargo and Noir's Nargo is that while Cargo allows a package to contain an unlimited number of binary crates and a single library crate, Nargo currently only allows a package to contain a single crate. - -In future this restriction may be lifted to allow a Nargo package to contain both a binary and library crate or multiple binary crates. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/modules_packages_crates/dependencies.md deleted file mode 100644 index 87a09293ea8..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/modules_packages_crates/dependencies.md +++ /dev/null @@ -1,123 +0,0 @@ ---- -title: Dependencies -description: - Learn how to specify and manage dependencies in Nargo, allowing you to upload packages to GitHub - and use them easily in your project. -keywords: [Nargo, dependencies, GitHub, package management, versioning] ---- - -Nargo allows you to upload packages to GitHub and use them as dependencies. - -## Specifying a dependency - -Specifying a dependency requires a tag to a specific commit and the git url to the url containing -the package. - -Currently, there are no requirements on the tag contents. If requirements are added, it would follow -semver 2.0 guidelines. - -> Note: Without a `tag` , there would be no versioning and dependencies would change each time you -> compile your project. - -For example, to add the [ecrecover-noir library](https://github.com/colinnielsen/ecrecover-noir) to your project, add it to `Nargo.toml`: - -```toml -# Nargo.toml - -[dependencies] -ecrecover = {tag = "v0.8.0", git = "https://github.com/colinnielsen/ecrecover-noir"} -``` - -If the module is in a subdirectory, you can define a subdirectory in your git repository, for example: - -```toml -# Nargo.toml - -[dependencies] -easy_private_token_contract = {tag ="v0.1.0-alpha62", git = "https://github.com/AztecProtocol/aztec-packages", directory = "yarn-project/noir-contracts/contracts/easy_private_token_contract"} -``` - -## Specifying a local dependency - -You can also specify dependencies that are local to your machine. - -For example, this file structure has a library and binary crate - -```tree -├── binary_crate -│   ├── Nargo.toml -│   └── src -│   └── main.nr -└── lib_a - ├── Nargo.toml - └── src - └── lib.nr -``` - -Inside of the binary crate, you can specify: - -```toml -# Nargo.toml - -[dependencies] -lib_a = { path = "../lib_a" } -``` - -## Importing dependencies - -You can import a dependency to a Noir file using the following syntax. For example, to import the -ecrecover-noir library and local lib_a referenced above: - -```rust -use dep::ecrecover; -use dep::lib_a; -``` - -You can also import only the specific parts of dependency that you want to use, like so: - -```rust -use dep::std::hash::sha256; -use dep::std::scalar_mul::fixed_base_embedded_curve; -``` - -Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you -can import multiple items in the same line by enclosing them in curly braces: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; -``` - -We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. - -Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. - -## Dependencies of Dependencies - -Note that when you import a dependency, you also get access to all of the dependencies of that package. - -For example, the [phy_vector](https://github.com/resurgencelabs/phy_vector) library imports an [fraction](https://github.com/resurgencelabs/fraction) library. If you're importing the phy_vector library, then you can access the functions in fractions library like so: - -```rust -use dep::phy_vector; - -fn main(x : Field, y : pub Field) { - //... - let f = phy_vector::fraction::toFraction(true, 2, 1); - //... -} -``` - -## Available Libraries - -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). - -Some libraries that are available today include: - -- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library -- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) -- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers -- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address -- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees -- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir -- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/modules_packages_crates/modules.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/modules_packages_crates/modules.md deleted file mode 100644 index 11e60cbf35e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/modules_packages_crates/modules.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: Modules -description: - Learn how to organize your files using modules in Noir, following the same convention as Rust's - module system. Examples included. -keywords: [Noir, Rust, modules, organizing files, sub-modules] ---- - -Noir's module system follows the same convention as the _newer_ version of Rust's module system. - -## Purpose of Modules - -Modules are used to organize files. Without modules all of your code would need to live in a single -file. In Noir, the compiler does not automatically scan all of your files to detect modules. This -must be done explicitly by the developer. - -## Examples - -### Importing a module in the crate root - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::hello_world(); -} -``` - -Filename : `src/foo.nr` - -```rust -fn from_foo() {} -``` - -In the above snippet, the crate root is the `src/main.nr` file. The compiler sees the module -declaration `mod foo` which prompts it to look for a foo.nr file. - -Visually this module hierarchy looks like the following : - -``` -crate - ├── main - │ - └── foo - └── from_foo - -``` - -### Importing a module throughout the tree - -All modules are accessible from the `crate::` namespace. - -``` -crate - ├── bar - ├── foo - └── main - -``` - -In the above snippet, if `bar` would like to use functions in `foo`, it can do so by `use crate::foo::function_name`. - -### Sub-modules - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::from_foo(); -} -``` - -Filename : `src/foo.nr` - -```rust -mod bar; -fn from_foo() {} -``` - -Filename : `src/foo/bar.nr` - -```rust -fn from_bar() {} -``` - -In the above snippet, we have added an extra module to the module tree; `bar`. `bar` is a submodule -of `foo` hence we declare bar in `foo.nr` with `mod bar`. Since `foo` is not the crate root, the -compiler looks for the file associated with the `bar` module in `src/foo/bar.nr` - -Visually the module hierarchy looks as follows: - -``` -crate - ├── main - │ - └── foo - ├── from_foo - └── bar - └── from_bar -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/modules_packages_crates/workspaces.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/modules_packages_crates/workspaces.md deleted file mode 100644 index 8168793fc80..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/modules_packages_crates/workspaces.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -title: Workspaces ---- - -Workspaces are a feature of nargo that allow you to manage multiple related Noir packages in a single repository. A workspace is essentially a group of related projects that share common build output directories and configurations. - -Each Noir project (with it's own Nargo.toml file) can be thought of as a package. Each package is expected to contain exactly one "named circuit", being the "name" defined in Nargo.toml with the program logic defined in `./src/main.nr`. - -For a project with the following structure: - -```tree -├── crates -│ ├── a -│ │ ├── Nargo.toml -│ │ └── Prover.toml -│ │ └── src -│ │ └── main.nr -│ └── b -│ ├── Nargo.toml -│ └── Prover.toml -│ └── src -│ └── main.nr -│ -└── Nargo.toml -``` - -You can define a workspace in Nargo.toml like so: - -```toml -[workspace] -members = ["crates/a", "crates/b"] -default-member = "crates/a" -``` - -`members` indicates which packages are included in the workspace. As such, all member packages of a workspace will be processed when the `--workspace` flag is used with various commands or if a `default-member` is not specified. - -`default-member` indicates which package various commands process by default. - -Libraries can be defined in a workspace. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. - -Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/nargo/01_commands.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/nargo/01_commands.md deleted file mode 100644 index e2b0af522f4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/nargo/01_commands.md +++ /dev/null @@ -1,250 +0,0 @@ ---- -title: Commands -description: - Noir CLI Commands for Noir Prover and Verifier to create, execute, prove and verify programs, - generate Solidity verifier smart contract and compile into JSON file containing ACIR - representation and ABI of circuit. -keywords: - [ - Nargo, - Noir CLI, - Noir Prover, - Noir Verifier, - generate Solidity verifier, - compile JSON file, - ACIR representation, - ABI of circuit, - TypeScript, - ] ---- - -## General options - -| Option | Description | -| -------------------- | -------------------------------------------------- | -| `--show-ssa` | Emit debug information for the intermediate SSA IR | -| `--deny-warnings` | Quit execution when warnings are emitted | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo help [subcommand]` - -Prints the list of available commands or specific information of a subcommand. - -_Arguments_ - -| Argument | Description | -| -------------- | -------------------------------------------- | -| `` | The subcommand whose help message to display | - -## `nargo backend` - -Installs and selects custom backends used to generate and verify proofs. - -### Commands - -| Command | Description | -| ----------- | --------------------------------------------------------- | -| `current` | Prints the name of the currently active backend | -| `ls` | Prints the list of currently installed backends | -| `use` | Select the backend to use | -| `install` | Install a new backend from a URL | -| `uninstall` | Uninstalls a backend | -| `help` | Print this message or the help of the given subcommand(s) | - -### Options - -| Option | Description | -| ------------ | ----------- | -| `-h, --help` | Print help | - -## `nargo check` - -Generate the `Prover.toml` and `Verifier.toml` files for specifying prover and verifier in/output -values of the Noir program respectively. - -### Options - -| Option | Description | -| --------------------- | ------------------------------------- | -| `--package ` | The name of the package to check | -| `--workspace` | Check all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -### `nargo codegen-verifier` - -Generate a Solidity verifier smart contract for the program. - -### Options - -| Option | Description | -| --------------------- | ------------------------------------- | -| `--package ` | The name of the package to codegen | -| `--workspace` | Codegen all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo compile` - -Compile the program into a JSON build artifact file containing the ACIR representation and the ABI -of the circuit. This build artifact can then be used to generate and verify proofs. - -You can also use "build" as an alias for compile (e.g. `nargo build`). - -### Options - -| Option | Description | -| --------------------- | ------------------------------------------------------------ | -| `--include-keys` | Include Proving and Verification keys in the build artifacts | -| `--package ` | The name of the package to compile | -| `--workspace` | Compile all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo new ` - -Creates a new Noir project in a new folder. - -**Arguments** - -| Argument | Description | -| -------- | -------------------------------- | -| `` | The path to save the new project | - -### Options - -| Option | Description | -| --------------- | ----------------------------------------------------- | -| `--name ` | Name of the package [default: package directory name] | -| `--lib` | Use a library template | -| `--bin` | Use a binary template [default] | -| `--contract` | Use a contract template | -| `-h, --help` | Print help | - -## `nargo init` - -Creates a new Noir project in the current directory. - -### Options - -| Option | Description | -| --------------- | ----------------------------------------------------- | -| `--name ` | Name of the package [default: current directory name] | -| `--lib` | Use a library template | -| `--bin` | Use a binary template [default] | -| `--contract` | Use a contract template | -| `-h, --help` | Print help | - -## `nargo execute [WITNESS_NAME]` - -Runs the Noir program and prints its return value. - -**Arguments** - -| Argument | Description | -| ---------------- | ----------------------------------------- | -| `[WITNESS_NAME]` | Write the execution witness to named file | - -### Options - -| Option | Description | -| --------------------------------- | ------------------------------------------------------------------------------------ | -| `-p, --prover-name ` | The name of the toml file which contains the inputs for the prover [default: Prover] | -| `--package ` | The name of the package to execute | -| `--workspace` | Execute all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -_Usage_ - -The inputs to the circuit are read from the `Prover.toml` file generated by `nargo check`, which -must be filled in. - -To save the witness to file, run the command with a value for the `WITNESS_NAME` argument. A -`.tr` file will then be saved in the `./target` folder. - -## `nargo prove` - -Creates a proof for the program. - -### Options - -| Option | Description | -| ------------------------------------- | ---------------------------------------------------------------------------------------- | -| `-p, --prover-name ` | The name of the toml file which contains the inputs for the prover [default: Prover] | -| `-v, --verifier-name ` | The name of the toml file which contains the inputs for the verifier [default: Verifier] | -| `--verify` | Verify proof after proving | -| `--package ` | The name of the package to prove | -| `--workspace` | Prove all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo verify` - -Given a proof and a program, verify whether the proof is valid. - -### Options - -| Option | Description | -| ------------------------------------- | ---------------------------------------------------------------------------------------- | -| `-v, --verifier-name ` | The name of the toml file which contains the inputs for the verifier [default: Verifier] | -| `--package ` | The name of the package to verify | -| `--workspace` | Verify all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo test [TEST_NAME]` - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. To print `println` statements in tests, use the `--show-output` flag. - -Takes an optional `--exact` flag which allows you to select tests based on an exact name. - -See an example on the [testing page](./testing.md). - -### Options - -| Option | Description | -| --------------------- | -------------------------------------- | -| `--show-output` | Display output of `println` statements | -| `--exact` | Only run tests that match exactly | -| `--package ` | The name of the package to test | -| `--workspace` | Test all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo info` - -Prints a table containing the information of the package. - -Currently the table provide - -1. The number of ACIR opcodes -2. The final number gates in the circuit used by a backend - -If the file contains a contract the table will provide the -above information about each function of the contract. - -## `nargo lsp` - -Start a long-running Language Server process that communicates over stdin/stdout. -Usually this command is not run by a user, but instead will be run by a Language Client, such as [vscode-noir](https://github.com/noir-lang/vscode-noir). - -## `nargo fmt` - -Automatically formats your Noir source code based on the default formatting settings. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/nargo/02_testing.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/nargo/02_testing.md deleted file mode 100644 index 5c57ef92705..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/nargo/02_testing.md +++ /dev/null @@ -1,61 +0,0 @@ ---- -title: Testing in Noir -description: Learn how to use Nargo to test your Noir program in a quick and easy way -keywords: [Nargo, testing, Noir, compile, test] ---- - -You can test your Noir programs using Noir circuits. - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. - -For example if you have a program like: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test] -fn test_add() { - assert(add(2,2) == 4); - assert(add(0,1) == 1); - assert(add(1,0) == 1); -} -``` - -Running `nargo test` will test that the `test_add` function can be executed while satisfying all -the constraints which allows you to test that add returns the expected values. Test functions can't -have any arguments currently. - -### Test fail - -You can write tests that are expected to fail by using the decorator `#[test(should_fail)]`. For example: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test(should_fail)] -fn test_add() { - assert(add(2,2) == 5); -} -``` - -You can be more specific and make it fail with a specific reason by using `should_fail_with = "`: - -```rust -fn main(african_swallow_avg_speed : Field) { - assert(african_swallow_avg_speed == 65, "What is the airspeed velocity of an unladen swallow"); -} - -#[test] -fn test_king_arthur() { - main(65); -} - -#[test(should_fail_with = "What is the airspeed velocity of an unladen swallow")] -fn test_bridgekeeper() { - main(32); -} - -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/nargo/03_solidity_verifier.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/nargo/03_solidity_verifier.md deleted file mode 100644 index 9ac60cb0ba7..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/nargo/03_solidity_verifier.md +++ /dev/null @@ -1,129 +0,0 @@ ---- -title: Solidity Verifier -description: - Learn how to run the verifier as a smart contract on the blockchain. Compile a Solidity verifier - contract for your Noir program and deploy it on any EVM blockchain acting as a verifier smart - contract. Read more to find out! -keywords: - [ - solidity verifier, - smart contract, - blockchain, - compiler, - plonk_vk.sol, - EVM blockchain, - verifying Noir programs, - proving backend, - Barretenberg, - ] ---- - -For certain applications, it may be desirable to run the verifier as a smart contract instead of on -a local machine. - -Compile a Solidity verifier contract for your Noir program by running: - -```sh -nargo codegen-verifier -``` - -A new `contract` folder would then be generated in your project directory, containing the Solidity -file `plonk_vk.sol`. It can be deployed on any EVM blockchain acting as a verifier smart contract. - -> **Note:** It is possible to compile verifier contracts of Noir programs for other smart contract -> platforms as long as the proving backend supplies an implementation. -> -> Barretenberg, the default proving backend for Nargo, supports compilation of verifier contracts in -> Solidity only for the time being. - -## Verify - -To verify a proof using the Solidity verifier contract, call the `verify` function with the -following signature: - -```solidity -function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) -``` - -You can see an example of how the `verify` function is called in the example zk voting application [here](https://github.com/noir-lang/noir-examples/blob/33e598c257e2402ea3a6b68dd4c5ad492bce1b0a/foundry-voting/src/zkVote.sol#L35): - -```solidity -function castVote(bytes calldata proof, uint proposalId, uint vote, bytes32 nullifierHash) public returns (bool) { - // ... - bytes32[] memory publicInputs = new bytes32[](4); - publicInputs[0] = merkleRoot; - publicInputs[1] = bytes32(proposalId); - publicInputs[2] = bytes32(vote); - publicInputs[3] = nullifierHash; - require(verifier.verify(proof, publicInputs), "Invalid proof"); -``` - -### Public Inputs - -:::tip - -A circuit doesn't have the concept of a return value. Return values are just syntactic sugar in -Noir. - -Under the hood, the return value is passed as an input to the circuit and is checked at the end of -the circuit program. - -::: - -The verifier contract uses the output (return) value of a Noir program as a public input. So if you -have the following function - -```rust -fn main( - // Public inputs - pubkey_x: pub Field, - pubkey_y: pub Field, - // Private inputs - priv_key: Field, -) -> pub Field -``` - -then `verify` in `plonk_vk.sol` will expect 3 public inputs. Passing two inputs will result in an -error like `Reason: PUBLIC_INPUT_COUNT_INVALID(3, 2)`. - -In this case the 3 inputs to `verify` would be ordered as `[pubkey_x, pubkey_y, return]`. - -#### Struct inputs - -Consider the following program: - -```rust -struct Type1 { - val1: Field, - val2: Field, -} - -struct Nested { - t1: Type1, - is_true: bool, -} - -fn main(x: pub Field, nested: pub Nested, y: pub Field) { - //... -} -``` - -Structs will be flattened so that the array of inputs is 1-dimensional array. The order of these inputs would be flattened to: `[x, nested.t1.val1, nested.t1.val2, nested.is_true, y]` - -## Noir for EVM chains - -You can currently deploy the Solidity verifier contracts to most EVM compatible chains. EVM chains that have been tested and are known to work include: - -- Optimism -- Arbitrum -- Polygon PoS -- Scroll -- Celo - -Other EVM chains should work, but have not been tested directly by our team. If you test any other chains, please open a PR on this page to update the list. See [this doc](https://github.com/noir-lang/noir-starter/tree/main/with-foundry#testing-on-chain) for more info about testing verifier contracts on different EVM chains. - -### Unsupported chains - -Unfortunately not all "EVM" chains are supported. - -**zkSync** and the **Polygon zkEVM** do _not_ currently support proof verification via Solidity verifier contracts. They are missing the bn256 precompile contract that the verifier contract requires. Once these chains support this precompile, they may work. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/nargo/04_language_server.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/nargo/04_language_server.md deleted file mode 100644 index 48c01465f6e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/nargo/04_language_server.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Language Server -description: Learn about the Noir Language Server, how to install the components, and configuration that may be required. -keywords: [Nargo, Language Server, LSP, VSCode, Visual Studio Code] ---- - -This section helps you install and configure the Noir Language Server. - -The Language Server Protocol (LSP) has two components, the [Server](#language-server) and the [Client](#language-client). Below we describe each in the context of Noir. - -## Language Server - -The Server component is provided by the Nargo command line tool that you installed at the beginning of this guide. -As long as Nargo is installed and you've used it to run other commands in this guide, it should be good to go! - -If you'd like to verify that the `nargo lsp` command is available, you can run `nargo --help` and look for `lsp` in the list of commands. If you see it, you're using a version of Noir with LSP support. - -## Language Client - -The Client component is usually an editor plugin that launches the Server. It communicates LSP messages between the editor and the Server. For example, when you save a file, the Client will alert the Server, so it can try to compile the project and report any errors. - -Currently, Noir provides a Language Client for Visual Studio Code via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). - -> **Note:** Noir's Language Server Protocol support currently assumes users' VSCode workspace root to be the same as users' Noir project root (i.e. where Nargo.toml lies). -> -> If LSP features seem to be missing / malfunctioning, make sure you are opening your Noir project directly (instead of as a sub-folder) in your VSCode instance. - -When your language server is running correctly and the VSCode plugin is installed, you should see handy codelens buttons for compilation, measuring circuit size, execution, and tests: - -![Compile and Execute](@site/static/img/codelens_compile_execute.png) -![Run test](@site/static/img/codelens_run_test.png) - -You should also see your tests in the `testing` panel: - -![Testing panel](@site/static/img/codelens_testing_panel.png) - -### Configuration - -- **Noir: Enable LSP** - If checked, the extension will launch the Language Server via `nargo lsp` and communicate with it. -- **Noir: Nargo Flags** - Additional flags may be specified if you require them to be added when the extension calls `nargo lsp`. -- **Noir: Nargo Path** - An absolute path to a Nargo binary with the `lsp` command. This may be useful if Nargo is not within the `PATH` of your editor. -- **Noir > Trace: Server** - Setting this to `"messages"` or `"verbose"` will log LSP messages between the Client and Server. Useful for debugging. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/getting_started/01_tiny_noir_app.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/getting_started/01_tiny_noir_app.md deleted file mode 100644 index 64ba4a2c44a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/getting_started/01_tiny_noir_app.md +++ /dev/null @@ -1,260 +0,0 @@ ---- -title: End-to-end -description: Learn how to setup a new app that uses Noir to generate and verify zero-knowledge SNARK proofs in a typescript or javascript environment -keywords: [how to, guide, javascript, typescript, noir, barretenberg, zero-knowledge, proofs] ---- - -NoirJS works both on the browser and on the server, and works for both ESM and CJS module systems. In this page, we will learn how can we write a simple test and a simple web app to verify the standard Noir example. - -You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). - -## Before we start - -:::note - -Feel free to use whatever versions, just keep in mind that Nargo and the NoirJS packages are meant to be in sync. For example, Nargo 0.18.x matches `noir_js@0.18.x`, etc. - -In this guide, we will be pinned to 0.17.0. - -::: - -Make sure you have Node installed on your machine by opening a terminal and executing `node --version`. If you don't see a version, you should install [node](https://github.com/nvm-sh/nvm). You can also use `yarn` if you prefer that package manager over npm (which comes with node). - -First of all, follow the [Nargo guide](../../getting_started/00_nargo_installation.md) to install nargo version 0.17.0 and create a new project with `nargo new circuit`. Once there, `cd` into the `circuit` folder. You should then be able to compile your circuit into `json` format and see it inside the `target` folder: - -```bash -nargo compile -``` - -Your folder structure should look like: - -```tree -. -└── circuit - ├── Nargo.toml - ├── src - │ └── main.nr - └── target - └── circuit.json -``` - -## Starting a new project - -Go back to the previous folder and start a new project by running run `npm init`. You can configure your project or just leave the defaults, and see a `package.json` appear in your root folder. - -## Installing dependencies - -We'll need two `npm` packages. These packages will provide us the methods we need to run and verify proofs: - -```bash -npm i @noir-lang/backend_barretenberg@^0.17.0 @noir-lang/noir_js@^0.17.0 -``` - -To serve our page, we can use a build tool such as `vite`. Because we're gonna use some `wasm` files, we need to install a plugin as well. Run: - -```bash -npm i --save-dev vite rollup-plugin-copy -``` - -Since we're on the dependency world, we may as well define a nice starting script. Vite makes it easy. Just open `package.json`, find the block "scripts" and add this just below the line with `"test" : "echo......."`: - -```json - "start": "vite --open" -``` - -If you want do build a static website, you can also add some build and preview scripts: - -```json - "build": "vite build", - "preview": "vite preview" -``` - -## Vite plugins - -Vite is great, but support from `wasm` doesn't work out-of-the-box. We're gonna write a quick plugin and use another one. Just copy and paste this into a file named `vite.config.js`. You don't need to understand it, just trust me bro. - -```js -import { defineConfig } from 'vite'; -import copy from 'rollup-plugin-copy'; -import fs from 'fs'; -import path from 'path'; - -const wasmContentTypePlugin = { - name: 'wasm-content-type-plugin', - configureServer(server) { - server.middlewares.use(async (req, res, next) => { - if (req.url.endsWith('.wasm')) { - res.setHeader('Content-Type', 'application/wasm'); - const newPath = req.url.replace('deps', 'dist'); - const targetPath = path.join(__dirname, newPath); - const wasmContent = fs.readFileSync(targetPath); - return res.end(wasmContent); - } - next(); - }); - }, -}; - -export default defineConfig(({ command }) => { - if (command === 'serve') { - return { - plugins: [ - copy({ - targets: [{ src: 'node_modules/**/*.wasm', dest: 'node_modules/.vite/dist' }], - copySync: true, - hook: 'buildStart', - }), - command === 'serve' ? wasmContentTypePlugin : [], - ], - }; - } - - return {}; -}); -``` - -## HTML - -Here's the simplest HTML with some terrible UI. Create a file called `index.html` and paste this: - -```html - - - - - - -

Very basic Noir app

-
-

Logs

-

Proof

-
- - -``` - -## Some good old vanilla Javascript - -Create a new file `app.js`, which is where our javascript code will live. Let's start with this code inside: - -```js -document.addEventListener('DOMContentLoaded', async () => { - // here's where the magic happens -}); - -function display(container, msg) { - const c = document.getElementById(container); - const p = document.createElement('p'); - p.textContent = msg; - c.appendChild(p); -} -``` - -We can manipulate our website with this little function, so we can see our website working. - -## Adding Noir - -If you come from the previous page, your folder structure should look like this: - -```tree -├── app.js -├── circuit -│ ├── Nargo.toml -│ ├── src -│ │ └── main.nr -│ └── target -│ └── circuit.json -├── index.html -├── package.json -└── vite.config.js -``` - -You'll see other files and folders showing up (like `package-lock.json`, `yarn.lock`, `node_modules`) but you shouldn't have to care about those. - -## Importing our dependencies - -We're starting with the good stuff now. At the top of the new javascript file, import the packages: - -```ts -import { BarretenbergBackend } from '@noir-lang/backend_barretenberg'; -import { Noir } from '@noir-lang/noir_js'; -``` - -We also need to import the `circuit` JSON file we created. If you have the suggested folder structure, you can add this line: - -```ts -import circuit from './circuit/target/circuit.json'; -``` - -## Write code - -:::note - -We're gonna be adding code inside the `document.addEventListener...etc` block: - -```js -// forget stuff here -document.addEventListener('DOMContentLoaded', async () => { - // here's where the magic happens -}); -// forget stuff here -``` - -::: - -Our dependencies exported two classes: `BarretenbergBackend` and `Noir`. Let's `init` them and add some logs, just to flex: - -```ts -const backend = new BarretenbergBackend(circuit); -const noir = new Noir(circuit, backend); -``` - -## Proving - -Now we're ready to prove stuff! Let's feed some inputs to our circuit and calculate the proof: - -```js -const input = { x: 1, y: 2 }; -display('logs', 'Generating proof... ⌛'); -const proof = await noir.generateFinalProof(input); -display('logs', 'Generating proof... ✅'); -display('results', proof.proof); -``` - -You're probably eager to see stuff happening, so go and run your app now! - -From your terminal, run `npm start` (or `yarn start`). If it doesn't open a browser for you, just visit `localhost:5173`. On a modern laptop, proof will generate in less than 100ms, and you'll see this: - -![Getting Started 0](@site/static/img/noir_getting_started_1.png) - -If you're human, you shouldn't be able to understand anything on the "proof" box. That's OK. We like you, human. - -In any case, this means your proof was generated! But you shouldn't trust me just yet. Add these lines to see it being verified: - -```js -display('logs', 'Verifying proof... ⌛'); -const verification = await noir.verifyFinalProof(proof); -if (verification) display('logs', 'Verifying proof... ✅'); -``` - -By saving, your app will refresh and here's our complete Tiny Noir App! - -You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). - -## Further Reading - -You can see how noirjs is used in a full stack Next.js hardhat application in the [noir-starter repo here](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat). The example shows how to calculate a proof in the browser and verify it with a deployed Solidity verifier contract from noirjs. - -You should also check out the more advanced examples in the [noir-examples repo](https://github.com/noir-lang/noir-examples), where you'll find reference usage for some cool apps. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/noir_js.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/noir_js.md deleted file mode 100644 index f895b22eaf8..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/noir_js.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: NoirJS -description: Interact with Noir in Typescript or Javascript -keywords: [Noir project, javascript, typescript, node.js, browser, react] ---- - -NoirJS is a TypeScript library that make it easy to use Noir on your dapp, webapp, Node.js server, website, etc. - -A typical workflow would be composed of two major elements: - -- NoirJS -- Proving backend of choice's JavaScript package - - - -To install NoirJS, install Node.js if you have not already and run this in your JavaScript project: - -```bash -npm i @noir-lang/noir_js -``` - -## Proving backend - -Since Noir is backend agnostic, you can instantiate NoirJS without any backend (i.e. to execute a function). But for proving, you would have to instantiate NoirJS with any of the supported backends through their own `js` interface. - -### Barretenberg - -Aztec Labs maintains the `barretenberg` proving backend, which you can instantiate and make use of alongside NoirJS. It is also the default proving backend installed and used with Nargo, the Noir CLI tool. - -To install its JavaScript library, run this in your project: - -```bash -npm i @noir-lang/backend_barretenberg -``` - -For more details on how to instantiate and use the libraries, refer to the [Full Noir App Guide](./getting_started/01_tiny_noir_app.md) and [Reference](./reference/noir_js/classes/Noir.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/.nojekyll deleted file mode 100644 index e2ac6616add..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/classes/BarretenbergBackend.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/classes/BarretenbergBackend.md deleted file mode 100644 index 5cbe9421b92..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/classes/BarretenbergBackend.md +++ /dev/null @@ -1,185 +0,0 @@ -# BarretenbergBackend - -## Implements - -- [`Backend`](../interfaces/Backend.md) - -## Constructors - -### new BarretenbergBackend(acirCircuit, options) - -```ts -new BarretenbergBackend(acirCircuit, options): BarretenbergBackend -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `acirCircuit` | [`CompiledCircuit`](../type-aliases/CompiledCircuit.md) | -| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | - -#### Returns - -[`BarretenbergBackend`](BarretenbergBackend.md) - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`destroy`](../interfaces/Backend.md#destroy) - -#### Description - -Destroys the backend - -*** - -### generateFinalProof() - -```ts -generateFinalProof(decompressedWitness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `decompressedWitness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`generateFinalProof`](../interfaces/Backend.md#generatefinalproof) - -#### Description - -Generates a final proof (not meant to be verified in another circuit) - -*** - -### generateIntermediateProof() - -```ts -generateIntermediateProof(witness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `witness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`generateIntermediateProof`](../interfaces/Backend.md#generateintermediateproof) - -#### Example - -```typescript -const intermediateProof = await backend.generateIntermediateProof(witness); -``` - -*** - -### generateIntermediateProofArtifacts() - -```ts -generateIntermediateProofArtifacts(proofData, numOfPublicInputs): Promise -``` - -#### Parameters - -| Parameter | Type | Default value | -| :------ | :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | `undefined` | -| `numOfPublicInputs` | `number` | `0` | - -#### Returns - -`Promise`\<`object`\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`generateIntermediateProofArtifacts`](../interfaces/Backend.md#generateintermediateproofartifacts) - -#### Example - -```typescript -const artifacts = await backend.generateIntermediateProofArtifacts(proof, numOfPublicInputs); -``` - -*** - -### verifyFinalProof() - -```ts -verifyFinalProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`verifyFinalProof`](../interfaces/Backend.md#verifyfinalproof) - -#### Description - -Verifies a final proof - -*** - -### verifyIntermediateProof() - -```ts -verifyIntermediateProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`verifyIntermediateProof`](../interfaces/Backend.md#verifyintermediateproof) - -#### Example - -```typescript -const isValidIntermediate = await backend.verifyIntermediateProof(proof); -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/index.md deleted file mode 100644 index 3680ba3ca77..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/index.md +++ /dev/null @@ -1,27 +0,0 @@ -# Backend Barretenberg - -## Exports - -### Classes - -| Class | Description | -| :------ | :------ | -| [BarretenbergBackend](classes/BarretenbergBackend.md) | - | - -### Interfaces - -| Interface | Description | -| :------ | :------ | -| [Backend](interfaces/Backend.md) | - | - -### Type Aliases - -| Type alias | Description | -| :------ | :------ | -| [BackendOptions](type-aliases/BackendOptions.md) | - | -| [CompiledCircuit](type-aliases/CompiledCircuit.md) | - | -| [ProofData](type-aliases/ProofData.md) | - | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/interfaces/Backend.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/interfaces/Backend.md deleted file mode 100644 index 3eb9645c8d2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/interfaces/Backend.md +++ /dev/null @@ -1,132 +0,0 @@ -# Backend - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Description - -Destroys the backend - -*** - -### generateFinalProof() - -```ts -generateFinalProof(decompressedWitness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `decompressedWitness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Description - -Generates a final proof (not meant to be verified in another circuit) - -*** - -### generateIntermediateProof() - -```ts -generateIntermediateProof(decompressedWitness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `decompressedWitness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Description - -Generates an intermediate proof (meant to be verified in another circuit) - -*** - -### generateIntermediateProofArtifacts() - -```ts -generateIntermediateProofArtifacts(proofData, numOfPublicInputs): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | -| `numOfPublicInputs` | `number` | - -#### Returns - -`Promise`\<`object`\> - -#### Description - -Retrieves the artifacts from a proof in the Field format - -*** - -### verifyFinalProof() - -```ts -verifyFinalProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Verifies a final proof - -*** - -### verifyIntermediateProof() - -```ts -verifyIntermediateProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Verifies an intermediate proof - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/type-aliases/BackendOptions.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/type-aliases/BackendOptions.md deleted file mode 100644 index 266ade75d17..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/type-aliases/BackendOptions.md +++ /dev/null @@ -1,19 +0,0 @@ -# BackendOptions - -```ts -type BackendOptions: object; -``` - -## Description - -An options object, currently only used to specify the number of threads to use. - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `threads` | `number` | **Description**

Number of threads | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit.md deleted file mode 100644 index 34e0dd04205..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit.md +++ /dev/null @@ -1,20 +0,0 @@ -# CompiledCircuit - -```ts -type CompiledCircuit: object; -``` - -## Description - -The representation of a compiled circuit - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `abi` | `Abi` | **Description**

ABI representation of the circuit | -| `bytecode` | `string` | **Description**

The bytecode of the circuit | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/type-aliases/ProofData.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/type-aliases/ProofData.md deleted file mode 100644 index 4aeff73d3e4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/type-aliases/ProofData.md +++ /dev/null @@ -1,20 +0,0 @@ -# ProofData - -```ts -type ProofData: object; -``` - -## Description - -The representation of a proof - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `proof` | `Uint8Array` | **Description**

An byte array representing the proof | -| `publicInputs` | `Uint8Array`[] | **Description**

Public inputs of a proof | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs deleted file mode 100644 index 04e662c845f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"noir_js/reference/backend_barretenberg/classes/BarretenbergBackend","label":"BarretenbergBackend"}]},{"type":"category","label":"Interfaces","items":[{"type":"doc","id":"noir_js/reference/backend_barretenberg/interfaces/Backend","label":"Backend"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"noir_js/reference/backend_barretenberg/type-aliases/BackendOptions","label":"BackendOptions"},{"type":"doc","id":"noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit","label":"CompiledCircuit"},{"type":"doc","id":"noir_js/reference/backend_barretenberg/type-aliases/ProofData","label":"ProofData"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/.nojekyll deleted file mode 100644 index e2ac6616add..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/classes/Noir.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/classes/Noir.md deleted file mode 100644 index 1d7b54a9dca..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/classes/Noir.md +++ /dev/null @@ -1,131 +0,0 @@ -# Noir - -## Constructors - -### new Noir(circuit, backend) - -```ts -new Noir(circuit, backend?): Noir -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `circuit` | [`CompiledCircuit`](../type-aliases/CompiledCircuit.md) | -| `backend`? | `Backend` | - -#### Returns - -[`Noir`](Noir.md) - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Description - -Destroys the underlying backend instance. - -#### Example - -```typescript -await noir.destroy(); -``` - -*** - -### execute() - -```ts -execute(inputs, foreignCallHandler?): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `inputs` | `InputMap` | -| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | - -#### Returns - -`Promise`\<`object`\> - -#### Description - -Allows to execute a circuit to get its witness and return value. - -#### Example - -```typescript -async execute(inputs) -``` - -*** - -### generateFinalProof() - -```ts -generateFinalProof(inputs): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `inputs` | `InputMap` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Description - -Generates a witness and a proof given an object as input. - -#### Example - -```typescript -async generateFinalProof(input) -``` - -*** - -### verifyFinalProof() - -```ts -verifyFinalProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Instantiates the verification key and verifies a proof. - -#### Example - -```typescript -async verifyFinalProof(proof) -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/functions/and.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/functions/and.md deleted file mode 100644 index c783283e396..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/functions/and.md +++ /dev/null @@ -1,22 +0,0 @@ -# and() - -```ts -and(lhs, rhs): string -``` - -Performs a bitwise AND operation between `lhs` and `rhs` - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `lhs` | `string` | | -| `rhs` | `string` | | - -## Returns - -`string` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/functions/blake2s256.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/functions/blake2s256.md deleted file mode 100644 index 7882d0da8d5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/functions/blake2s256.md +++ /dev/null @@ -1,21 +0,0 @@ -# blake2s256() - -```ts -blake2s256(inputs): Uint8Array -``` - -Calculates the Blake2s256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify.md deleted file mode 100644 index 0ba5783f0d5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify.md +++ /dev/null @@ -1,29 +0,0 @@ -# ecdsa\_secp256k1\_verify() - -```ts -ecdsa_secp256k1_verify( - hashed_msg, - public_key_x_bytes, - public_key_y_bytes, - signature): boolean -``` - -Calculates the Blake2s256 hash of the input bytes and represents these as a single field element. -Verifies a ECDSA signature over the secp256k1 curve. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `hashed_msg` | `Uint8Array` | | -| `public_key_x_bytes` | `Uint8Array` | | -| `public_key_y_bytes` | `Uint8Array` | | -| `signature` | `Uint8Array` | | - -## Returns - -`boolean` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify.md deleted file mode 100644 index 0b20ff68957..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify.md +++ /dev/null @@ -1,28 +0,0 @@ -# ecdsa\_secp256r1\_verify() - -```ts -ecdsa_secp256r1_verify( - hashed_msg, - public_key_x_bytes, - public_key_y_bytes, - signature): boolean -``` - -Verifies a ECDSA signature over the secp256r1 curve. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `hashed_msg` | `Uint8Array` | | -| `public_key_x_bytes` | `Uint8Array` | | -| `public_key_y_bytes` | `Uint8Array` | | -| `signature` | `Uint8Array` | | - -## Returns - -`boolean` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/functions/keccak256.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/functions/keccak256.md deleted file mode 100644 index d10f155ce86..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/functions/keccak256.md +++ /dev/null @@ -1,21 +0,0 @@ -# keccak256() - -```ts -keccak256(inputs): Uint8Array -``` - -Calculates the Keccak256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/functions/sha256.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/functions/sha256.md deleted file mode 100644 index 6ba4ecac022..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/functions/sha256.md +++ /dev/null @@ -1,21 +0,0 @@ -# sha256() - -```ts -sha256(inputs): Uint8Array -``` - -Calculates the SHA256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/functions/xor.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/functions/xor.md deleted file mode 100644 index 8d762b895d3..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/functions/xor.md +++ /dev/null @@ -1,22 +0,0 @@ -# xor() - -```ts -xor(lhs, rhs): string -``` - -Performs a bitwise XOR operation between `lhs` and `rhs` - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `lhs` | `string` | | -| `rhs` | `string` | | - -## Returns - -`string` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/index.md deleted file mode 100644 index 58902c17b99..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/index.md +++ /dev/null @@ -1,36 +0,0 @@ -# Noir JS - -## Exports - -### Classes - -| Class | Description | -| :------ | :------ | -| [Noir](classes/Noir.md) | - | - -### Type Aliases - -| Type alias | Description | -| :------ | :------ | -| [CompiledCircuit](type-aliases/CompiledCircuit.md) | - | -| [ForeignCallHandler](type-aliases/ForeignCallHandler.md) | A callback which performs an foreign call and returns the response. | -| [ForeignCallInput](type-aliases/ForeignCallInput.md) | - | -| [ForeignCallOutput](type-aliases/ForeignCallOutput.md) | - | -| [ProofData](type-aliases/ProofData.md) | - | -| [WitnessMap](type-aliases/WitnessMap.md) | - | - -### Functions - -| Function | Description | -| :------ | :------ | -| [and](functions/and.md) | Performs a bitwise AND operation between `lhs` and `rhs` | -| [blake2s256](functions/blake2s256.md) | Calculates the Blake2s256 hash of the input bytes | -| [ecdsa\_secp256k1\_verify](functions/ecdsa_secp256k1_verify.md) | Calculates the Blake2s256 hash of the input bytes and represents these as a single field element. | -| [ecdsa\_secp256r1\_verify](functions/ecdsa_secp256r1_verify.md) | Verifies a ECDSA signature over the secp256r1 curve. | -| [keccak256](functions/keccak256.md) | Calculates the Keccak256 hash of the input bytes | -| [sha256](functions/sha256.md) | Calculates the SHA256 hash of the input bytes | -| [xor](functions/xor.md) | Performs a bitwise XOR operation between `lhs` and `rhs` | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/type-aliases/CompiledCircuit.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/type-aliases/CompiledCircuit.md deleted file mode 100644 index 34e0dd04205..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/type-aliases/CompiledCircuit.md +++ /dev/null @@ -1,20 +0,0 @@ -# CompiledCircuit - -```ts -type CompiledCircuit: object; -``` - -## Description - -The representation of a compiled circuit - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `abi` | `Abi` | **Description**

ABI representation of the circuit | -| `bytecode` | `string` | **Description**

The bytecode of the circuit | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/type-aliases/ForeignCallHandler.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/type-aliases/ForeignCallHandler.md deleted file mode 100644 index 812b8b16481..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/type-aliases/ForeignCallHandler.md +++ /dev/null @@ -1,24 +0,0 @@ -# ForeignCallHandler - -```ts -type ForeignCallHandler: (name, inputs) => Promise; -``` - -A callback which performs an foreign call and returns the response. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `name` | `string` | The identifier for the type of foreign call being performed. | -| `inputs` | [`ForeignCallInput`](ForeignCallInput.md)[] | An array of hex encoded inputs to the foreign call. | - -## Returns - -`Promise`\<[`ForeignCallOutput`](ForeignCallOutput.md)[]\> - -outputs - An array of hex encoded outputs containing the results of the foreign call. - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/type-aliases/ForeignCallInput.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/type-aliases/ForeignCallInput.md deleted file mode 100644 index dd95809186a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/type-aliases/ForeignCallInput.md +++ /dev/null @@ -1,9 +0,0 @@ -# ForeignCallInput - -```ts -type ForeignCallInput: string[]; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/type-aliases/ForeignCallOutput.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/type-aliases/ForeignCallOutput.md deleted file mode 100644 index b71fb78a946..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/type-aliases/ForeignCallOutput.md +++ /dev/null @@ -1,9 +0,0 @@ -# ForeignCallOutput - -```ts -type ForeignCallOutput: string | string[]; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/type-aliases/ProofData.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/type-aliases/ProofData.md deleted file mode 100644 index 4aeff73d3e4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/type-aliases/ProofData.md +++ /dev/null @@ -1,20 +0,0 @@ -# ProofData - -```ts -type ProofData: object; -``` - -## Description - -The representation of a proof - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `proof` | `Uint8Array` | **Description**

An byte array representing the proof | -| `publicInputs` | `Uint8Array`[] | **Description**

Public inputs of a proof | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/type-aliases/WitnessMap.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/type-aliases/WitnessMap.md deleted file mode 100644 index 258c46f9d0c..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/type-aliases/WitnessMap.md +++ /dev/null @@ -1,9 +0,0 @@ -# WitnessMap - -```ts -type WitnessMap: Map; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/typedoc-sidebar.cjs deleted file mode 100644 index c18318850d0..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"noir_js/reference/noir_js/classes/Noir","label":"Noir"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/CompiledCircuit","label":"CompiledCircuit"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/ForeignCallHandler","label":"ForeignCallHandler"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/ForeignCallInput","label":"ForeignCallInput"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/ForeignCallOutput","label":"ForeignCallOutput"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/ProofData","label":"ProofData"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/WitnessMap","label":"WitnessMap"}]},{"type":"category","label":"Functions","items":[{"type":"doc","id":"noir_js/reference/noir_js/functions/and","label":"and"},{"type":"doc","id":"noir_js/reference/noir_js/functions/blake2s256","label":"blake2s256"},{"type":"doc","id":"noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify","label":"ecdsa_secp256k1_verify"},{"type":"doc","id":"noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify","label":"ecdsa_secp256r1_verify"},{"type":"doc","id":"noir_js/reference/noir_js/functions/keccak256","label":"keccak256"},{"type":"doc","id":"noir_js/reference/noir_js/functions/sha256","label":"sha256"},{"type":"doc","id":"noir_js/reference/noir_js/functions/xor","label":"xor"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/black_box_fns.md deleted file mode 100644 index 985bb7c879d..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/black_box_fns.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: Black Box Functions -description: Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. -keywords: [noir, black box functions] ---- - -Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. This makes certain zk-snark unfriendly computations cheaper than if they were implemented in Noir. - -:::warning - -It is likely that not all backends will support a particular black box function. - -::: - -Because it is not guaranteed that all backends will support black box functions, it is possible that certain Noir programs won't compile against a particular backend if they use an unsupported black box function. It is possible to fallback to less efficient implementations written in Noir/ACIR in some cases. - -Black box functions are specified with the `#[foreign(black_box_fn)]` attribute. For example, the SHA256 function in the Noir [source code](https://github.com/noir-lang/noir/blob/v0.5.1/noir_stdlib/src/hash.nr) looks like: - -```rust -#[foreign(sha256)] -fn sha256(_input : [u8; N]) -> [u8; 32] {} -``` - -## Function list - -Here is a list of the current black box functions that are supported by UltraPlonk: - -- AES -- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) -- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) -- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash) -- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment) -- [HashToField128Security](./cryptographic_primitives/hashes.mdx#hash_to_field) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx) -- [Compute merkle root](./merkle_trees.md#compute_merkle_root) -- AND -- XOR -- RANGE -- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion.md) - -Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. - -You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/noir/blob/master/acvm-repo/acir/src/circuit/black_box_functions.rs). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives.md deleted file mode 100644 index 2df4f929474..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Cryptographic primitives in Noir -description: - Learn about the cryptographic primitives ready to use for any Noir project -keywords: - [ - cryptographic primitives, - Noir project, - ] ---- - -The Noir team is progressively adding new cryptographic primitives to the standard library. Reach out for news or if you would be interested in adding more of these calculations in Noir. - -Some methods are available thanks to the Aztec backend, not being performed using Noir. When using other backends, these methods may or may not be supplied. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives/00_hashes.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives/00_hashes.mdx deleted file mode 100644 index 76745196681..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives/00_hashes.mdx +++ /dev/null @@ -1,167 +0,0 @@ ---- -title: Hash methods -description: - Learn about the cryptographic primitives ready to use for any Noir project, including sha256, - blake2s, pedersen, mimc_bn254 and mimc -keywords: - [cryptographic primitives, Noir project, sha256, blake2s, pedersen, mimc_bn254, mimc, hash] ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## sha256 - -Given an array of bytes, returns the resulting sha256 hash. - -```rust -fn sha256(_input : [u8]) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::sha256(x); -} -``` - - - -## blake2s - -Given an array of bytes, returns an array with the Blake2 hash - -```rust -fn blake2s(_input : [u8]) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::blake2s(x); -} -``` - - - -## pedersen_hash - -Given an array of Fields, returns the Pedersen hash. - -```rust -fn pedersen_hash(_input : [Field]) -> Field -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::pedersen_hash(x); -} -``` - - - - - -## pedersen_commitment - -Given an array of Fields, returns the Pedersen commitment. - -```rust -fn pedersen_commitment(_input : [Field]) -> [Field; 2] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let commitment = std::hash::pedersen_commitment(x); -} -``` - - - -## keccak256 - -Given an array of bytes (`u8`), returns the resulting keccak hash as an array of 32 bytes -(`[u8; 32]`). Specify a message_size to hash only the first `message_size` bytes -of the input. - -```rust -fn keccak256(_input : [u8; N], _message_size: u32) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let message_size = 4; - let hash = std::hash::keccak256(x, message_size); -} -``` - - - -## poseidon - -Given an array of Fields, returns a new Field with the Poseidon Hash. Mind that you need to specify -how many inputs are there to your Poseidon function. - -```rust -// example for hash_1, hash_2 accepts an array of length 2, etc -fn hash_1(input: [Field; 1]) -> Field -``` - -example: - -```rust -fn main() -{ - let hash1 = std::hash::poseidon::bn254::hash_2([1, 2]); - assert(hash1 == 0x115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189a); -} -``` - -## mimc_bn254 and mimc - -`mimc_bn254` is `mimc`, but with hardcoded parameters for the BN254 curve. You can use it by -providing an array of Fields, and it returns a Field with the hash. You can use the `mimc` method if -you're willing to input your own constants: - -```rust -fn mimc(x: Field, k: Field, constants: [Field; N], exp : Field) -> Field -``` - -otherwise, use the `mimc_bn254` method: - -```rust -fn mimc_bn254(array: [Field; N]) -> Field -``` - -example: - -```rust - -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::mimc::mimc_bn254(x); -} -``` - -## hash_to_field - -```rust -fn hash_to_field(_input : [Field; N]) -> Field {} -``` - -Calculates the `blake2s` hash of the inputs and returns the hash modulo the field modulus to return -a value which can be represented as a `Field`. - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives/01_scalar.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives/01_scalar.mdx deleted file mode 100644 index c7eed820a80..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives/01_scalar.mdx +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: Scalar multiplication -description: See how you can perform scalar multiplications over a fixed base in Noir -keywords: [cryptographic primitives, Noir project, scalar multiplication] ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## scalar_mul::fixed_base_embedded_curve - -Performs scalar multiplication over the embedded curve whose coordinates are defined by the -configured noir field. For the BN254 scalar field, this is BabyJubJub or Grumpkin. - -```rust -fn fixed_base_embedded_curve(_input : Field) -> [Field; 2] -``` - -example - -```rust -fn main(x : Field) { - let scal = std::scalar_mul::fixed_base_embedded_curve(x); - std::println(scal); -} -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives/02_schnorr.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives/02_schnorr.mdx deleted file mode 100644 index c184ce28120..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives/02_schnorr.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: Schnorr Signatures -description: Learn how you can verify Schnorr signatures using Noir -keywords: [cryptographic primitives, Noir project, schnorr, signatures] ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## schnorr::verify_signature - -Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin). - -```rust -fn verify_signature(_public_key_x: Field, _public_key_y: Field, _signature: [u8; 64], _message: [u8]) -> bool -``` - -where `_signature` can be generated like so using the npm package -[@noir-lang/barretenberg](https://www.npmjs.com/package/@noir-lang/barretenberg) - -```js -const { BarretenbergWasm } = require('@noir-lang/barretenberg/dest/wasm'); -const { Schnorr } = require('@noir-lang/barretenberg/dest/crypto/schnorr'); - -... - -const barretenberg = await BarretenbergWasm.new(); -const schnorr = new Schnorr(barretenberg); -const pubKey = schnorr.computePublicKey(privateKey); -const message = ... -const signature = Array.from( - schnorr.constructSignature(hash, privateKey).toBuffer() -); - -... -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx deleted file mode 100644 index 72bce984821..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: ECDSA Signature Verification -description: Learn about the cryptographic primitives regarding ECDSA over the secp256k1 and secp256r1 curves -keywords: [cryptographic primitives, Noir project, ecdsa, secp256k1, secp256r1, signatures] ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -Noir supports ECDSA signatures verification over the secp256k1 and secp256r1 curves. - -## ecdsa_secp256k1::verify_signature - -Verifier for ECDSA Secp256k1 signatures - -```rust -fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message: [u8]) -> bool -``` - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - -## ecdsa_secp256r1::verify_signature - -Verifier for ECDSA Secp256r1 signatures - -```rust -fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message: [u8]) -> bool -``` - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives/04_ec_primitives.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives/04_ec_primitives.md deleted file mode 100644 index 14ce71d4d39..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives/04_ec_primitives.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -title: Elliptic Curve Primitives -keywords: [cryptographic primitives, Noir project] ---- - -Data structures and methods on them that allow you to carry out computations involving elliptic -curves over the (mathematical) field corresponding to `Field`. For the field currently at our -disposal, applications would involve a curve embedded in BN254, e.g. the -[Baby Jubjub curve](https://eips.ethereum.org/EIPS/eip-2494). - -## Data structures - -### Elliptic curve configurations - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Curve`), i.e. the specific elliptic -curve you want to use, which would be specified using any one of the methods -`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::new` which take the coefficients in the -defining equation together with a generator point as parameters. You can find more detail in the -comments in -[`noir_stdlib/src/ec.nr`](https://github.com/noir-lang/noir/blob/v0.19.2/noir_stdlib/src/ec.nr), but -the gist of it is that the elliptic curves of interest are usually expressed in one of the standard -forms implemented here (Twisted Edwards, Montgomery and Short Weierstraß), and in addition to that, -you could choose to use `affine` coordinates (Cartesian coordinates - the usual (x,y) - possibly -together with a point at infinity) or `curvegroup` coordinates (some form of projective coordinates -requiring more coordinates but allowing for more efficient implementations of elliptic curve -operations). Conversions between all of these forms are provided, and under the hood these -conversions are done whenever an operation is more efficient in a different representation (or a -mixed coordinate representation is employed). - -### Points - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Point`), i.e. points lying on the -elliptic curve. For a curve configuration `c` and a point `p`, it may be checked that `p` -does indeed lie on `c` by calling `c.contains(p1)`. - -## Methods - -(given a choice of curve representation, e.g. use `std::ec::tecurve::affine::Curve` and use -`std::ec::tecurve::affine::Point`) - -- The **zero element** is given by `Point::zero()`, and we can verify whether a point `p: Point` is - zero by calling `p.is_zero()`. -- **Equality**: Points `p1: Point` and `p2: Point` may be checked for equality by calling - `p1.eq(p2)`. -- **Addition**: For `c: Curve` and points `p1: Point` and `p2: Point` on the curve, adding these two - points is accomplished by calling `c.add(p1,p2)`. -- **Negation**: For a point `p: Point`, `p.negate()` is its negation. -- **Subtraction**: For `c` and `p1`, `p2` as above, subtracting `p2` from `p1` is accomplished by - calling `c.subtract(p1,p2)`. -- **Scalar multiplication**: For `c` as above, `p: Point` a point on the curve and `n: Field`, - scalar multiplication is given by `c.mul(n,p)`. If instead `n :: [u1; N]`, i.e. `n` is a bit - array, the `bit_mul` method may be used instead: `c.bit_mul(n,p)` -- **Multi-scalar multiplication**: For `c` as above and arrays `n: [Field; N]` and `p: [Point; N]`, - multi-scalar multiplication is given by `c.msm(n,p)`. -- **Coordinate representation conversions**: The `into_group` method converts a point or curve - configuration in the affine representation to one in the CurveGroup representation, and - `into_affine` goes in the other direction. -- **Curve representation conversions**: `tecurve` and `montcurve` curves and points are equivalent - and may be converted between one another by calling `into_montcurve` or `into_tecurve` on their - configurations or points. `swcurve` is more general and a curve c of one of the other two types - may be converted to this representation by calling `c.into_swcurve()`, whereas a point `p` lying - on the curve given by `c` may be mapped to its corresponding `swcurve` point by calling - `c.map_into_swcurve(p)`. -- **Map-to-curve methods**: The Elligator 2 method of mapping a field element `n: Field` into a - `tecurve` or `montcurve` with configuration `c` may be called as `c.elligator2_map(n)`. For all of - the curve configurations, the SWU map-to-curve method may be called as `c.swu_map(z,n)`, where - `z: Field` depends on `Field` and `c` and must be chosen by the user (the conditions it needs to - satisfy are specified in the comments - [here](https://github.com/noir-lang/noir/blob/v0.19.2/noir_stdlib/src/ec.nr). - -## Examples - -The -[ec_baby_jubjub test](https://github.com/noir-lang/noir/blob/master/test_programs/compile_success_empty/ec_baby_jubjub/src/main.nr) -illustrates all of the above primitives on various forms of the Baby Jubjub curve. A couple of more -interesting examples in Noir would be: - -Public-key cryptography: Given an elliptic curve and a 'base point' on it, determine the public key -from the private key. This is a matter of using scalar multiplication. In the case of Baby Jubjub, -for example, this code would do: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; - -fn bjj_pub_key(priv_key: Field) -> Point -{ - - let bjj = Curve::new(168700, 168696, G::new(995203441582195749578291179787384436505546430278305826713579947235728471134,5472060717959818805561601436314318772137091100104008585924551046643952123905)); - - let base_pt = Point::new(5299619240641551281634865583518297030282874472190772894086521144482721001553, 16950150798460657717958625567821834550301663161624707787222815936182638968203); - - bjj.mul(priv_key,base_pt) -} -``` - -This would come in handy in a Merkle proof. - -- EdDSA signature verification: This is a matter of combining these primitives with a suitable hash - function. See - [feat(stdlib): EdDSA sig verification noir#1136](https://github.com/noir-lang/noir/pull/1136) for - the case of Baby Jubjub and the Poseidon hash function. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives/05_eddsa.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives/05_eddsa.mdx deleted file mode 100644 index 9a5beb55ee9..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives/05_eddsa.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: EdDSA Verification -description: Learn about the cryptographic primitives regarding EdDSA -keywords: [cryptographic primitives, Noir project, eddsa, signatures] ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## eddsa::eddsa_poseidon_verify - -Verifier for EdDSA signatures - -```rust -fn eddsa_poseidon_verify(public_key_x : Field, public_key_y : Field, signature_s: Field, signature_r8_x: Field, signature_r8_y: Field, message: Field) -> bool -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/logging.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/logging.md deleted file mode 100644 index 4ba0fe0e656..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/logging.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -title: Logging -description: - Learn how to use the println statement for debugging in Noir with this tutorial. Understand the - basics of logging in Noir and how to implement it in your code. -keywords: - [ - noir logging, - println statement, - debugging in noir, - noir std library, - logging tutorial, - basic logging in noir, - noir logging implementation, - noir debugging techniques, - rust, - ] ---- - -The standard library provides a familiar `println` statement you can use. Despite being a limited -implementation of rust's `println!` macro, this construct can be useful for debugging. - -You can print the output of println statements in your Noir code by using the `nargo execute` command or the `--show-output` flag when using `nargo test` (provided there are println statements in your tests). - -It is recommended to use `nargo execute` if you want to debug failing constraints with `println` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). `println` will not work for failed constraints caught at compile time. - -The `println` statement is unconstrained, so it works for outputting integers, fields, strings, and even structs or expressions. For example: - -```rust -use dep::std; - -struct Person { - age : Field, - height : Field, -} - -fn main(age : Field, height : Field) { - let person = Person { age : age, height : height }; - std::println(person); - std::println(age + height); - std::println("Hello world!"); -} - -``` - -You can print multiple different types in the same statement and string as well as a new "fmtstr" type. A `fmtstr` can be specified in the same way as a normal string it just should be prepended with an "f" character: - -```rust - let fmt_str = f"i: {i}, j: {j}"; - std::println(fmt_str); - - let s = myStruct { y: x, x: y }; - std::println(s); - - std::println(f"i: {i}, s: {s}"); - - std::println(x); - std::println([x, y]); - - let foo = fooStruct { my_struct: s, foo: 15 }; - std::println(f"s: {s}, foo: {foo}"); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/merkle_trees.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/merkle_trees.md deleted file mode 100644 index dc383a1426b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/merkle_trees.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: Merkle Trees -description: Learn about Merkle Trees in Noir with this tutorial. Explore the basics of computing a merkle root using a proof, with examples. -keywords: - [ - Merkle trees in Noir, - Noir programming language, - check membership, - computing root from leaf, - Noir Merkle tree implementation, - Merkle tree tutorial, - Merkle tree code examples, - Noir libraries, - pedersen hash., - ] ---- - -## compute_merkle_root - -Returns the root of the tree from the provided leaf and its hash path, using a [Pedersen hash](cryptographic_primitives/00_hashes.mdx#pedersen_hash). - -```rust -fn compute_merkle_root(leaf : Field, index : Field, hash_path: [Field]) -> Field -``` - -example: - -```rust -/** - // these values are for this example only - index = "0" - priv_key = "0x000000000000000000000000000000000000000000000000000000616c696365" - secret = "0x1929ea3ab8d9106a899386883d9428f8256cfedb3c4f6b66bf4aa4d28a79988f" - note_hash_path = [ - "0x1e61bdae0f027b1b2159e1f9d3f8d00fa668a952dddd822fda80dc745d6f65cc", - "0x0e4223f3925f98934393c74975142bd73079ab0621f4ee133cee050a3c194f1a", - "0x2fd7bb412155bf8693a3bd2a3e7581a679c95c68a052f835dddca85fa1569a40" - ] - */ -fn main(index: Field, priv_key: Field, secret: Field, note_hash_path: [Field; 3]) { - - let pubkey = std::scalar_mul::fixed_base_embedded_curve(priv_key); - let pubkey_x = pubkey[0]; - let pubkey_y = pubkey[1]; - let note_commitment = std::hash::pedersen([pubkey_x, pubkey_y, secret]); - - let root = std::merkle::compute_merkle_root(note_commitment[0], index, note_hash_path); - std::println(root); -} -``` - -To check merkle tree membership: - -1. Include a merkle root as a program input. -2. Compute the merkle root of a given leaf, index and hash path. -3. Assert the merkle roots are equal. - -For more info about merkle trees, see the Wikipedia [page](https://en.wikipedia.org/wiki/Merkle_tree). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/options.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/options.md deleted file mode 100644 index 3d3139fb98b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/options.md +++ /dev/null @@ -1,99 +0,0 @@ ---- -title: Option Type ---- - -The `Option` type is a way to express that a value might be present (`Some(T))` or absent (`None`). It's a safer way to handle potential absence of values, compared to using nulls in many other languages. - -```rust -struct Option { - None, - Some(T), -} -``` - -You can import the Option type into your Noir program like so: - -```rust -use dep::std::option::Option; - -fn main() { - let none = Option::none(); - let some = Option::some(3); -} -``` - -See [this test](https://github.com/noir-lang/noir/blob/5cbfb9c4a06c8865c98ff2b594464b037d821a5c/crates/nargo_cli/tests/test_data/option/src/main.nr) for a more comprehensive set of examples of each of the methods described below. - -## Methods - -### none - -Constructs a none value. - -### some - -Constructs a some wrapper around a given value. - -### is_none - -Returns true if the Option is None. - -### is_some - -Returns true of the Option is Some. - -### unwrap - -Asserts `self.is_some()` and returns the wrapped value. - -### unwrap_unchecked - -Returns the inner value without asserting `self.is_some()`. This method can be useful within an if condition when we already know that `option.is_some()`. If the option is None, there is no guarantee what value will be returned, only that it will be of type T for an `Option`. - -### unwrap_or - -Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value. - -### unwrap_or_else - -Returns the wrapped value if `self.is_some()`. Otherwise, calls the given function to return a default value. - -### map - -If self is `Some(x)`, this returns `Some(f(x))`. Otherwise, this returns `None`. - -### map_or - -If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns the given default value. - -### map_or_else - -If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns `default()`. - -### and - -Returns None if self is None. Otherwise, this returns `other`. - -### and_then - -If self is None, this returns None. Otherwise, this calls the given function with the Some value contained within self, and returns the result of that call. In some languages this function is called `flat_map` or `bind`. - -### or - -If self is Some, return self. Otherwise, return `other`. - -### or_else - -If self is Some, return self. Otherwise, return `default()`. - -### xor - -If only one of the two Options is Some, return that option. Otherwise, if both options are Some or both are None, None is returned. - -### filter - -Returns `Some(x)` if self is `Some(x)` and `predicate(x)` is true. Otherwise, this returns `None`. - -### flatten - -Flattens an `Option>` into a `Option`. This returns `None` if the outer Option is None. Otherwise, this returns the inner Option. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/recursion.md deleted file mode 100644 index 5e592a2fd89..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/recursion.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: Recursive Proofs -description: Learn about how to write recursive proofs in Noir. -keywords: [recursion, recursive proofs, verification_key, aggregation object, verify_proof] ---- - -Noir supports recursively verifying proofs, meaning you verify the proof of a Noir program in another Noir program. This enables creating proofs of arbitrary size by doing step-wise verification of smaller components of a large proof. - -The `verify_proof` function takes a verification key, proof and public inputs for a zk program, as well as a key hash and an input aggregation object. The key hash is used to check the validity of the verification key and the input aggregation object is required by some proving systems. The `verify_proof` function returns an output aggregation object that can then be fed into future iterations of the proof verification if required. - -```rust -#[foreign(verify_proof)] -fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : Field, _key_hash : Field, _input_aggregation_object : [Field]) -> [Field] {} -``` - -:::info - -This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. - -::: - -## Aggregation Object - -The purpose of the input aggregation object is a little less clear though (and the output aggregation object that is returned from the `std::verify_proof` method). Recursive zkSNARK schemes do not necessarily "verify a proof" in the sense that you expect a true or false to be spit out by the verifier. Rather an aggregation object is built over the public inputs. In the case of PLONK the recursive aggregation object is two G1 points (expressed as 16 witness values). The final verifier (in our case this is most often the smart contract verifier) has to be aware of this aggregation object to execute a pairing and check the validity of these points (thus completing the recursive verification). - -So for example in this circuit: - -```rust -use dep::std; - -fn main( - verification_key : [Field; 114], - proof : [Field; 94], - public_inputs : [Field; 1], - key_hash : Field, - input_aggregation_object : [Field; 16], - proof_b : [Field; 94], -) -> pub [Field; 16] { - let output_aggregation_object_a = std::verify_proof( - verification_key, - proof, - public_inputs, - key_hash, - input_aggregation_object - ); - - let output_aggregation_object = std::verify_proof( - verification_key, - proof_b, - public_inputs, - key_hash, - output_aggregation_object_a - ); - - let mut output = [0; 16]; - for i in 0..16 { - output[i] = output_aggregation_object[i]; - } - output -} -``` - -In this example we have a circuit, that generates proofs A and B, that is being verified in circuit C. Assuming that the proof being passed in is not already a recursive proof, the `input_aggregation_object` will be all zeros. It will then generate an `output_aggregation_object`. This blob of data then becomes the `input_aggregation_object` of the next recursive aggregation we wish to compute. We can see here as the same public inputs, verification key, and key hash are used that we are verifying two proofs generated from the same circuit in this single circuit. `std::verify_proof` returns a `[Field]` because the size of an aggregation object is proof system dependent--in barretenberg, aggregation objects are two G1 points, while in Halo2, the aggregation object is a list of G1 points that is log the circuit size. So for the final step we convert the slice into an array of size 16 because we are generating proofs using UltraPlonk. - -## Parameters - -### `verification_key` - -The verification key for the zk program that is being verified. - -### `proof` - -The proof for the zk program that is being verified. - -### `public_inputs` - -These represent the public inputs of the proof we are verifying. They should be checked against in the circuit after construction of a new aggregation state. - -### `key_hash` - -A key hash is used to check the validity of the verification key. The circuit implementing this opcode can use this hash to ensure that the key provided to the circuit matches the key produced by the circuit creator. - -### `input_aggregation_object` - -An aggregation object is blob of data that the top-level verifier must run some proof system specific algorithm on to complete verification. The size is proof system specific and will be set by the backend integrating this opcode. The input aggregation object is only not `None` when we are verifying a previous recursive aggregation in the current circuit. If this is the first recursive aggregation there is no input aggregation object. It is left to the backend to determine how to handle when there is no input aggregation object. - -## Return value - -### `output_aggregation_object` - -This is the result of a recursive aggregation and is what will be fed into the next verifier. -The next verifier can either perform a final verification (returning true or false) or perform another recursive aggregation where this output aggregation object will be the input aggregation object of the next recursive aggregation. - -## Example - -You can see an example of how to do recursive proofs in [this example recursion demo repo](https://github.com/noir-lang/noir-examples/tree/master/recursion). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/zeroed.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/zeroed.md deleted file mode 100644 index 97dab02dac2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/zeroed.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: Zeroed Function -description: - The zeroed function returns a zeroed value of any type. -keywords: - [ - zeroed - ] ---- - -Implements `fn zeroed() -> T` to return a zeroed value of any type. This function is generally unsafe to use as the zeroed bit pattern is not guaranteed to be valid for all types. It can however, be useful in cases when the value is guaranteed not to be used such as in a BoundedVec library implementing a growable vector, up to a certain length, backed by an array. The array can be initialized with zeroed values which are guaranteed to be inaccessible until the vector is pushed to. Similarly, enumerations in noir can be implemented using this method by providing zeroed values for the unused variants. - -You can access the function at `std::unsafe::zeroed`. - -This function currently supports the following types: - -- Field -- Bool -- Uint -- Array -- String -- Tuple -- Function - -Using it on other types could result in unexpected behavior. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/examples/merkle-proof.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/examples/merkle-proof.mdx deleted file mode 100644 index 832fb4bb55e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/examples/merkle-proof.mdx +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Merkle Proof Membership -description: - Learn how to use merkle membership proof in Noir to prove that a given leaf is a member of a - merkle tree with a specified root, at a given index. -keywords: - [merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree] ---- - -Let's walk through an example of a merkle membership proof in Noir that proves that a given leaf is -in a merkle tree. - -```rust -use dep::std; - -fn main(message : [Field; 62], index : Field, hashpath : [Field; 40], root : Field) { - let leaf = std::hash::hash_to_field(message); - let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); - assert(merkle_root == root); -} - -``` - -The message is hashed using `hash_to_field`. The specific hash function that is being used is chosen -by the backend. The only requirement is that this hash function can heuristically be used as a -random oracle. If only collision resistance is needed, then one can call `std::hash::pedersen_hash` -instead. - -```rust -let leaf = std::hash::hash_to_field(message); -``` - -The leaf is then passed to a compute_merkle_root function with the root, index and hashpath. The returned root can then be asserted to be the same as the provided root. - -```rust -let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); -assert (merkle_root == root); -``` - -> **Note:** It is possible to re-implement the merkle tree implementation without standard library. -> However, for most usecases, it is enough. In general, the standard library will always opt to be -> as conservative as possible, while striking a balance with efficiency. - -An example, the merkle membership proof, only requires a hash function that has collision -resistance, hence a hash function like Pedersen is allowed, which in most cases is more efficient -than the even more conservative sha256. - -[View an example on the starter repo](https://github.com/noir-lang/noir-examples/blob/3ea09545cabfa464124ec2f3ea8e60c608abe6df/stealthdrop/circuits/src/main.nr#L20) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/getting_started/00_nargo_installation.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/getting_started/00_nargo_installation.md deleted file mode 100644 index 7d3c88c7693..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/getting_started/00_nargo_installation.md +++ /dev/null @@ -1,249 +0,0 @@ ---- -title: Nargo Installation -description: - nargo is a command line tool for interacting with Noir programs (e.g. compiling, proving, - verifying and more). Learn how to install and use Nargo for your projects with this comprehensive - guide. -keywords: [Nargo, command line tool, Noir programs, installation guide, how to use Nargo] ---- - -`nargo` is a command line tool for interacting with Noir programs (e.g. compiling, proving, -verifying and more). - -Alternatively, the interactions can also be performed in [NoirJS](../noir_js/noir_js.md). - -### UltraPlonk - -Nargo versions \<0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk -version of Aztec Backend, which lacks efficient implementations of useful primitives (e.g. Keccak256 in 18k constraints, ECDSA verification in 36k constraints) that the UltraPlonk version offers. - -## Installation - -There are four approaches for installing Nargo: - -- [Option 1: Noirup](#option-1-noirup) -- [Option 2: Binaries](#option-2-binaries) -- [Option 3: Compile from Source](#option-3-compile-from-source) -- [Option 4: WSL for Windows](#option-4-wsl-for-windows) - -Optionally you can also install [Noir VS Code extension] for syntax highlighting. - -### Option 1: Noirup - -If you're on OSX or Linux, the easiest way to start using Noir and Nargo is via noirup. Just open a -terminal and run: - -```bash -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -Close the terminal, open another one, and run - -```bash -noirup -``` - -Done, you should have the latest version working. You can check with `nargo --version`. - -You can also install nightlies, specific versions -or branches, check out the [noirup repository](https://github.com/noir-lang/noirup) for more -information. - -#### GitHub Actions - -You can use `noirup` with GitHub Actions for CI/CD and automated testing. It is as simple as -installing `noirup` and running tests in your GitHub Action `yml` file. - -See the -[config file](https://github.com/TomAFrench/noir-hashes/blob/master/.github/workflows/noir.yml) in -this repo containing hash functions in Noir for an example. - -#### Nightly versions - -To install the nightly version of Noir (updated daily) run: - -```bash -noirup -n -``` - -### Option 2: Binaries - -See [GitHub Releases](https://github.com/noir-lang/noir/releases) for the latest and previous -platform specific binaries. - -#### Step 1 - -Paste and run the following in the terminal to extract and install the binary: - -> **macOS / Linux:** If you are prompted with `Permission denied` when running commands, prepend -> `sudo` and re-run it. - -##### macOS (Apple Silicon) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-aarch64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### macOS (Intel) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### Linux (Bash) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-unknown-linux-gnu.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -C $HOME/.nargo/bin/ && \ -echo -e '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.bashrc && \ -source ~/.bashrc -``` - -#### Step 2 - -Check if the installation was successful by running `nargo --help`. - -> **macOS:** If you are prompted with an OS alert, right-click and open the _nargo_ executable from -> Finder. Close the new terminal popped up and `nargo` should now be accessible. - -For a successful installation, you should see something similar to the following after running the -command: - -```sh -$ nargo --help - -Noir's package manager - -Usage: nargo - -Commands: - check Checks the constraint system for errors - codegen-verifier Generates a Solidity verifier smart contract for the program - compile Compile the program and its secret execution trace into ACIR format - new Create a new binary project - execute Executes a circuit to calculate its return value - prove Create proof for this program. The proof is returned as a hex encoded string - verify Given a proof and a program, verify whether the proof is valid - test Run the tests for this program - gates Counts the occurrences of different gates in circuit - help Print this message or the help of the given subcommand(s) -``` - -### Option 3: Compile from Source - -Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. It helps mitigating issues commonly associated with dependency management, such as conflicts between required package versions for different projects (often referred to as "dependency hell"). - -Combined with direnv, which automatically sets or clears environment variables based on the directory, it further simplifies the development process by seamlessly integrating with the developer's shell, facilitating an efficient and reliable workflow for managing and deploying Noir projects with multiple dependencies. - -#### Setting up your environment - -For the best experience, please follow these instructions to setup your environment: - -1. Install Nix following [their guide](https://nixos.org/download.html) for your operating system. -2. Create the file `~/.config/nix/nix.conf` with the contents: - -```ini -experimental-features = nix-command -extra-experimental-features = flakes -``` - -3. Install direnv into your Nix profile by running: - -```sh -nix profile install nixpkgs#direnv -``` - -4. Add direnv to your shell following [their guide](https://direnv.net/docs/hook.html). - 1. For bash or zshell, add `eval "$(direnv hook bash)"` or `eval "$(direnv hook zsh)"` to your ~/.bashrc or ~/.zshrc file, respectively. -5. Restart your shell. - -#### Shell & editor experience - -Now that your environment is set up, you can get to work on the project. - -1. Clone the repository, such as: - -```sh -git clone git@github.com:noir-lang/noir -``` - -> Replacing `noir` with whichever repository you want to work on. - -2. Navigate to the directory: - -```sh -cd noir -``` - -> Replacing `noir` with whichever repository you cloned. - -3. You should see a **direnv error** because projects aren't allowed by default. Make sure you've reviewed and trust our `.envrc` file, then you need to run: - -```sh -direnv allow -``` - -4. Now, wait awhile for all the native dependencies to be built. This will take some time and direnv will warn you that it is taking a long time, but we just need to let it run. - -5. Once you are presented with your prompt again, you can start your editor within the project directory (we recommend [VSCode](https://code.visualstudio.com/)): - -```sh -code . -``` - -6. (Recommended) When launching VSCode for the first time, you should be prompted to install our recommended plugins. We highly recommend installing these for the best development experience. - -#### Building and testing - -Assuming you are using `direnv` to populate your environment, building and testing the project can be done -with the typical `cargo build`, `cargo test`, and `cargo clippy` commands. You'll notice that the `cargo` version matches the version we specify in `rust-toolchain.toml`, which is 1.71.1 at the time of this writing. - -If you want to build the entire project in an isolated sandbox, you can use Nix commands: - -1. `nix build .` (or `nix build . -L` for verbose output) to build the project in a Nix sandbox. -2. `nix flake check` (or `nix flake check -L` for verbose output) to run clippy and tests in a Nix sandbox. - -#### Without `direnv` - -If you have hesitations with using direnv, you can launch a subshell with `nix develop` and then launch your editor from within the subshell. However, if VSCode was already launched in the project directory, the environment won't be updated. - -Advanced: If you aren't using direnv nor launching your editor within the subshell, you can try to install Barretenberg and other global dependencies the package needs. This is an advanced workflow and likely won't receive support! - -### Option 4: WSL (for Windows) - -The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed natively. However, it is available by using Windows Subsystem for Linux (WSL). - -Step 1: Follow the instructions [here](https://learn.microsoft.com/en-us/windows/wsl/install) to install and run WSL. - -step 2: Follow the [Noirup instructions](#option-1-noirup). - -## Uninstalling Nargo - -### Noirup - -If you installed Noir with `noirup`, you can uninstall Noir by removing the files in `~/.nargo`, `~/nargo` and `~/noir_cache`. - -```bash -rm -r ~/.nargo -rm -r ~/nargo -rm -r ~/noir_cache -``` - -### Nix - -If you installed Noir with Nix or from source, you can remove the binary located at `~/.nix-profile/bin/nargo`. - -```bash -rm ~/.nix-profile/bin/nargo -``` - -[noir vs code extension]: https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/getting_started/01_hello_world.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/getting_started/01_hello_world.md deleted file mode 100644 index 34f8cd96fcd..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/getting_started/01_hello_world.md +++ /dev/null @@ -1,147 +0,0 @@ ---- -title: Create A Project -description: - Learn how to create and verify your first Noir program using Nargo, a programming language for - zero-knowledge proofs. -keywords: - [ - Nargo, - Noir, - zero-knowledge proofs, - programming language, - create Noir program, - verify Noir program, - step-by-step guide, - ] ---- - -Now that we have installed Nargo, it is time to make our first hello world program! - -## Create a Project Directory - -Noir code can live anywhere on your computer. Let us create a _projects_ folder in the home -directory to house our Noir programs. - -For Linux, macOS, and Windows PowerShell, create the directory and change directory into it by -running: - -```sh -mkdir ~/projects -cd ~/projects -``` - -For Windows CMD, run: - -```sh -> mkdir "%USERPROFILE%\projects" -> cd /d "%USERPROFILE%\projects" -``` - -## Create Our First Nargo Project - -Now that we are in the projects directory, create a new Nargo project by running: - -```sh -nargo new hello_world -``` - -> **Note:** `hello_world` can be any arbitrary project name, we are simply using `hello_world` for -> demonstration. -> -> In production, the common practice is to name the project folder as `circuits` for better -> identifiability when sitting alongside other folders in the codebase (e.g. `contracts`, `scripts`, -> `test`). - -A `hello_world` folder would be created. Similar to Rust, the folder houses _src/main.nr_ and -_Nargo.toml_ that contains the source code and environmental options of your Noir program -respectively. - -### Intro to Noir Syntax - -Let us take a closer look at _main.nr_. The default _main.nr_ generated should look like this: - -```rust -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` - -The first line of the program specifies the program's inputs: - -```rust -x : Field, y : pub Field -``` - -Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the -keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](../language_concepts/data_types.md) section. - -The next line of the program specifies its body: - -```rust -assert(x != y); -``` - -The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. - -For more Noir syntax, check the [Language Concepts](../language_concepts/comments.md) chapter. - -## Build In/Output Files - -Change directory into _hello_world_ and build in/output files for your Noir program by running: - -```sh -cd hello_world -nargo check -``` - -Two additional files would be generated in your project directory: - -_Prover.toml_ houses input values, and _Verifier.toml_ houses public values. - -## Prove Our Noir Program - -Now that the project is set up, we can create a proof of correct execution on our Noir program. - -Fill in input values for execution in the _Prover.toml_ file. For example: - -```toml -x = "1" -y = "2" -``` - -Prove the valid execution of your Noir program: - -```sh -nargo prove -``` - -A new folder _proofs_ would then be generated in your project directory, containing the proof file -`.proof`, where the project name is defined in Nargo.toml. - -The _Verifier.toml_ file would also be updated with the public values computed from program -execution (in this case the value of `y`): - -```toml -y = "0x0000000000000000000000000000000000000000000000000000000000000002" -``` - -> **Note:** Values in _Verifier.toml_ are computed as 32-byte hex values. - -## Verify Our Noir Program - -Once a proof is generated, we can verify correct execution of our Noir program by verifying the -proof file. - -Verify your proof by running: - -```sh -nargo verify -``` - -The verification will complete in silence if it is successful. If it fails, it will log the -corresponding error instead. - -Congratulations, you have now created and verified a proof for your very first Noir program! - -In the [next section](./02_breakdown.md), we will go into more detail on each step performed. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/getting_started/02_breakdown.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/getting_started/02_breakdown.md deleted file mode 100644 index 10422029661..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/getting_started/02_breakdown.md +++ /dev/null @@ -1,198 +0,0 @@ ---- -title: Project Breakdown -description: - Learn about the anatomy of a Nargo project, including the purpose of the Prover and Verifier TOML - files, and how to prove and verify your program. -keywords: - [Nargo, Nargo project, Prover.toml, Verifier.toml, proof verification, private asset transfer] ---- - -This section breaks down our hello world program in section _1.2_. We elaborate on the project -structure and what the `prove` and `verify` commands did in the previous section. - -## Anatomy of a Nargo Project - -Upon creating a new project with `nargo new` and building the in/output files with `nargo check` -commands, you would get a minimal Nargo project of the following structure: - - - src - - Prover.toml - - Verifier.toml - - Nargo.toml - -The source directory _src_ holds the source code for your Noir program. By default only a _main.nr_ -file will be generated within it. - -### Prover.toml - -_Prover.toml_ is used for specifying the input values for executing and proving the program. You can specify `toml` files with different names by using the `--prover-name` or `-p` flags, see the [Prover](#provertoml) section below. Optionally you may specify expected output values for prove-time checking as well. - -### Verifier.toml - -_Verifier.toml_ contains public in/output values computed when executing the Noir program. - -### Nargo.toml - -_Nargo.toml_ contains the environmental options of your project. It contains a "package" section and a "dependencies" section. - -Example Nargo.toml: - -```toml -[package] -name = "noir_starter'" -type = "bin" -authors = ["Alice"] -compiler_version = "0.9.0" -description = "Getting started with Noir" -entry = "circuit/main.nr" -license = "MIT" - -[dependencies] -ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} -``` - -Nargo.toml for a [workspace](../modules_packages_crates/workspaces.md) will look a bit different. For example: - -```toml -[workspace] -members = ["crates/a", "crates/b"] -default-member = "crates/a" -``` - -#### Package section - -The package section requires a number of fields including: - -- `name` (**required**) - the name of the package -- `type` (**required**) - can be "bin", "lib", or "contract" to specify whether its a binary, library or Aztec contract -- `authors` (optional) - authors of the project -- `compiler_version` - specifies the version of the compiler to use. This is enforced by the compiler and follow's [Rust's versioning](https://doc.rust-lang.org/cargo/reference/manifest.html#the-version-field), so a `compiler_version = 0.18.0` will enforce Nargo version 0.18.0, `compiler_version = ^0.18.0` will enforce anything above 0.18.0 but below 0.19.0, etc. For more information, see how [Rust handles these operators](https://docs.rs/semver/latest/semver/enum.Op.html) -- `description` (optional) -- `entry` (optional) - a relative filepath to use as the entry point into your package (overrides the default of `src/lib.nr` or `src/main.nr`) -- `backend` (optional) -- `license` (optional) - -#### Dependencies section - -This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies.md)for more info. - -`./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or -verifier contract respectively. - -### main.nr - -The _main.nr_ file contains a `main` method, this method is the entry point into your Noir program. - -In our sample program, _main.nr_ looks like this: - -```rust -fn main(x : Field, y : Field) { - assert(x != y); -} -``` - -The parameters `x` and `y` can be seen as the API for the program and must be supplied by the -prover. Since neither `x` nor `y` is marked as public, the verifier does not supply any inputs, when -verifying the proof. - -The prover supplies the values for `x` and `y` in the _Prover.toml_ file. - -As for the program body, `assert` ensures the satisfaction of the condition (e.g. `x != y`) is -constrained by the proof of the execution of said program (i.e. if the condition was not met, the -verifier would reject the proof as an invalid proof). - -### Prover.toml - -The _Prover.toml_ file is a file which the prover uses to supply his witness values(both private and -public). - -In our hello world program the _Prover.toml_ file looks like this: - -```toml -x = "1" -y = "2" -``` - -When the command `nargo prove` is executed, two processes happen: - -1. Noir creates a proof that `x` which holds the value of `1` and `y` which holds the value of `2` - is not equal. This not equal constraint is due to the line `assert(x != y)`. - -2. Noir creates and stores the proof of this statement in the _proofs_ directory in a file called your-project.proof. So if your project is named "private_voting" (defined in the project Nargo.toml), the proof will be saved at `./proofs/private_voting.proof`. Opening this file will display the proof in hex format. - -#### Arrays of Structs - -The following code shows how to pass an array of structs to a Noir program to generate a proof. - -```rust -// main.nr -struct Foo { - bar: Field, - baz: Field, -} - -fn main(foos: [Foo; 3]) -> pub Field { - foos[2].bar + foos[2].baz -} -``` - -Prover.toml: - -```toml -[[foos]] # foos[0] -bar = 0 -baz = 0 - -[[foos]] # foos[1] -bar = 0 -baz = 0 - -[[foos]] # foos[2] -bar = 1 -baz = 2 -``` - -#### Custom toml files - -You can specify a `toml` file with a different name to use for proving by using the `--prover-name` or `-p` flags. - -This command looks for proof inputs in the default **Prover.toml** and generates the proof and saves it at `./proofs/.proof`: - -```bash -nargo prove -``` - -This command looks for proof inputs in the custom **OtherProver.toml** and generates proof and saves it at `./proofs/.proof`: - -```bash -nargo prove -p OtherProver -``` - -## Verifying a Proof - -When the command `nargo verify` is executed, two processes happen: - -1. Noir checks in the _proofs_ directory for a proof file with the project name (eg. test_project.proof) - -2. If that file is found, the proof's validity is checked - -> **Note:** The validity of the proof is linked to the current Noir program; if the program is -> changed and the verifier verifies the proof, it will fail because the proof is not valid for the -> _modified_ Noir program. - -In production, the prover and the verifier are usually two separate entities. A prover would -retrieve the necessary inputs, execute the Noir program, generate a proof and pass it to the -verifier. The verifier would then retrieve the public inputs from usually external sources and -verifies the validity of the proof against it. - -Take a private asset transfer as an example: - -A user on browser as the prover would retrieve private inputs (e.g. the user's private key) and -public inputs (e.g. the user's encrypted balance on-chain), compute the transfer, generate a proof -and submit it to the verifier smart contract. - -The verifier contract would then draw the user's encrypted balance directly from the blockchain and -verify the proof submitted against it. If the verification passes, additional functions in the -verifier contract could trigger (e.g. approve the asset transfer). - -Now that you understand the concepts, you'll probably want some editor feedback while you are writing more complex code. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/index.md deleted file mode 100644 index e8d86020a20..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/index.md +++ /dev/null @@ -1,100 +0,0 @@ ---- -title: Introducing Noir -description: - Learn about the public alpha release of Noir, a domain specific language heavily influenced by - Rust that compiles to an intermediate language which can be compiled to an arithmetic circuit or a - rank-1 constraint system. -keywords: - [ - Noir, - Domain Specific Language, - Rust, - Intermediate Language, - Arithmetic Circuit, - Rank-1 Constraint System, - Ethereum Developers, - Protocol Developers, - Blockchain Developers, - Proving System, - Smart Contract Language, - ] -slug: / ---- - -## What is Noir? - -Noir is a Domain Specific Language for SNARK proving systems. It has been designed to use any ACIR compatible proving system. - -Its design choices are influenced heavily by Rust and focuses on a simple, familiar syntax. - -## Who is Noir for? - -Noir can be used for a variety of purposes. - -### Solidity Developers - -Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will -be modularized in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier.md) command to create -a verifier contract. - -### Protocol Developers - -As a protocol developer, you may not want to use the Aztec backend due to it not being a fit for -your stack, or maybe you simply want to use a different proving system. Since Noir does not compile -to a specific proof system, it is possible for protocol developers to replace the PLONK-based -proving system with a different proving system altogether. - -### Blockchain developers - -As a blockchain developer, you will be constrained by parameters set by your blockchain (for example, the -proving system and smart contract language has been pre-defined). In order for you to use Noir in -your blockchain, a proving system backend and a smart contract interface -must be implemented for it. - -## What's new about Noir? - -Noir is simple and flexible in its design, as it does not compile immediately to a fixed -NP-complete language. Instead, Noir compiles to an intermediate language (ACIR), which itself can be compiled -to an arithmetic circuit (if choosing to target Aztec's barretenberg backend) or a rank-1 constraint system (if choosing to target an R1CS backend like Arkworks' Marlin backend, or others). - -This in itself brings up a few challenges within the design process, but allows one to decouple the programming language completely from the backend. This is similar in theory to LLVM. - -## Current Features - -Compiler: - -- Module System -- For expressions -- Arrays -- Bit Operations -- Binary operations (\<, \<=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] -- Unsigned integers -- If statements -- Structures and Tuples -- Generics - -ACIR Supported OPCODES: - -- Sha256 -- Blake2s -- Schnorr signature verification -- MerkleMembership -- Pedersen Commitment -- Pedersen Hash -- HashToField - -## Libraries - -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). - -Some libraries that are available today include: - -- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library -- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) -- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers -- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address -- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees -- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir -- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers - -See the section on [dependencies](./modules_packages_crates/dependencies.md) for more information. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/01_functions.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/01_functions.md deleted file mode 100644 index 5eb22170e54..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/01_functions.md +++ /dev/null @@ -1,225 +0,0 @@ ---- -title: Functions -description: - Learn how to declare functions and methods in Noir, a programming language with Rust semantics. - This guide covers parameter declaration, return types, call expressions, and more. -keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] ---- - -Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. - -To declare a function the `fn` keyword is used. - -```rust -fn foo() {} -``` - -By default, functions are visible only within the package they are defined. To make them visible outside of that package (for example, as part of a [library](../modules_packages_crates/crates_and_packages.md#libraries)), you should mark them as `pub`: - -```rust -pub fn foo() {} -``` - -You can also restrict the visibility of the function to only the crate it was defined in, by specifying `pub(crate)`: - -```rust -pub(crate) fn foo() {} //foo can only be called within its crate -``` - -All parameters in a function must have a type and all types are known at compile time. The parameter -is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. - -```rust -fn foo(x : Field, y : Field){} -``` - -The return type of a function can be stated by using the `->` arrow notation. The function below -states that the foo function must return a `Field`. If the function returns no value, then the arrow -is omitted. - -```rust -fn foo(x : Field, y : Field) -> Field { - x + y -} -``` - -Note that a `return` keyword is unneeded in this case - the last expression in a function's body is -returned. - -## Main function - -If you're writing a binary, the `main` function is the starting point of your program. You can pass all types of expressions to it, as long as they have a fixed size at compile time: - -```rust -fn main(x : Field) // this is fine: passing a Field -fn main(x : [Field; 2]) // this is also fine: passing a Field with known size at compile-time -fn main(x : (Field, bool)) // 👌: passing a (Field, bool) tuple means size 2 -fn main(x : str<5>) // this is fine, as long as you pass a string of size 5 - -fn main(x : Vec) // can't compile, has variable size -fn main(x : [Field]) // can't compile, has variable size -fn main(....// i think you got it by now -``` - -Keep in mind [tests](../nargo/02_testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: - -```rust -fn main(x : [Field]) { - assert(x[0] == 1); -} - -#[test] -fn test_one() { - main([1, 2]); -} -``` - -```bash -$ nargo test -[testing] Running 1 test functions -[testing] Testing test_one... ok -[testing] All tests passed - -$ nargo check -The application panicked (crashed). -Message: Cannot have variable sized arrays as a parameter to main -``` - -## Call Expressions - -Calling a function in Noir is executed by using the function name and passing in the necessary -arguments. - -Below we show how to call the `foo` function from the `main` function using a call expression: - -```rust -fn main(x : Field, y : Field) { - let z = foo(x); -} - -fn foo(x : Field) -> Field { - x + x -} -``` - -## Methods - -You can define methods in Noir on any struct type in scope. - -```rust -struct MyStruct { - foo: Field, - bar: Field, -} - -impl MyStruct { - fn new(foo: Field) -> MyStruct { - MyStruct { - foo, - bar: 2, - } - } - - fn sum(self) -> Field { - self.foo + self.bar - } -} - -fn main() { - let s = MyStruct::new(40); - assert(s.sum() == 42); -} -``` - -Methods are just syntactic sugar for functions, so if we wanted to we could also call `sum` as -follows: - -```rust -assert(MyStruct::sum(s) == 42); -``` - -It is also possible to specialize which method is chosen depending on the [generic](./06_generics.md) type that is used. In this example, the `foo` function returns different values depending on its type: - -```rust -struct Foo {} - -impl Foo { - fn foo(self) -> Field { 1 } -} - -impl Foo { - fn foo(self) -> Field { 2 } -} - -fn main() { - let f1: Foo = Foo{}; - let f2: Foo = Foo{}; - assert(f1.foo() + f2.foo() == 3); -} -``` - -Also note that impls with the same method name defined in them cannot overlap. For example, if we already have `foo` defined for `Foo` and `Foo` like we do above, we cannot also define `foo` in an `impl Foo` since it would be ambiguous which version of `foo` to choose. - -```rust -// Including this impl in the same project as the above snippet would -// cause an overlapping impls error -impl Foo { - fn foo(self) -> Field { 3 } -} -``` - -## Lambdas - -Lambdas are anonymous functions. They follow the syntax of Rust - `|arg1, arg2, ..., argN| return_expression`. - -```rust -let add_50 = |val| val + 50; -assert(add_50(100) == 150); -``` - -See [Lambdas](./08_lambdas.md) for more details. - -## Attributes - -Attributes are metadata that can be applied to a function, using the following syntax: `#[attribute(value)]`. - -Supported attributes include: - -- **builtin**: the function is implemented by the compiler, for efficiency purposes. -- **deprecated**: mark the function as _deprecated_. Calling the function will generate a warning: `warning: use of deprecated function` -- **field**: Used to enable conditional compilation of code depending on the field size. See below for more details -- **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./05_unconstrained.md) and [NoirJS](../noir_js/noir_js.md) for more details. -- **test**: mark the function as unit tests. See [Tests](../nargo/02_testing.md) for more details - -### Field Attribute - -The field attribute defines which field the function is compatible for. The function is conditionally compiled, under the condition that the field attribute matches the Noir native field. -The field can be defined implicitly, by using the name of the elliptic curve usually associated to it - for instance bn254, bls12_381 - or explicitly by using the field (prime) order, in decimal or hexadecimal form. -As a result, it is possible to define multiple versions of a function with each version specialized for a different field attribute. This can be useful when a function requires different parameters depending on the underlying elliptic curve. - -Example: we define the function `foo()` three times below. Once for the default Noir bn254 curve, once for the field $\mathbb F_{23}$, which will normally never be used by Noir, and once again for the bls12_381 curve. - -```rust -#[field(bn254)] -fn foo() -> u32 { - 1 -} - -#[field(23)] -fn foo() -> u32 { - 2 -} - -// This commented code would not compile as foo would be defined twice because it is the same field as bn254 -// #[field(21888242871839275222246405745257275088548364400416034343698204186575808495617)] -// fn foo() -> u32 { -// 2 -// } - -#[field(bls12_381)] -fn foo() -> u32 { - 3 -} -``` - -If the field name is not known to Noir, it will discard the function. Field names are case insensitive. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/02_control_flow.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/02_control_flow.md deleted file mode 100644 index a7f85360197..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/02_control_flow.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Control Flow -description: - Learn how to use loops and if expressions in the Noir programming language. Discover the syntax - and examples for for loops and if-else statements. -keywords: [Noir programming language, loops, for loop, if-else statements, Rust syntax] ---- - -## Loops - -Noir has one kind of loop: the `for` loop. `for` loops allow you to repeat a block of code multiple -times. - -The following block of code between the braces is run 10 times. - -```rust -for i in 0..10 { - // do something -}; -``` - -The index for loops is of type `u64`. - -## If Expressions - -Noir supports `if-else` statements. The syntax is most similar to Rust's where it is not required -for the statement's conditional to be surrounded by parentheses. - -```rust -let a = 0; -let mut x: u32 = 0; - -if a == 0 { - if a != 0 { - x = 6; - } else { - x = 2; - } -} else { - x = 5; - assert(x == 5); -} -assert(x == 2); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/03_ops.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/03_ops.md deleted file mode 100644 index 0e35ef5e584..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/03_ops.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -title: Logical Operations -description: - Learn about the supported arithmetic and logical operations in the Noir programming language. - Discover how to perform operations on private input types, integers, and booleans. -keywords: - [ - Noir programming language, - supported operations, - arithmetic operations, - logical operations, - predicate operators, - bitwise operations, - short-circuiting, - backend, - ] ---- - -# Operations - -## Table of Supported Operations - -| Operation | Description | Requirements | -| :-------- | :------------------------------------------------------------: | -------------------------------------: | -| + | Adds two private input types together | Types must be private input | -| - | Subtracts two private input types together | Types must be private input | -| \* | Multiplies two private input types together | Types must be private input | -| / | Divides two private input types together | Types must be private input | -| ^ | XOR two private input types together | Types must be integer | -| & | AND two private input types together | Types must be integer | -| \| | OR two private input types together | Types must be integer | -| \<\< | Left shift an integer by another integer amount | Types must be integer | -| >> | Right shift an integer by another integer amount | Types must be integer | -| ! | Bitwise not of a value | Type must be integer or boolean | -| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | -| > | returns a bool if one value is more than the other | Upper bound must have a known bit size | -| >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | -| == | returns a bool if one value is equal to the other | Both types must not be constants | -| != | returns a bool if one value is not equal to the other | Both types must not be constants | - -### Predicate Operators - -`<,<=, !=, == , >, >=` are known as predicate/comparison operations because they compare two values. -This differs from the operations such as `+` where the operands are used in _computation_. - -### Bitwise Operations Example - -```rust -fn main(x : Field) { - let y = x as u32; - let z = y & y; -} -``` - -`z` is implicitly constrained to be the result of `y & y`. The `&` operand is used to denote bitwise -`&`. - -> `x & x` would not compile as `x` is a `Field` and not an integer type. - -### Logical Operators - -Noir has no support for the logical operators `||` and `&&`. This is because encoding the -short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can -use the bitwise operators `|` and `&` which operate identically for booleans, just without the -short-circuiting. - -```rust -let my_val = 5; - -let mut flag = 1; -if (my_val > 6) | (my_val == 0) { - flag = 0; -} -assert(flag == 1); - -if (my_val != 10) & (my_val < 50) { - flag = 0; -} -assert(flag == 0); -``` - -### Shorthand operators - -Noir shorthand operators for most of the above operators, namely `+=, -=, *=, /=, %=, &=, |=, ^=, <<=`, and `>>=`. These allow for more concise syntax. For example: - -```rust -let mut i = 0; -i = i + 1; -``` - -could be written as: - -```rust -let mut i = 0; -i += 1; -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/04_assert.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/04_assert.md deleted file mode 100644 index 7427ec6cc63..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/04_assert.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Assert Function -description: - Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or - comparison expression that follows to be true, and what happens if the expression is false at - runtime. -keywords: [Noir programming language, assert statement, predicate expression, comparison expression] ---- - -Noir includes a special `assert` function which will explicitly constrain the predicate/comparison -expression that follows to be true. If this expression is false at runtime, the program will fail to -be proven. Example: - -```rust -fn main(x : Field, y : Field) { - assert(x == y); -} -``` - -You can optionally provide a message to be logged when the assertion fails: - -```rust -assert(x == y, "x and y are not equal"); -``` - -> Assertions only work for predicate operations, such as `==`. If there's any ambiguity on the operation, the program will fail to compile. For example, it is unclear if `assert(x + y)` would check for `x + y == 0` or simply would return `true`. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/05_unconstrained.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/05_unconstrained.md deleted file mode 100644 index 097d6ee9894..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/05_unconstrained.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: Unconstrained Functions -description: "Learn about what unconstrained functions in Noir are, how to use them and when you'd want to." - -keywords: [Noir programming language, unconstrained, open] ---- - - - -Unconstrained functions are functions which do not constrain any of the included computation and allow for non-deterministic computation. - -## Why? - -Zero-knowledge (ZK) domain-specific languages (DSL) enable developers to generate ZK proofs from their programs by compiling code down to the constraints of an NP complete language (such as R1CS or PLONKish languages). However, the hard bounds of a constraint system can be very limiting to the functionality of a ZK DSL. - -Enabling a circuit language to perform unconstrained execution is a powerful tool. Said another way, unconstrained execution lets developers generate witnesses from code that does not generate any constraints. Being able to execute logic outside of a circuit is critical for both circuit performance and constructing proofs on information that is external to a circuit. - -Fetching information from somewhere external to a circuit can also be used to enable developers to improve circuit efficiency. - -A ZK DSL does not just prove computation, but proves that some computation was handled correctly. Thus, it is necessary that when we switch from performing some operation directly inside of a circuit to inside of an unconstrained environment that the appropriate constraints are still laid down elsewhere in the circuit. - -## Example - -An in depth example might help drive the point home. This example comes from the excellent [post](https://discord.com/channels/1113924620781883405/1124022445054111926/1128747641853972590) by Tom in the Noir Discord. - -Let's look at how we can optimize a function to turn a `u72` into an array of `u8`s. - -```rust -fn main(num: u72) -> pub [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8)) as u72 & 0xff) as u8; - } - - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 91 -Backend circuit size: 3619 -``` - -A lot of the operations in this function are optimized away by the compiler (all the bit-shifts turn into divisions by constants). However we can save a bunch of gates by casting to u8 a bit earlier. This automatically truncates the bit-shifted value to fit in a u8 which allows us to remove the XOR against 0xff. This saves us ~480 gates in total. - -```rust -fn main(num: u72) -> pub [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8)) as u8; - } - - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 75 -Backend circuit size: 3143 -``` - -Those are some nice savings already but we can do better. This code is all constrained so we're proving every step of calculating out using num, but we don't actually care about how we calculate this, just that it's correct. This is where brillig comes in. - -It turns out that truncating a u72 into a u8 is hard to do inside a snark, each time we do as u8 we lay down 4 ACIR opcodes which get converted into multiple gates. It's actually much easier to calculate num from out than the other way around. All we need to do is multiply each element of out by a constant and add them all together, both relatively easy operations inside a snark. - -We can then run u72_to_u8 as unconstrained brillig code in order to calculate out, then use that result in our constrained function and assert that if we were to do the reverse calculation we'd get back num. This looks a little like the below: - -```rust -fn main(num: u72) -> pub [u8; 8] { - let out = u72_to_u8(num); - - let mut reconstructed_num: u72 = 0; - for i in 0..8 { - reconstructed_num += (out[i] as u72 << (56 - (8 * i))); - } - assert(num == reconstructed_num); - out -} - -unconstrained fn u72_to_u8(num: u72) -> [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8))) as u8; - } - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 78 -Backend circuit size: 2902 -``` - -This ends up taking off another ~250 gates from our circuit! We've ended up with more ACIR opcodes than before but they're easier for the backend to prove (resulting in fewer gates). - -Generally we want to use brillig whenever there's something that's easy to verify but hard to compute within the circuit. For example, if you wanted to calculate a square root of a number it'll be a much better idea to calculate this in brillig and then assert that if you square the result you get back your number. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/06_generics.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/06_generics.md deleted file mode 100644 index 36c2b593fcd..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/06_generics.md +++ /dev/null @@ -1,113 +0,0 @@ ---- -title: Generics -description: Learn how to use Generics in Noir -keywords: [Noir, Rust, generics, functions, structs] ---- - -Generics allow you to use the same functions with multiple different concrete data types. You can -read more about the concept of generics in the Rust documentation -[here](https://doc.rust-lang.org/book/ch10-01-syntax.html). - -Here is a trivial example showing the identity function that supports any type. In Rust, it is -common to refer to the most general type as `T`. We follow the same convention in Noir. - -```rust -fn id(x: T) -> T { - x -} -``` - -## In Structs - -Generics are useful for specifying types in structs. For example, we can specify that a field in a -struct will be of a certain generic type. In this case `value` is of type `T`. - -```rust -struct RepeatedValue { - value: T, - count: Field, -} - -impl RepeatedValue { - fn new(value: T) -> Self { - Self { value, count: 1 } - } - - fn increment(mut repeated: Self) -> Self { - repeated.count += 1; - repeated - } - - fn print(self) { - for _i in 0 .. self.count { - dep::std::println(self.value); - } - } -} - -fn main() { - let mut repeated = RepeatedValue::new("Hello!"); - repeated = repeated.increment(); - repeated.print(); -} -``` - -The `print` function will print `Hello!` an arbitrary number of times, twice in this case. - -If we want to be generic over array lengths (which are type-level integers), we can use numeric -generics. Using these looks just like using regular generics, but these generics can resolve to -integers at compile-time, rather than resolving to types. Here's an example of a struct that is -generic over the size of the array it contains internally: - -```rust -struct BigInt { - limbs: [u32; N], -} - -impl BigInt { - // `N` is in scope of all methods in the impl - fn first(first: BigInt, second: BigInt) -> Self { - assert(first.limbs != second.limbs); - first - - fn second(first: BigInt, second: Self) -> Self { - assert(first.limbs != second.limbs); - second - } -} -``` - -## Calling functions on generic parameters - -Unlike Rust, Noir does not have traits, so how can one translate the equivalent of a trait bound in -Rust into Noir? That is, how can we write a function that is generic over some type `T`, while also -requiring there is a function like `eq: fn(T, T) -> bool` that works on the type? - -The answer is that we can translate this by passing in the function manually. Here's an example of -implementing array equality in Noir: - -```rust -fn array_eq(array1: [T; N], array2: [T; N], elem_eq: fn(T, T) -> bool) -> bool { - if array1.len() != array2.len() { - false - } else { - let mut result = true; - for i in 0 .. array1.len() { - result &= elem_eq(array1[i], array2[i]); - } - result - } -} - -fn main() { - assert(array_eq([1, 2, 3], [1, 2, 3], |a, b| a == b)); - - // We can use array_eq even for arrays of structs, as long as we have - // an equality function for these structs we can pass in - let array = [MyStruct::new(), MyStruct::new()]; - assert(array_eq(array, array, MyStruct::eq)); -} -``` - -You can see an example of generics in the tests -[here](https://github.com/noir-lang/noir/blob/master/test_programs/execution_success/generics/src/main.nr). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/07_mutability.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/07_mutability.md deleted file mode 100644 index ed3fed820ec..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/07_mutability.md +++ /dev/null @@ -1,92 +0,0 @@ ---- -title: Mutability -description: - Learn about mutable variables, constants, and globals in Noir programming language. Discover how - to declare, modify, and use them in your programs. -keywords: [noir programming language, mutability in noir, mutable variables, constants, globals] ---- - -Variables in noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned -to via an assignment expression. - -```rust -let x = 2; -x = 3; // error: x must be mutable to be assigned to - -let mut y = 3; -let y = 4; // OK -``` - -The `mut` modifier can also apply to patterns: - -```rust -let (a, mut b) = (1, 2); -a = 11; // error: a must be mutable to be assigned to -b = 12; // OK - -let mut (c, d) = (3, 4); -c = 13; // OK -d = 14; // OK - -// etc. -let MyStruct { x: mut y } = MyStruct { x: a }; -// y is now in scope -``` - -Note that mutability in noir is local and everything is passed by value, so if a called function -mutates its parameters then the parent function will keep the old value of the parameters. - -```rust -fn main() -> pub Field { - let x = 3; - helper(x); - x // x is still 3 -} - -fn helper(mut x: i32) { - x = 4; -} -``` - -## Comptime Values - -:::warning - -The 'comptime' keyword was removed in version 0.10. The comptime keyword and syntax are currently still kept and parsed for backwards compatibility, but are now deprecated and will issue a warning when used. `comptime` has been removed because it is no longer needed for accessing arrays. - -::: - -## Globals - -Noir also supports global variables. However, they must be known at compile-time. The global type can also be inferred by the compiler entirely. Globals can also be used to specify array -annotations for function parameters and can be imported from submodules. - -```rust -global N: Field = 5; // Same as `global N: Field = 5` - -fn main(x : Field, y : [Field; N]) { - let res = x * N; - - assert(res == y[0]); - - let res2 = x * my_submodule::N; - assert(res != res2); -} - -mod my_submodule { - use dep::std; - - global N: Field = 10; - - fn my_helper() -> Field { - let x = N; - x - } -} -``` - -## Why only local mutability? - -Witnesses in a proving system are immutable in nature. Noir aims to _closely_ mirror this setting -without applying additional overhead to the user. Modeling a mutable reference is not as -straightforward as on conventional architectures and would incur some possibly unexpected overhead. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/08_lambdas.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/08_lambdas.md deleted file mode 100644 index ae1e6aecab1..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/08_lambdas.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: Lambdas -description: Learn how to use anonymous functions in Noir programming language. -keywords: [Noir programming language, lambda, closure, function, anonymous function] ---- - -## Introduction - -Lambdas are anonymous functions. The syntax is `|arg1, arg2, ..., argN| return_expression`. - -```rust -let add_50 = |val| val + 50; -assert(add_50(100) == 150); -``` - -A block can be used as the body of a lambda, allowing you to declare local variables inside it: - -```rust -let cool = || { - let x = 100; - let y = 100; - x + y -} - -assert(cool() == 200); -``` - -## Closures - -Inside the body of a lambda, you can use variables defined in the enclosing function. Such lambdas are called **closures**. In this example `x` is defined inside `main` and is accessed from within the lambda: - -```rust -fn main() { - let x = 100; - let closure = || x + 150; - assert(closure() == 250); -} -``` - -## Passing closures to higher-order functions - -It may catch you by surprise that the following code fails to compile: - -```rust -fn foo(f: fn () -> Field) -> Field { - f() -} - -fn main() { - let (x, y) = (50, 50); - assert(foo(|| x + y) == 100); // error :( -} -``` - -The reason is that the closure's capture environment affects its type - we have a closure that captures two Fields and `foo` -expects a regular function as an argument - those are incompatible. -:::note - -Variables contained within the `||` are the closure's parameters, and the expression that follows it is the closure's body. The capture environment is comprised of any variables used in the closure's body that are not parameters. - -E.g. in |x| x + y, y would be a captured variable, but x would not be, since it is a parameter of the closure. - -::: -The syntax for the type of a closure is `fn[env](args) -> ret_type`, where `env` is the capture environment of the closure - -in this example that's `(Field, Field)`. - -The best solution in our case is to make `foo` generic over the environment type of its parameter, so that it can be called -with closures with any environment, as well as with regular functions: - -```rust -fn foo(f: fn[Env]() -> Field) -> Field { - f() -} - -fn main() { - let (x, y) = (50, 50); - assert(foo(|| x + y) == 100); // compiles fine - assert(foo(|| 60) == 60); // compiles fine -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/09_comments.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/09_comments.md deleted file mode 100644 index 3bb4d2f25a4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/09_comments.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: Comments -description: - Learn how to write comments in Noir programming language. A comment is a line of code that is - ignored by the compiler, but it can be read by programmers. Single-line and multi-line comments - are supported in Noir. -keywords: [Noir programming language, comments, single-line comments, multi-line comments] ---- - -A comment is a line in your codebase which the compiler ignores, however it can be read by -programmers. - -Here is a single line comment: - -```rust -// This is a comment and is ignored -``` - -`//` is used to tell the compiler to ignore the rest of the line. - -Noir also supports multi-line block comments. Start a block comment with `/*` and end the block with `*/`. - -Noir does not natively support doc comments. You may be able to use [Rust doc comments](https://doc.rust-lang.org/reference/comments.html) in your code to leverage some Rust documentation build tools with Noir code. - -```rust -/* - This is a block comment describing a complex function. -*/ -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/10_distinct.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/10_distinct.md deleted file mode 100644 index e7ff7f5017a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/10_distinct.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: Distinct Witnesses ---- - -The `distinct` keyword prevents repetitions of witness indices in the program's ABI. This ensures -that the witnesses being returned as public inputs are all unique. - -The `distinct` keyword is only used for return values on program entry points (usually the `main()` -function). - -When using `distinct` and `pub` simultaneously, `distinct` comes first. See the example below. - -You can read more about the problem this solves -[here](https://github.com/noir-lang/noir/issues/1183). - -## Example - -Without the `distinct` keyword, the following program - -```rust -fn main(x : pub Field, y : pub Field) -> pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - "return_witnesses": [3, 2, 4, 4] - } -} -``` - -Whereas (with the `distinct` keyword) - -```rust -fn main(x : pub Field, y : pub Field) -> distinct pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - //... - "return_witnesses": [3, 4, 5, 6] - } -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/11_shadowing.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/11_shadowing.md deleted file mode 100644 index efd743e764f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/11_shadowing.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Shadowing ---- - -Noir allows for inheriting variables' values and re-declaring them with the same name similar to Rust, known as shadowing. - -For example, the following function is valid in Noir: - -```rust -fn main() { - let x = 5; - - { - let x = x * 2; - assert (x == 10); - } - - assert (x == 5); -} -``` - -In this example, a variable x is first defined with the value 5. - -The local scope that follows shadows the original x, i.e. creates a local mutable x based on the value of the original x. It is given a value of 2 times the original x. - -When we return to the main scope, x once again refers to just the original x, which stays at the value of 5. - -## Temporal mutability - -One way that shadowing is useful, in addition to ergonomics across scopes, is for temporarily mutating variables. - -```rust -fn main() { - let age = 30; - // age = age + 5; // Would error as `age` is immutable by default. - - let mut age = age + 5; // Temporarily mutates `age` with a new value. - - let age = age; // Locks `age`'s mutability again. - - assert (age == 35); -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types.md deleted file mode 100644 index 74f573f7d3f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: Data Types -description: - Get a clear understanding of the two categories of Noir data types - primitive types and compound - types. Learn about their characteristics, differences, and how to use them in your Noir - programming. -keywords: - [ - noir, - data types, - primitive types, - compound types, - private types, - public types, - ] ---- - -Every value in Noir has a type, which determines which operations are valid for it. - -All values in Noir are fundamentally composed of `Field` elements. For a more approachable -developing experience, abstractions are added on top to introduce different data types in Noir. - -Noir has two category of data types: primitive types (e.g. `Field`, integers, `bool`) and compound -types that group primitive types (e.g. arrays, tuples, structs). Each value can either be private or -public. - -## Private & Public Types - -A **private value** is known only to the Prover, while a **public value** is known by both the -Prover and Verifier. Mark values as `private` when the value should only be known to the prover. All -primitive types (including individual fields of compound types) in Noir are private by default, and -can be marked public when certain values are intended to be revealed to the Verifier. - -> **Note:** For public values defined in Noir programs paired with smart contract verifiers, once -> the proofs are verified on-chain the values can be considered known to everyone that has access to -> that blockchain. - -Public data types are treated no differently to private types apart from the fact that their values -will be revealed in proofs generated. Simply changing the value of a public type will not change the -circuit (where the same goes for changing values of private types as well). - -_Private values_ are also referred to as _witnesses_ sometimes. - -> **Note:** The terms private and public when applied to a type (e.g. `pub Field`) have a different -> meaning than when applied to a function (e.g. `pub fn foo() {}`). -> -> The former is a visibility modifier for the Prover to interpret if a value should be made known to -> the Verifier, while the latter is a visibility modifier for the compiler to interpret if a -> function should be made accessible to external Noir programs like in other languages. - -### pub Modifier - -All data types in Noir are private by default. Types are explicitly declared as public using the -`pub` modifier: - -```rust -fn main(x : Field, y : pub Field) -> pub Field { - x + y -} -``` - -In this example, `x` is **private** while `y` and `x + y` (the return value) are **public**. Note -that visibility is handled **per variable**, so it is perfectly valid to have one input that is -private and another that is public. - -> **Note:** Public types can only be declared through parameters on `main`. - -## Type Aliases - -A type alias is a new name for an existing type. Type aliases are declared with the keyword `type`: - -```rust -type Id = u8; - -fn main() { - let id: Id = 1; - let zero: u8 = 0; - assert(zero + 1 == id); -} -``` - -Type aliases can also be used with [generics](./06_generics.md): - -```rust -type Id = Size; - -fn main() { - let id: Id = 1; - let zero: u32 = 0; - assert(zero + 1 == id); -} -``` - -### BigInt - -You can achieve BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/00_fields.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/00_fields.md deleted file mode 100644 index 78d3d2af166..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/00_fields.md +++ /dev/null @@ -1,165 +0,0 @@ ---- -title: Fields -description: - Dive deep into the Field data type in Noir. Understand its methods, practical examples, and best practices to effectively use Fields in your Noir programs. -keywords: - [ - noir, - field type, - methods, - examples, - best practices, - ] ---- - -The field type corresponds to the native field type of the proving backend. - -The size of a Noir field depends on the elliptic curve's finite field for the proving backend -adopted. For example, a field would be a 254-bit integer when paired with the default backend that -spans the Grumpkin curve. - -Fields support integer arithmetic and are often used as the default numeric type in Noir: - -```rust -fn main(x : Field, y : Field) { - let z = x + y; -} -``` - -`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new -private value `z` constrained to be equal to `x + y`. - -If proving efficiency is of priority, fields should be used as a default for solving problems. -Smaller integer types (e.g. `u64`) incur extra range constraints. - -## Methods - -After declaring a Field, you can use these common methods on it: - -### to_le_bits - -Transforms the field into an array of bits, Little Endian. - -```rust -fn to_le_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_le_bits(32); -} -``` - -### to_be_bits - -Transforms the field into an array of bits, Big Endian. - -```rust -fn to_be_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_be_bits(32); -} -``` - -### to_le_bytes - -Transforms into an array of bytes, Little Endian - -```rust -fn to_le_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_le_bytes(4); -} -``` - -### to_be_bytes - -Transforms into an array of bytes, Big Endian - -```rust -fn to_be_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_be_bytes(4); -} -``` - -### to_le_radix - -Decomposes into a vector over the specified base, Little Endian - -```rust -fn to_le_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_le_radix(256, 4); -} -``` - -### to_be_radix - -Decomposes into a vector over the specified base, Big Endian - -```rust -fn to_be_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_be_radix(256, 4); -} -``` - -### pow_32 - -Returns the value to the power of the specified exponent - -```rust -fn pow_32(self, exponent: Field) -> Field -``` - -example: - -```rust -fn main() { - let field = 2 - let pow = field.pow_32(4); - assert(pow == 16); -} -``` - -### sgn0 - -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. - -```rust -fn sgn0(self) -> u1 -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/01_integers.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/01_integers.md deleted file mode 100644 index 1814365800a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/01_integers.md +++ /dev/null @@ -1,112 +0,0 @@ ---- -title: Integers -description: Explore the Integer data type in Noir. Learn about its methods, see real-world examples, and grasp how to efficiently use Integers in your Noir code. -keywords: [noir, integer types, methods, examples, arithmetic] ---- - -An integer type is a range constrained field type. The Noir frontend supports arbitrarily-sized, both unsigned and signed integer types. - -:::info - -When an integer is defined in Noir without a specific type, it will default to `Field`. - -The one exception is for loop indices which default to `u64` since comparisons on `Field`s are not possible. - -::: - -## Unsigned Integers - -An unsigned integer type is specified first with the letter `u` (indicating its unsigned nature) followed by its bit size (e.g. `8`): - -```rust -fn main() { - let x: u8 = 1; - let y: u8 = 1; - let z = x + y; - assert (z == 2); -} -``` - -The bit size determines the maximum value the integer type can store. For example, a `u8` variable can store a value in the range of 0 to 255 (i.e. $\\2^{8}-1\\$). - -## Signed Integers - -A signed integer type is specified first with the letter `i` (which stands for integer) followed by its bit size (e.g. `8`): - -```rust -fn main() { - let x: i8 = -1; - let y: i8 = -1; - let z = x + y; - assert (z == -2); -} -``` - -The bit size determines the maximum and minimum range of value the integer type can store. For example, an `i8` variable can store a value in the range of -128 to 127 (i.e. $\\-2^{7}\\$ to $\\2^{7}-1\\$). - -:::tip - -If you are using the default proving backend with Noir, both even (e.g. _u2_, _i2_) and odd (e.g. _u3_, _i3_) arbitrarily-sized integer types up to 127 bits (i.e. _u127_ and _i127_) are supported. - -::: - -## Overflows - -Computations that exceed the type boundaries will result in overflow errors. This happens with both signed and unsigned integers. For example, attempting to prove: - -```rust -fn main(x: u8, y: u8) { - let z = x + y; -} -``` - -With: - -```toml -x = "255" -y = "1" -``` - -Would result in: - -``` -$ nargo prove -error: Assertion failed: 'attempt to add with overflow' -┌─ ~/src/main.nr:9:13 -│ -│ let z = x + y; -│ ----- -│ -= Call stack: - ... -``` - -A similar error would happen with signed integers: - -```rust -fn main() { - let x: i8 = -118; - let y: i8 = -11; - let z = x + y; -} -``` - -### Wrapping methods - -Although integer overflow is expected to error, some use-cases rely on wrapping. For these use-cases, the standard library provides `wrapping` variants of certain common operations: - -```rust -fn wrapping_add(x: T, y: T) -> T; -fn wrapping_sub(x: T, y: T) -> T; -fn wrapping_mul(x: T, y: T) -> T; -``` - -Example of how it is used: - -```rust -use dep::std; - -fn main(x: u8, y: u8) -> pub u8 { - std::wrapping_add(x, y) -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/02_booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/02_booleans.md deleted file mode 100644 index d353606210a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/02_booleans.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: Booleans -description: - Delve into the Boolean data type in Noir. Understand its methods, practical examples, and best practices for using Booleans in your Noir programs. -keywords: - [ - noir, - boolean type, - methods, - examples, - logical operations, - ] ---- - - -The `bool` type in Noir has two possible values: `true` and `false`: - -```rust -fn main() { - let t = true; - let f: bool = false; -} -``` - -> **Note:** When returning a boolean value, it will show up as a value of 1 for `true` and 0 for -> `false` in _Verifier.toml_. - -The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and -[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/03_strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/03_strings.md deleted file mode 100644 index 4360893e9a2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/03_strings.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: Strings -description: - Discover the String data type in Noir. Learn about its methods, see real-world examples, and understand how to effectively manipulate and use Strings in Noir. -keywords: - [ - noir, - string type, - methods, - examples, - concatenation, - ] ---- - - -The string type is a fixed length value defined with `str`. - -You can use strings in `assert()` functions or print them with -`std::println()`. See more about [Logging](../../standard_library/logging.md). - -```rust -use dep::std; - -fn main(message : pub str<11>, hex_as_string : str<4>) { - std::println(message); - assert(message == "hello world"); - assert(hex_as_string == "0x41"); -} -``` - -You can convert a `str` to a byte array by calling `as_bytes()` -or a vector by calling `as_bytes_vec()`. - -```rust -fn main() { - let message = "hello world"; - let message_bytes = message.as_bytes(); - let mut message_vec = message.as_bytes_vec(); - assert(message_bytes.len() == 11); - assert(message_bytes[0] == 104); - assert(message_bytes[0] == message_vec.get(0)); -} -``` - -## Escape characters - -You can use escape characters for your strings: - -| Escape Sequence | Description | -|-----------------|-----------------| -| `\r` | Carriage Return | -| `\n` | Newline | -| `\t` | Tab | -| `\0` | Null Character | -| `\"` | Double Quote | -| `\\` | Backslash | - -Example: - -```rust -let s = "Hello \"world" // prints "Hello "world" -let s = "hey \tyou"; // prints "hey you" -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/04_arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/04_arrays.md deleted file mode 100644 index 3c84da3f8ad..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/04_arrays.md +++ /dev/null @@ -1,244 +0,0 @@ ---- -title: Arrays -description: - Dive into the Array data type in Noir. Grasp its methods, practical examples, and best practices for efficiently using Arrays in your Noir code. -keywords: - [ - noir, - array type, - methods, - examples, - indexing, - ] ---- - -An array is one way of grouping together values into one compound type. Array types can be inferred -or explicitly specified via the syntax `[; ]`: - -```rust -fn main(x : Field, y : Field) { - let my_arr = [x, y]; - let your_arr: [Field; 2] = [x, y]; -} -``` - -Here, both `my_arr` and `your_arr` are instantiated as an array containing two `Field` elements. - -Array elements can be accessed using indexing: - -```rust -fn main() { - let a = [1, 2, 3, 4, 5]; - - let first = a[0]; - let second = a[1]; -} -``` - -All elements in an array must be of the same type (i.e. homogeneous). That is, an array cannot group -a `Field` value and a `u8` value together for example. - -You can write mutable arrays, like: - -```rust -fn main() { - let mut arr = [1, 2, 3, 4, 5]; - assert(arr[0] == 1); - - arr[0] = 42; - assert(arr[0] == 42); -} -``` - -You can instantiate a new array of a fixed size with the same value repeated for each element. The following example instantiates an array of length 32 where each element is of type Field and has the value 0. - -```rust -let array: [Field; 32] = [0; 32]; -``` - -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: - -```rust -let array: [Field; 32] = [0; 32]; -let sl = array.as_slice() -``` - -You can define multidimensional arrays: - -```rust -let array : [[Field; 2]; 2]; -let element = array[0][0]; -``` - -## Types - -You can create arrays of primitive types or structs. There is not yet support for nested arrays -(arrays of arrays) or arrays of structs that contain arrays. - -## Methods - -For convenience, the STD provides some ready-to-use, common methods for arrays: - -### len - -Returns the length of an array - -```rust -fn len(_array: [T; N]) -> comptime Field -``` - -example - -```rust -fn main() { - let array = [42, 42]; - assert(array.len() == 2); -} -``` - -### sort - -Returns a new sorted array. The original array remains untouched. Notice that this function will -only work for arrays of fields or integers, not for any arbitrary type. This is because the sorting -logic it uses internally is optimized specifically for these values. If you need a sort function to -sort any type, you should use the function `sort_via` described below. - -```rust -fn sort(_array: [T; N]) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32]; - let sorted = arr.sort(); - assert(sorted == [32, 42]); -} -``` - -### sort_via - -Sorts the array with a custom comparison function - -```rust -fn sort_via(mut a: [T; N], ordering: fn(T, T) -> bool) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32] - let sorted_ascending = arr.sort_via(|a, b| a <= b); - assert(sorted_ascending == [32, 42]); // verifies - - let sorted_descending = arr.sort_via(|a, b| a >= b); - assert(sorted_descending == [32, 42]); // does not verify -} -``` - -### map - -Applies a function to each element of the array, returning a new array containing the mapped elements. - -```rust -fn map(f: fn(T) -> U) -> [U; N] -``` - -example - -```rust -let a = [1, 2, 3]; -let b = a.map(|a| a * 2); // b is now [2, 4, 6] -``` - -### fold - -Applies a function to each element of the array, returning the final accumulated value. The first -parameter is the initial value. - -```rust -fn fold(mut accumulator: U, f: fn(U, T) -> U) -> U -``` - -This is a left fold, so the given function will be applied to the accumulator and first element of -the array, then the second, and so on. For a given call the expected result would be equivalent to: - -```rust -let a1 = [1]; -let a2 = [1, 2]; -let a3 = [1, 2, 3]; - -let f = |a, b| a - b; -a1.fold(10, f) //=> f(10, 1) -a2.fold(10, f) //=> f(f(10, 1), 2) -a3.fold(10, f) //=> f(f(f(10, 1), 2), 3) -``` - -example: - -```rust - -fn main() { - let arr = [2, 2, 2, 2, 2]; - let folded = arr.fold(0, |a, b| a + b); - assert(folded == 10); -} - -``` - -### reduce - -Same as fold, but uses the first element as starting element. - -```rust -fn reduce(f: fn(T, T) -> T) -> T -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let reduced = arr.reduce(|a, b| a + b); - assert(reduced == 10); -} -``` - -### all - -Returns true if all the elements satisfy the given predicate - -```rust -fn all(predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let all = arr.all(|a| a == 2); - assert(all); -} -``` - -### any - -Returns true if any of the elements satisfy the given predicate - -```rust -fn any(predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 5]; - let any = arr.any(|a| a == 5); - assert(any); -} - -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/05_slices.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/05_slices.mdx deleted file mode 100644 index 1be0ec4a137..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/05_slices.mdx +++ /dev/null @@ -1,146 +0,0 @@ ---- -title: Slices -description: Explore the Slice data type in Noir. Understand its methods, see real-world examples, and learn how to effectively use Slices in your Noir programs. -keywords: [noir, slice type, methods, examples, subarrays] ---- - -import Experimental from '@site/src/components/Notes/_experimental.mdx'; - - - -A slice is a dynamically-sized view into a sequence of elements. They can be resized at runtime, but because they don't own the data, they cannot be returned from a circuit. You can treat slices as arrays without a constrained size. - -```rust -use dep::std::slice; - -fn main() -> pub Field { - let mut slice: [Field] = [0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -View the corresponding test file [here][test-file]. - -[test-file]: https://github.com/noir-lang/noir/blob/f387ec1475129732f72ba294877efdf6857135ac/crates/nargo_cli/tests/test_data_ssa_refactor/slices/src/main.nr - -## Methods - -For convenience, the STD provides some ready-to-use, common methods for slices: - -### push_back - -Pushes a new element to the end of the slice, returning a new slice with a length one greater than the original unmodified slice. - -```rust -fn push_back(_self: [T], _elem: T) -> [T] -``` - -example: - -```rust -fn main() -> pub Field { - let mut slice: [Field] = [0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -View the corresponding test file [here][test-file]. - -### push_front - -Returns a new array with the specified element inserted at index 0. The existing elements indexes are incremented by 1. - -```rust -fn push_front(_self: Self, _elem: T) -> Self -``` - -Example: - -```rust -let mut new_slice: [Field] = []; -new_slice = new_slice.push_front(20); -assert(new_slice[0] == 20); // returns true -``` - -View the corresponding test file [here][test-file]. - -### pop_front - -Returns a tuple of two items, the first element of the array and the rest of the array. - -```rust -fn pop_front(_self: Self) -> (T, Self) -``` - -Example: - -```rust -let (first_elem, rest_of_slice) = slice.pop_front(); -``` - -View the corresponding test file [here][test-file]. - -### pop_back - -Returns a tuple of two items, the beginning of the array with the last element omitted and the last element. - -```rust -fn pop_back(_self: Self) -> (Self, T) -``` - -Example: - -```rust -let (popped_slice, last_elem) = slice.pop_back(); -``` - -View the corresponding test file [here][test-file]. - -### append - -Loops over a slice and adds it to the end of another. - -```rust -fn append(mut self, other: Self) -> Self -``` - -Example: - -```rust -let append = [1, 2].append([3, 4, 5]); -``` - -### insert - -Inserts an element at a specified index and shifts all following elements by 1. - -```rust -fn insert(_self: Self, _index: Field, _elem: T) -> Self -``` - -Example: - -```rust -new_slice = rest_of_slice.insert(2, 100); -assert(new_slice[2] == 100); -``` - -View the corresponding test file [here][test-file]. - -### remove - -Remove an element at a specified index, shifting all elements after it to the left, returning the altered slice and the removed element. - -```rust -fn remove(_self: Self, _index: Field) -> (Self, T) -``` - -Example: - -```rust -let (remove_slice, removed_elem) = slice.remove(3); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/06_vectors.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/06_vectors.mdx deleted file mode 100644 index 4617e90d038..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/06_vectors.mdx +++ /dev/null @@ -1,172 +0,0 @@ ---- -title: Vectors -description: Delve into the Vector data type in Noir. Learn about its methods, practical examples, and best practices for using Vectors in your Noir code. -keywords: [noir, vector type, methods, examples, dynamic arrays] ---- - -import Experimental from '@site/src/components/Notes/_experimental.mdx'; - - - -A vector is a collection type similar to Rust's Vector type. It's convenient way to use slices as mutable arrays. - -Example: - -```rust -use dep::std::collections::vec::Vec; - -let mut vector: Vec = Vec::new(); -for i in 0..5 { - vector.push(i); -} -assert(vector.len() == 5); -``` - -## Methods - -### new - -Creates a new, empty vector. - -```rust -pub fn new() -> Self { - Self { slice: [] } -} -``` - -Example: - -```rust -let empty_vector: Vec = Vec::new(); -assert(empty_vector.len() == 0); -``` - -### from_slice - -Creates a vector containing each element from a given slice. Mutations to the resulting vector will not affect the original slice. - -```rust -pub fn from_slice(slice: [T]) -> Self { - Self { slice } -} -``` - -Example: - -```rust -let arr: [Field] = [1, 2, 3]; -let vector_from_slice = Vec::from_slice(arr); -assert(vector_from_slice.len() == 3); -``` - -### get - -Retrieves an element from the vector at a given index. Panics if the index points beyond the vector's end. - -```rust -pub fn get(self, index: Field) -> T { - self.slice[index] -} -``` - -Example: - -```rust -let vector: Vec = Vec::from_slice([10, 20, 30]); -assert(vector.get(1) == 20); -``` - -### push - -Adds a new element to the vector's end, returning a new vector with a length one greater than the original unmodified vector. - -```rust -pub fn push(&mut self, elem: T) { - self.slice = self.slice.push_back(elem); -} -``` - -Example: - -```rust -let mut vector: Vec = Vec::new(); -vector.push(10); -assert(vector.len() == 1); -``` - -### pop - -Removes an element from the vector's end, returning a new vector with a length one less than the original vector, along with the removed element. Panics if the vector's length is zero. - -```rust -pub fn pop(&mut self) -> T { - let (popped_slice, last_elem) = self.slice.pop_back(); - self.slice = popped_slice; - last_elem -} -``` - -Example: - -```rust -let mut vector = Vec::from_slice([10, 20]); -let popped_elem = vector.pop(); -assert(popped_elem == 20); -assert(vector.len() == 1); -``` - -### insert - -Inserts an element at a specified index, shifting subsequent elements to the right. - -```rust -pub fn insert(&mut self, index: Field, elem: T) { - self.slice = self.slice.insert(index, elem); -} -``` - -Example: - -```rust -let mut vector = Vec::from_slice([10, 30]); -vector.insert(1, 20); -assert(vector.get(1) == 20); -``` - -### remove - -Removes an element at a specified index, shifting subsequent elements to the left, and returns the removed element. - -```rust -pub fn remove(&mut self, index: Field) -> T { - let (new_slice, elem) = self.slice.remove(index); - self.slice = new_slice; - elem -} -``` - -Example: - -```rust -let mut vector = Vec::from_slice([10, 20, 30]); -let removed_elem = vector.remove(1); -assert(removed_elem == 20); -assert(vector.len() == 2); -``` - -### len - -Returns the number of elements in the vector. - -```rust -pub fn len(self) -> Field { - self.slice.len() -} -``` - -Example: - -```rust -let empty_vector: Vec = Vec::new(); -assert(empty_vector.len() == 0); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/07_tuples.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/07_tuples.md deleted file mode 100644 index 5f6cab974a8..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/07_tuples.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: Tuples -description: - Dive into the Tuple data type in Noir. Understand its methods, practical examples, and best practices for efficiently using Tuples in your Noir code. -keywords: - [ - noir, - tuple type, - methods, - examples, - multi-value containers, - ] ---- - -A tuple collects multiple values like an array, but with the added ability to collect values of -different types: - -```rust -fn main() { - let tup: (u8, u64, Field) = (255, 500, 1000); -} -``` - -One way to access tuple elements is via destructuring using pattern matching: - -```rust -fn main() { - let tup = (1, 2); - - let (one, two) = tup; - - let three = one + two; -} -``` - -Another way to access tuple elements is via direct member access, using a period (`.`) followed by -the index of the element we want to access. Index `0` corresponds to the first tuple element, `1` to -the second and so on: - -```rust -fn main() { - let tup = (5, 6, 7, 8); - - let five = tup.0; - let eight = tup.3; -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/08_structs.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/08_structs.md deleted file mode 100644 index 35421734639..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/08_structs.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -title: Structs -description: - Explore the Struct data type in Noir. Learn about its methods, see real-world examples, and grasp how to effectively define and use Structs in your Noir programs. -keywords: - [ - noir, - struct type, - methods, - examples, - data structures, - ] ---- - -A struct also allows for grouping multiple values of different types. Unlike tuples, we can also -name each field. - -> **Note:** The usage of _field_ here refers to each element of the struct and is unrelated to the -> field type of Noir. - -Defining a struct requires giving it a name and listing each field within as `: ` pairs: - -```rust -struct Animal { - hands: Field, - legs: Field, - eyes: u8, -} -``` - -An instance of a struct can then be created with actual values in `: ` pairs in any -order. Struct fields are accessible using their given names: - -```rust -fn main() { - let legs = 4; - - let dog = Animal { - eyes: 2, - hands: 0, - legs, - }; - - let zero = dog.hands; -} -``` - -Structs can also be destructured in a pattern, binding each field to a new variable: - -```rust -fn main() { - let Animal { hands, legs: feet, eyes } = get_octopus(); - - let ten = hands + feet + eyes as u8; -} - -fn get_octopus() -> Animal { - let octopus = Animal { - hands: 0, - legs: 8, - eyes: 2, - }; - - octopus -} -``` - -The new variables can be bound with names different from the original struct field names, as -showcased in the `legs --> feet` binding in the example above. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/09_references.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/09_references.md deleted file mode 100644 index b0c35ce2cb9..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/09_references.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: References ---- - -Noir supports first-class references. References are a bit like pointers: they point to a specific address that can be followed to access the data stored at that address. You can use Rust-like syntax to use pointers in Noir: the `&` operator references the variable, the `*` operator dereferences it. - -Example: - -```rust -fn main() { - let mut x = 2; - - // you can reference x as &mut and pass it to multiplyBy2 - multiplyBy2(&mut x); -} - -// you can access &mut here -fn multiplyBy2(x: &mut Field) { - // and dereference it with * - *x = *x * 2; -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/10_function_types.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/10_function_types.md deleted file mode 100644 index 1ec92efd594..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/10_function_types.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: Function types ---- - -Noir supports higher-order functions. The syntax for a function type is as follows: - -```rust -fn(arg1_type, arg2_type, ...) -> return_type -``` - -Example: - -```rust -fn assert_returns_100(f: fn() -> Field) { // f takes no args and returns a Field - assert(f() == 100); -} - -fn main() { - assert_returns_100(|| 100); // ok - assert_returns_100(|| 150); // fails -} -``` - -A function type also has an optional capture environment - this is necessary to support closures. -See [Lambdas](../08_lambdas.md) for more details. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/migration_notes.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/migration_notes.md deleted file mode 100644 index 905bca3d30c..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/migration_notes.md +++ /dev/null @@ -1,91 +0,0 @@ ---- -title: Migration notes -description: Read about migration notes from previous versions, which could solve problems while updating -keywords: [Noir, notes, migration, updating, upgrading] ---- - -Noir is in full-speed development. Things break fast, wild, and often. This page attempts to leave some notes on errors you might encounter when upgrading and how to resolve them until proper patches are built. - -## ≥0.19 - -### Enforcing `compiler_version` - -From this version on, the compiler will check for the `compiler_version` field in `Nargo.toml`, and will error if it doesn't match the current Nargo version in use. - -To update, please make sure this field in `Nargo.toml` matches the output of `nargo --version`. - -## ≥0.14 - -The index of the [for loops](./language_concepts/02_control_flow.md#loops) is now of type `u64` instead of `Field`. An example refactor would be: - -```rust -for i in 0..10 { - let i = i as Field; -} -``` - -## ≥v0.11.0 and Nargo backend - -From this version onwards, Nargo starts managing backends through the `nargo backend` command. Upgrading to the versions per usual steps might lead to: - -### `backend encountered an error` - -This is likely due to the existing locally installed version of proving backend (e.g. barretenberg) is incompatible with the version of Nargo in use. - -To fix the issue: - -1. Uninstall the existing backend - -```bash -nargo backend uninstall acvm-backend-barretenberg -``` - -You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. - -2. Reinstall a compatible version of the proving backend. - -If you are using the default barretenberg backend, simply run: - -``` -nargo prove -``` - -with your Noir program. - -This will trigger the download and installation of the latest version of barretenberg compatible with your Nargo in use. - -### `backend encountered an error: illegal instruction` - -On certain Intel-based systems, an `illegal instruction` error may arise due to incompatibility of barretenberg with certain CPU instructions. - -To fix the issue: - -1. Uninstall the existing backend - -```bash -nargo backend uninstall acvm-backend-barretenberg -``` - -You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. - -2. Reinstall a compatible version of the proving backend. - -If you are using the default barretenberg backend, simply run: - -``` -nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/barretenberg-js-binary/raw/master/run-bb.tar.gz -``` - -This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. - -The gzipped file is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. - -Then run: - -``` -DESIRED_BINARY_VERSION=0.8.1 nargo info -``` - -This overrides the bb native binary with a bb.js node application instead, which should be compatible with most if not all hardware. This does come with the drawback of being generally slower than native binary. - -0.8.1 indicates bb.js version 0.8.1, so if you change that it will update to a different version or the default version in the script if none was supplied. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/modules_packages_crates/crates_and_packages.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/modules_packages_crates/crates_and_packages.md deleted file mode 100644 index 23f60855c30..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/modules_packages_crates/crates_and_packages.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Crates and Packages -description: Learn how to use Crates and Packages in your Noir project -keywords: [Nargo, dependencies, package management, crates, package] ---- - -## Crates - -A crate is the smallest amount of code that the Noir compiler considers at a time. -Crates can contain modules, and the modules may be defined in other files that get compiled with the crate, as we’ll see in the coming sections. - -### Crate Types - -A Noir crate can come in several forms: binaries, libraries or contracts. - -#### Binaries - -_Binary crates_ are programs which you can compile to an ACIR circuit which you can then create proofs against. Each must have a function called `main` that defines the ACIR circuit which is to be proved. - -#### Libraries - -_Library crates_ don't have a `main` function and they don't compile down to ACIR. Instead they define functionality intended to be shared with multiple projects, and eventually included in a binary crate. - -#### Contracts - -Contract crates are similar to binary crates in that they compile to ACIR which you can create proofs against. They are different in that they do not have a single `main` function, but are a collection of functions to be deployed to the [Aztec network](https://aztec.network). You can learn more about the technical details of Aztec in the [monorepo](https://github.com/AztecProtocol/aztec-packages) or contract [examples](https://github.com/AztecProtocol/aztec-packages/tree/master/noir-projects/noir-contracts/contracts). - -### Crate Root - -Every crate has a root, which is the source file that the compiler starts, this is also known as the root module. The Noir compiler does not enforce any conditions on the name of the file which is the crate root, however if you are compiling via Nargo the crate root must be called `lib.nr` or `main.nr` for library or binary crates respectively. - -## Packages - -A Nargo _package_ is a collection of one of more crates that provides a set of functionality. A package must include a Nargo.toml file. - -A package _must_ contain either a library or a binary crate, but not both. - -### Differences from Cargo Packages - -One notable difference between Rust's Cargo and Noir's Nargo is that while Cargo allows a package to contain an unlimited number of binary crates and a single library crate, Nargo currently only allows a package to contain a single crate. - -In future this restriction may be lifted to allow a Nargo package to contain both a binary and library crate or multiple binary crates. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/modules_packages_crates/dependencies.md deleted file mode 100644 index 87a09293ea8..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/modules_packages_crates/dependencies.md +++ /dev/null @@ -1,123 +0,0 @@ ---- -title: Dependencies -description: - Learn how to specify and manage dependencies in Nargo, allowing you to upload packages to GitHub - and use them easily in your project. -keywords: [Nargo, dependencies, GitHub, package management, versioning] ---- - -Nargo allows you to upload packages to GitHub and use them as dependencies. - -## Specifying a dependency - -Specifying a dependency requires a tag to a specific commit and the git url to the url containing -the package. - -Currently, there are no requirements on the tag contents. If requirements are added, it would follow -semver 2.0 guidelines. - -> Note: Without a `tag` , there would be no versioning and dependencies would change each time you -> compile your project. - -For example, to add the [ecrecover-noir library](https://github.com/colinnielsen/ecrecover-noir) to your project, add it to `Nargo.toml`: - -```toml -# Nargo.toml - -[dependencies] -ecrecover = {tag = "v0.8.0", git = "https://github.com/colinnielsen/ecrecover-noir"} -``` - -If the module is in a subdirectory, you can define a subdirectory in your git repository, for example: - -```toml -# Nargo.toml - -[dependencies] -easy_private_token_contract = {tag ="v0.1.0-alpha62", git = "https://github.com/AztecProtocol/aztec-packages", directory = "yarn-project/noir-contracts/contracts/easy_private_token_contract"} -``` - -## Specifying a local dependency - -You can also specify dependencies that are local to your machine. - -For example, this file structure has a library and binary crate - -```tree -├── binary_crate -│   ├── Nargo.toml -│   └── src -│   └── main.nr -└── lib_a - ├── Nargo.toml - └── src - └── lib.nr -``` - -Inside of the binary crate, you can specify: - -```toml -# Nargo.toml - -[dependencies] -lib_a = { path = "../lib_a" } -``` - -## Importing dependencies - -You can import a dependency to a Noir file using the following syntax. For example, to import the -ecrecover-noir library and local lib_a referenced above: - -```rust -use dep::ecrecover; -use dep::lib_a; -``` - -You can also import only the specific parts of dependency that you want to use, like so: - -```rust -use dep::std::hash::sha256; -use dep::std::scalar_mul::fixed_base_embedded_curve; -``` - -Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you -can import multiple items in the same line by enclosing them in curly braces: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; -``` - -We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. - -Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. - -## Dependencies of Dependencies - -Note that when you import a dependency, you also get access to all of the dependencies of that package. - -For example, the [phy_vector](https://github.com/resurgencelabs/phy_vector) library imports an [fraction](https://github.com/resurgencelabs/fraction) library. If you're importing the phy_vector library, then you can access the functions in fractions library like so: - -```rust -use dep::phy_vector; - -fn main(x : Field, y : pub Field) { - //... - let f = phy_vector::fraction::toFraction(true, 2, 1); - //... -} -``` - -## Available Libraries - -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). - -Some libraries that are available today include: - -- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library -- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) -- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers -- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address -- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees -- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir -- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/modules_packages_crates/modules.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/modules_packages_crates/modules.md deleted file mode 100644 index 11e60cbf35e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/modules_packages_crates/modules.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: Modules -description: - Learn how to organize your files using modules in Noir, following the same convention as Rust's - module system. Examples included. -keywords: [Noir, Rust, modules, organizing files, sub-modules] ---- - -Noir's module system follows the same convention as the _newer_ version of Rust's module system. - -## Purpose of Modules - -Modules are used to organize files. Without modules all of your code would need to live in a single -file. In Noir, the compiler does not automatically scan all of your files to detect modules. This -must be done explicitly by the developer. - -## Examples - -### Importing a module in the crate root - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::hello_world(); -} -``` - -Filename : `src/foo.nr` - -```rust -fn from_foo() {} -``` - -In the above snippet, the crate root is the `src/main.nr` file. The compiler sees the module -declaration `mod foo` which prompts it to look for a foo.nr file. - -Visually this module hierarchy looks like the following : - -``` -crate - ├── main - │ - └── foo - └── from_foo - -``` - -### Importing a module throughout the tree - -All modules are accessible from the `crate::` namespace. - -``` -crate - ├── bar - ├── foo - └── main - -``` - -In the above snippet, if `bar` would like to use functions in `foo`, it can do so by `use crate::foo::function_name`. - -### Sub-modules - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::from_foo(); -} -``` - -Filename : `src/foo.nr` - -```rust -mod bar; -fn from_foo() {} -``` - -Filename : `src/foo/bar.nr` - -```rust -fn from_bar() {} -``` - -In the above snippet, we have added an extra module to the module tree; `bar`. `bar` is a submodule -of `foo` hence we declare bar in `foo.nr` with `mod bar`. Since `foo` is not the crate root, the -compiler looks for the file associated with the `bar` module in `src/foo/bar.nr` - -Visually the module hierarchy looks as follows: - -``` -crate - ├── main - │ - └── foo - ├── from_foo - └── bar - └── from_bar -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/modules_packages_crates/workspaces.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/modules_packages_crates/workspaces.md deleted file mode 100644 index 8168793fc80..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/modules_packages_crates/workspaces.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -title: Workspaces ---- - -Workspaces are a feature of nargo that allow you to manage multiple related Noir packages in a single repository. A workspace is essentially a group of related projects that share common build output directories and configurations. - -Each Noir project (with it's own Nargo.toml file) can be thought of as a package. Each package is expected to contain exactly one "named circuit", being the "name" defined in Nargo.toml with the program logic defined in `./src/main.nr`. - -For a project with the following structure: - -```tree -├── crates -│ ├── a -│ │ ├── Nargo.toml -│ │ └── Prover.toml -│ │ └── src -│ │ └── main.nr -│ └── b -│ ├── Nargo.toml -│ └── Prover.toml -│ └── src -│ └── main.nr -│ -└── Nargo.toml -``` - -You can define a workspace in Nargo.toml like so: - -```toml -[workspace] -members = ["crates/a", "crates/b"] -default-member = "crates/a" -``` - -`members` indicates which packages are included in the workspace. As such, all member packages of a workspace will be processed when the `--workspace` flag is used with various commands or if a `default-member` is not specified. - -`default-member` indicates which package various commands process by default. - -Libraries can be defined in a workspace. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. - -Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/nargo/01_commands.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/nargo/01_commands.md deleted file mode 100644 index e2b0af522f4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/nargo/01_commands.md +++ /dev/null @@ -1,250 +0,0 @@ ---- -title: Commands -description: - Noir CLI Commands for Noir Prover and Verifier to create, execute, prove and verify programs, - generate Solidity verifier smart contract and compile into JSON file containing ACIR - representation and ABI of circuit. -keywords: - [ - Nargo, - Noir CLI, - Noir Prover, - Noir Verifier, - generate Solidity verifier, - compile JSON file, - ACIR representation, - ABI of circuit, - TypeScript, - ] ---- - -## General options - -| Option | Description | -| -------------------- | -------------------------------------------------- | -| `--show-ssa` | Emit debug information for the intermediate SSA IR | -| `--deny-warnings` | Quit execution when warnings are emitted | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo help [subcommand]` - -Prints the list of available commands or specific information of a subcommand. - -_Arguments_ - -| Argument | Description | -| -------------- | -------------------------------------------- | -| `` | The subcommand whose help message to display | - -## `nargo backend` - -Installs and selects custom backends used to generate and verify proofs. - -### Commands - -| Command | Description | -| ----------- | --------------------------------------------------------- | -| `current` | Prints the name of the currently active backend | -| `ls` | Prints the list of currently installed backends | -| `use` | Select the backend to use | -| `install` | Install a new backend from a URL | -| `uninstall` | Uninstalls a backend | -| `help` | Print this message or the help of the given subcommand(s) | - -### Options - -| Option | Description | -| ------------ | ----------- | -| `-h, --help` | Print help | - -## `nargo check` - -Generate the `Prover.toml` and `Verifier.toml` files for specifying prover and verifier in/output -values of the Noir program respectively. - -### Options - -| Option | Description | -| --------------------- | ------------------------------------- | -| `--package ` | The name of the package to check | -| `--workspace` | Check all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -### `nargo codegen-verifier` - -Generate a Solidity verifier smart contract for the program. - -### Options - -| Option | Description | -| --------------------- | ------------------------------------- | -| `--package ` | The name of the package to codegen | -| `--workspace` | Codegen all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo compile` - -Compile the program into a JSON build artifact file containing the ACIR representation and the ABI -of the circuit. This build artifact can then be used to generate and verify proofs. - -You can also use "build" as an alias for compile (e.g. `nargo build`). - -### Options - -| Option | Description | -| --------------------- | ------------------------------------------------------------ | -| `--include-keys` | Include Proving and Verification keys in the build artifacts | -| `--package ` | The name of the package to compile | -| `--workspace` | Compile all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo new ` - -Creates a new Noir project in a new folder. - -**Arguments** - -| Argument | Description | -| -------- | -------------------------------- | -| `` | The path to save the new project | - -### Options - -| Option | Description | -| --------------- | ----------------------------------------------------- | -| `--name ` | Name of the package [default: package directory name] | -| `--lib` | Use a library template | -| `--bin` | Use a binary template [default] | -| `--contract` | Use a contract template | -| `-h, --help` | Print help | - -## `nargo init` - -Creates a new Noir project in the current directory. - -### Options - -| Option | Description | -| --------------- | ----------------------------------------------------- | -| `--name ` | Name of the package [default: current directory name] | -| `--lib` | Use a library template | -| `--bin` | Use a binary template [default] | -| `--contract` | Use a contract template | -| `-h, --help` | Print help | - -## `nargo execute [WITNESS_NAME]` - -Runs the Noir program and prints its return value. - -**Arguments** - -| Argument | Description | -| ---------------- | ----------------------------------------- | -| `[WITNESS_NAME]` | Write the execution witness to named file | - -### Options - -| Option | Description | -| --------------------------------- | ------------------------------------------------------------------------------------ | -| `-p, --prover-name ` | The name of the toml file which contains the inputs for the prover [default: Prover] | -| `--package ` | The name of the package to execute | -| `--workspace` | Execute all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -_Usage_ - -The inputs to the circuit are read from the `Prover.toml` file generated by `nargo check`, which -must be filled in. - -To save the witness to file, run the command with a value for the `WITNESS_NAME` argument. A -`.tr` file will then be saved in the `./target` folder. - -## `nargo prove` - -Creates a proof for the program. - -### Options - -| Option | Description | -| ------------------------------------- | ---------------------------------------------------------------------------------------- | -| `-p, --prover-name ` | The name of the toml file which contains the inputs for the prover [default: Prover] | -| `-v, --verifier-name ` | The name of the toml file which contains the inputs for the verifier [default: Verifier] | -| `--verify` | Verify proof after proving | -| `--package ` | The name of the package to prove | -| `--workspace` | Prove all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo verify` - -Given a proof and a program, verify whether the proof is valid. - -### Options - -| Option | Description | -| ------------------------------------- | ---------------------------------------------------------------------------------------- | -| `-v, --verifier-name ` | The name of the toml file which contains the inputs for the verifier [default: Verifier] | -| `--package ` | The name of the package to verify | -| `--workspace` | Verify all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo test [TEST_NAME]` - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. To print `println` statements in tests, use the `--show-output` flag. - -Takes an optional `--exact` flag which allows you to select tests based on an exact name. - -See an example on the [testing page](./testing.md). - -### Options - -| Option | Description | -| --------------------- | -------------------------------------- | -| `--show-output` | Display output of `println` statements | -| `--exact` | Only run tests that match exactly | -| `--package ` | The name of the package to test | -| `--workspace` | Test all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo info` - -Prints a table containing the information of the package. - -Currently the table provide - -1. The number of ACIR opcodes -2. The final number gates in the circuit used by a backend - -If the file contains a contract the table will provide the -above information about each function of the contract. - -## `nargo lsp` - -Start a long-running Language Server process that communicates over stdin/stdout. -Usually this command is not run by a user, but instead will be run by a Language Client, such as [vscode-noir](https://github.com/noir-lang/vscode-noir). - -## `nargo fmt` - -Automatically formats your Noir source code based on the default formatting settings. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/nargo/02_testing.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/nargo/02_testing.md deleted file mode 100644 index 5c57ef92705..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/nargo/02_testing.md +++ /dev/null @@ -1,61 +0,0 @@ ---- -title: Testing in Noir -description: Learn how to use Nargo to test your Noir program in a quick and easy way -keywords: [Nargo, testing, Noir, compile, test] ---- - -You can test your Noir programs using Noir circuits. - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. - -For example if you have a program like: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test] -fn test_add() { - assert(add(2,2) == 4); - assert(add(0,1) == 1); - assert(add(1,0) == 1); -} -``` - -Running `nargo test` will test that the `test_add` function can be executed while satisfying all -the constraints which allows you to test that add returns the expected values. Test functions can't -have any arguments currently. - -### Test fail - -You can write tests that are expected to fail by using the decorator `#[test(should_fail)]`. For example: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test(should_fail)] -fn test_add() { - assert(add(2,2) == 5); -} -``` - -You can be more specific and make it fail with a specific reason by using `should_fail_with = "`: - -```rust -fn main(african_swallow_avg_speed : Field) { - assert(african_swallow_avg_speed == 65, "What is the airspeed velocity of an unladen swallow"); -} - -#[test] -fn test_king_arthur() { - main(65); -} - -#[test(should_fail_with = "What is the airspeed velocity of an unladen swallow")] -fn test_bridgekeeper() { - main(32); -} - -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/nargo/03_solidity_verifier.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/nargo/03_solidity_verifier.md deleted file mode 100644 index 9ac60cb0ba7..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/nargo/03_solidity_verifier.md +++ /dev/null @@ -1,129 +0,0 @@ ---- -title: Solidity Verifier -description: - Learn how to run the verifier as a smart contract on the blockchain. Compile a Solidity verifier - contract for your Noir program and deploy it on any EVM blockchain acting as a verifier smart - contract. Read more to find out! -keywords: - [ - solidity verifier, - smart contract, - blockchain, - compiler, - plonk_vk.sol, - EVM blockchain, - verifying Noir programs, - proving backend, - Barretenberg, - ] ---- - -For certain applications, it may be desirable to run the verifier as a smart contract instead of on -a local machine. - -Compile a Solidity verifier contract for your Noir program by running: - -```sh -nargo codegen-verifier -``` - -A new `contract` folder would then be generated in your project directory, containing the Solidity -file `plonk_vk.sol`. It can be deployed on any EVM blockchain acting as a verifier smart contract. - -> **Note:** It is possible to compile verifier contracts of Noir programs for other smart contract -> platforms as long as the proving backend supplies an implementation. -> -> Barretenberg, the default proving backend for Nargo, supports compilation of verifier contracts in -> Solidity only for the time being. - -## Verify - -To verify a proof using the Solidity verifier contract, call the `verify` function with the -following signature: - -```solidity -function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) -``` - -You can see an example of how the `verify` function is called in the example zk voting application [here](https://github.com/noir-lang/noir-examples/blob/33e598c257e2402ea3a6b68dd4c5ad492bce1b0a/foundry-voting/src/zkVote.sol#L35): - -```solidity -function castVote(bytes calldata proof, uint proposalId, uint vote, bytes32 nullifierHash) public returns (bool) { - // ... - bytes32[] memory publicInputs = new bytes32[](4); - publicInputs[0] = merkleRoot; - publicInputs[1] = bytes32(proposalId); - publicInputs[2] = bytes32(vote); - publicInputs[3] = nullifierHash; - require(verifier.verify(proof, publicInputs), "Invalid proof"); -``` - -### Public Inputs - -:::tip - -A circuit doesn't have the concept of a return value. Return values are just syntactic sugar in -Noir. - -Under the hood, the return value is passed as an input to the circuit and is checked at the end of -the circuit program. - -::: - -The verifier contract uses the output (return) value of a Noir program as a public input. So if you -have the following function - -```rust -fn main( - // Public inputs - pubkey_x: pub Field, - pubkey_y: pub Field, - // Private inputs - priv_key: Field, -) -> pub Field -``` - -then `verify` in `plonk_vk.sol` will expect 3 public inputs. Passing two inputs will result in an -error like `Reason: PUBLIC_INPUT_COUNT_INVALID(3, 2)`. - -In this case the 3 inputs to `verify` would be ordered as `[pubkey_x, pubkey_y, return]`. - -#### Struct inputs - -Consider the following program: - -```rust -struct Type1 { - val1: Field, - val2: Field, -} - -struct Nested { - t1: Type1, - is_true: bool, -} - -fn main(x: pub Field, nested: pub Nested, y: pub Field) { - //... -} -``` - -Structs will be flattened so that the array of inputs is 1-dimensional array. The order of these inputs would be flattened to: `[x, nested.t1.val1, nested.t1.val2, nested.is_true, y]` - -## Noir for EVM chains - -You can currently deploy the Solidity verifier contracts to most EVM compatible chains. EVM chains that have been tested and are known to work include: - -- Optimism -- Arbitrum -- Polygon PoS -- Scroll -- Celo - -Other EVM chains should work, but have not been tested directly by our team. If you test any other chains, please open a PR on this page to update the list. See [this doc](https://github.com/noir-lang/noir-starter/tree/main/with-foundry#testing-on-chain) for more info about testing verifier contracts on different EVM chains. - -### Unsupported chains - -Unfortunately not all "EVM" chains are supported. - -**zkSync** and the **Polygon zkEVM** do _not_ currently support proof verification via Solidity verifier contracts. They are missing the bn256 precompile contract that the verifier contract requires. Once these chains support this precompile, they may work. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/nargo/04_language_server.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/nargo/04_language_server.md deleted file mode 100644 index 48c01465f6e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/nargo/04_language_server.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Language Server -description: Learn about the Noir Language Server, how to install the components, and configuration that may be required. -keywords: [Nargo, Language Server, LSP, VSCode, Visual Studio Code] ---- - -This section helps you install and configure the Noir Language Server. - -The Language Server Protocol (LSP) has two components, the [Server](#language-server) and the [Client](#language-client). Below we describe each in the context of Noir. - -## Language Server - -The Server component is provided by the Nargo command line tool that you installed at the beginning of this guide. -As long as Nargo is installed and you've used it to run other commands in this guide, it should be good to go! - -If you'd like to verify that the `nargo lsp` command is available, you can run `nargo --help` and look for `lsp` in the list of commands. If you see it, you're using a version of Noir with LSP support. - -## Language Client - -The Client component is usually an editor plugin that launches the Server. It communicates LSP messages between the editor and the Server. For example, when you save a file, the Client will alert the Server, so it can try to compile the project and report any errors. - -Currently, Noir provides a Language Client for Visual Studio Code via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). - -> **Note:** Noir's Language Server Protocol support currently assumes users' VSCode workspace root to be the same as users' Noir project root (i.e. where Nargo.toml lies). -> -> If LSP features seem to be missing / malfunctioning, make sure you are opening your Noir project directly (instead of as a sub-folder) in your VSCode instance. - -When your language server is running correctly and the VSCode plugin is installed, you should see handy codelens buttons for compilation, measuring circuit size, execution, and tests: - -![Compile and Execute](@site/static/img/codelens_compile_execute.png) -![Run test](@site/static/img/codelens_run_test.png) - -You should also see your tests in the `testing` panel: - -![Testing panel](@site/static/img/codelens_testing_panel.png) - -### Configuration - -- **Noir: Enable LSP** - If checked, the extension will launch the Language Server via `nargo lsp` and communicate with it. -- **Noir: Nargo Flags** - Additional flags may be specified if you require them to be added when the extension calls `nargo lsp`. -- **Noir: Nargo Path** - An absolute path to a Nargo binary with the `lsp` command. This may be useful if Nargo is not within the `PATH` of your editor. -- **Noir > Trace: Server** - Setting this to `"messages"` or `"verbose"` will log LSP messages between the Client and Server. Useful for debugging. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/getting_started/01_tiny_noir_app.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/getting_started/01_tiny_noir_app.md deleted file mode 100644 index 64ba4a2c44a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/getting_started/01_tiny_noir_app.md +++ /dev/null @@ -1,260 +0,0 @@ ---- -title: End-to-end -description: Learn how to setup a new app that uses Noir to generate and verify zero-knowledge SNARK proofs in a typescript or javascript environment -keywords: [how to, guide, javascript, typescript, noir, barretenberg, zero-knowledge, proofs] ---- - -NoirJS works both on the browser and on the server, and works for both ESM and CJS module systems. In this page, we will learn how can we write a simple test and a simple web app to verify the standard Noir example. - -You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). - -## Before we start - -:::note - -Feel free to use whatever versions, just keep in mind that Nargo and the NoirJS packages are meant to be in sync. For example, Nargo 0.18.x matches `noir_js@0.18.x`, etc. - -In this guide, we will be pinned to 0.17.0. - -::: - -Make sure you have Node installed on your machine by opening a terminal and executing `node --version`. If you don't see a version, you should install [node](https://github.com/nvm-sh/nvm). You can also use `yarn` if you prefer that package manager over npm (which comes with node). - -First of all, follow the [Nargo guide](../../getting_started/00_nargo_installation.md) to install nargo version 0.17.0 and create a new project with `nargo new circuit`. Once there, `cd` into the `circuit` folder. You should then be able to compile your circuit into `json` format and see it inside the `target` folder: - -```bash -nargo compile -``` - -Your folder structure should look like: - -```tree -. -└── circuit - ├── Nargo.toml - ├── src - │ └── main.nr - └── target - └── circuit.json -``` - -## Starting a new project - -Go back to the previous folder and start a new project by running run `npm init`. You can configure your project or just leave the defaults, and see a `package.json` appear in your root folder. - -## Installing dependencies - -We'll need two `npm` packages. These packages will provide us the methods we need to run and verify proofs: - -```bash -npm i @noir-lang/backend_barretenberg@^0.17.0 @noir-lang/noir_js@^0.17.0 -``` - -To serve our page, we can use a build tool such as `vite`. Because we're gonna use some `wasm` files, we need to install a plugin as well. Run: - -```bash -npm i --save-dev vite rollup-plugin-copy -``` - -Since we're on the dependency world, we may as well define a nice starting script. Vite makes it easy. Just open `package.json`, find the block "scripts" and add this just below the line with `"test" : "echo......."`: - -```json - "start": "vite --open" -``` - -If you want do build a static website, you can also add some build and preview scripts: - -```json - "build": "vite build", - "preview": "vite preview" -``` - -## Vite plugins - -Vite is great, but support from `wasm` doesn't work out-of-the-box. We're gonna write a quick plugin and use another one. Just copy and paste this into a file named `vite.config.js`. You don't need to understand it, just trust me bro. - -```js -import { defineConfig } from 'vite'; -import copy from 'rollup-plugin-copy'; -import fs from 'fs'; -import path from 'path'; - -const wasmContentTypePlugin = { - name: 'wasm-content-type-plugin', - configureServer(server) { - server.middlewares.use(async (req, res, next) => { - if (req.url.endsWith('.wasm')) { - res.setHeader('Content-Type', 'application/wasm'); - const newPath = req.url.replace('deps', 'dist'); - const targetPath = path.join(__dirname, newPath); - const wasmContent = fs.readFileSync(targetPath); - return res.end(wasmContent); - } - next(); - }); - }, -}; - -export default defineConfig(({ command }) => { - if (command === 'serve') { - return { - plugins: [ - copy({ - targets: [{ src: 'node_modules/**/*.wasm', dest: 'node_modules/.vite/dist' }], - copySync: true, - hook: 'buildStart', - }), - command === 'serve' ? wasmContentTypePlugin : [], - ], - }; - } - - return {}; -}); -``` - -## HTML - -Here's the simplest HTML with some terrible UI. Create a file called `index.html` and paste this: - -```html - - - - - - -

Very basic Noir app

-
-

Logs

-

Proof

-
- - -``` - -## Some good old vanilla Javascript - -Create a new file `app.js`, which is where our javascript code will live. Let's start with this code inside: - -```js -document.addEventListener('DOMContentLoaded', async () => { - // here's where the magic happens -}); - -function display(container, msg) { - const c = document.getElementById(container); - const p = document.createElement('p'); - p.textContent = msg; - c.appendChild(p); -} -``` - -We can manipulate our website with this little function, so we can see our website working. - -## Adding Noir - -If you come from the previous page, your folder structure should look like this: - -```tree -├── app.js -├── circuit -│ ├── Nargo.toml -│ ├── src -│ │ └── main.nr -│ └── target -│ └── circuit.json -├── index.html -├── package.json -└── vite.config.js -``` - -You'll see other files and folders showing up (like `package-lock.json`, `yarn.lock`, `node_modules`) but you shouldn't have to care about those. - -## Importing our dependencies - -We're starting with the good stuff now. At the top of the new javascript file, import the packages: - -```ts -import { BarretenbergBackend } from '@noir-lang/backend_barretenberg'; -import { Noir } from '@noir-lang/noir_js'; -``` - -We also need to import the `circuit` JSON file we created. If you have the suggested folder structure, you can add this line: - -```ts -import circuit from './circuit/target/circuit.json'; -``` - -## Write code - -:::note - -We're gonna be adding code inside the `document.addEventListener...etc` block: - -```js -// forget stuff here -document.addEventListener('DOMContentLoaded', async () => { - // here's where the magic happens -}); -// forget stuff here -``` - -::: - -Our dependencies exported two classes: `BarretenbergBackend` and `Noir`. Let's `init` them and add some logs, just to flex: - -```ts -const backend = new BarretenbergBackend(circuit); -const noir = new Noir(circuit, backend); -``` - -## Proving - -Now we're ready to prove stuff! Let's feed some inputs to our circuit and calculate the proof: - -```js -const input = { x: 1, y: 2 }; -display('logs', 'Generating proof... ⌛'); -const proof = await noir.generateFinalProof(input); -display('logs', 'Generating proof... ✅'); -display('results', proof.proof); -``` - -You're probably eager to see stuff happening, so go and run your app now! - -From your terminal, run `npm start` (or `yarn start`). If it doesn't open a browser for you, just visit `localhost:5173`. On a modern laptop, proof will generate in less than 100ms, and you'll see this: - -![Getting Started 0](@site/static/img/noir_getting_started_1.png) - -If you're human, you shouldn't be able to understand anything on the "proof" box. That's OK. We like you, human. - -In any case, this means your proof was generated! But you shouldn't trust me just yet. Add these lines to see it being verified: - -```js -display('logs', 'Verifying proof... ⌛'); -const verification = await noir.verifyFinalProof(proof); -if (verification) display('logs', 'Verifying proof... ✅'); -``` - -By saving, your app will refresh and here's our complete Tiny Noir App! - -You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). - -## Further Reading - -You can see how noirjs is used in a full stack Next.js hardhat application in the [noir-starter repo here](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat). The example shows how to calculate a proof in the browser and verify it with a deployed Solidity verifier contract from noirjs. - -You should also check out the more advanced examples in the [noir-examples repo](https://github.com/noir-lang/noir-examples), where you'll find reference usage for some cool apps. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/noir_js.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/noir_js.md deleted file mode 100644 index f895b22eaf8..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/noir_js.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: NoirJS -description: Interact with Noir in Typescript or Javascript -keywords: [Noir project, javascript, typescript, node.js, browser, react] ---- - -NoirJS is a TypeScript library that make it easy to use Noir on your dapp, webapp, Node.js server, website, etc. - -A typical workflow would be composed of two major elements: - -- NoirJS -- Proving backend of choice's JavaScript package - - - -To install NoirJS, install Node.js if you have not already and run this in your JavaScript project: - -```bash -npm i @noir-lang/noir_js -``` - -## Proving backend - -Since Noir is backend agnostic, you can instantiate NoirJS without any backend (i.e. to execute a function). But for proving, you would have to instantiate NoirJS with any of the supported backends through their own `js` interface. - -### Barretenberg - -Aztec Labs maintains the `barretenberg` proving backend, which you can instantiate and make use of alongside NoirJS. It is also the default proving backend installed and used with Nargo, the Noir CLI tool. - -To install its JavaScript library, run this in your project: - -```bash -npm i @noir-lang/backend_barretenberg -``` - -For more details on how to instantiate and use the libraries, refer to the [Full Noir App Guide](./getting_started/01_tiny_noir_app.md) and [Reference](./reference/noir_js/classes/Noir.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/.nojekyll deleted file mode 100644 index e2ac6616add..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/classes/BarretenbergBackend.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/classes/BarretenbergBackend.md deleted file mode 100644 index 5cbe9421b92..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/classes/BarretenbergBackend.md +++ /dev/null @@ -1,185 +0,0 @@ -# BarretenbergBackend - -## Implements - -- [`Backend`](../interfaces/Backend.md) - -## Constructors - -### new BarretenbergBackend(acirCircuit, options) - -```ts -new BarretenbergBackend(acirCircuit, options): BarretenbergBackend -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `acirCircuit` | [`CompiledCircuit`](../type-aliases/CompiledCircuit.md) | -| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | - -#### Returns - -[`BarretenbergBackend`](BarretenbergBackend.md) - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`destroy`](../interfaces/Backend.md#destroy) - -#### Description - -Destroys the backend - -*** - -### generateFinalProof() - -```ts -generateFinalProof(decompressedWitness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `decompressedWitness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`generateFinalProof`](../interfaces/Backend.md#generatefinalproof) - -#### Description - -Generates a final proof (not meant to be verified in another circuit) - -*** - -### generateIntermediateProof() - -```ts -generateIntermediateProof(witness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `witness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`generateIntermediateProof`](../interfaces/Backend.md#generateintermediateproof) - -#### Example - -```typescript -const intermediateProof = await backend.generateIntermediateProof(witness); -``` - -*** - -### generateIntermediateProofArtifacts() - -```ts -generateIntermediateProofArtifacts(proofData, numOfPublicInputs): Promise -``` - -#### Parameters - -| Parameter | Type | Default value | -| :------ | :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | `undefined` | -| `numOfPublicInputs` | `number` | `0` | - -#### Returns - -`Promise`\<`object`\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`generateIntermediateProofArtifacts`](../interfaces/Backend.md#generateintermediateproofartifacts) - -#### Example - -```typescript -const artifacts = await backend.generateIntermediateProofArtifacts(proof, numOfPublicInputs); -``` - -*** - -### verifyFinalProof() - -```ts -verifyFinalProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`verifyFinalProof`](../interfaces/Backend.md#verifyfinalproof) - -#### Description - -Verifies a final proof - -*** - -### verifyIntermediateProof() - -```ts -verifyIntermediateProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`verifyIntermediateProof`](../interfaces/Backend.md#verifyintermediateproof) - -#### Example - -```typescript -const isValidIntermediate = await backend.verifyIntermediateProof(proof); -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/index.md deleted file mode 100644 index 3680ba3ca77..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/index.md +++ /dev/null @@ -1,27 +0,0 @@ -# Backend Barretenberg - -## Exports - -### Classes - -| Class | Description | -| :------ | :------ | -| [BarretenbergBackend](classes/BarretenbergBackend.md) | - | - -### Interfaces - -| Interface | Description | -| :------ | :------ | -| [Backend](interfaces/Backend.md) | - | - -### Type Aliases - -| Type alias | Description | -| :------ | :------ | -| [BackendOptions](type-aliases/BackendOptions.md) | - | -| [CompiledCircuit](type-aliases/CompiledCircuit.md) | - | -| [ProofData](type-aliases/ProofData.md) | - | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/interfaces/Backend.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/interfaces/Backend.md deleted file mode 100644 index 3eb9645c8d2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/interfaces/Backend.md +++ /dev/null @@ -1,132 +0,0 @@ -# Backend - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Description - -Destroys the backend - -*** - -### generateFinalProof() - -```ts -generateFinalProof(decompressedWitness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `decompressedWitness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Description - -Generates a final proof (not meant to be verified in another circuit) - -*** - -### generateIntermediateProof() - -```ts -generateIntermediateProof(decompressedWitness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `decompressedWitness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Description - -Generates an intermediate proof (meant to be verified in another circuit) - -*** - -### generateIntermediateProofArtifacts() - -```ts -generateIntermediateProofArtifacts(proofData, numOfPublicInputs): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | -| `numOfPublicInputs` | `number` | - -#### Returns - -`Promise`\<`object`\> - -#### Description - -Retrieves the artifacts from a proof in the Field format - -*** - -### verifyFinalProof() - -```ts -verifyFinalProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Verifies a final proof - -*** - -### verifyIntermediateProof() - -```ts -verifyIntermediateProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Verifies an intermediate proof - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/type-aliases/BackendOptions.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/type-aliases/BackendOptions.md deleted file mode 100644 index 266ade75d17..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/type-aliases/BackendOptions.md +++ /dev/null @@ -1,19 +0,0 @@ -# BackendOptions - -```ts -type BackendOptions: object; -``` - -## Description - -An options object, currently only used to specify the number of threads to use. - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `threads` | `number` | **Description**

Number of threads | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit.md deleted file mode 100644 index 34e0dd04205..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit.md +++ /dev/null @@ -1,20 +0,0 @@ -# CompiledCircuit - -```ts -type CompiledCircuit: object; -``` - -## Description - -The representation of a compiled circuit - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `abi` | `Abi` | **Description**

ABI representation of the circuit | -| `bytecode` | `string` | **Description**

The bytecode of the circuit | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/type-aliases/ProofData.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/type-aliases/ProofData.md deleted file mode 100644 index 4aeff73d3e4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/type-aliases/ProofData.md +++ /dev/null @@ -1,20 +0,0 @@ -# ProofData - -```ts -type ProofData: object; -``` - -## Description - -The representation of a proof - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `proof` | `Uint8Array` | **Description**

An byte array representing the proof | -| `publicInputs` | `Uint8Array`[] | **Description**

Public inputs of a proof | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs deleted file mode 100644 index 04e662c845f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"noir_js/reference/backend_barretenberg/classes/BarretenbergBackend","label":"BarretenbergBackend"}]},{"type":"category","label":"Interfaces","items":[{"type":"doc","id":"noir_js/reference/backend_barretenberg/interfaces/Backend","label":"Backend"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"noir_js/reference/backend_barretenberg/type-aliases/BackendOptions","label":"BackendOptions"},{"type":"doc","id":"noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit","label":"CompiledCircuit"},{"type":"doc","id":"noir_js/reference/backend_barretenberg/type-aliases/ProofData","label":"ProofData"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/.nojekyll deleted file mode 100644 index e2ac6616add..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/classes/Noir.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/classes/Noir.md deleted file mode 100644 index 1d7b54a9dca..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/classes/Noir.md +++ /dev/null @@ -1,131 +0,0 @@ -# Noir - -## Constructors - -### new Noir(circuit, backend) - -```ts -new Noir(circuit, backend?): Noir -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `circuit` | [`CompiledCircuit`](../type-aliases/CompiledCircuit.md) | -| `backend`? | `Backend` | - -#### Returns - -[`Noir`](Noir.md) - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Description - -Destroys the underlying backend instance. - -#### Example - -```typescript -await noir.destroy(); -``` - -*** - -### execute() - -```ts -execute(inputs, foreignCallHandler?): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `inputs` | `InputMap` | -| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | - -#### Returns - -`Promise`\<`object`\> - -#### Description - -Allows to execute a circuit to get its witness and return value. - -#### Example - -```typescript -async execute(inputs) -``` - -*** - -### generateFinalProof() - -```ts -generateFinalProof(inputs): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `inputs` | `InputMap` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Description - -Generates a witness and a proof given an object as input. - -#### Example - -```typescript -async generateFinalProof(input) -``` - -*** - -### verifyFinalProof() - -```ts -verifyFinalProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Instantiates the verification key and verifies a proof. - -#### Example - -```typescript -async verifyFinalProof(proof) -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/and.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/and.md deleted file mode 100644 index c783283e396..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/and.md +++ /dev/null @@ -1,22 +0,0 @@ -# and() - -```ts -and(lhs, rhs): string -``` - -Performs a bitwise AND operation between `lhs` and `rhs` - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `lhs` | `string` | | -| `rhs` | `string` | | - -## Returns - -`string` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/blake2s256.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/blake2s256.md deleted file mode 100644 index 7882d0da8d5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/blake2s256.md +++ /dev/null @@ -1,21 +0,0 @@ -# blake2s256() - -```ts -blake2s256(inputs): Uint8Array -``` - -Calculates the Blake2s256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify.md deleted file mode 100644 index 0ba5783f0d5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify.md +++ /dev/null @@ -1,29 +0,0 @@ -# ecdsa\_secp256k1\_verify() - -```ts -ecdsa_secp256k1_verify( - hashed_msg, - public_key_x_bytes, - public_key_y_bytes, - signature): boolean -``` - -Calculates the Blake2s256 hash of the input bytes and represents these as a single field element. -Verifies a ECDSA signature over the secp256k1 curve. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `hashed_msg` | `Uint8Array` | | -| `public_key_x_bytes` | `Uint8Array` | | -| `public_key_y_bytes` | `Uint8Array` | | -| `signature` | `Uint8Array` | | - -## Returns - -`boolean` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify.md deleted file mode 100644 index 0b20ff68957..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify.md +++ /dev/null @@ -1,28 +0,0 @@ -# ecdsa\_secp256r1\_verify() - -```ts -ecdsa_secp256r1_verify( - hashed_msg, - public_key_x_bytes, - public_key_y_bytes, - signature): boolean -``` - -Verifies a ECDSA signature over the secp256r1 curve. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `hashed_msg` | `Uint8Array` | | -| `public_key_x_bytes` | `Uint8Array` | | -| `public_key_y_bytes` | `Uint8Array` | | -| `signature` | `Uint8Array` | | - -## Returns - -`boolean` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/keccak256.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/keccak256.md deleted file mode 100644 index d10f155ce86..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/keccak256.md +++ /dev/null @@ -1,21 +0,0 @@ -# keccak256() - -```ts -keccak256(inputs): Uint8Array -``` - -Calculates the Keccak256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/sha256.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/sha256.md deleted file mode 100644 index 6ba4ecac022..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/sha256.md +++ /dev/null @@ -1,21 +0,0 @@ -# sha256() - -```ts -sha256(inputs): Uint8Array -``` - -Calculates the SHA256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/xor.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/xor.md deleted file mode 100644 index 8d762b895d3..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/xor.md +++ /dev/null @@ -1,22 +0,0 @@ -# xor() - -```ts -xor(lhs, rhs): string -``` - -Performs a bitwise XOR operation between `lhs` and `rhs` - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `lhs` | `string` | | -| `rhs` | `string` | | - -## Returns - -`string` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/index.md deleted file mode 100644 index 58902c17b99..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/index.md +++ /dev/null @@ -1,36 +0,0 @@ -# Noir JS - -## Exports - -### Classes - -| Class | Description | -| :------ | :------ | -| [Noir](classes/Noir.md) | - | - -### Type Aliases - -| Type alias | Description | -| :------ | :------ | -| [CompiledCircuit](type-aliases/CompiledCircuit.md) | - | -| [ForeignCallHandler](type-aliases/ForeignCallHandler.md) | A callback which performs an foreign call and returns the response. | -| [ForeignCallInput](type-aliases/ForeignCallInput.md) | - | -| [ForeignCallOutput](type-aliases/ForeignCallOutput.md) | - | -| [ProofData](type-aliases/ProofData.md) | - | -| [WitnessMap](type-aliases/WitnessMap.md) | - | - -### Functions - -| Function | Description | -| :------ | :------ | -| [and](functions/and.md) | Performs a bitwise AND operation between `lhs` and `rhs` | -| [blake2s256](functions/blake2s256.md) | Calculates the Blake2s256 hash of the input bytes | -| [ecdsa\_secp256k1\_verify](functions/ecdsa_secp256k1_verify.md) | Calculates the Blake2s256 hash of the input bytes and represents these as a single field element. | -| [ecdsa\_secp256r1\_verify](functions/ecdsa_secp256r1_verify.md) | Verifies a ECDSA signature over the secp256r1 curve. | -| [keccak256](functions/keccak256.md) | Calculates the Keccak256 hash of the input bytes | -| [sha256](functions/sha256.md) | Calculates the SHA256 hash of the input bytes | -| [xor](functions/xor.md) | Performs a bitwise XOR operation between `lhs` and `rhs` | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/CompiledCircuit.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/CompiledCircuit.md deleted file mode 100644 index 34e0dd04205..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/CompiledCircuit.md +++ /dev/null @@ -1,20 +0,0 @@ -# CompiledCircuit - -```ts -type CompiledCircuit: object; -``` - -## Description - -The representation of a compiled circuit - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `abi` | `Abi` | **Description**

ABI representation of the circuit | -| `bytecode` | `string` | **Description**

The bytecode of the circuit | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/ForeignCallHandler.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/ForeignCallHandler.md deleted file mode 100644 index 812b8b16481..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/ForeignCallHandler.md +++ /dev/null @@ -1,24 +0,0 @@ -# ForeignCallHandler - -```ts -type ForeignCallHandler: (name, inputs) => Promise; -``` - -A callback which performs an foreign call and returns the response. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `name` | `string` | The identifier for the type of foreign call being performed. | -| `inputs` | [`ForeignCallInput`](ForeignCallInput.md)[] | An array of hex encoded inputs to the foreign call. | - -## Returns - -`Promise`\<[`ForeignCallOutput`](ForeignCallOutput.md)[]\> - -outputs - An array of hex encoded outputs containing the results of the foreign call. - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/ForeignCallInput.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/ForeignCallInput.md deleted file mode 100644 index dd95809186a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/ForeignCallInput.md +++ /dev/null @@ -1,9 +0,0 @@ -# ForeignCallInput - -```ts -type ForeignCallInput: string[]; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/ForeignCallOutput.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/ForeignCallOutput.md deleted file mode 100644 index b71fb78a946..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/ForeignCallOutput.md +++ /dev/null @@ -1,9 +0,0 @@ -# ForeignCallOutput - -```ts -type ForeignCallOutput: string | string[]; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/ProofData.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/ProofData.md deleted file mode 100644 index 4aeff73d3e4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/ProofData.md +++ /dev/null @@ -1,20 +0,0 @@ -# ProofData - -```ts -type ProofData: object; -``` - -## Description - -The representation of a proof - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `proof` | `Uint8Array` | **Description**

An byte array representing the proof | -| `publicInputs` | `Uint8Array`[] | **Description**

Public inputs of a proof | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/WitnessMap.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/WitnessMap.md deleted file mode 100644 index 258c46f9d0c..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/WitnessMap.md +++ /dev/null @@ -1,9 +0,0 @@ -# WitnessMap - -```ts -type WitnessMap: Map; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/typedoc-sidebar.cjs deleted file mode 100644 index c18318850d0..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"noir_js/reference/noir_js/classes/Noir","label":"Noir"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/CompiledCircuit","label":"CompiledCircuit"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/ForeignCallHandler","label":"ForeignCallHandler"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/ForeignCallInput","label":"ForeignCallInput"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/ForeignCallOutput","label":"ForeignCallOutput"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/ProofData","label":"ProofData"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/WitnessMap","label":"WitnessMap"}]},{"type":"category","label":"Functions","items":[{"type":"doc","id":"noir_js/reference/noir_js/functions/and","label":"and"},{"type":"doc","id":"noir_js/reference/noir_js/functions/blake2s256","label":"blake2s256"},{"type":"doc","id":"noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify","label":"ecdsa_secp256k1_verify"},{"type":"doc","id":"noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify","label":"ecdsa_secp256r1_verify"},{"type":"doc","id":"noir_js/reference/noir_js/functions/keccak256","label":"keccak256"},{"type":"doc","id":"noir_js/reference/noir_js/functions/sha256","label":"sha256"},{"type":"doc","id":"noir_js/reference/noir_js/functions/xor","label":"xor"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/black_box_fns.md deleted file mode 100644 index 985bb7c879d..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/black_box_fns.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: Black Box Functions -description: Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. -keywords: [noir, black box functions] ---- - -Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. This makes certain zk-snark unfriendly computations cheaper than if they were implemented in Noir. - -:::warning - -It is likely that not all backends will support a particular black box function. - -::: - -Because it is not guaranteed that all backends will support black box functions, it is possible that certain Noir programs won't compile against a particular backend if they use an unsupported black box function. It is possible to fallback to less efficient implementations written in Noir/ACIR in some cases. - -Black box functions are specified with the `#[foreign(black_box_fn)]` attribute. For example, the SHA256 function in the Noir [source code](https://github.com/noir-lang/noir/blob/v0.5.1/noir_stdlib/src/hash.nr) looks like: - -```rust -#[foreign(sha256)] -fn sha256(_input : [u8; N]) -> [u8; 32] {} -``` - -## Function list - -Here is a list of the current black box functions that are supported by UltraPlonk: - -- AES -- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) -- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) -- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash) -- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment) -- [HashToField128Security](./cryptographic_primitives/hashes.mdx#hash_to_field) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx) -- [Compute merkle root](./merkle_trees.md#compute_merkle_root) -- AND -- XOR -- RANGE -- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion.md) - -Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. - -You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/noir/blob/master/acvm-repo/acir/src/circuit/black_box_functions.rs). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives.md deleted file mode 100644 index 2df4f929474..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Cryptographic primitives in Noir -description: - Learn about the cryptographic primitives ready to use for any Noir project -keywords: - [ - cryptographic primitives, - Noir project, - ] ---- - -The Noir team is progressively adding new cryptographic primitives to the standard library. Reach out for news or if you would be interested in adding more of these calculations in Noir. - -Some methods are available thanks to the Aztec backend, not being performed using Noir. When using other backends, these methods may or may not be supplied. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/00_hashes.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/00_hashes.mdx deleted file mode 100644 index 76745196681..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/00_hashes.mdx +++ /dev/null @@ -1,167 +0,0 @@ ---- -title: Hash methods -description: - Learn about the cryptographic primitives ready to use for any Noir project, including sha256, - blake2s, pedersen, mimc_bn254 and mimc -keywords: - [cryptographic primitives, Noir project, sha256, blake2s, pedersen, mimc_bn254, mimc, hash] ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## sha256 - -Given an array of bytes, returns the resulting sha256 hash. - -```rust -fn sha256(_input : [u8]) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::sha256(x); -} -``` - - - -## blake2s - -Given an array of bytes, returns an array with the Blake2 hash - -```rust -fn blake2s(_input : [u8]) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::blake2s(x); -} -``` - - - -## pedersen_hash - -Given an array of Fields, returns the Pedersen hash. - -```rust -fn pedersen_hash(_input : [Field]) -> Field -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::pedersen_hash(x); -} -``` - - - - - -## pedersen_commitment - -Given an array of Fields, returns the Pedersen commitment. - -```rust -fn pedersen_commitment(_input : [Field]) -> [Field; 2] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let commitment = std::hash::pedersen_commitment(x); -} -``` - - - -## keccak256 - -Given an array of bytes (`u8`), returns the resulting keccak hash as an array of 32 bytes -(`[u8; 32]`). Specify a message_size to hash only the first `message_size` bytes -of the input. - -```rust -fn keccak256(_input : [u8; N], _message_size: u32) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let message_size = 4; - let hash = std::hash::keccak256(x, message_size); -} -``` - - - -## poseidon - -Given an array of Fields, returns a new Field with the Poseidon Hash. Mind that you need to specify -how many inputs are there to your Poseidon function. - -```rust -// example for hash_1, hash_2 accepts an array of length 2, etc -fn hash_1(input: [Field; 1]) -> Field -``` - -example: - -```rust -fn main() -{ - let hash1 = std::hash::poseidon::bn254::hash_2([1, 2]); - assert(hash1 == 0x115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189a); -} -``` - -## mimc_bn254 and mimc - -`mimc_bn254` is `mimc`, but with hardcoded parameters for the BN254 curve. You can use it by -providing an array of Fields, and it returns a Field with the hash. You can use the `mimc` method if -you're willing to input your own constants: - -```rust -fn mimc(x: Field, k: Field, constants: [Field; N], exp : Field) -> Field -``` - -otherwise, use the `mimc_bn254` method: - -```rust -fn mimc_bn254(array: [Field; N]) -> Field -``` - -example: - -```rust - -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::mimc::mimc_bn254(x); -} -``` - -## hash_to_field - -```rust -fn hash_to_field(_input : [Field; N]) -> Field {} -``` - -Calculates the `blake2s` hash of the inputs and returns the hash modulo the field modulus to return -a value which can be represented as a `Field`. - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/01_scalar.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/01_scalar.mdx deleted file mode 100644 index c7eed820a80..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/01_scalar.mdx +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: Scalar multiplication -description: See how you can perform scalar multiplications over a fixed base in Noir -keywords: [cryptographic primitives, Noir project, scalar multiplication] ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## scalar_mul::fixed_base_embedded_curve - -Performs scalar multiplication over the embedded curve whose coordinates are defined by the -configured noir field. For the BN254 scalar field, this is BabyJubJub or Grumpkin. - -```rust -fn fixed_base_embedded_curve(_input : Field) -> [Field; 2] -``` - -example - -```rust -fn main(x : Field) { - let scal = std::scalar_mul::fixed_base_embedded_curve(x); - std::println(scal); -} -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/02_schnorr.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/02_schnorr.mdx deleted file mode 100644 index c184ce28120..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/02_schnorr.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: Schnorr Signatures -description: Learn how you can verify Schnorr signatures using Noir -keywords: [cryptographic primitives, Noir project, schnorr, signatures] ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## schnorr::verify_signature - -Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin). - -```rust -fn verify_signature(_public_key_x: Field, _public_key_y: Field, _signature: [u8; 64], _message: [u8]) -> bool -``` - -where `_signature` can be generated like so using the npm package -[@noir-lang/barretenberg](https://www.npmjs.com/package/@noir-lang/barretenberg) - -```js -const { BarretenbergWasm } = require('@noir-lang/barretenberg/dest/wasm'); -const { Schnorr } = require('@noir-lang/barretenberg/dest/crypto/schnorr'); - -... - -const barretenberg = await BarretenbergWasm.new(); -const schnorr = new Schnorr(barretenberg); -const pubKey = schnorr.computePublicKey(privateKey); -const message = ... -const signature = Array.from( - schnorr.constructSignature(hash, privateKey).toBuffer() -); - -... -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx deleted file mode 100644 index 72bce984821..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: ECDSA Signature Verification -description: Learn about the cryptographic primitives regarding ECDSA over the secp256k1 and secp256r1 curves -keywords: [cryptographic primitives, Noir project, ecdsa, secp256k1, secp256r1, signatures] ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -Noir supports ECDSA signatures verification over the secp256k1 and secp256r1 curves. - -## ecdsa_secp256k1::verify_signature - -Verifier for ECDSA Secp256k1 signatures - -```rust -fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message: [u8]) -> bool -``` - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - -## ecdsa_secp256r1::verify_signature - -Verifier for ECDSA Secp256r1 signatures - -```rust -fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message: [u8]) -> bool -``` - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/04_ec_primitives.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/04_ec_primitives.md deleted file mode 100644 index b4e20e091ba..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/04_ec_primitives.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -title: Elliptic Curve Primitives -keywords: [cryptographic primitives, Noir project] ---- - -Data structures and methods on them that allow you to carry out computations involving elliptic -curves over the (mathematical) field corresponding to `Field`. For the field currently at our -disposal, applications would involve a curve embedded in BN254, e.g. the -[Baby Jubjub curve](https://eips.ethereum.org/EIPS/eip-2494). - -## Data structures - -### Elliptic curve configurations - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Curve`), i.e. the specific elliptic -curve you want to use, which would be specified using any one of the methods -`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::new` which take the coefficients in the -defining equation together with a generator point as parameters. You can find more detail in the -comments in -[`noir_stdlib/src/ec.nr`](https://github.com/noir-lang/noir/blob/v0.19.3/noir_stdlib/src/ec.nr), but -the gist of it is that the elliptic curves of interest are usually expressed in one of the standard -forms implemented here (Twisted Edwards, Montgomery and Short Weierstraß), and in addition to that, -you could choose to use `affine` coordinates (Cartesian coordinates - the usual (x,y) - possibly -together with a point at infinity) or `curvegroup` coordinates (some form of projective coordinates -requiring more coordinates but allowing for more efficient implementations of elliptic curve -operations). Conversions between all of these forms are provided, and under the hood these -conversions are done whenever an operation is more efficient in a different representation (or a -mixed coordinate representation is employed). - -### Points - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Point`), i.e. points lying on the -elliptic curve. For a curve configuration `c` and a point `p`, it may be checked that `p` -does indeed lie on `c` by calling `c.contains(p1)`. - -## Methods - -(given a choice of curve representation, e.g. use `std::ec::tecurve::affine::Curve` and use -`std::ec::tecurve::affine::Point`) - -- The **zero element** is given by `Point::zero()`, and we can verify whether a point `p: Point` is - zero by calling `p.is_zero()`. -- **Equality**: Points `p1: Point` and `p2: Point` may be checked for equality by calling - `p1.eq(p2)`. -- **Addition**: For `c: Curve` and points `p1: Point` and `p2: Point` on the curve, adding these two - points is accomplished by calling `c.add(p1,p2)`. -- **Negation**: For a point `p: Point`, `p.negate()` is its negation. -- **Subtraction**: For `c` and `p1`, `p2` as above, subtracting `p2` from `p1` is accomplished by - calling `c.subtract(p1,p2)`. -- **Scalar multiplication**: For `c` as above, `p: Point` a point on the curve and `n: Field`, - scalar multiplication is given by `c.mul(n,p)`. If instead `n :: [u1; N]`, i.e. `n` is a bit - array, the `bit_mul` method may be used instead: `c.bit_mul(n,p)` -- **Multi-scalar multiplication**: For `c` as above and arrays `n: [Field; N]` and `p: [Point; N]`, - multi-scalar multiplication is given by `c.msm(n,p)`. -- **Coordinate representation conversions**: The `into_group` method converts a point or curve - configuration in the affine representation to one in the CurveGroup representation, and - `into_affine` goes in the other direction. -- **Curve representation conversions**: `tecurve` and `montcurve` curves and points are equivalent - and may be converted between one another by calling `into_montcurve` or `into_tecurve` on their - configurations or points. `swcurve` is more general and a curve c of one of the other two types - may be converted to this representation by calling `c.into_swcurve()`, whereas a point `p` lying - on the curve given by `c` may be mapped to its corresponding `swcurve` point by calling - `c.map_into_swcurve(p)`. -- **Map-to-curve methods**: The Elligator 2 method of mapping a field element `n: Field` into a - `tecurve` or `montcurve` with configuration `c` may be called as `c.elligator2_map(n)`. For all of - the curve configurations, the SWU map-to-curve method may be called as `c.swu_map(z,n)`, where - `z: Field` depends on `Field` and `c` and must be chosen by the user (the conditions it needs to - satisfy are specified in the comments - [here](https://github.com/noir-lang/noir/blob/v0.19.3/noir_stdlib/src/ec.nr). - -## Examples - -The -[ec_baby_jubjub test](https://github.com/noir-lang/noir/blob/master/test_programs/compile_success_empty/ec_baby_jubjub/src/main.nr) -illustrates all of the above primitives on various forms of the Baby Jubjub curve. A couple of more -interesting examples in Noir would be: - -Public-key cryptography: Given an elliptic curve and a 'base point' on it, determine the public key -from the private key. This is a matter of using scalar multiplication. In the case of Baby Jubjub, -for example, this code would do: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; - -fn bjj_pub_key(priv_key: Field) -> Point -{ - - let bjj = Curve::new(168700, 168696, G::new(995203441582195749578291179787384436505546430278305826713579947235728471134,5472060717959818805561601436314318772137091100104008585924551046643952123905)); - - let base_pt = Point::new(5299619240641551281634865583518297030282874472190772894086521144482721001553, 16950150798460657717958625567821834550301663161624707787222815936182638968203); - - bjj.mul(priv_key,base_pt) -} -``` - -This would come in handy in a Merkle proof. - -- EdDSA signature verification: This is a matter of combining these primitives with a suitable hash - function. See - [feat(stdlib): EdDSA sig verification noir#1136](https://github.com/noir-lang/noir/pull/1136) for - the case of Baby Jubjub and the Poseidon hash function. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/05_eddsa.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/05_eddsa.mdx deleted file mode 100644 index 9a5beb55ee9..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/05_eddsa.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: EdDSA Verification -description: Learn about the cryptographic primitives regarding EdDSA -keywords: [cryptographic primitives, Noir project, eddsa, signatures] ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## eddsa::eddsa_poseidon_verify - -Verifier for EdDSA signatures - -```rust -fn eddsa_poseidon_verify(public_key_x : Field, public_key_y : Field, signature_s: Field, signature_r8_x: Field, signature_r8_y: Field, message: Field) -> bool -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/logging.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/logging.md deleted file mode 100644 index 4ba0fe0e656..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/logging.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -title: Logging -description: - Learn how to use the println statement for debugging in Noir with this tutorial. Understand the - basics of logging in Noir and how to implement it in your code. -keywords: - [ - noir logging, - println statement, - debugging in noir, - noir std library, - logging tutorial, - basic logging in noir, - noir logging implementation, - noir debugging techniques, - rust, - ] ---- - -The standard library provides a familiar `println` statement you can use. Despite being a limited -implementation of rust's `println!` macro, this construct can be useful for debugging. - -You can print the output of println statements in your Noir code by using the `nargo execute` command or the `--show-output` flag when using `nargo test` (provided there are println statements in your tests). - -It is recommended to use `nargo execute` if you want to debug failing constraints with `println` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). `println` will not work for failed constraints caught at compile time. - -The `println` statement is unconstrained, so it works for outputting integers, fields, strings, and even structs or expressions. For example: - -```rust -use dep::std; - -struct Person { - age : Field, - height : Field, -} - -fn main(age : Field, height : Field) { - let person = Person { age : age, height : height }; - std::println(person); - std::println(age + height); - std::println("Hello world!"); -} - -``` - -You can print multiple different types in the same statement and string as well as a new "fmtstr" type. A `fmtstr` can be specified in the same way as a normal string it just should be prepended with an "f" character: - -```rust - let fmt_str = f"i: {i}, j: {j}"; - std::println(fmt_str); - - let s = myStruct { y: x, x: y }; - std::println(s); - - std::println(f"i: {i}, s: {s}"); - - std::println(x); - std::println([x, y]); - - let foo = fooStruct { my_struct: s, foo: 15 }; - std::println(f"s: {s}, foo: {foo}"); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/merkle_trees.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/merkle_trees.md deleted file mode 100644 index dc383a1426b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/merkle_trees.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: Merkle Trees -description: Learn about Merkle Trees in Noir with this tutorial. Explore the basics of computing a merkle root using a proof, with examples. -keywords: - [ - Merkle trees in Noir, - Noir programming language, - check membership, - computing root from leaf, - Noir Merkle tree implementation, - Merkle tree tutorial, - Merkle tree code examples, - Noir libraries, - pedersen hash., - ] ---- - -## compute_merkle_root - -Returns the root of the tree from the provided leaf and its hash path, using a [Pedersen hash](cryptographic_primitives/00_hashes.mdx#pedersen_hash). - -```rust -fn compute_merkle_root(leaf : Field, index : Field, hash_path: [Field]) -> Field -``` - -example: - -```rust -/** - // these values are for this example only - index = "0" - priv_key = "0x000000000000000000000000000000000000000000000000000000616c696365" - secret = "0x1929ea3ab8d9106a899386883d9428f8256cfedb3c4f6b66bf4aa4d28a79988f" - note_hash_path = [ - "0x1e61bdae0f027b1b2159e1f9d3f8d00fa668a952dddd822fda80dc745d6f65cc", - "0x0e4223f3925f98934393c74975142bd73079ab0621f4ee133cee050a3c194f1a", - "0x2fd7bb412155bf8693a3bd2a3e7581a679c95c68a052f835dddca85fa1569a40" - ] - */ -fn main(index: Field, priv_key: Field, secret: Field, note_hash_path: [Field; 3]) { - - let pubkey = std::scalar_mul::fixed_base_embedded_curve(priv_key); - let pubkey_x = pubkey[0]; - let pubkey_y = pubkey[1]; - let note_commitment = std::hash::pedersen([pubkey_x, pubkey_y, secret]); - - let root = std::merkle::compute_merkle_root(note_commitment[0], index, note_hash_path); - std::println(root); -} -``` - -To check merkle tree membership: - -1. Include a merkle root as a program input. -2. Compute the merkle root of a given leaf, index and hash path. -3. Assert the merkle roots are equal. - -For more info about merkle trees, see the Wikipedia [page](https://en.wikipedia.org/wiki/Merkle_tree). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/options.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/options.md deleted file mode 100644 index 3d3139fb98b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/options.md +++ /dev/null @@ -1,99 +0,0 @@ ---- -title: Option Type ---- - -The `Option` type is a way to express that a value might be present (`Some(T))` or absent (`None`). It's a safer way to handle potential absence of values, compared to using nulls in many other languages. - -```rust -struct Option { - None, - Some(T), -} -``` - -You can import the Option type into your Noir program like so: - -```rust -use dep::std::option::Option; - -fn main() { - let none = Option::none(); - let some = Option::some(3); -} -``` - -See [this test](https://github.com/noir-lang/noir/blob/5cbfb9c4a06c8865c98ff2b594464b037d821a5c/crates/nargo_cli/tests/test_data/option/src/main.nr) for a more comprehensive set of examples of each of the methods described below. - -## Methods - -### none - -Constructs a none value. - -### some - -Constructs a some wrapper around a given value. - -### is_none - -Returns true if the Option is None. - -### is_some - -Returns true of the Option is Some. - -### unwrap - -Asserts `self.is_some()` and returns the wrapped value. - -### unwrap_unchecked - -Returns the inner value without asserting `self.is_some()`. This method can be useful within an if condition when we already know that `option.is_some()`. If the option is None, there is no guarantee what value will be returned, only that it will be of type T for an `Option`. - -### unwrap_or - -Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value. - -### unwrap_or_else - -Returns the wrapped value if `self.is_some()`. Otherwise, calls the given function to return a default value. - -### map - -If self is `Some(x)`, this returns `Some(f(x))`. Otherwise, this returns `None`. - -### map_or - -If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns the given default value. - -### map_or_else - -If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns `default()`. - -### and - -Returns None if self is None. Otherwise, this returns `other`. - -### and_then - -If self is None, this returns None. Otherwise, this calls the given function with the Some value contained within self, and returns the result of that call. In some languages this function is called `flat_map` or `bind`. - -### or - -If self is Some, return self. Otherwise, return `other`. - -### or_else - -If self is Some, return self. Otherwise, return `default()`. - -### xor - -If only one of the two Options is Some, return that option. Otherwise, if both options are Some or both are None, None is returned. - -### filter - -Returns `Some(x)` if self is `Some(x)` and `predicate(x)` is true. Otherwise, this returns `None`. - -### flatten - -Flattens an `Option>` into a `Option`. This returns `None` if the outer Option is None. Otherwise, this returns the inner Option. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/recursion.md deleted file mode 100644 index 5e592a2fd89..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/recursion.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: Recursive Proofs -description: Learn about how to write recursive proofs in Noir. -keywords: [recursion, recursive proofs, verification_key, aggregation object, verify_proof] ---- - -Noir supports recursively verifying proofs, meaning you verify the proof of a Noir program in another Noir program. This enables creating proofs of arbitrary size by doing step-wise verification of smaller components of a large proof. - -The `verify_proof` function takes a verification key, proof and public inputs for a zk program, as well as a key hash and an input aggregation object. The key hash is used to check the validity of the verification key and the input aggregation object is required by some proving systems. The `verify_proof` function returns an output aggregation object that can then be fed into future iterations of the proof verification if required. - -```rust -#[foreign(verify_proof)] -fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : Field, _key_hash : Field, _input_aggregation_object : [Field]) -> [Field] {} -``` - -:::info - -This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. - -::: - -## Aggregation Object - -The purpose of the input aggregation object is a little less clear though (and the output aggregation object that is returned from the `std::verify_proof` method). Recursive zkSNARK schemes do not necessarily "verify a proof" in the sense that you expect a true or false to be spit out by the verifier. Rather an aggregation object is built over the public inputs. In the case of PLONK the recursive aggregation object is two G1 points (expressed as 16 witness values). The final verifier (in our case this is most often the smart contract verifier) has to be aware of this aggregation object to execute a pairing and check the validity of these points (thus completing the recursive verification). - -So for example in this circuit: - -```rust -use dep::std; - -fn main( - verification_key : [Field; 114], - proof : [Field; 94], - public_inputs : [Field; 1], - key_hash : Field, - input_aggregation_object : [Field; 16], - proof_b : [Field; 94], -) -> pub [Field; 16] { - let output_aggregation_object_a = std::verify_proof( - verification_key, - proof, - public_inputs, - key_hash, - input_aggregation_object - ); - - let output_aggregation_object = std::verify_proof( - verification_key, - proof_b, - public_inputs, - key_hash, - output_aggregation_object_a - ); - - let mut output = [0; 16]; - for i in 0..16 { - output[i] = output_aggregation_object[i]; - } - output -} -``` - -In this example we have a circuit, that generates proofs A and B, that is being verified in circuit C. Assuming that the proof being passed in is not already a recursive proof, the `input_aggregation_object` will be all zeros. It will then generate an `output_aggregation_object`. This blob of data then becomes the `input_aggregation_object` of the next recursive aggregation we wish to compute. We can see here as the same public inputs, verification key, and key hash are used that we are verifying two proofs generated from the same circuit in this single circuit. `std::verify_proof` returns a `[Field]` because the size of an aggregation object is proof system dependent--in barretenberg, aggregation objects are two G1 points, while in Halo2, the aggregation object is a list of G1 points that is log the circuit size. So for the final step we convert the slice into an array of size 16 because we are generating proofs using UltraPlonk. - -## Parameters - -### `verification_key` - -The verification key for the zk program that is being verified. - -### `proof` - -The proof for the zk program that is being verified. - -### `public_inputs` - -These represent the public inputs of the proof we are verifying. They should be checked against in the circuit after construction of a new aggregation state. - -### `key_hash` - -A key hash is used to check the validity of the verification key. The circuit implementing this opcode can use this hash to ensure that the key provided to the circuit matches the key produced by the circuit creator. - -### `input_aggregation_object` - -An aggregation object is blob of data that the top-level verifier must run some proof system specific algorithm on to complete verification. The size is proof system specific and will be set by the backend integrating this opcode. The input aggregation object is only not `None` when we are verifying a previous recursive aggregation in the current circuit. If this is the first recursive aggregation there is no input aggregation object. It is left to the backend to determine how to handle when there is no input aggregation object. - -## Return value - -### `output_aggregation_object` - -This is the result of a recursive aggregation and is what will be fed into the next verifier. -The next verifier can either perform a final verification (returning true or false) or perform another recursive aggregation where this output aggregation object will be the input aggregation object of the next recursive aggregation. - -## Example - -You can see an example of how to do recursive proofs in [this example recursion demo repo](https://github.com/noir-lang/noir-examples/tree/master/recursion). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/zeroed.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/zeroed.md deleted file mode 100644 index 97dab02dac2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/zeroed.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: Zeroed Function -description: - The zeroed function returns a zeroed value of any type. -keywords: - [ - zeroed - ] ---- - -Implements `fn zeroed() -> T` to return a zeroed value of any type. This function is generally unsafe to use as the zeroed bit pattern is not guaranteed to be valid for all types. It can however, be useful in cases when the value is guaranteed not to be used such as in a BoundedVec library implementing a growable vector, up to a certain length, backed by an array. The array can be initialized with zeroed values which are guaranteed to be inaccessible until the vector is pushed to. Similarly, enumerations in noir can be implemented using this method by providing zeroed values for the unused variants. - -You can access the function at `std::unsafe::zeroed`. - -This function currently supports the following types: - -- Field -- Bool -- Uint -- Array -- String -- Tuple -- Function - -Using it on other types could result in unexpected behavior. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/examples/merkle-proof.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/examples/merkle-proof.mdx deleted file mode 100644 index 832fb4bb55e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/examples/merkle-proof.mdx +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Merkle Proof Membership -description: - Learn how to use merkle membership proof in Noir to prove that a given leaf is a member of a - merkle tree with a specified root, at a given index. -keywords: - [merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree] ---- - -Let's walk through an example of a merkle membership proof in Noir that proves that a given leaf is -in a merkle tree. - -```rust -use dep::std; - -fn main(message : [Field; 62], index : Field, hashpath : [Field; 40], root : Field) { - let leaf = std::hash::hash_to_field(message); - let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); - assert(merkle_root == root); -} - -``` - -The message is hashed using `hash_to_field`. The specific hash function that is being used is chosen -by the backend. The only requirement is that this hash function can heuristically be used as a -random oracle. If only collision resistance is needed, then one can call `std::hash::pedersen_hash` -instead. - -```rust -let leaf = std::hash::hash_to_field(message); -``` - -The leaf is then passed to a compute_merkle_root function with the root, index and hashpath. The returned root can then be asserted to be the same as the provided root. - -```rust -let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); -assert (merkle_root == root); -``` - -> **Note:** It is possible to re-implement the merkle tree implementation without standard library. -> However, for most usecases, it is enough. In general, the standard library will always opt to be -> as conservative as possible, while striking a balance with efficiency. - -An example, the merkle membership proof, only requires a hash function that has collision -resistance, hence a hash function like Pedersen is allowed, which in most cases is more efficient -than the even more conservative sha256. - -[View an example on the starter repo](https://github.com/noir-lang/noir-examples/blob/3ea09545cabfa464124ec2f3ea8e60c608abe6df/stealthdrop/circuits/src/main.nr#L20) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/getting_started/00_nargo_installation.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/getting_started/00_nargo_installation.md deleted file mode 100644 index 7d3c88c7693..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/getting_started/00_nargo_installation.md +++ /dev/null @@ -1,249 +0,0 @@ ---- -title: Nargo Installation -description: - nargo is a command line tool for interacting with Noir programs (e.g. compiling, proving, - verifying and more). Learn how to install and use Nargo for your projects with this comprehensive - guide. -keywords: [Nargo, command line tool, Noir programs, installation guide, how to use Nargo] ---- - -`nargo` is a command line tool for interacting with Noir programs (e.g. compiling, proving, -verifying and more). - -Alternatively, the interactions can also be performed in [NoirJS](../noir_js/noir_js.md). - -### UltraPlonk - -Nargo versions \<0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk -version of Aztec Backend, which lacks efficient implementations of useful primitives (e.g. Keccak256 in 18k constraints, ECDSA verification in 36k constraints) that the UltraPlonk version offers. - -## Installation - -There are four approaches for installing Nargo: - -- [Option 1: Noirup](#option-1-noirup) -- [Option 2: Binaries](#option-2-binaries) -- [Option 3: Compile from Source](#option-3-compile-from-source) -- [Option 4: WSL for Windows](#option-4-wsl-for-windows) - -Optionally you can also install [Noir VS Code extension] for syntax highlighting. - -### Option 1: Noirup - -If you're on OSX or Linux, the easiest way to start using Noir and Nargo is via noirup. Just open a -terminal and run: - -```bash -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -Close the terminal, open another one, and run - -```bash -noirup -``` - -Done, you should have the latest version working. You can check with `nargo --version`. - -You can also install nightlies, specific versions -or branches, check out the [noirup repository](https://github.com/noir-lang/noirup) for more -information. - -#### GitHub Actions - -You can use `noirup` with GitHub Actions for CI/CD and automated testing. It is as simple as -installing `noirup` and running tests in your GitHub Action `yml` file. - -See the -[config file](https://github.com/TomAFrench/noir-hashes/blob/master/.github/workflows/noir.yml) in -this repo containing hash functions in Noir for an example. - -#### Nightly versions - -To install the nightly version of Noir (updated daily) run: - -```bash -noirup -n -``` - -### Option 2: Binaries - -See [GitHub Releases](https://github.com/noir-lang/noir/releases) for the latest and previous -platform specific binaries. - -#### Step 1 - -Paste and run the following in the terminal to extract and install the binary: - -> **macOS / Linux:** If you are prompted with `Permission denied` when running commands, prepend -> `sudo` and re-run it. - -##### macOS (Apple Silicon) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-aarch64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### macOS (Intel) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### Linux (Bash) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-unknown-linux-gnu.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -C $HOME/.nargo/bin/ && \ -echo -e '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.bashrc && \ -source ~/.bashrc -``` - -#### Step 2 - -Check if the installation was successful by running `nargo --help`. - -> **macOS:** If you are prompted with an OS alert, right-click and open the _nargo_ executable from -> Finder. Close the new terminal popped up and `nargo` should now be accessible. - -For a successful installation, you should see something similar to the following after running the -command: - -```sh -$ nargo --help - -Noir's package manager - -Usage: nargo - -Commands: - check Checks the constraint system for errors - codegen-verifier Generates a Solidity verifier smart contract for the program - compile Compile the program and its secret execution trace into ACIR format - new Create a new binary project - execute Executes a circuit to calculate its return value - prove Create proof for this program. The proof is returned as a hex encoded string - verify Given a proof and a program, verify whether the proof is valid - test Run the tests for this program - gates Counts the occurrences of different gates in circuit - help Print this message or the help of the given subcommand(s) -``` - -### Option 3: Compile from Source - -Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. It helps mitigating issues commonly associated with dependency management, such as conflicts between required package versions for different projects (often referred to as "dependency hell"). - -Combined with direnv, which automatically sets or clears environment variables based on the directory, it further simplifies the development process by seamlessly integrating with the developer's shell, facilitating an efficient and reliable workflow for managing and deploying Noir projects with multiple dependencies. - -#### Setting up your environment - -For the best experience, please follow these instructions to setup your environment: - -1. Install Nix following [their guide](https://nixos.org/download.html) for your operating system. -2. Create the file `~/.config/nix/nix.conf` with the contents: - -```ini -experimental-features = nix-command -extra-experimental-features = flakes -``` - -3. Install direnv into your Nix profile by running: - -```sh -nix profile install nixpkgs#direnv -``` - -4. Add direnv to your shell following [their guide](https://direnv.net/docs/hook.html). - 1. For bash or zshell, add `eval "$(direnv hook bash)"` or `eval "$(direnv hook zsh)"` to your ~/.bashrc or ~/.zshrc file, respectively. -5. Restart your shell. - -#### Shell & editor experience - -Now that your environment is set up, you can get to work on the project. - -1. Clone the repository, such as: - -```sh -git clone git@github.com:noir-lang/noir -``` - -> Replacing `noir` with whichever repository you want to work on. - -2. Navigate to the directory: - -```sh -cd noir -``` - -> Replacing `noir` with whichever repository you cloned. - -3. You should see a **direnv error** because projects aren't allowed by default. Make sure you've reviewed and trust our `.envrc` file, then you need to run: - -```sh -direnv allow -``` - -4. Now, wait awhile for all the native dependencies to be built. This will take some time and direnv will warn you that it is taking a long time, but we just need to let it run. - -5. Once you are presented with your prompt again, you can start your editor within the project directory (we recommend [VSCode](https://code.visualstudio.com/)): - -```sh -code . -``` - -6. (Recommended) When launching VSCode for the first time, you should be prompted to install our recommended plugins. We highly recommend installing these for the best development experience. - -#### Building and testing - -Assuming you are using `direnv` to populate your environment, building and testing the project can be done -with the typical `cargo build`, `cargo test`, and `cargo clippy` commands. You'll notice that the `cargo` version matches the version we specify in `rust-toolchain.toml`, which is 1.71.1 at the time of this writing. - -If you want to build the entire project in an isolated sandbox, you can use Nix commands: - -1. `nix build .` (or `nix build . -L` for verbose output) to build the project in a Nix sandbox. -2. `nix flake check` (or `nix flake check -L` for verbose output) to run clippy and tests in a Nix sandbox. - -#### Without `direnv` - -If you have hesitations with using direnv, you can launch a subshell with `nix develop` and then launch your editor from within the subshell. However, if VSCode was already launched in the project directory, the environment won't be updated. - -Advanced: If you aren't using direnv nor launching your editor within the subshell, you can try to install Barretenberg and other global dependencies the package needs. This is an advanced workflow and likely won't receive support! - -### Option 4: WSL (for Windows) - -The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed natively. However, it is available by using Windows Subsystem for Linux (WSL). - -Step 1: Follow the instructions [here](https://learn.microsoft.com/en-us/windows/wsl/install) to install and run WSL. - -step 2: Follow the [Noirup instructions](#option-1-noirup). - -## Uninstalling Nargo - -### Noirup - -If you installed Noir with `noirup`, you can uninstall Noir by removing the files in `~/.nargo`, `~/nargo` and `~/noir_cache`. - -```bash -rm -r ~/.nargo -rm -r ~/nargo -rm -r ~/noir_cache -``` - -### Nix - -If you installed Noir with Nix or from source, you can remove the binary located at `~/.nix-profile/bin/nargo`. - -```bash -rm ~/.nix-profile/bin/nargo -``` - -[noir vs code extension]: https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/getting_started/01_hello_world.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/getting_started/01_hello_world.md deleted file mode 100644 index 0384ba4a0cd..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/getting_started/01_hello_world.md +++ /dev/null @@ -1,147 +0,0 @@ ---- -title: Create A Project -description: - Learn how to create and verify your first Noir program using Nargo, a programming language for - zero-knowledge proofs. -keywords: - [ - Nargo, - Noir, - zero-knowledge proofs, - programming language, - create Noir program, - verify Noir program, - step-by-step guide, - ] ---- - -Now that we have installed Nargo, it is time to make our first hello world program! - -## Create a Project Directory - -Noir code can live anywhere on your computer. Let us create a _projects_ folder in the home -directory to house our Noir programs. - -For Linux, macOS, and Windows PowerShell, create the directory and change directory into it by -running: - -```sh -mkdir ~/projects -cd ~/projects -``` - -For Windows CMD, run: - -```sh -> mkdir "%USERPROFILE%\projects" -> cd /d "%USERPROFILE%\projects" -``` - -## Create Our First Nargo Project - -Now that we are in the projects directory, create a new Nargo project by running: - -```sh -nargo new hello_world -``` - -> **Note:** `hello_world` can be any arbitrary project name, we are simply using `hello_world` for -> demonstration. -> -> In production, the common practice is to name the project folder as `circuits` for better -> identifiability when sitting alongside other folders in the codebase (e.g. `contracts`, `scripts`, -> `test`). - -A `hello_world` folder would be created. Similar to Rust, the folder houses _src/main.nr_ and -_Nargo.toml_ that contains the source code and environmental options of your Noir program -respectively. - -### Intro to Noir Syntax - -Let us take a closer look at _main.nr_. The default _main.nr_ generated should look like this: - -```rust -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` - -The first line of the program specifies the program's inputs: - -```rust -x : Field, y : pub Field -``` - -Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the -keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](../language_concepts/data_types.md) section. - -The next line of the program specifies its body: - -```rust -assert(x != y); -``` - -The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. - -For more Noir syntax, check the [Language Concepts](../language_concepts/09_comments.md) chapter. - -## Build In/Output Files - -Change directory into _hello_world_ and build in/output files for your Noir program by running: - -```sh -cd hello_world -nargo check -``` - -Two additional files would be generated in your project directory: - -_Prover.toml_ houses input values, and _Verifier.toml_ houses public values. - -## Prove Our Noir Program - -Now that the project is set up, we can create a proof of correct execution on our Noir program. - -Fill in input values for execution in the _Prover.toml_ file. For example: - -```toml -x = "1" -y = "2" -``` - -Prove the valid execution of your Noir program: - -```sh -nargo prove -``` - -A new folder _proofs_ would then be generated in your project directory, containing the proof file -`.proof`, where the project name is defined in Nargo.toml. - -The _Verifier.toml_ file would also be updated with the public values computed from program -execution (in this case the value of `y`): - -```toml -y = "0x0000000000000000000000000000000000000000000000000000000000000002" -``` - -> **Note:** Values in _Verifier.toml_ are computed as 32-byte hex values. - -## Verify Our Noir Program - -Once a proof is generated, we can verify correct execution of our Noir program by verifying the -proof file. - -Verify your proof by running: - -```sh -nargo verify -``` - -The verification will complete in silence if it is successful. If it fails, it will log the -corresponding error instead. - -Congratulations, you have now created and verified a proof for your very first Noir program! - -In the [next section](./02_breakdown.md), we will go into more detail on each step performed. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/getting_started/02_breakdown.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/getting_started/02_breakdown.md deleted file mode 100644 index f928370b2e8..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/getting_started/02_breakdown.md +++ /dev/null @@ -1,198 +0,0 @@ ---- -title: Project Breakdown -description: - Learn about the anatomy of a Nargo project, including the purpose of the Prover and Verifier TOML - files, and how to prove and verify your program. -keywords: - [Nargo, Nargo project, Prover.toml, Verifier.toml, proof verification, private asset transfer] ---- - -This section breaks down our hello world program in section _1.2_. We elaborate on the project -structure and what the `prove` and `verify` commands did in the previous section. - -## Anatomy of a Nargo Project - -Upon creating a new project with `nargo new` and building the in/output files with `nargo check` -commands, you would get a minimal Nargo project of the following structure: - - - src - - Prover.toml - - Verifier.toml - - Nargo.toml - -The source directory _src_ holds the source code for your Noir program. By default only a _main.nr_ -file will be generated within it. - -### Prover.toml - -_Prover.toml_ is used for specifying the input values for executing and proving the program. You can specify `toml` files with different names by using the `--prover-name` or `-p` flags, see the [Prover](#provertoml) section below. Optionally you may specify expected output values for prove-time checking as well. - -### Verifier.toml - -_Verifier.toml_ contains public in/output values computed when executing the Noir program. - -### Nargo.toml - -_Nargo.toml_ contains the environmental options of your project. It contains a "package" section and a "dependencies" section. - -Example Nargo.toml: - -```toml -[package] -name = "noir_starter" -type = "bin" -authors = ["Alice"] -compiler_version = "0.9.0" -description = "Getting started with Noir" -entry = "circuit/main.nr" -license = "MIT" - -[dependencies] -ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} -``` - -Nargo.toml for a [workspace](../modules_packages_crates/workspaces.md) will look a bit different. For example: - -```toml -[workspace] -members = ["crates/a", "crates/b"] -default-member = "crates/a" -``` - -#### Package section - -The package section requires a number of fields including: - -- `name` (**required**) - the name of the package -- `type` (**required**) - can be "bin", "lib", or "contract" to specify whether its a binary, library or Aztec contract -- `authors` (optional) - authors of the project -- `compiler_version` - specifies the version of the compiler to use. This is enforced by the compiler and follow's [Rust's versioning](https://doc.rust-lang.org/cargo/reference/manifest.html#the-version-field), so a `compiler_version = 0.18.0` will enforce Nargo version 0.18.0, `compiler_version = ^0.18.0` will enforce anything above 0.18.0 but below 0.19.0, etc. For more information, see how [Rust handles these operators](https://docs.rs/semver/latest/semver/enum.Op.html) -- `description` (optional) -- `entry` (optional) - a relative filepath to use as the entry point into your package (overrides the default of `src/lib.nr` or `src/main.nr`) -- `backend` (optional) -- `license` (optional) - -#### Dependencies section - -This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies.md)for more info. - -`./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or -verifier contract respectively. - -### main.nr - -The _main.nr_ file contains a `main` method, this method is the entry point into your Noir program. - -In our sample program, _main.nr_ looks like this: - -```rust -fn main(x : Field, y : Field) { - assert(x != y); -} -``` - -The parameters `x` and `y` can be seen as the API for the program and must be supplied by the -prover. Since neither `x` nor `y` is marked as public, the verifier does not supply any inputs, when -verifying the proof. - -The prover supplies the values for `x` and `y` in the _Prover.toml_ file. - -As for the program body, `assert` ensures the satisfaction of the condition (e.g. `x != y`) is -constrained by the proof of the execution of said program (i.e. if the condition was not met, the -verifier would reject the proof as an invalid proof). - -### Prover.toml - -The _Prover.toml_ file is a file which the prover uses to supply his witness values(both private and -public). - -In our hello world program the _Prover.toml_ file looks like this: - -```toml -x = "1" -y = "2" -``` - -When the command `nargo prove` is executed, two processes happen: - -1. Noir creates a proof that `x` which holds the value of `1` and `y` which holds the value of `2` - is not equal. This not equal constraint is due to the line `assert(x != y)`. - -2. Noir creates and stores the proof of this statement in the _proofs_ directory in a file called your-project.proof. So if your project is named "private_voting" (defined in the project Nargo.toml), the proof will be saved at `./proofs/private_voting.proof`. Opening this file will display the proof in hex format. - -#### Arrays of Structs - -The following code shows how to pass an array of structs to a Noir program to generate a proof. - -```rust -// main.nr -struct Foo { - bar: Field, - baz: Field, -} - -fn main(foos: [Foo; 3]) -> pub Field { - foos[2].bar + foos[2].baz -} -``` - -Prover.toml: - -```toml -[[foos]] # foos[0] -bar = 0 -baz = 0 - -[[foos]] # foos[1] -bar = 0 -baz = 0 - -[[foos]] # foos[2] -bar = 1 -baz = 2 -``` - -#### Custom toml files - -You can specify a `toml` file with a different name to use for proving by using the `--prover-name` or `-p` flags. - -This command looks for proof inputs in the default **Prover.toml** and generates the proof and saves it at `./proofs/.proof`: - -```bash -nargo prove -``` - -This command looks for proof inputs in the custom **OtherProver.toml** and generates proof and saves it at `./proofs/.proof`: - -```bash -nargo prove -p OtherProver -``` - -## Verifying a Proof - -When the command `nargo verify` is executed, two processes happen: - -1. Noir checks in the _proofs_ directory for a proof file with the project name (eg. test_project.proof) - -2. If that file is found, the proof's validity is checked - -> **Note:** The validity of the proof is linked to the current Noir program; if the program is -> changed and the verifier verifies the proof, it will fail because the proof is not valid for the -> _modified_ Noir program. - -In production, the prover and the verifier are usually two separate entities. A prover would -retrieve the necessary inputs, execute the Noir program, generate a proof and pass it to the -verifier. The verifier would then retrieve the public inputs from usually external sources and -verifies the validity of the proof against it. - -Take a private asset transfer as an example: - -A user on browser as the prover would retrieve private inputs (e.g. the user's private key) and -public inputs (e.g. the user's encrypted balance on-chain), compute the transfer, generate a proof -and submit it to the verifier smart contract. - -The verifier contract would then draw the user's encrypted balance directly from the blockchain and -verify the proof submitted against it. If the verification passes, additional functions in the -verifier contract could trigger (e.g. approve the asset transfer). - -Now that you understand the concepts, you'll probably want some editor feedback while you are writing more complex code. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/index.md deleted file mode 100644 index e8d86020a20..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/index.md +++ /dev/null @@ -1,100 +0,0 @@ ---- -title: Introducing Noir -description: - Learn about the public alpha release of Noir, a domain specific language heavily influenced by - Rust that compiles to an intermediate language which can be compiled to an arithmetic circuit or a - rank-1 constraint system. -keywords: - [ - Noir, - Domain Specific Language, - Rust, - Intermediate Language, - Arithmetic Circuit, - Rank-1 Constraint System, - Ethereum Developers, - Protocol Developers, - Blockchain Developers, - Proving System, - Smart Contract Language, - ] -slug: / ---- - -## What is Noir? - -Noir is a Domain Specific Language for SNARK proving systems. It has been designed to use any ACIR compatible proving system. - -Its design choices are influenced heavily by Rust and focuses on a simple, familiar syntax. - -## Who is Noir for? - -Noir can be used for a variety of purposes. - -### Solidity Developers - -Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will -be modularized in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier.md) command to create -a verifier contract. - -### Protocol Developers - -As a protocol developer, you may not want to use the Aztec backend due to it not being a fit for -your stack, or maybe you simply want to use a different proving system. Since Noir does not compile -to a specific proof system, it is possible for protocol developers to replace the PLONK-based -proving system with a different proving system altogether. - -### Blockchain developers - -As a blockchain developer, you will be constrained by parameters set by your blockchain (for example, the -proving system and smart contract language has been pre-defined). In order for you to use Noir in -your blockchain, a proving system backend and a smart contract interface -must be implemented for it. - -## What's new about Noir? - -Noir is simple and flexible in its design, as it does not compile immediately to a fixed -NP-complete language. Instead, Noir compiles to an intermediate language (ACIR), which itself can be compiled -to an arithmetic circuit (if choosing to target Aztec's barretenberg backend) or a rank-1 constraint system (if choosing to target an R1CS backend like Arkworks' Marlin backend, or others). - -This in itself brings up a few challenges within the design process, but allows one to decouple the programming language completely from the backend. This is similar in theory to LLVM. - -## Current Features - -Compiler: - -- Module System -- For expressions -- Arrays -- Bit Operations -- Binary operations (\<, \<=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] -- Unsigned integers -- If statements -- Structures and Tuples -- Generics - -ACIR Supported OPCODES: - -- Sha256 -- Blake2s -- Schnorr signature verification -- MerkleMembership -- Pedersen Commitment -- Pedersen Hash -- HashToField - -## Libraries - -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). - -Some libraries that are available today include: - -- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library -- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) -- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers -- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address -- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees -- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir -- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers - -See the section on [dependencies](./modules_packages_crates/dependencies.md) for more information. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/01_functions.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/01_functions.md deleted file mode 100644 index 5eb22170e54..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/01_functions.md +++ /dev/null @@ -1,225 +0,0 @@ ---- -title: Functions -description: - Learn how to declare functions and methods in Noir, a programming language with Rust semantics. - This guide covers parameter declaration, return types, call expressions, and more. -keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] ---- - -Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. - -To declare a function the `fn` keyword is used. - -```rust -fn foo() {} -``` - -By default, functions are visible only within the package they are defined. To make them visible outside of that package (for example, as part of a [library](../modules_packages_crates/crates_and_packages.md#libraries)), you should mark them as `pub`: - -```rust -pub fn foo() {} -``` - -You can also restrict the visibility of the function to only the crate it was defined in, by specifying `pub(crate)`: - -```rust -pub(crate) fn foo() {} //foo can only be called within its crate -``` - -All parameters in a function must have a type and all types are known at compile time. The parameter -is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. - -```rust -fn foo(x : Field, y : Field){} -``` - -The return type of a function can be stated by using the `->` arrow notation. The function below -states that the foo function must return a `Field`. If the function returns no value, then the arrow -is omitted. - -```rust -fn foo(x : Field, y : Field) -> Field { - x + y -} -``` - -Note that a `return` keyword is unneeded in this case - the last expression in a function's body is -returned. - -## Main function - -If you're writing a binary, the `main` function is the starting point of your program. You can pass all types of expressions to it, as long as they have a fixed size at compile time: - -```rust -fn main(x : Field) // this is fine: passing a Field -fn main(x : [Field; 2]) // this is also fine: passing a Field with known size at compile-time -fn main(x : (Field, bool)) // 👌: passing a (Field, bool) tuple means size 2 -fn main(x : str<5>) // this is fine, as long as you pass a string of size 5 - -fn main(x : Vec) // can't compile, has variable size -fn main(x : [Field]) // can't compile, has variable size -fn main(....// i think you got it by now -``` - -Keep in mind [tests](../nargo/02_testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: - -```rust -fn main(x : [Field]) { - assert(x[0] == 1); -} - -#[test] -fn test_one() { - main([1, 2]); -} -``` - -```bash -$ nargo test -[testing] Running 1 test functions -[testing] Testing test_one... ok -[testing] All tests passed - -$ nargo check -The application panicked (crashed). -Message: Cannot have variable sized arrays as a parameter to main -``` - -## Call Expressions - -Calling a function in Noir is executed by using the function name and passing in the necessary -arguments. - -Below we show how to call the `foo` function from the `main` function using a call expression: - -```rust -fn main(x : Field, y : Field) { - let z = foo(x); -} - -fn foo(x : Field) -> Field { - x + x -} -``` - -## Methods - -You can define methods in Noir on any struct type in scope. - -```rust -struct MyStruct { - foo: Field, - bar: Field, -} - -impl MyStruct { - fn new(foo: Field) -> MyStruct { - MyStruct { - foo, - bar: 2, - } - } - - fn sum(self) -> Field { - self.foo + self.bar - } -} - -fn main() { - let s = MyStruct::new(40); - assert(s.sum() == 42); -} -``` - -Methods are just syntactic sugar for functions, so if we wanted to we could also call `sum` as -follows: - -```rust -assert(MyStruct::sum(s) == 42); -``` - -It is also possible to specialize which method is chosen depending on the [generic](./06_generics.md) type that is used. In this example, the `foo` function returns different values depending on its type: - -```rust -struct Foo {} - -impl Foo { - fn foo(self) -> Field { 1 } -} - -impl Foo { - fn foo(self) -> Field { 2 } -} - -fn main() { - let f1: Foo = Foo{}; - let f2: Foo = Foo{}; - assert(f1.foo() + f2.foo() == 3); -} -``` - -Also note that impls with the same method name defined in them cannot overlap. For example, if we already have `foo` defined for `Foo` and `Foo` like we do above, we cannot also define `foo` in an `impl Foo` since it would be ambiguous which version of `foo` to choose. - -```rust -// Including this impl in the same project as the above snippet would -// cause an overlapping impls error -impl Foo { - fn foo(self) -> Field { 3 } -} -``` - -## Lambdas - -Lambdas are anonymous functions. They follow the syntax of Rust - `|arg1, arg2, ..., argN| return_expression`. - -```rust -let add_50 = |val| val + 50; -assert(add_50(100) == 150); -``` - -See [Lambdas](./08_lambdas.md) for more details. - -## Attributes - -Attributes are metadata that can be applied to a function, using the following syntax: `#[attribute(value)]`. - -Supported attributes include: - -- **builtin**: the function is implemented by the compiler, for efficiency purposes. -- **deprecated**: mark the function as _deprecated_. Calling the function will generate a warning: `warning: use of deprecated function` -- **field**: Used to enable conditional compilation of code depending on the field size. See below for more details -- **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./05_unconstrained.md) and [NoirJS](../noir_js/noir_js.md) for more details. -- **test**: mark the function as unit tests. See [Tests](../nargo/02_testing.md) for more details - -### Field Attribute - -The field attribute defines which field the function is compatible for. The function is conditionally compiled, under the condition that the field attribute matches the Noir native field. -The field can be defined implicitly, by using the name of the elliptic curve usually associated to it - for instance bn254, bls12_381 - or explicitly by using the field (prime) order, in decimal or hexadecimal form. -As a result, it is possible to define multiple versions of a function with each version specialized for a different field attribute. This can be useful when a function requires different parameters depending on the underlying elliptic curve. - -Example: we define the function `foo()` three times below. Once for the default Noir bn254 curve, once for the field $\mathbb F_{23}$, which will normally never be used by Noir, and once again for the bls12_381 curve. - -```rust -#[field(bn254)] -fn foo() -> u32 { - 1 -} - -#[field(23)] -fn foo() -> u32 { - 2 -} - -// This commented code would not compile as foo would be defined twice because it is the same field as bn254 -// #[field(21888242871839275222246405745257275088548364400416034343698204186575808495617)] -// fn foo() -> u32 { -// 2 -// } - -#[field(bls12_381)] -fn foo() -> u32 { - 3 -} -``` - -If the field name is not known to Noir, it will discard the function. Field names are case insensitive. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/02_control_flow.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/02_control_flow.md deleted file mode 100644 index a7f85360197..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/02_control_flow.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Control Flow -description: - Learn how to use loops and if expressions in the Noir programming language. Discover the syntax - and examples for for loops and if-else statements. -keywords: [Noir programming language, loops, for loop, if-else statements, Rust syntax] ---- - -## Loops - -Noir has one kind of loop: the `for` loop. `for` loops allow you to repeat a block of code multiple -times. - -The following block of code between the braces is run 10 times. - -```rust -for i in 0..10 { - // do something -}; -``` - -The index for loops is of type `u64`. - -## If Expressions - -Noir supports `if-else` statements. The syntax is most similar to Rust's where it is not required -for the statement's conditional to be surrounded by parentheses. - -```rust -let a = 0; -let mut x: u32 = 0; - -if a == 0 { - if a != 0 { - x = 6; - } else { - x = 2; - } -} else { - x = 5; - assert(x == 5); -} -assert(x == 2); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/03_ops.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/03_ops.md deleted file mode 100644 index 0e35ef5e584..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/03_ops.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -title: Logical Operations -description: - Learn about the supported arithmetic and logical operations in the Noir programming language. - Discover how to perform operations on private input types, integers, and booleans. -keywords: - [ - Noir programming language, - supported operations, - arithmetic operations, - logical operations, - predicate operators, - bitwise operations, - short-circuiting, - backend, - ] ---- - -# Operations - -## Table of Supported Operations - -| Operation | Description | Requirements | -| :-------- | :------------------------------------------------------------: | -------------------------------------: | -| + | Adds two private input types together | Types must be private input | -| - | Subtracts two private input types together | Types must be private input | -| \* | Multiplies two private input types together | Types must be private input | -| / | Divides two private input types together | Types must be private input | -| ^ | XOR two private input types together | Types must be integer | -| & | AND two private input types together | Types must be integer | -| \| | OR two private input types together | Types must be integer | -| \<\< | Left shift an integer by another integer amount | Types must be integer | -| >> | Right shift an integer by another integer amount | Types must be integer | -| ! | Bitwise not of a value | Type must be integer or boolean | -| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | -| > | returns a bool if one value is more than the other | Upper bound must have a known bit size | -| >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | -| == | returns a bool if one value is equal to the other | Both types must not be constants | -| != | returns a bool if one value is not equal to the other | Both types must not be constants | - -### Predicate Operators - -`<,<=, !=, == , >, >=` are known as predicate/comparison operations because they compare two values. -This differs from the operations such as `+` where the operands are used in _computation_. - -### Bitwise Operations Example - -```rust -fn main(x : Field) { - let y = x as u32; - let z = y & y; -} -``` - -`z` is implicitly constrained to be the result of `y & y`. The `&` operand is used to denote bitwise -`&`. - -> `x & x` would not compile as `x` is a `Field` and not an integer type. - -### Logical Operators - -Noir has no support for the logical operators `||` and `&&`. This is because encoding the -short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can -use the bitwise operators `|` and `&` which operate identically for booleans, just without the -short-circuiting. - -```rust -let my_val = 5; - -let mut flag = 1; -if (my_val > 6) | (my_val == 0) { - flag = 0; -} -assert(flag == 1); - -if (my_val != 10) & (my_val < 50) { - flag = 0; -} -assert(flag == 0); -``` - -### Shorthand operators - -Noir shorthand operators for most of the above operators, namely `+=, -=, *=, /=, %=, &=, |=, ^=, <<=`, and `>>=`. These allow for more concise syntax. For example: - -```rust -let mut i = 0; -i = i + 1; -``` - -could be written as: - -```rust -let mut i = 0; -i += 1; -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/04_assert.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/04_assert.md deleted file mode 100644 index 7427ec6cc63..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/04_assert.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Assert Function -description: - Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or - comparison expression that follows to be true, and what happens if the expression is false at - runtime. -keywords: [Noir programming language, assert statement, predicate expression, comparison expression] ---- - -Noir includes a special `assert` function which will explicitly constrain the predicate/comparison -expression that follows to be true. If this expression is false at runtime, the program will fail to -be proven. Example: - -```rust -fn main(x : Field, y : Field) { - assert(x == y); -} -``` - -You can optionally provide a message to be logged when the assertion fails: - -```rust -assert(x == y, "x and y are not equal"); -``` - -> Assertions only work for predicate operations, such as `==`. If there's any ambiguity on the operation, the program will fail to compile. For example, it is unclear if `assert(x + y)` would check for `x + y == 0` or simply would return `true`. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/05_unconstrained.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/05_unconstrained.md deleted file mode 100644 index 097d6ee9894..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/05_unconstrained.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: Unconstrained Functions -description: "Learn about what unconstrained functions in Noir are, how to use them and when you'd want to." - -keywords: [Noir programming language, unconstrained, open] ---- - - - -Unconstrained functions are functions which do not constrain any of the included computation and allow for non-deterministic computation. - -## Why? - -Zero-knowledge (ZK) domain-specific languages (DSL) enable developers to generate ZK proofs from their programs by compiling code down to the constraints of an NP complete language (such as R1CS or PLONKish languages). However, the hard bounds of a constraint system can be very limiting to the functionality of a ZK DSL. - -Enabling a circuit language to perform unconstrained execution is a powerful tool. Said another way, unconstrained execution lets developers generate witnesses from code that does not generate any constraints. Being able to execute logic outside of a circuit is critical for both circuit performance and constructing proofs on information that is external to a circuit. - -Fetching information from somewhere external to a circuit can also be used to enable developers to improve circuit efficiency. - -A ZK DSL does not just prove computation, but proves that some computation was handled correctly. Thus, it is necessary that when we switch from performing some operation directly inside of a circuit to inside of an unconstrained environment that the appropriate constraints are still laid down elsewhere in the circuit. - -## Example - -An in depth example might help drive the point home. This example comes from the excellent [post](https://discord.com/channels/1113924620781883405/1124022445054111926/1128747641853972590) by Tom in the Noir Discord. - -Let's look at how we can optimize a function to turn a `u72` into an array of `u8`s. - -```rust -fn main(num: u72) -> pub [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8)) as u72 & 0xff) as u8; - } - - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 91 -Backend circuit size: 3619 -``` - -A lot of the operations in this function are optimized away by the compiler (all the bit-shifts turn into divisions by constants). However we can save a bunch of gates by casting to u8 a bit earlier. This automatically truncates the bit-shifted value to fit in a u8 which allows us to remove the XOR against 0xff. This saves us ~480 gates in total. - -```rust -fn main(num: u72) -> pub [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8)) as u8; - } - - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 75 -Backend circuit size: 3143 -``` - -Those are some nice savings already but we can do better. This code is all constrained so we're proving every step of calculating out using num, but we don't actually care about how we calculate this, just that it's correct. This is where brillig comes in. - -It turns out that truncating a u72 into a u8 is hard to do inside a snark, each time we do as u8 we lay down 4 ACIR opcodes which get converted into multiple gates. It's actually much easier to calculate num from out than the other way around. All we need to do is multiply each element of out by a constant and add them all together, both relatively easy operations inside a snark. - -We can then run u72_to_u8 as unconstrained brillig code in order to calculate out, then use that result in our constrained function and assert that if we were to do the reverse calculation we'd get back num. This looks a little like the below: - -```rust -fn main(num: u72) -> pub [u8; 8] { - let out = u72_to_u8(num); - - let mut reconstructed_num: u72 = 0; - for i in 0..8 { - reconstructed_num += (out[i] as u72 << (56 - (8 * i))); - } - assert(num == reconstructed_num); - out -} - -unconstrained fn u72_to_u8(num: u72) -> [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8))) as u8; - } - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 78 -Backend circuit size: 2902 -``` - -This ends up taking off another ~250 gates from our circuit! We've ended up with more ACIR opcodes than before but they're easier for the backend to prove (resulting in fewer gates). - -Generally we want to use brillig whenever there's something that's easy to verify but hard to compute within the circuit. For example, if you wanted to calculate a square root of a number it'll be a much better idea to calculate this in brillig and then assert that if you square the result you get back your number. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/06_generics.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/06_generics.md deleted file mode 100644 index 36c2b593fcd..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/06_generics.md +++ /dev/null @@ -1,113 +0,0 @@ ---- -title: Generics -description: Learn how to use Generics in Noir -keywords: [Noir, Rust, generics, functions, structs] ---- - -Generics allow you to use the same functions with multiple different concrete data types. You can -read more about the concept of generics in the Rust documentation -[here](https://doc.rust-lang.org/book/ch10-01-syntax.html). - -Here is a trivial example showing the identity function that supports any type. In Rust, it is -common to refer to the most general type as `T`. We follow the same convention in Noir. - -```rust -fn id(x: T) -> T { - x -} -``` - -## In Structs - -Generics are useful for specifying types in structs. For example, we can specify that a field in a -struct will be of a certain generic type. In this case `value` is of type `T`. - -```rust -struct RepeatedValue { - value: T, - count: Field, -} - -impl RepeatedValue { - fn new(value: T) -> Self { - Self { value, count: 1 } - } - - fn increment(mut repeated: Self) -> Self { - repeated.count += 1; - repeated - } - - fn print(self) { - for _i in 0 .. self.count { - dep::std::println(self.value); - } - } -} - -fn main() { - let mut repeated = RepeatedValue::new("Hello!"); - repeated = repeated.increment(); - repeated.print(); -} -``` - -The `print` function will print `Hello!` an arbitrary number of times, twice in this case. - -If we want to be generic over array lengths (which are type-level integers), we can use numeric -generics. Using these looks just like using regular generics, but these generics can resolve to -integers at compile-time, rather than resolving to types. Here's an example of a struct that is -generic over the size of the array it contains internally: - -```rust -struct BigInt { - limbs: [u32; N], -} - -impl BigInt { - // `N` is in scope of all methods in the impl - fn first(first: BigInt, second: BigInt) -> Self { - assert(first.limbs != second.limbs); - first - - fn second(first: BigInt, second: Self) -> Self { - assert(first.limbs != second.limbs); - second - } -} -``` - -## Calling functions on generic parameters - -Unlike Rust, Noir does not have traits, so how can one translate the equivalent of a trait bound in -Rust into Noir? That is, how can we write a function that is generic over some type `T`, while also -requiring there is a function like `eq: fn(T, T) -> bool` that works on the type? - -The answer is that we can translate this by passing in the function manually. Here's an example of -implementing array equality in Noir: - -```rust -fn array_eq(array1: [T; N], array2: [T; N], elem_eq: fn(T, T) -> bool) -> bool { - if array1.len() != array2.len() { - false - } else { - let mut result = true; - for i in 0 .. array1.len() { - result &= elem_eq(array1[i], array2[i]); - } - result - } -} - -fn main() { - assert(array_eq([1, 2, 3], [1, 2, 3], |a, b| a == b)); - - // We can use array_eq even for arrays of structs, as long as we have - // an equality function for these structs we can pass in - let array = [MyStruct::new(), MyStruct::new()]; - assert(array_eq(array, array, MyStruct::eq)); -} -``` - -You can see an example of generics in the tests -[here](https://github.com/noir-lang/noir/blob/master/test_programs/execution_success/generics/src/main.nr). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/07_mutability.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/07_mutability.md deleted file mode 100644 index ed3fed820ec..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/07_mutability.md +++ /dev/null @@ -1,92 +0,0 @@ ---- -title: Mutability -description: - Learn about mutable variables, constants, and globals in Noir programming language. Discover how - to declare, modify, and use them in your programs. -keywords: [noir programming language, mutability in noir, mutable variables, constants, globals] ---- - -Variables in noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned -to via an assignment expression. - -```rust -let x = 2; -x = 3; // error: x must be mutable to be assigned to - -let mut y = 3; -let y = 4; // OK -``` - -The `mut` modifier can also apply to patterns: - -```rust -let (a, mut b) = (1, 2); -a = 11; // error: a must be mutable to be assigned to -b = 12; // OK - -let mut (c, d) = (3, 4); -c = 13; // OK -d = 14; // OK - -// etc. -let MyStruct { x: mut y } = MyStruct { x: a }; -// y is now in scope -``` - -Note that mutability in noir is local and everything is passed by value, so if a called function -mutates its parameters then the parent function will keep the old value of the parameters. - -```rust -fn main() -> pub Field { - let x = 3; - helper(x); - x // x is still 3 -} - -fn helper(mut x: i32) { - x = 4; -} -``` - -## Comptime Values - -:::warning - -The 'comptime' keyword was removed in version 0.10. The comptime keyword and syntax are currently still kept and parsed for backwards compatibility, but are now deprecated and will issue a warning when used. `comptime` has been removed because it is no longer needed for accessing arrays. - -::: - -## Globals - -Noir also supports global variables. However, they must be known at compile-time. The global type can also be inferred by the compiler entirely. Globals can also be used to specify array -annotations for function parameters and can be imported from submodules. - -```rust -global N: Field = 5; // Same as `global N: Field = 5` - -fn main(x : Field, y : [Field; N]) { - let res = x * N; - - assert(res == y[0]); - - let res2 = x * my_submodule::N; - assert(res != res2); -} - -mod my_submodule { - use dep::std; - - global N: Field = 10; - - fn my_helper() -> Field { - let x = N; - x - } -} -``` - -## Why only local mutability? - -Witnesses in a proving system are immutable in nature. Noir aims to _closely_ mirror this setting -without applying additional overhead to the user. Modeling a mutable reference is not as -straightforward as on conventional architectures and would incur some possibly unexpected overhead. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/08_lambdas.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/08_lambdas.md deleted file mode 100644 index ae1e6aecab1..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/08_lambdas.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: Lambdas -description: Learn how to use anonymous functions in Noir programming language. -keywords: [Noir programming language, lambda, closure, function, anonymous function] ---- - -## Introduction - -Lambdas are anonymous functions. The syntax is `|arg1, arg2, ..., argN| return_expression`. - -```rust -let add_50 = |val| val + 50; -assert(add_50(100) == 150); -``` - -A block can be used as the body of a lambda, allowing you to declare local variables inside it: - -```rust -let cool = || { - let x = 100; - let y = 100; - x + y -} - -assert(cool() == 200); -``` - -## Closures - -Inside the body of a lambda, you can use variables defined in the enclosing function. Such lambdas are called **closures**. In this example `x` is defined inside `main` and is accessed from within the lambda: - -```rust -fn main() { - let x = 100; - let closure = || x + 150; - assert(closure() == 250); -} -``` - -## Passing closures to higher-order functions - -It may catch you by surprise that the following code fails to compile: - -```rust -fn foo(f: fn () -> Field) -> Field { - f() -} - -fn main() { - let (x, y) = (50, 50); - assert(foo(|| x + y) == 100); // error :( -} -``` - -The reason is that the closure's capture environment affects its type - we have a closure that captures two Fields and `foo` -expects a regular function as an argument - those are incompatible. -:::note - -Variables contained within the `||` are the closure's parameters, and the expression that follows it is the closure's body. The capture environment is comprised of any variables used in the closure's body that are not parameters. - -E.g. in |x| x + y, y would be a captured variable, but x would not be, since it is a parameter of the closure. - -::: -The syntax for the type of a closure is `fn[env](args) -> ret_type`, where `env` is the capture environment of the closure - -in this example that's `(Field, Field)`. - -The best solution in our case is to make `foo` generic over the environment type of its parameter, so that it can be called -with closures with any environment, as well as with regular functions: - -```rust -fn foo(f: fn[Env]() -> Field) -> Field { - f() -} - -fn main() { - let (x, y) = (50, 50); - assert(foo(|| x + y) == 100); // compiles fine - assert(foo(|| 60) == 60); // compiles fine -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/09_comments.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/09_comments.md deleted file mode 100644 index 3bb4d2f25a4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/09_comments.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: Comments -description: - Learn how to write comments in Noir programming language. A comment is a line of code that is - ignored by the compiler, but it can be read by programmers. Single-line and multi-line comments - are supported in Noir. -keywords: [Noir programming language, comments, single-line comments, multi-line comments] ---- - -A comment is a line in your codebase which the compiler ignores, however it can be read by -programmers. - -Here is a single line comment: - -```rust -// This is a comment and is ignored -``` - -`//` is used to tell the compiler to ignore the rest of the line. - -Noir also supports multi-line block comments. Start a block comment with `/*` and end the block with `*/`. - -Noir does not natively support doc comments. You may be able to use [Rust doc comments](https://doc.rust-lang.org/reference/comments.html) in your code to leverage some Rust documentation build tools with Noir code. - -```rust -/* - This is a block comment describing a complex function. -*/ -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/10_distinct.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/10_distinct.md deleted file mode 100644 index e7ff7f5017a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/10_distinct.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: Distinct Witnesses ---- - -The `distinct` keyword prevents repetitions of witness indices in the program's ABI. This ensures -that the witnesses being returned as public inputs are all unique. - -The `distinct` keyword is only used for return values on program entry points (usually the `main()` -function). - -When using `distinct` and `pub` simultaneously, `distinct` comes first. See the example below. - -You can read more about the problem this solves -[here](https://github.com/noir-lang/noir/issues/1183). - -## Example - -Without the `distinct` keyword, the following program - -```rust -fn main(x : pub Field, y : pub Field) -> pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - "return_witnesses": [3, 2, 4, 4] - } -} -``` - -Whereas (with the `distinct` keyword) - -```rust -fn main(x : pub Field, y : pub Field) -> distinct pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - //... - "return_witnesses": [3, 4, 5, 6] - } -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/11_shadowing.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/11_shadowing.md deleted file mode 100644 index efd743e764f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/11_shadowing.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Shadowing ---- - -Noir allows for inheriting variables' values and re-declaring them with the same name similar to Rust, known as shadowing. - -For example, the following function is valid in Noir: - -```rust -fn main() { - let x = 5; - - { - let x = x * 2; - assert (x == 10); - } - - assert (x == 5); -} -``` - -In this example, a variable x is first defined with the value 5. - -The local scope that follows shadows the original x, i.e. creates a local mutable x based on the value of the original x. It is given a value of 2 times the original x. - -When we return to the main scope, x once again refers to just the original x, which stays at the value of 5. - -## Temporal mutability - -One way that shadowing is useful, in addition to ergonomics across scopes, is for temporarily mutating variables. - -```rust -fn main() { - let age = 30; - // age = age + 5; // Would error as `age` is immutable by default. - - let mut age = age + 5; // Temporarily mutates `age` with a new value. - - let age = age; // Locks `age`'s mutability again. - - assert (age == 35); -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types.md deleted file mode 100644 index 74f573f7d3f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: Data Types -description: - Get a clear understanding of the two categories of Noir data types - primitive types and compound - types. Learn about their characteristics, differences, and how to use them in your Noir - programming. -keywords: - [ - noir, - data types, - primitive types, - compound types, - private types, - public types, - ] ---- - -Every value in Noir has a type, which determines which operations are valid for it. - -All values in Noir are fundamentally composed of `Field` elements. For a more approachable -developing experience, abstractions are added on top to introduce different data types in Noir. - -Noir has two category of data types: primitive types (e.g. `Field`, integers, `bool`) and compound -types that group primitive types (e.g. arrays, tuples, structs). Each value can either be private or -public. - -## Private & Public Types - -A **private value** is known only to the Prover, while a **public value** is known by both the -Prover and Verifier. Mark values as `private` when the value should only be known to the prover. All -primitive types (including individual fields of compound types) in Noir are private by default, and -can be marked public when certain values are intended to be revealed to the Verifier. - -> **Note:** For public values defined in Noir programs paired with smart contract verifiers, once -> the proofs are verified on-chain the values can be considered known to everyone that has access to -> that blockchain. - -Public data types are treated no differently to private types apart from the fact that their values -will be revealed in proofs generated. Simply changing the value of a public type will not change the -circuit (where the same goes for changing values of private types as well). - -_Private values_ are also referred to as _witnesses_ sometimes. - -> **Note:** The terms private and public when applied to a type (e.g. `pub Field`) have a different -> meaning than when applied to a function (e.g. `pub fn foo() {}`). -> -> The former is a visibility modifier for the Prover to interpret if a value should be made known to -> the Verifier, while the latter is a visibility modifier for the compiler to interpret if a -> function should be made accessible to external Noir programs like in other languages. - -### pub Modifier - -All data types in Noir are private by default. Types are explicitly declared as public using the -`pub` modifier: - -```rust -fn main(x : Field, y : pub Field) -> pub Field { - x + y -} -``` - -In this example, `x` is **private** while `y` and `x + y` (the return value) are **public**. Note -that visibility is handled **per variable**, so it is perfectly valid to have one input that is -private and another that is public. - -> **Note:** Public types can only be declared through parameters on `main`. - -## Type Aliases - -A type alias is a new name for an existing type. Type aliases are declared with the keyword `type`: - -```rust -type Id = u8; - -fn main() { - let id: Id = 1; - let zero: u8 = 0; - assert(zero + 1 == id); -} -``` - -Type aliases can also be used with [generics](./06_generics.md): - -```rust -type Id = Size; - -fn main() { - let id: Id = 1; - let zero: u32 = 0; - assert(zero + 1 == id); -} -``` - -### BigInt - -You can achieve BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/00_fields.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/00_fields.md deleted file mode 100644 index 78d3d2af166..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/00_fields.md +++ /dev/null @@ -1,165 +0,0 @@ ---- -title: Fields -description: - Dive deep into the Field data type in Noir. Understand its methods, practical examples, and best practices to effectively use Fields in your Noir programs. -keywords: - [ - noir, - field type, - methods, - examples, - best practices, - ] ---- - -The field type corresponds to the native field type of the proving backend. - -The size of a Noir field depends on the elliptic curve's finite field for the proving backend -adopted. For example, a field would be a 254-bit integer when paired with the default backend that -spans the Grumpkin curve. - -Fields support integer arithmetic and are often used as the default numeric type in Noir: - -```rust -fn main(x : Field, y : Field) { - let z = x + y; -} -``` - -`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new -private value `z` constrained to be equal to `x + y`. - -If proving efficiency is of priority, fields should be used as a default for solving problems. -Smaller integer types (e.g. `u64`) incur extra range constraints. - -## Methods - -After declaring a Field, you can use these common methods on it: - -### to_le_bits - -Transforms the field into an array of bits, Little Endian. - -```rust -fn to_le_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_le_bits(32); -} -``` - -### to_be_bits - -Transforms the field into an array of bits, Big Endian. - -```rust -fn to_be_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_be_bits(32); -} -``` - -### to_le_bytes - -Transforms into an array of bytes, Little Endian - -```rust -fn to_le_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_le_bytes(4); -} -``` - -### to_be_bytes - -Transforms into an array of bytes, Big Endian - -```rust -fn to_be_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_be_bytes(4); -} -``` - -### to_le_radix - -Decomposes into a vector over the specified base, Little Endian - -```rust -fn to_le_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_le_radix(256, 4); -} -``` - -### to_be_radix - -Decomposes into a vector over the specified base, Big Endian - -```rust -fn to_be_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_be_radix(256, 4); -} -``` - -### pow_32 - -Returns the value to the power of the specified exponent - -```rust -fn pow_32(self, exponent: Field) -> Field -``` - -example: - -```rust -fn main() { - let field = 2 - let pow = field.pow_32(4); - assert(pow == 16); -} -``` - -### sgn0 - -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. - -```rust -fn sgn0(self) -> u1 -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/01_integers.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/01_integers.md deleted file mode 100644 index 1814365800a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/01_integers.md +++ /dev/null @@ -1,112 +0,0 @@ ---- -title: Integers -description: Explore the Integer data type in Noir. Learn about its methods, see real-world examples, and grasp how to efficiently use Integers in your Noir code. -keywords: [noir, integer types, methods, examples, arithmetic] ---- - -An integer type is a range constrained field type. The Noir frontend supports arbitrarily-sized, both unsigned and signed integer types. - -:::info - -When an integer is defined in Noir without a specific type, it will default to `Field`. - -The one exception is for loop indices which default to `u64` since comparisons on `Field`s are not possible. - -::: - -## Unsigned Integers - -An unsigned integer type is specified first with the letter `u` (indicating its unsigned nature) followed by its bit size (e.g. `8`): - -```rust -fn main() { - let x: u8 = 1; - let y: u8 = 1; - let z = x + y; - assert (z == 2); -} -``` - -The bit size determines the maximum value the integer type can store. For example, a `u8` variable can store a value in the range of 0 to 255 (i.e. $\\2^{8}-1\\$). - -## Signed Integers - -A signed integer type is specified first with the letter `i` (which stands for integer) followed by its bit size (e.g. `8`): - -```rust -fn main() { - let x: i8 = -1; - let y: i8 = -1; - let z = x + y; - assert (z == -2); -} -``` - -The bit size determines the maximum and minimum range of value the integer type can store. For example, an `i8` variable can store a value in the range of -128 to 127 (i.e. $\\-2^{7}\\$ to $\\2^{7}-1\\$). - -:::tip - -If you are using the default proving backend with Noir, both even (e.g. _u2_, _i2_) and odd (e.g. _u3_, _i3_) arbitrarily-sized integer types up to 127 bits (i.e. _u127_ and _i127_) are supported. - -::: - -## Overflows - -Computations that exceed the type boundaries will result in overflow errors. This happens with both signed and unsigned integers. For example, attempting to prove: - -```rust -fn main(x: u8, y: u8) { - let z = x + y; -} -``` - -With: - -```toml -x = "255" -y = "1" -``` - -Would result in: - -``` -$ nargo prove -error: Assertion failed: 'attempt to add with overflow' -┌─ ~/src/main.nr:9:13 -│ -│ let z = x + y; -│ ----- -│ -= Call stack: - ... -``` - -A similar error would happen with signed integers: - -```rust -fn main() { - let x: i8 = -118; - let y: i8 = -11; - let z = x + y; -} -``` - -### Wrapping methods - -Although integer overflow is expected to error, some use-cases rely on wrapping. For these use-cases, the standard library provides `wrapping` variants of certain common operations: - -```rust -fn wrapping_add(x: T, y: T) -> T; -fn wrapping_sub(x: T, y: T) -> T; -fn wrapping_mul(x: T, y: T) -> T; -``` - -Example of how it is used: - -```rust -use dep::std; - -fn main(x: u8, y: u8) -> pub u8 { - std::wrapping_add(x, y) -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/02_booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/02_booleans.md deleted file mode 100644 index 67baa00f930..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/02_booleans.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: Booleans -description: - Delve into the Boolean data type in Noir. Understand its methods, practical examples, and best practices for using Booleans in your Noir programs. -keywords: - [ - noir, - boolean type, - methods, - examples, - logical operations, - ] ---- - - -The `bool` type in Noir has two possible values: `true` and `false`: - -```rust -fn main() { - let t = true; - let f: bool = false; -} -``` - -> **Note:** When returning a boolean value, it will show up as a value of 1 for `true` and 0 for -> `false` in _Verifier.toml_. - -The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../02_control_flow.md) and -[Assert Function](../04_assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/03_strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/03_strings.md deleted file mode 100644 index baa3f205094..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/03_strings.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -title: Strings -description: - Discover the String data type in Noir. Learn about its methods, see real-world examples, and understand how to effectively manipulate and use Strings in Noir. -keywords: - [ - noir, - string type, - methods, - examples, - concatenation, - ] ---- - - -The string type is a fixed length value defined with `str`. - -You can use strings in `assert()` functions or print them with `std::println()`. See more about [Logging](../../standard_library/logging.md). - -```rust -use dep::std; - -fn main(message : pub str<11>, hex_as_string : str<4>) { - std::println(message); - assert(message == "hello world"); - assert(hex_as_string == "0x41"); -} -``` - -You can convert a `str` to a byte array by calling `as_bytes()` -or a vector by calling `as_bytes_vec()`. - -```rust -fn main() { - let message = "hello world"; - let message_bytes = message.as_bytes(); - let mut message_vec = message.as_bytes_vec(); - assert(message_bytes.len() == 11); - assert(message_bytes[0] == 104); - assert(message_bytes[0] == message_vec.get(0)); -} -``` - -## Escape Characters - -You can use escape characters for your strings: - -| Escape Sequence | Description | -|-----------------|-----------------| -| `\r` | Carriage Return | -| `\n` | Newline | -| `\t` | Tab | -| `\0` | Null Character | -| `\"` | Double Quote | -| `\\` | Backslash | - -Example: - -```rust -let s = "Hello \"world"; // prints "Hello "world" -let s = "hey \tyou"; // prints "hey you" -``` - -## Formatted Strings - -You can prepend a string with the singular `f` token to create a formatted string. This is useful when logging, as it allows injection of local variables: - -```rust -let var = 15; -std::println(f"var {var}") // prints "var 0x0F" - -let var = -1 as u8; -std::println(f"var {var}") // prints "var 255" - -let var : i8 = -1; -std::println(f"var {var}") // prints "var -1" - -// prints "Hello -//world" -std::println(f"Hello -world"); - -std::println(f"hey \tyou"); // prints "hey \tyou" -``` - -A type can be specified to print numbers either as hex via `Field`, unsigned via `u*` types and signed via `i*` types. - -Note that escaped characters in formatted strings `fmtstr` will be outputted as defined, i.e. "\n" will be printed `\n`, not as a new line. You can add a newline or other whitespace by creating a multiline string as in the example above. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/04_arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/04_arrays.md deleted file mode 100644 index 36410468ec1..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/04_arrays.md +++ /dev/null @@ -1,244 +0,0 @@ ---- -title: Arrays -description: - Dive into the Array data type in Noir. Grasp its methods, practical examples, and best practices for efficiently using Arrays in your Noir code. -keywords: - [ - noir, - array type, - methods, - examples, - indexing, - ] ---- - -An array is one way of grouping together values into one compound type. Array types can be inferred -or explicitly specified via the syntax `[; ]`: - -```rust -fn main(x : Field, y : Field) { - let my_arr = [x, y]; - let your_arr: [Field; 2] = [x, y]; -} -``` - -Here, both `my_arr` and `your_arr` are instantiated as an array containing two `Field` elements. - -Array elements can be accessed using indexing: - -```rust -fn main() { - let a = [1, 2, 3, 4, 5]; - - let first = a[0]; - let second = a[1]; -} -``` - -All elements in an array must be of the same type (i.e. homogeneous). That is, an array cannot group -a `Field` value and a `u8` value together for example. - -You can write mutable arrays, like: - -```rust -fn main() { - let mut arr = [1, 2, 3, 4, 5]; - assert(arr[0] == 1); - - arr[0] = 42; - assert(arr[0] == 42); -} -``` - -You can instantiate a new array of a fixed size with the same value repeated for each element. The following example instantiates an array of length 32 where each element is of type Field and has the value 0. - -```rust -let array: [Field; 32] = [0; 32]; -``` - -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./05_slices.mdx), you can just call `as_slice` on your array: - -```rust -let array: [Field; 32] = [0; 32]; -let sl = array.as_slice() -``` - -You can define multidimensional arrays: - -```rust -let array : [[Field; 2]; 2]; -let element = array[0][0]; -``` - -## Types - -You can create arrays of primitive types or structs. There is not yet support for nested arrays -(arrays of arrays) or arrays of structs that contain arrays. - -## Methods - -For convenience, the STD provides some ready-to-use, common methods for arrays: - -### len - -Returns the length of an array - -```rust -fn len(_array: [T; N]) -> comptime Field -``` - -example - -```rust -fn main() { - let array = [42, 42]; - assert(array.len() == 2); -} -``` - -### sort - -Returns a new sorted array. The original array remains untouched. Notice that this function will -only work for arrays of fields or integers, not for any arbitrary type. This is because the sorting -logic it uses internally is optimized specifically for these values. If you need a sort function to -sort any type, you should use the function `sort_via` described below. - -```rust -fn sort(_array: [T; N]) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32]; - let sorted = arr.sort(); - assert(sorted == [32, 42]); -} -``` - -### sort_via - -Sorts the array with a custom comparison function - -```rust -fn sort_via(mut a: [T; N], ordering: fn(T, T) -> bool) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32] - let sorted_ascending = arr.sort_via(|a, b| a <= b); - assert(sorted_ascending == [32, 42]); // verifies - - let sorted_descending = arr.sort_via(|a, b| a >= b); - assert(sorted_descending == [32, 42]); // does not verify -} -``` - -### map - -Applies a function to each element of the array, returning a new array containing the mapped elements. - -```rust -fn map(f: fn(T) -> U) -> [U; N] -``` - -example - -```rust -let a = [1, 2, 3]; -let b = a.map(|a| a * 2); // b is now [2, 4, 6] -``` - -### fold - -Applies a function to each element of the array, returning the final accumulated value. The first -parameter is the initial value. - -```rust -fn fold(mut accumulator: U, f: fn(U, T) -> U) -> U -``` - -This is a left fold, so the given function will be applied to the accumulator and first element of -the array, then the second, and so on. For a given call the expected result would be equivalent to: - -```rust -let a1 = [1]; -let a2 = [1, 2]; -let a3 = [1, 2, 3]; - -let f = |a, b| a - b; -a1.fold(10, f) //=> f(10, 1) -a2.fold(10, f) //=> f(f(10, 1), 2) -a3.fold(10, f) //=> f(f(f(10, 1), 2), 3) -``` - -example: - -```rust - -fn main() { - let arr = [2, 2, 2, 2, 2]; - let folded = arr.fold(0, |a, b| a + b); - assert(folded == 10); -} - -``` - -### reduce - -Same as fold, but uses the first element as starting element. - -```rust -fn reduce(f: fn(T, T) -> T) -> T -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let reduced = arr.reduce(|a, b| a + b); - assert(reduced == 10); -} -``` - -### all - -Returns true if all the elements satisfy the given predicate - -```rust -fn all(predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let all = arr.all(|a| a == 2); - assert(all); -} -``` - -### any - -Returns true if any of the elements satisfy the given predicate - -```rust -fn any(predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 5]; - let any = arr.any(|a| a == 5); - assert(any); -} - -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/05_slices.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/05_slices.mdx deleted file mode 100644 index 1be0ec4a137..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/05_slices.mdx +++ /dev/null @@ -1,146 +0,0 @@ ---- -title: Slices -description: Explore the Slice data type in Noir. Understand its methods, see real-world examples, and learn how to effectively use Slices in your Noir programs. -keywords: [noir, slice type, methods, examples, subarrays] ---- - -import Experimental from '@site/src/components/Notes/_experimental.mdx'; - - - -A slice is a dynamically-sized view into a sequence of elements. They can be resized at runtime, but because they don't own the data, they cannot be returned from a circuit. You can treat slices as arrays without a constrained size. - -```rust -use dep::std::slice; - -fn main() -> pub Field { - let mut slice: [Field] = [0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -View the corresponding test file [here][test-file]. - -[test-file]: https://github.com/noir-lang/noir/blob/f387ec1475129732f72ba294877efdf6857135ac/crates/nargo_cli/tests/test_data_ssa_refactor/slices/src/main.nr - -## Methods - -For convenience, the STD provides some ready-to-use, common methods for slices: - -### push_back - -Pushes a new element to the end of the slice, returning a new slice with a length one greater than the original unmodified slice. - -```rust -fn push_back(_self: [T], _elem: T) -> [T] -``` - -example: - -```rust -fn main() -> pub Field { - let mut slice: [Field] = [0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -View the corresponding test file [here][test-file]. - -### push_front - -Returns a new array with the specified element inserted at index 0. The existing elements indexes are incremented by 1. - -```rust -fn push_front(_self: Self, _elem: T) -> Self -``` - -Example: - -```rust -let mut new_slice: [Field] = []; -new_slice = new_slice.push_front(20); -assert(new_slice[0] == 20); // returns true -``` - -View the corresponding test file [here][test-file]. - -### pop_front - -Returns a tuple of two items, the first element of the array and the rest of the array. - -```rust -fn pop_front(_self: Self) -> (T, Self) -``` - -Example: - -```rust -let (first_elem, rest_of_slice) = slice.pop_front(); -``` - -View the corresponding test file [here][test-file]. - -### pop_back - -Returns a tuple of two items, the beginning of the array with the last element omitted and the last element. - -```rust -fn pop_back(_self: Self) -> (Self, T) -``` - -Example: - -```rust -let (popped_slice, last_elem) = slice.pop_back(); -``` - -View the corresponding test file [here][test-file]. - -### append - -Loops over a slice and adds it to the end of another. - -```rust -fn append(mut self, other: Self) -> Self -``` - -Example: - -```rust -let append = [1, 2].append([3, 4, 5]); -``` - -### insert - -Inserts an element at a specified index and shifts all following elements by 1. - -```rust -fn insert(_self: Self, _index: Field, _elem: T) -> Self -``` - -Example: - -```rust -new_slice = rest_of_slice.insert(2, 100); -assert(new_slice[2] == 100); -``` - -View the corresponding test file [here][test-file]. - -### remove - -Remove an element at a specified index, shifting all elements after it to the left, returning the altered slice and the removed element. - -```rust -fn remove(_self: Self, _index: Field) -> (Self, T) -``` - -Example: - -```rust -let (remove_slice, removed_elem) = slice.remove(3); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/06_vectors.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/06_vectors.mdx deleted file mode 100644 index 4617e90d038..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/06_vectors.mdx +++ /dev/null @@ -1,172 +0,0 @@ ---- -title: Vectors -description: Delve into the Vector data type in Noir. Learn about its methods, practical examples, and best practices for using Vectors in your Noir code. -keywords: [noir, vector type, methods, examples, dynamic arrays] ---- - -import Experimental from '@site/src/components/Notes/_experimental.mdx'; - - - -A vector is a collection type similar to Rust's Vector type. It's convenient way to use slices as mutable arrays. - -Example: - -```rust -use dep::std::collections::vec::Vec; - -let mut vector: Vec = Vec::new(); -for i in 0..5 { - vector.push(i); -} -assert(vector.len() == 5); -``` - -## Methods - -### new - -Creates a new, empty vector. - -```rust -pub fn new() -> Self { - Self { slice: [] } -} -``` - -Example: - -```rust -let empty_vector: Vec = Vec::new(); -assert(empty_vector.len() == 0); -``` - -### from_slice - -Creates a vector containing each element from a given slice. Mutations to the resulting vector will not affect the original slice. - -```rust -pub fn from_slice(slice: [T]) -> Self { - Self { slice } -} -``` - -Example: - -```rust -let arr: [Field] = [1, 2, 3]; -let vector_from_slice = Vec::from_slice(arr); -assert(vector_from_slice.len() == 3); -``` - -### get - -Retrieves an element from the vector at a given index. Panics if the index points beyond the vector's end. - -```rust -pub fn get(self, index: Field) -> T { - self.slice[index] -} -``` - -Example: - -```rust -let vector: Vec = Vec::from_slice([10, 20, 30]); -assert(vector.get(1) == 20); -``` - -### push - -Adds a new element to the vector's end, returning a new vector with a length one greater than the original unmodified vector. - -```rust -pub fn push(&mut self, elem: T) { - self.slice = self.slice.push_back(elem); -} -``` - -Example: - -```rust -let mut vector: Vec = Vec::new(); -vector.push(10); -assert(vector.len() == 1); -``` - -### pop - -Removes an element from the vector's end, returning a new vector with a length one less than the original vector, along with the removed element. Panics if the vector's length is zero. - -```rust -pub fn pop(&mut self) -> T { - let (popped_slice, last_elem) = self.slice.pop_back(); - self.slice = popped_slice; - last_elem -} -``` - -Example: - -```rust -let mut vector = Vec::from_slice([10, 20]); -let popped_elem = vector.pop(); -assert(popped_elem == 20); -assert(vector.len() == 1); -``` - -### insert - -Inserts an element at a specified index, shifting subsequent elements to the right. - -```rust -pub fn insert(&mut self, index: Field, elem: T) { - self.slice = self.slice.insert(index, elem); -} -``` - -Example: - -```rust -let mut vector = Vec::from_slice([10, 30]); -vector.insert(1, 20); -assert(vector.get(1) == 20); -``` - -### remove - -Removes an element at a specified index, shifting subsequent elements to the left, and returns the removed element. - -```rust -pub fn remove(&mut self, index: Field) -> T { - let (new_slice, elem) = self.slice.remove(index); - self.slice = new_slice; - elem -} -``` - -Example: - -```rust -let mut vector = Vec::from_slice([10, 20, 30]); -let removed_elem = vector.remove(1); -assert(removed_elem == 20); -assert(vector.len() == 2); -``` - -### len - -Returns the number of elements in the vector. - -```rust -pub fn len(self) -> Field { - self.slice.len() -} -``` - -Example: - -```rust -let empty_vector: Vec = Vec::new(); -assert(empty_vector.len() == 0); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/07_tuples.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/07_tuples.md deleted file mode 100644 index 5f6cab974a8..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/07_tuples.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: Tuples -description: - Dive into the Tuple data type in Noir. Understand its methods, practical examples, and best practices for efficiently using Tuples in your Noir code. -keywords: - [ - noir, - tuple type, - methods, - examples, - multi-value containers, - ] ---- - -A tuple collects multiple values like an array, but with the added ability to collect values of -different types: - -```rust -fn main() { - let tup: (u8, u64, Field) = (255, 500, 1000); -} -``` - -One way to access tuple elements is via destructuring using pattern matching: - -```rust -fn main() { - let tup = (1, 2); - - let (one, two) = tup; - - let three = one + two; -} -``` - -Another way to access tuple elements is via direct member access, using a period (`.`) followed by -the index of the element we want to access. Index `0` corresponds to the first tuple element, `1` to -the second and so on: - -```rust -fn main() { - let tup = (5, 6, 7, 8); - - let five = tup.0; - let eight = tup.3; -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/08_structs.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/08_structs.md deleted file mode 100644 index 35421734639..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/08_structs.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -title: Structs -description: - Explore the Struct data type in Noir. Learn about its methods, see real-world examples, and grasp how to effectively define and use Structs in your Noir programs. -keywords: - [ - noir, - struct type, - methods, - examples, - data structures, - ] ---- - -A struct also allows for grouping multiple values of different types. Unlike tuples, we can also -name each field. - -> **Note:** The usage of _field_ here refers to each element of the struct and is unrelated to the -> field type of Noir. - -Defining a struct requires giving it a name and listing each field within as `: ` pairs: - -```rust -struct Animal { - hands: Field, - legs: Field, - eyes: u8, -} -``` - -An instance of a struct can then be created with actual values in `: ` pairs in any -order. Struct fields are accessible using their given names: - -```rust -fn main() { - let legs = 4; - - let dog = Animal { - eyes: 2, - hands: 0, - legs, - }; - - let zero = dog.hands; -} -``` - -Structs can also be destructured in a pattern, binding each field to a new variable: - -```rust -fn main() { - let Animal { hands, legs: feet, eyes } = get_octopus(); - - let ten = hands + feet + eyes as u8; -} - -fn get_octopus() -> Animal { - let octopus = Animal { - hands: 0, - legs: 8, - eyes: 2, - }; - - octopus -} -``` - -The new variables can be bound with names different from the original struct field names, as -showcased in the `legs --> feet` binding in the example above. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/09_references.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/09_references.md deleted file mode 100644 index b0c35ce2cb9..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/09_references.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: References ---- - -Noir supports first-class references. References are a bit like pointers: they point to a specific address that can be followed to access the data stored at that address. You can use Rust-like syntax to use pointers in Noir: the `&` operator references the variable, the `*` operator dereferences it. - -Example: - -```rust -fn main() { - let mut x = 2; - - // you can reference x as &mut and pass it to multiplyBy2 - multiplyBy2(&mut x); -} - -// you can access &mut here -fn multiplyBy2(x: &mut Field) { - // and dereference it with * - *x = *x * 2; -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/10_function_types.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/10_function_types.md deleted file mode 100644 index 1ec92efd594..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/10_function_types.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: Function types ---- - -Noir supports higher-order functions. The syntax for a function type is as follows: - -```rust -fn(arg1_type, arg2_type, ...) -> return_type -``` - -Example: - -```rust -fn assert_returns_100(f: fn() -> Field) { // f takes no args and returns a Field - assert(f() == 100); -} - -fn main() { - assert_returns_100(|| 100); // ok - assert_returns_100(|| 150); // fails -} -``` - -A function type also has an optional capture environment - this is necessary to support closures. -See [Lambdas](../08_lambdas.md) for more details. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/migration_notes.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/migration_notes.md deleted file mode 100644 index 905bca3d30c..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/migration_notes.md +++ /dev/null @@ -1,91 +0,0 @@ ---- -title: Migration notes -description: Read about migration notes from previous versions, which could solve problems while updating -keywords: [Noir, notes, migration, updating, upgrading] ---- - -Noir is in full-speed development. Things break fast, wild, and often. This page attempts to leave some notes on errors you might encounter when upgrading and how to resolve them until proper patches are built. - -## ≥0.19 - -### Enforcing `compiler_version` - -From this version on, the compiler will check for the `compiler_version` field in `Nargo.toml`, and will error if it doesn't match the current Nargo version in use. - -To update, please make sure this field in `Nargo.toml` matches the output of `nargo --version`. - -## ≥0.14 - -The index of the [for loops](./language_concepts/02_control_flow.md#loops) is now of type `u64` instead of `Field`. An example refactor would be: - -```rust -for i in 0..10 { - let i = i as Field; -} -``` - -## ≥v0.11.0 and Nargo backend - -From this version onwards, Nargo starts managing backends through the `nargo backend` command. Upgrading to the versions per usual steps might lead to: - -### `backend encountered an error` - -This is likely due to the existing locally installed version of proving backend (e.g. barretenberg) is incompatible with the version of Nargo in use. - -To fix the issue: - -1. Uninstall the existing backend - -```bash -nargo backend uninstall acvm-backend-barretenberg -``` - -You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. - -2. Reinstall a compatible version of the proving backend. - -If you are using the default barretenberg backend, simply run: - -``` -nargo prove -``` - -with your Noir program. - -This will trigger the download and installation of the latest version of barretenberg compatible with your Nargo in use. - -### `backend encountered an error: illegal instruction` - -On certain Intel-based systems, an `illegal instruction` error may arise due to incompatibility of barretenberg with certain CPU instructions. - -To fix the issue: - -1. Uninstall the existing backend - -```bash -nargo backend uninstall acvm-backend-barretenberg -``` - -You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. - -2. Reinstall a compatible version of the proving backend. - -If you are using the default barretenberg backend, simply run: - -``` -nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/barretenberg-js-binary/raw/master/run-bb.tar.gz -``` - -This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. - -The gzipped file is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. - -Then run: - -``` -DESIRED_BINARY_VERSION=0.8.1 nargo info -``` - -This overrides the bb native binary with a bb.js node application instead, which should be compatible with most if not all hardware. This does come with the drawback of being generally slower than native binary. - -0.8.1 indicates bb.js version 0.8.1, so if you change that it will update to a different version or the default version in the script if none was supplied. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/modules_packages_crates/crates_and_packages.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/modules_packages_crates/crates_and_packages.md deleted file mode 100644 index 23f60855c30..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/modules_packages_crates/crates_and_packages.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Crates and Packages -description: Learn how to use Crates and Packages in your Noir project -keywords: [Nargo, dependencies, package management, crates, package] ---- - -## Crates - -A crate is the smallest amount of code that the Noir compiler considers at a time. -Crates can contain modules, and the modules may be defined in other files that get compiled with the crate, as we’ll see in the coming sections. - -### Crate Types - -A Noir crate can come in several forms: binaries, libraries or contracts. - -#### Binaries - -_Binary crates_ are programs which you can compile to an ACIR circuit which you can then create proofs against. Each must have a function called `main` that defines the ACIR circuit which is to be proved. - -#### Libraries - -_Library crates_ don't have a `main` function and they don't compile down to ACIR. Instead they define functionality intended to be shared with multiple projects, and eventually included in a binary crate. - -#### Contracts - -Contract crates are similar to binary crates in that they compile to ACIR which you can create proofs against. They are different in that they do not have a single `main` function, but are a collection of functions to be deployed to the [Aztec network](https://aztec.network). You can learn more about the technical details of Aztec in the [monorepo](https://github.com/AztecProtocol/aztec-packages) or contract [examples](https://github.com/AztecProtocol/aztec-packages/tree/master/noir-projects/noir-contracts/contracts). - -### Crate Root - -Every crate has a root, which is the source file that the compiler starts, this is also known as the root module. The Noir compiler does not enforce any conditions on the name of the file which is the crate root, however if you are compiling via Nargo the crate root must be called `lib.nr` or `main.nr` for library or binary crates respectively. - -## Packages - -A Nargo _package_ is a collection of one of more crates that provides a set of functionality. A package must include a Nargo.toml file. - -A package _must_ contain either a library or a binary crate, but not both. - -### Differences from Cargo Packages - -One notable difference between Rust's Cargo and Noir's Nargo is that while Cargo allows a package to contain an unlimited number of binary crates and a single library crate, Nargo currently only allows a package to contain a single crate. - -In future this restriction may be lifted to allow a Nargo package to contain both a binary and library crate or multiple binary crates. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/modules_packages_crates/dependencies.md deleted file mode 100644 index 753b6038703..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/modules_packages_crates/dependencies.md +++ /dev/null @@ -1,123 +0,0 @@ ---- -title: Dependencies -description: - Learn how to specify and manage dependencies in Nargo, allowing you to upload packages to GitHub - and use them easily in your project. -keywords: [Nargo, dependencies, GitHub, package management, versioning] ---- - -Nargo allows you to upload packages to GitHub and use them as dependencies. - -## Specifying a dependency - -Specifying a dependency requires a tag to a specific commit and the git url to the url containing -the package. - -Currently, there are no requirements on the tag contents. If requirements are added, it would follow -semver 2.0 guidelines. - -> Note: Without a `tag` , there would be no versioning and dependencies would change each time you -> compile your project. - -For example, to add the [ecrecover-noir library](https://github.com/colinnielsen/ecrecover-noir) to your project, add it to `Nargo.toml`: - -```toml -# Nargo.toml - -[dependencies] -ecrecover = {tag = "v0.8.0", git = "https://github.com/colinnielsen/ecrecover-noir"} -``` - -If the module is in a subdirectory, you can define a subdirectory in your git repository, for example: - -```toml -# Nargo.toml - -[dependencies] -easy_private_token_contract = {tag ="v0.1.0-alpha62", git = "https://github.com/AztecProtocol/aztec-packages", directory = "yarn-project/noir-contracts/contracts/easy_private_token_contract"} -``` - -## Specifying a local dependency - -You can also specify dependencies that are local to your machine. - -For example, this file structure has a library and binary crate - -```tree -├── binary_crate -│   ├── Nargo.toml -│   └── src -│   └── main.nr -└── lib_a - ├── Nargo.toml - └── src - └── lib.nr -``` - -Inside of the binary crate, you can specify: - -```toml -# Nargo.toml - -[dependencies] -lib_a = { path = "../lib_a" } -``` - -## Importing dependencies - -You can import a dependency to a Noir file using the following syntax. For example, to import the -ecrecover-noir library and local lib_a referenced above: - -```rust -use dep::ecrecover; -use dep::lib_a; -``` - -You can also import only the specific parts of dependency that you want to use, like so: - -```rust -use dep::std::hash::sha256; -use dep::std::scalar_mul::fixed_base_embedded_curve; -``` - -Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/04_ec_primitives.md#examples), you -can import multiple items in the same line by enclosing them in curly braces: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; -``` - -We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. - -Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. - -## Dependencies of Dependencies - -Note that when you import a dependency, you also get access to all of the dependencies of that package. - -For example, the [phy_vector](https://github.com/resurgencelabs/phy_vector) library imports an [fraction](https://github.com/resurgencelabs/fraction) library. If you're importing the phy_vector library, then you can access the functions in fractions library like so: - -```rust -use dep::phy_vector; - -fn main(x : Field, y : pub Field) { - //... - let f = phy_vector::fraction::toFraction(true, 2, 1); - //... -} -``` - -## Available Libraries - -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). - -Some libraries that are available today include: - -- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library -- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) -- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers -- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address -- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees -- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir -- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/modules_packages_crates/modules.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/modules_packages_crates/modules.md deleted file mode 100644 index 11e60cbf35e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/modules_packages_crates/modules.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: Modules -description: - Learn how to organize your files using modules in Noir, following the same convention as Rust's - module system. Examples included. -keywords: [Noir, Rust, modules, organizing files, sub-modules] ---- - -Noir's module system follows the same convention as the _newer_ version of Rust's module system. - -## Purpose of Modules - -Modules are used to organize files. Without modules all of your code would need to live in a single -file. In Noir, the compiler does not automatically scan all of your files to detect modules. This -must be done explicitly by the developer. - -## Examples - -### Importing a module in the crate root - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::hello_world(); -} -``` - -Filename : `src/foo.nr` - -```rust -fn from_foo() {} -``` - -In the above snippet, the crate root is the `src/main.nr` file. The compiler sees the module -declaration `mod foo` which prompts it to look for a foo.nr file. - -Visually this module hierarchy looks like the following : - -``` -crate - ├── main - │ - └── foo - └── from_foo - -``` - -### Importing a module throughout the tree - -All modules are accessible from the `crate::` namespace. - -``` -crate - ├── bar - ├── foo - └── main - -``` - -In the above snippet, if `bar` would like to use functions in `foo`, it can do so by `use crate::foo::function_name`. - -### Sub-modules - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::from_foo(); -} -``` - -Filename : `src/foo.nr` - -```rust -mod bar; -fn from_foo() {} -``` - -Filename : `src/foo/bar.nr` - -```rust -fn from_bar() {} -``` - -In the above snippet, we have added an extra module to the module tree; `bar`. `bar` is a submodule -of `foo` hence we declare bar in `foo.nr` with `mod bar`. Since `foo` is not the crate root, the -compiler looks for the file associated with the `bar` module in `src/foo/bar.nr` - -Visually the module hierarchy looks as follows: - -``` -crate - ├── main - │ - └── foo - ├── from_foo - └── bar - └── from_bar -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/modules_packages_crates/workspaces.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/modules_packages_crates/workspaces.md deleted file mode 100644 index 8168793fc80..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/modules_packages_crates/workspaces.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -title: Workspaces ---- - -Workspaces are a feature of nargo that allow you to manage multiple related Noir packages in a single repository. A workspace is essentially a group of related projects that share common build output directories and configurations. - -Each Noir project (with it's own Nargo.toml file) can be thought of as a package. Each package is expected to contain exactly one "named circuit", being the "name" defined in Nargo.toml with the program logic defined in `./src/main.nr`. - -For a project with the following structure: - -```tree -├── crates -│ ├── a -│ │ ├── Nargo.toml -│ │ └── Prover.toml -│ │ └── src -│ │ └── main.nr -│ └── b -│ ├── Nargo.toml -│ └── Prover.toml -│ └── src -│ └── main.nr -│ -└── Nargo.toml -``` - -You can define a workspace in Nargo.toml like so: - -```toml -[workspace] -members = ["crates/a", "crates/b"] -default-member = "crates/a" -``` - -`members` indicates which packages are included in the workspace. As such, all member packages of a workspace will be processed when the `--workspace` flag is used with various commands or if a `default-member` is not specified. - -`default-member` indicates which package various commands process by default. - -Libraries can be defined in a workspace. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. - -Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/nargo/01_commands.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/nargo/01_commands.md deleted file mode 100644 index 914856a0f43..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/nargo/01_commands.md +++ /dev/null @@ -1,250 +0,0 @@ ---- -title: Commands -description: - Noir CLI Commands for Noir Prover and Verifier to create, execute, prove and verify programs, - generate Solidity verifier smart contract and compile into JSON file containing ACIR - representation and ABI of circuit. -keywords: - [ - Nargo, - Noir CLI, - Noir Prover, - Noir Verifier, - generate Solidity verifier, - compile JSON file, - ACIR representation, - ABI of circuit, - TypeScript, - ] ---- - -## General options - -| Option | Description | -| -------------------- | -------------------------------------------------- | -| `--show-ssa` | Emit debug information for the intermediate SSA IR | -| `--deny-warnings` | Quit execution when warnings are emitted | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo help [subcommand]` - -Prints the list of available commands or specific information of a subcommand. - -_Arguments_ - -| Argument | Description | -| -------------- | -------------------------------------------- | -| `` | The subcommand whose help message to display | - -## `nargo backend` - -Installs and selects custom backends used to generate and verify proofs. - -### Commands - -| Command | Description | -| ----------- | --------------------------------------------------------- | -| `current` | Prints the name of the currently active backend | -| `ls` | Prints the list of currently installed backends | -| `use` | Select the backend to use | -| `install` | Install a new backend from a URL | -| `uninstall` | Uninstalls a backend | -| `help` | Print this message or the help of the given subcommand(s) | - -### Options - -| Option | Description | -| ------------ | ----------- | -| `-h, --help` | Print help | - -## `nargo check` - -Generate the `Prover.toml` and `Verifier.toml` files for specifying prover and verifier in/output -values of the Noir program respectively. - -### Options - -| Option | Description | -| --------------------- | ------------------------------------- | -| `--package ` | The name of the package to check | -| `--workspace` | Check all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -### `nargo codegen-verifier` - -Generate a Solidity verifier smart contract for the program. - -### Options - -| Option | Description | -| --------------------- | ------------------------------------- | -| `--package ` | The name of the package to codegen | -| `--workspace` | Codegen all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo compile` - -Compile the program into a JSON build artifact file containing the ACIR representation and the ABI -of the circuit. This build artifact can then be used to generate and verify proofs. - -You can also use "build" as an alias for compile (e.g. `nargo build`). - -### Options - -| Option | Description | -| --------------------- | ------------------------------------------------------------ | -| `--include-keys` | Include Proving and Verification keys in the build artifacts | -| `--package ` | The name of the package to compile | -| `--workspace` | Compile all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo new ` - -Creates a new Noir project in a new folder. - -**Arguments** - -| Argument | Description | -| -------- | -------------------------------- | -| `` | The path to save the new project | - -### Options - -| Option | Description | -| --------------- | ----------------------------------------------------- | -| `--name ` | Name of the package [default: package directory name] | -| `--lib` | Use a library template | -| `--bin` | Use a binary template [default] | -| `--contract` | Use a contract template | -| `-h, --help` | Print help | - -## `nargo init` - -Creates a new Noir project in the current directory. - -### Options - -| Option | Description | -| --------------- | ----------------------------------------------------- | -| `--name ` | Name of the package [default: current directory name] | -| `--lib` | Use a library template | -| `--bin` | Use a binary template [default] | -| `--contract` | Use a contract template | -| `-h, --help` | Print help | - -## `nargo execute [WITNESS_NAME]` - -Runs the Noir program and prints its return value. - -**Arguments** - -| Argument | Description | -| ---------------- | ----------------------------------------- | -| `[WITNESS_NAME]` | Write the execution witness to named file | - -### Options - -| Option | Description | -| --------------------------------- | ------------------------------------------------------------------------------------ | -| `-p, --prover-name ` | The name of the toml file which contains the inputs for the prover [default: Prover] | -| `--package ` | The name of the package to execute | -| `--workspace` | Execute all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -_Usage_ - -The inputs to the circuit are read from the `Prover.toml` file generated by `nargo check`, which -must be filled in. - -To save the witness to file, run the command with a value for the `WITNESS_NAME` argument. A -`.tr` file will then be saved in the `./target` folder. - -## `nargo prove` - -Creates a proof for the program. - -### Options - -| Option | Description | -| ------------------------------------- | ---------------------------------------------------------------------------------------- | -| `-p, --prover-name ` | The name of the toml file which contains the inputs for the prover [default: Prover] | -| `-v, --verifier-name ` | The name of the toml file which contains the inputs for the verifier [default: Verifier] | -| `--verify` | Verify proof after proving | -| `--package ` | The name of the package to prove | -| `--workspace` | Prove all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo verify` - -Given a proof and a program, verify whether the proof is valid. - -### Options - -| Option | Description | -| ------------------------------------- | ---------------------------------------------------------------------------------------- | -| `-v, --verifier-name ` | The name of the toml file which contains the inputs for the verifier [default: Verifier] | -| `--package ` | The name of the package to verify | -| `--workspace` | Verify all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo test [TEST_NAME]` - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. To print `println` statements in tests, use the `--show-output` flag. - -Takes an optional `--exact` flag which allows you to select tests based on an exact name. - -See an example on the [testing page](./02_testing.md). - -### Options - -| Option | Description | -| --------------------- | -------------------------------------- | -| `--show-output` | Display output of `println` statements | -| `--exact` | Only run tests that match exactly | -| `--package ` | The name of the package to test | -| `--workspace` | Test all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo info` - -Prints a table containing the information of the package. - -Currently the table provide - -1. The number of ACIR opcodes -2. The final number gates in the circuit used by a backend - -If the file contains a contract the table will provide the -above information about each function of the contract. - -## `nargo lsp` - -Start a long-running Language Server process that communicates over stdin/stdout. -Usually this command is not run by a user, but instead will be run by a Language Client, such as [vscode-noir](https://github.com/noir-lang/vscode-noir). - -## `nargo fmt` - -Automatically formats your Noir source code based on the default formatting settings. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/nargo/02_testing.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/nargo/02_testing.md deleted file mode 100644 index 5c57ef92705..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/nargo/02_testing.md +++ /dev/null @@ -1,61 +0,0 @@ ---- -title: Testing in Noir -description: Learn how to use Nargo to test your Noir program in a quick and easy way -keywords: [Nargo, testing, Noir, compile, test] ---- - -You can test your Noir programs using Noir circuits. - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. - -For example if you have a program like: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test] -fn test_add() { - assert(add(2,2) == 4); - assert(add(0,1) == 1); - assert(add(1,0) == 1); -} -``` - -Running `nargo test` will test that the `test_add` function can be executed while satisfying all -the constraints which allows you to test that add returns the expected values. Test functions can't -have any arguments currently. - -### Test fail - -You can write tests that are expected to fail by using the decorator `#[test(should_fail)]`. For example: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test(should_fail)] -fn test_add() { - assert(add(2,2) == 5); -} -``` - -You can be more specific and make it fail with a specific reason by using `should_fail_with = "`: - -```rust -fn main(african_swallow_avg_speed : Field) { - assert(african_swallow_avg_speed == 65, "What is the airspeed velocity of an unladen swallow"); -} - -#[test] -fn test_king_arthur() { - main(65); -} - -#[test(should_fail_with = "What is the airspeed velocity of an unladen swallow")] -fn test_bridgekeeper() { - main(32); -} - -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/nargo/03_solidity_verifier.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/nargo/03_solidity_verifier.md deleted file mode 100644 index 9ac60cb0ba7..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/nargo/03_solidity_verifier.md +++ /dev/null @@ -1,129 +0,0 @@ ---- -title: Solidity Verifier -description: - Learn how to run the verifier as a smart contract on the blockchain. Compile a Solidity verifier - contract for your Noir program and deploy it on any EVM blockchain acting as a verifier smart - contract. Read more to find out! -keywords: - [ - solidity verifier, - smart contract, - blockchain, - compiler, - plonk_vk.sol, - EVM blockchain, - verifying Noir programs, - proving backend, - Barretenberg, - ] ---- - -For certain applications, it may be desirable to run the verifier as a smart contract instead of on -a local machine. - -Compile a Solidity verifier contract for your Noir program by running: - -```sh -nargo codegen-verifier -``` - -A new `contract` folder would then be generated in your project directory, containing the Solidity -file `plonk_vk.sol`. It can be deployed on any EVM blockchain acting as a verifier smart contract. - -> **Note:** It is possible to compile verifier contracts of Noir programs for other smart contract -> platforms as long as the proving backend supplies an implementation. -> -> Barretenberg, the default proving backend for Nargo, supports compilation of verifier contracts in -> Solidity only for the time being. - -## Verify - -To verify a proof using the Solidity verifier contract, call the `verify` function with the -following signature: - -```solidity -function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) -``` - -You can see an example of how the `verify` function is called in the example zk voting application [here](https://github.com/noir-lang/noir-examples/blob/33e598c257e2402ea3a6b68dd4c5ad492bce1b0a/foundry-voting/src/zkVote.sol#L35): - -```solidity -function castVote(bytes calldata proof, uint proposalId, uint vote, bytes32 nullifierHash) public returns (bool) { - // ... - bytes32[] memory publicInputs = new bytes32[](4); - publicInputs[0] = merkleRoot; - publicInputs[1] = bytes32(proposalId); - publicInputs[2] = bytes32(vote); - publicInputs[3] = nullifierHash; - require(verifier.verify(proof, publicInputs), "Invalid proof"); -``` - -### Public Inputs - -:::tip - -A circuit doesn't have the concept of a return value. Return values are just syntactic sugar in -Noir. - -Under the hood, the return value is passed as an input to the circuit and is checked at the end of -the circuit program. - -::: - -The verifier contract uses the output (return) value of a Noir program as a public input. So if you -have the following function - -```rust -fn main( - // Public inputs - pubkey_x: pub Field, - pubkey_y: pub Field, - // Private inputs - priv_key: Field, -) -> pub Field -``` - -then `verify` in `plonk_vk.sol` will expect 3 public inputs. Passing two inputs will result in an -error like `Reason: PUBLIC_INPUT_COUNT_INVALID(3, 2)`. - -In this case the 3 inputs to `verify` would be ordered as `[pubkey_x, pubkey_y, return]`. - -#### Struct inputs - -Consider the following program: - -```rust -struct Type1 { - val1: Field, - val2: Field, -} - -struct Nested { - t1: Type1, - is_true: bool, -} - -fn main(x: pub Field, nested: pub Nested, y: pub Field) { - //... -} -``` - -Structs will be flattened so that the array of inputs is 1-dimensional array. The order of these inputs would be flattened to: `[x, nested.t1.val1, nested.t1.val2, nested.is_true, y]` - -## Noir for EVM chains - -You can currently deploy the Solidity verifier contracts to most EVM compatible chains. EVM chains that have been tested and are known to work include: - -- Optimism -- Arbitrum -- Polygon PoS -- Scroll -- Celo - -Other EVM chains should work, but have not been tested directly by our team. If you test any other chains, please open a PR on this page to update the list. See [this doc](https://github.com/noir-lang/noir-starter/tree/main/with-foundry#testing-on-chain) for more info about testing verifier contracts on different EVM chains. - -### Unsupported chains - -Unfortunately not all "EVM" chains are supported. - -**zkSync** and the **Polygon zkEVM** do _not_ currently support proof verification via Solidity verifier contracts. They are missing the bn256 precompile contract that the verifier contract requires. Once these chains support this precompile, they may work. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/nargo/04_language_server.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/nargo/04_language_server.md deleted file mode 100644 index 48c01465f6e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/nargo/04_language_server.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Language Server -description: Learn about the Noir Language Server, how to install the components, and configuration that may be required. -keywords: [Nargo, Language Server, LSP, VSCode, Visual Studio Code] ---- - -This section helps you install and configure the Noir Language Server. - -The Language Server Protocol (LSP) has two components, the [Server](#language-server) and the [Client](#language-client). Below we describe each in the context of Noir. - -## Language Server - -The Server component is provided by the Nargo command line tool that you installed at the beginning of this guide. -As long as Nargo is installed and you've used it to run other commands in this guide, it should be good to go! - -If you'd like to verify that the `nargo lsp` command is available, you can run `nargo --help` and look for `lsp` in the list of commands. If you see it, you're using a version of Noir with LSP support. - -## Language Client - -The Client component is usually an editor plugin that launches the Server. It communicates LSP messages between the editor and the Server. For example, when you save a file, the Client will alert the Server, so it can try to compile the project and report any errors. - -Currently, Noir provides a Language Client for Visual Studio Code via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). - -> **Note:** Noir's Language Server Protocol support currently assumes users' VSCode workspace root to be the same as users' Noir project root (i.e. where Nargo.toml lies). -> -> If LSP features seem to be missing / malfunctioning, make sure you are opening your Noir project directly (instead of as a sub-folder) in your VSCode instance. - -When your language server is running correctly and the VSCode plugin is installed, you should see handy codelens buttons for compilation, measuring circuit size, execution, and tests: - -![Compile and Execute](@site/static/img/codelens_compile_execute.png) -![Run test](@site/static/img/codelens_run_test.png) - -You should also see your tests in the `testing` panel: - -![Testing panel](@site/static/img/codelens_testing_panel.png) - -### Configuration - -- **Noir: Enable LSP** - If checked, the extension will launch the Language Server via `nargo lsp` and communicate with it. -- **Noir: Nargo Flags** - Additional flags may be specified if you require them to be added when the extension calls `nargo lsp`. -- **Noir: Nargo Path** - An absolute path to a Nargo binary with the `lsp` command. This may be useful if Nargo is not within the `PATH` of your editor. -- **Noir > Trace: Server** - Setting this to `"messages"` or `"verbose"` will log LSP messages between the Client and Server. Useful for debugging. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/getting_started/01_tiny_noir_app.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/getting_started/01_tiny_noir_app.md deleted file mode 100644 index 64ba4a2c44a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/getting_started/01_tiny_noir_app.md +++ /dev/null @@ -1,260 +0,0 @@ ---- -title: End-to-end -description: Learn how to setup a new app that uses Noir to generate and verify zero-knowledge SNARK proofs in a typescript or javascript environment -keywords: [how to, guide, javascript, typescript, noir, barretenberg, zero-knowledge, proofs] ---- - -NoirJS works both on the browser and on the server, and works for both ESM and CJS module systems. In this page, we will learn how can we write a simple test and a simple web app to verify the standard Noir example. - -You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). - -## Before we start - -:::note - -Feel free to use whatever versions, just keep in mind that Nargo and the NoirJS packages are meant to be in sync. For example, Nargo 0.18.x matches `noir_js@0.18.x`, etc. - -In this guide, we will be pinned to 0.17.0. - -::: - -Make sure you have Node installed on your machine by opening a terminal and executing `node --version`. If you don't see a version, you should install [node](https://github.com/nvm-sh/nvm). You can also use `yarn` if you prefer that package manager over npm (which comes with node). - -First of all, follow the [Nargo guide](../../getting_started/00_nargo_installation.md) to install nargo version 0.17.0 and create a new project with `nargo new circuit`. Once there, `cd` into the `circuit` folder. You should then be able to compile your circuit into `json` format and see it inside the `target` folder: - -```bash -nargo compile -``` - -Your folder structure should look like: - -```tree -. -└── circuit - ├── Nargo.toml - ├── src - │ └── main.nr - └── target - └── circuit.json -``` - -## Starting a new project - -Go back to the previous folder and start a new project by running run `npm init`. You can configure your project or just leave the defaults, and see a `package.json` appear in your root folder. - -## Installing dependencies - -We'll need two `npm` packages. These packages will provide us the methods we need to run and verify proofs: - -```bash -npm i @noir-lang/backend_barretenberg@^0.17.0 @noir-lang/noir_js@^0.17.0 -``` - -To serve our page, we can use a build tool such as `vite`. Because we're gonna use some `wasm` files, we need to install a plugin as well. Run: - -```bash -npm i --save-dev vite rollup-plugin-copy -``` - -Since we're on the dependency world, we may as well define a nice starting script. Vite makes it easy. Just open `package.json`, find the block "scripts" and add this just below the line with `"test" : "echo......."`: - -```json - "start": "vite --open" -``` - -If you want do build a static website, you can also add some build and preview scripts: - -```json - "build": "vite build", - "preview": "vite preview" -``` - -## Vite plugins - -Vite is great, but support from `wasm` doesn't work out-of-the-box. We're gonna write a quick plugin and use another one. Just copy and paste this into a file named `vite.config.js`. You don't need to understand it, just trust me bro. - -```js -import { defineConfig } from 'vite'; -import copy from 'rollup-plugin-copy'; -import fs from 'fs'; -import path from 'path'; - -const wasmContentTypePlugin = { - name: 'wasm-content-type-plugin', - configureServer(server) { - server.middlewares.use(async (req, res, next) => { - if (req.url.endsWith('.wasm')) { - res.setHeader('Content-Type', 'application/wasm'); - const newPath = req.url.replace('deps', 'dist'); - const targetPath = path.join(__dirname, newPath); - const wasmContent = fs.readFileSync(targetPath); - return res.end(wasmContent); - } - next(); - }); - }, -}; - -export default defineConfig(({ command }) => { - if (command === 'serve') { - return { - plugins: [ - copy({ - targets: [{ src: 'node_modules/**/*.wasm', dest: 'node_modules/.vite/dist' }], - copySync: true, - hook: 'buildStart', - }), - command === 'serve' ? wasmContentTypePlugin : [], - ], - }; - } - - return {}; -}); -``` - -## HTML - -Here's the simplest HTML with some terrible UI. Create a file called `index.html` and paste this: - -```html - - - - - - -

Very basic Noir app

-
-

Logs

-

Proof

-
- - -``` - -## Some good old vanilla Javascript - -Create a new file `app.js`, which is where our javascript code will live. Let's start with this code inside: - -```js -document.addEventListener('DOMContentLoaded', async () => { - // here's where the magic happens -}); - -function display(container, msg) { - const c = document.getElementById(container); - const p = document.createElement('p'); - p.textContent = msg; - c.appendChild(p); -} -``` - -We can manipulate our website with this little function, so we can see our website working. - -## Adding Noir - -If you come from the previous page, your folder structure should look like this: - -```tree -├── app.js -├── circuit -│ ├── Nargo.toml -│ ├── src -│ │ └── main.nr -│ └── target -│ └── circuit.json -├── index.html -├── package.json -└── vite.config.js -``` - -You'll see other files and folders showing up (like `package-lock.json`, `yarn.lock`, `node_modules`) but you shouldn't have to care about those. - -## Importing our dependencies - -We're starting with the good stuff now. At the top of the new javascript file, import the packages: - -```ts -import { BarretenbergBackend } from '@noir-lang/backend_barretenberg'; -import { Noir } from '@noir-lang/noir_js'; -``` - -We also need to import the `circuit` JSON file we created. If you have the suggested folder structure, you can add this line: - -```ts -import circuit from './circuit/target/circuit.json'; -``` - -## Write code - -:::note - -We're gonna be adding code inside the `document.addEventListener...etc` block: - -```js -// forget stuff here -document.addEventListener('DOMContentLoaded', async () => { - // here's where the magic happens -}); -// forget stuff here -``` - -::: - -Our dependencies exported two classes: `BarretenbergBackend` and `Noir`. Let's `init` them and add some logs, just to flex: - -```ts -const backend = new BarretenbergBackend(circuit); -const noir = new Noir(circuit, backend); -``` - -## Proving - -Now we're ready to prove stuff! Let's feed some inputs to our circuit and calculate the proof: - -```js -const input = { x: 1, y: 2 }; -display('logs', 'Generating proof... ⌛'); -const proof = await noir.generateFinalProof(input); -display('logs', 'Generating proof... ✅'); -display('results', proof.proof); -``` - -You're probably eager to see stuff happening, so go and run your app now! - -From your terminal, run `npm start` (or `yarn start`). If it doesn't open a browser for you, just visit `localhost:5173`. On a modern laptop, proof will generate in less than 100ms, and you'll see this: - -![Getting Started 0](@site/static/img/noir_getting_started_1.png) - -If you're human, you shouldn't be able to understand anything on the "proof" box. That's OK. We like you, human. - -In any case, this means your proof was generated! But you shouldn't trust me just yet. Add these lines to see it being verified: - -```js -display('logs', 'Verifying proof... ⌛'); -const verification = await noir.verifyFinalProof(proof); -if (verification) display('logs', 'Verifying proof... ✅'); -``` - -By saving, your app will refresh and here's our complete Tiny Noir App! - -You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). - -## Further Reading - -You can see how noirjs is used in a full stack Next.js hardhat application in the [noir-starter repo here](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat). The example shows how to calculate a proof in the browser and verify it with a deployed Solidity verifier contract from noirjs. - -You should also check out the more advanced examples in the [noir-examples repo](https://github.com/noir-lang/noir-examples), where you'll find reference usage for some cool apps. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/noir_js.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/noir_js.md deleted file mode 100644 index f895b22eaf8..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/noir_js.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: NoirJS -description: Interact with Noir in Typescript or Javascript -keywords: [Noir project, javascript, typescript, node.js, browser, react] ---- - -NoirJS is a TypeScript library that make it easy to use Noir on your dapp, webapp, Node.js server, website, etc. - -A typical workflow would be composed of two major elements: - -- NoirJS -- Proving backend of choice's JavaScript package - - - -To install NoirJS, install Node.js if you have not already and run this in your JavaScript project: - -```bash -npm i @noir-lang/noir_js -``` - -## Proving backend - -Since Noir is backend agnostic, you can instantiate NoirJS without any backend (i.e. to execute a function). But for proving, you would have to instantiate NoirJS with any of the supported backends through their own `js` interface. - -### Barretenberg - -Aztec Labs maintains the `barretenberg` proving backend, which you can instantiate and make use of alongside NoirJS. It is also the default proving backend installed and used with Nargo, the Noir CLI tool. - -To install its JavaScript library, run this in your project: - -```bash -npm i @noir-lang/backend_barretenberg -``` - -For more details on how to instantiate and use the libraries, refer to the [Full Noir App Guide](./getting_started/01_tiny_noir_app.md) and [Reference](./reference/noir_js/classes/Noir.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/.nojekyll deleted file mode 100644 index e2ac6616add..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/classes/BarretenbergBackend.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/classes/BarretenbergBackend.md deleted file mode 100644 index 5cbe9421b92..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/classes/BarretenbergBackend.md +++ /dev/null @@ -1,185 +0,0 @@ -# BarretenbergBackend - -## Implements - -- [`Backend`](../interfaces/Backend.md) - -## Constructors - -### new BarretenbergBackend(acirCircuit, options) - -```ts -new BarretenbergBackend(acirCircuit, options): BarretenbergBackend -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `acirCircuit` | [`CompiledCircuit`](../type-aliases/CompiledCircuit.md) | -| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | - -#### Returns - -[`BarretenbergBackend`](BarretenbergBackend.md) - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`destroy`](../interfaces/Backend.md#destroy) - -#### Description - -Destroys the backend - -*** - -### generateFinalProof() - -```ts -generateFinalProof(decompressedWitness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `decompressedWitness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`generateFinalProof`](../interfaces/Backend.md#generatefinalproof) - -#### Description - -Generates a final proof (not meant to be verified in another circuit) - -*** - -### generateIntermediateProof() - -```ts -generateIntermediateProof(witness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `witness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`generateIntermediateProof`](../interfaces/Backend.md#generateintermediateproof) - -#### Example - -```typescript -const intermediateProof = await backend.generateIntermediateProof(witness); -``` - -*** - -### generateIntermediateProofArtifacts() - -```ts -generateIntermediateProofArtifacts(proofData, numOfPublicInputs): Promise -``` - -#### Parameters - -| Parameter | Type | Default value | -| :------ | :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | `undefined` | -| `numOfPublicInputs` | `number` | `0` | - -#### Returns - -`Promise`\<`object`\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`generateIntermediateProofArtifacts`](../interfaces/Backend.md#generateintermediateproofartifacts) - -#### Example - -```typescript -const artifacts = await backend.generateIntermediateProofArtifacts(proof, numOfPublicInputs); -``` - -*** - -### verifyFinalProof() - -```ts -verifyFinalProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`verifyFinalProof`](../interfaces/Backend.md#verifyfinalproof) - -#### Description - -Verifies a final proof - -*** - -### verifyIntermediateProof() - -```ts -verifyIntermediateProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`verifyIntermediateProof`](../interfaces/Backend.md#verifyintermediateproof) - -#### Example - -```typescript -const isValidIntermediate = await backend.verifyIntermediateProof(proof); -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/index.md deleted file mode 100644 index 93b248b0f65..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/index.md +++ /dev/null @@ -1,45 +0,0 @@ -# Backend Barretenberg - -## Exports - -### Classes - -| Class | Description | -| :------ | :------ | -| [BarretenbergBackend](classes/BarretenbergBackend.md) | - | - -### Interfaces - -| Interface | Description | -| :------ | :------ | -| [Backend](interfaces/Backend.md) | - | - -### Type Aliases - -| Type alias | Description | -| :------ | :------ | -| [BackendOptions](type-aliases/BackendOptions.md) | - | -| [CompiledCircuit](type-aliases/CompiledCircuit.md) | - | -| [ProofData](type-aliases/ProofData.md) | - | - -## Functions - -### flattenPublicInputs() - -```ts -flattenPublicInputs(publicInputs): string[] -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `publicInputs` | `WitnessMap` | - -#### Returns - -`string`[] - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/interfaces/Backend.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/interfaces/Backend.md deleted file mode 100644 index 3eb9645c8d2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/interfaces/Backend.md +++ /dev/null @@ -1,132 +0,0 @@ -# Backend - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Description - -Destroys the backend - -*** - -### generateFinalProof() - -```ts -generateFinalProof(decompressedWitness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `decompressedWitness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Description - -Generates a final proof (not meant to be verified in another circuit) - -*** - -### generateIntermediateProof() - -```ts -generateIntermediateProof(decompressedWitness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `decompressedWitness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Description - -Generates an intermediate proof (meant to be verified in another circuit) - -*** - -### generateIntermediateProofArtifacts() - -```ts -generateIntermediateProofArtifacts(proofData, numOfPublicInputs): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | -| `numOfPublicInputs` | `number` | - -#### Returns - -`Promise`\<`object`\> - -#### Description - -Retrieves the artifacts from a proof in the Field format - -*** - -### verifyFinalProof() - -```ts -verifyFinalProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Verifies a final proof - -*** - -### verifyIntermediateProof() - -```ts -verifyIntermediateProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Verifies an intermediate proof - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/type-aliases/BackendOptions.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/type-aliases/BackendOptions.md deleted file mode 100644 index 266ade75d17..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/type-aliases/BackendOptions.md +++ /dev/null @@ -1,19 +0,0 @@ -# BackendOptions - -```ts -type BackendOptions: object; -``` - -## Description - -An options object, currently only used to specify the number of threads to use. - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `threads` | `number` | **Description**

Number of threads | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit.md deleted file mode 100644 index 34e0dd04205..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit.md +++ /dev/null @@ -1,20 +0,0 @@ -# CompiledCircuit - -```ts -type CompiledCircuit: object; -``` - -## Description - -The representation of a compiled circuit - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `abi` | `Abi` | **Description**

ABI representation of the circuit | -| `bytecode` | `string` | **Description**

The bytecode of the circuit | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/type-aliases/ProofData.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/type-aliases/ProofData.md deleted file mode 100644 index 3eb360a78f1..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/type-aliases/ProofData.md +++ /dev/null @@ -1,20 +0,0 @@ -# ProofData - -```ts -type ProofData: object; -``` - -## Description - -The representation of a proof - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `proof` | `Uint8Array` | **Description**

An byte array representing the proof | -| `publicInputs` | `WitnessMap` | **Description**

Public inputs of a proof | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs deleted file mode 100644 index 04e662c845f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"noir_js/reference/backend_barretenberg/classes/BarretenbergBackend","label":"BarretenbergBackend"}]},{"type":"category","label":"Interfaces","items":[{"type":"doc","id":"noir_js/reference/backend_barretenberg/interfaces/Backend","label":"Backend"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"noir_js/reference/backend_barretenberg/type-aliases/BackendOptions","label":"BackendOptions"},{"type":"doc","id":"noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit","label":"CompiledCircuit"},{"type":"doc","id":"noir_js/reference/backend_barretenberg/type-aliases/ProofData","label":"ProofData"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/.nojekyll deleted file mode 100644 index e2ac6616add..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/classes/Noir.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/classes/Noir.md deleted file mode 100644 index c54468891af..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/classes/Noir.md +++ /dev/null @@ -1,131 +0,0 @@ -# Noir - -## Constructors - -### new Noir(circuit, backend) - -```ts -new Noir(circuit, backend?): Noir -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `circuit` | [`CompiledCircuit`](../type-aliases/CompiledCircuit.md) | -| `backend`? | `Backend` | - -#### Returns - -[`Noir`](Noir.md) - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Description - -Destroys the underlying backend instance. - -#### Example - -```typescript -await noir.destroy(); -``` - -*** - -### execute() - -```ts -execute(inputs, foreignCallHandler?): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `inputs` | [`InputMap`](../type-aliases/InputMap.md) | -| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | - -#### Returns - -`Promise`\<`object`\> - -#### Description - -Allows to execute a circuit to get its witness and return value. - -#### Example - -```typescript -async execute(inputs) -``` - -*** - -### generateFinalProof() - -```ts -generateFinalProof(inputs): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `inputs` | [`InputMap`](../type-aliases/InputMap.md) | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Description - -Generates a witness and a proof given an object as input. - -#### Example - -```typescript -async generateFinalProof(input) -``` - -*** - -### verifyFinalProof() - -```ts -verifyFinalProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Instantiates the verification key and verifies a proof. - -#### Example - -```typescript -async verifyFinalProof(proof) -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/and.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/and.md deleted file mode 100644 index c783283e396..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/and.md +++ /dev/null @@ -1,22 +0,0 @@ -# and() - -```ts -and(lhs, rhs): string -``` - -Performs a bitwise AND operation between `lhs` and `rhs` - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `lhs` | `string` | | -| `rhs` | `string` | | - -## Returns - -`string` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/blake2s256.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/blake2s256.md deleted file mode 100644 index 7882d0da8d5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/blake2s256.md +++ /dev/null @@ -1,21 +0,0 @@ -# blake2s256() - -```ts -blake2s256(inputs): Uint8Array -``` - -Calculates the Blake2s256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify.md deleted file mode 100644 index 0ba5783f0d5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify.md +++ /dev/null @@ -1,29 +0,0 @@ -# ecdsa\_secp256k1\_verify() - -```ts -ecdsa_secp256k1_verify( - hashed_msg, - public_key_x_bytes, - public_key_y_bytes, - signature): boolean -``` - -Calculates the Blake2s256 hash of the input bytes and represents these as a single field element. -Verifies a ECDSA signature over the secp256k1 curve. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `hashed_msg` | `Uint8Array` | | -| `public_key_x_bytes` | `Uint8Array` | | -| `public_key_y_bytes` | `Uint8Array` | | -| `signature` | `Uint8Array` | | - -## Returns - -`boolean` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify.md deleted file mode 100644 index 0b20ff68957..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify.md +++ /dev/null @@ -1,28 +0,0 @@ -# ecdsa\_secp256r1\_verify() - -```ts -ecdsa_secp256r1_verify( - hashed_msg, - public_key_x_bytes, - public_key_y_bytes, - signature): boolean -``` - -Verifies a ECDSA signature over the secp256r1 curve. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `hashed_msg` | `Uint8Array` | | -| `public_key_x_bytes` | `Uint8Array` | | -| `public_key_y_bytes` | `Uint8Array` | | -| `signature` | `Uint8Array` | | - -## Returns - -`boolean` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/keccak256.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/keccak256.md deleted file mode 100644 index d10f155ce86..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/keccak256.md +++ /dev/null @@ -1,21 +0,0 @@ -# keccak256() - -```ts -keccak256(inputs): Uint8Array -``` - -Calculates the Keccak256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/sha256.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/sha256.md deleted file mode 100644 index 6ba4ecac022..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/sha256.md +++ /dev/null @@ -1,21 +0,0 @@ -# sha256() - -```ts -sha256(inputs): Uint8Array -``` - -Calculates the SHA256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/xor.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/xor.md deleted file mode 100644 index 8d762b895d3..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/xor.md +++ /dev/null @@ -1,22 +0,0 @@ -# xor() - -```ts -xor(lhs, rhs): string -``` - -Performs a bitwise XOR operation between `lhs` and `rhs` - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `lhs` | `string` | | -| `rhs` | `string` | | - -## Returns - -`string` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/index.md deleted file mode 100644 index 348453c0059..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/index.md +++ /dev/null @@ -1,37 +0,0 @@ -# Noir JS - -## Exports - -### Classes - -| Class | Description | -| :------ | :------ | -| [Noir](classes/Noir.md) | - | - -### Type Aliases - -| Type alias | Description | -| :------ | :------ | -| [CompiledCircuit](type-aliases/CompiledCircuit.md) | - | -| [ForeignCallHandler](type-aliases/ForeignCallHandler.md) | A callback which performs an foreign call and returns the response. | -| [ForeignCallInput](type-aliases/ForeignCallInput.md) | - | -| [ForeignCallOutput](type-aliases/ForeignCallOutput.md) | - | -| [InputMap](type-aliases/InputMap.md) | - | -| [ProofData](type-aliases/ProofData.md) | - | -| [WitnessMap](type-aliases/WitnessMap.md) | - | - -### Functions - -| Function | Description | -| :------ | :------ | -| [and](functions/and.md) | Performs a bitwise AND operation between `lhs` and `rhs` | -| [blake2s256](functions/blake2s256.md) | Calculates the Blake2s256 hash of the input bytes | -| [ecdsa\_secp256k1\_verify](functions/ecdsa_secp256k1_verify.md) | Calculates the Blake2s256 hash of the input bytes and represents these as a single field element. | -| [ecdsa\_secp256r1\_verify](functions/ecdsa_secp256r1_verify.md) | Verifies a ECDSA signature over the secp256r1 curve. | -| [keccak256](functions/keccak256.md) | Calculates the Keccak256 hash of the input bytes | -| [sha256](functions/sha256.md) | Calculates the SHA256 hash of the input bytes | -| [xor](functions/xor.md) | Performs a bitwise XOR operation between `lhs` and `rhs` | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/CompiledCircuit.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/CompiledCircuit.md deleted file mode 100644 index 34e0dd04205..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/CompiledCircuit.md +++ /dev/null @@ -1,20 +0,0 @@ -# CompiledCircuit - -```ts -type CompiledCircuit: object; -``` - -## Description - -The representation of a compiled circuit - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `abi` | `Abi` | **Description**

ABI representation of the circuit | -| `bytecode` | `string` | **Description**

The bytecode of the circuit | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/ForeignCallHandler.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/ForeignCallHandler.md deleted file mode 100644 index 812b8b16481..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/ForeignCallHandler.md +++ /dev/null @@ -1,24 +0,0 @@ -# ForeignCallHandler - -```ts -type ForeignCallHandler: (name, inputs) => Promise; -``` - -A callback which performs an foreign call and returns the response. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `name` | `string` | The identifier for the type of foreign call being performed. | -| `inputs` | [`ForeignCallInput`](ForeignCallInput.md)[] | An array of hex encoded inputs to the foreign call. | - -## Returns - -`Promise`\<[`ForeignCallOutput`](ForeignCallOutput.md)[]\> - -outputs - An array of hex encoded outputs containing the results of the foreign call. - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/ForeignCallInput.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/ForeignCallInput.md deleted file mode 100644 index dd95809186a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/ForeignCallInput.md +++ /dev/null @@ -1,9 +0,0 @@ -# ForeignCallInput - -```ts -type ForeignCallInput: string[]; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/ForeignCallOutput.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/ForeignCallOutput.md deleted file mode 100644 index b71fb78a946..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/ForeignCallOutput.md +++ /dev/null @@ -1,9 +0,0 @@ -# ForeignCallOutput - -```ts -type ForeignCallOutput: string | string[]; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/InputMap.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/InputMap.md deleted file mode 100644 index c714e999d93..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/InputMap.md +++ /dev/null @@ -1,13 +0,0 @@ -# InputMap - -```ts -type InputMap: object; -``` - -## Index signature - - \[`key`: `string`\]: `InputValue` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/ProofData.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/ProofData.md deleted file mode 100644 index 3eb360a78f1..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/ProofData.md +++ /dev/null @@ -1,20 +0,0 @@ -# ProofData - -```ts -type ProofData: object; -``` - -## Description - -The representation of a proof - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `proof` | `Uint8Array` | **Description**

An byte array representing the proof | -| `publicInputs` | `WitnessMap` | **Description**

Public inputs of a proof | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/WitnessMap.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/WitnessMap.md deleted file mode 100644 index 258c46f9d0c..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/WitnessMap.md +++ /dev/null @@ -1,9 +0,0 @@ -# WitnessMap - -```ts -type WitnessMap: Map; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/typedoc-sidebar.cjs deleted file mode 100644 index 077ebeb133e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"noir_js/reference/noir_js/classes/Noir","label":"Noir"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/CompiledCircuit","label":"CompiledCircuit"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/ForeignCallHandler","label":"ForeignCallHandler"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/ForeignCallInput","label":"ForeignCallInput"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/ForeignCallOutput","label":"ForeignCallOutput"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/InputMap","label":"InputMap"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/ProofData","label":"ProofData"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/WitnessMap","label":"WitnessMap"}]},{"type":"category","label":"Functions","items":[{"type":"doc","id":"noir_js/reference/noir_js/functions/and","label":"and"},{"type":"doc","id":"noir_js/reference/noir_js/functions/blake2s256","label":"blake2s256"},{"type":"doc","id":"noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify","label":"ecdsa_secp256k1_verify"},{"type":"doc","id":"noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify","label":"ecdsa_secp256r1_verify"},{"type":"doc","id":"noir_js/reference/noir_js/functions/keccak256","label":"keccak256"},{"type":"doc","id":"noir_js/reference/noir_js/functions/sha256","label":"sha256"},{"type":"doc","id":"noir_js/reference/noir_js/functions/xor","label":"xor"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/black_box_fns.md deleted file mode 100644 index b115a450ed3..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/black_box_fns.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: Black Box Functions -description: Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. -keywords: [noir, black box functions] ---- - -Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. This makes certain zk-snark unfriendly computations cheaper than if they were implemented in Noir. - -:::warning - -It is likely that not all backends will support a particular black box function. - -::: - -Because it is not guaranteed that all backends will support black box functions, it is possible that certain Noir programs won't compile against a particular backend if they use an unsupported black box function. It is possible to fallback to less efficient implementations written in Noir/ACIR in some cases. - -Black box functions are specified with the `#[foreign(black_box_fn)]` attribute. For example, the SHA256 function in the Noir [source code](https://github.com/noir-lang/noir/blob/v0.5.1/noir_stdlib/src/hash.nr) looks like: - -```rust -#[foreign(sha256)] -fn sha256(_input : [u8; N]) -> [u8; 32] {} -``` - -## Function list - -Here is a list of the current black box functions that are supported by UltraPlonk: - -- AES -- [SHA256](./cryptographic_primitives/00_hashes.mdx#sha256) -- [Schnorr signature verification](./cryptographic_primitives/02_schnorr.mdx) -- [Blake2s](./cryptographic_primitives/00_hashes.mdx#blake2s) -- [Pedersen Hash](./cryptographic_primitives/00_hashes.mdx#pedersen_hash) -- [Pedersen Commitment](./cryptographic_primitives/00_hashes.mdx#pedersen_commitment) -- [HashToField128Security](./cryptographic_primitives/00_hashes.mdx#hash_to_field) -- [ECDSA signature verification](./cryptographic_primitives/03_ecdsa_sig_verification.mdx) -- [Fixed base scalar multiplication](./cryptographic_primitives/01_scalar.mdx) -- [Compute merkle root](./merkle_trees.md#compute_merkle_root) -- AND -- XOR -- RANGE -- [Keccak256](./cryptographic_primitives/00_hashes.mdx#keccak256) -- [Recursive proof verification](./recursion.md) - -Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. - -You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/noir/blob/master/acvm-repo/acir/src/circuit/black_box_functions.rs). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives.md deleted file mode 100644 index 2df4f929474..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Cryptographic primitives in Noir -description: - Learn about the cryptographic primitives ready to use for any Noir project -keywords: - [ - cryptographic primitives, - Noir project, - ] ---- - -The Noir team is progressively adding new cryptographic primitives to the standard library. Reach out for news or if you would be interested in adding more of these calculations in Noir. - -Some methods are available thanks to the Aztec backend, not being performed using Noir. When using other backends, these methods may or may not be supplied. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/00_hashes.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/00_hashes.mdx deleted file mode 100644 index 76745196681..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/00_hashes.mdx +++ /dev/null @@ -1,167 +0,0 @@ ---- -title: Hash methods -description: - Learn about the cryptographic primitives ready to use for any Noir project, including sha256, - blake2s, pedersen, mimc_bn254 and mimc -keywords: - [cryptographic primitives, Noir project, sha256, blake2s, pedersen, mimc_bn254, mimc, hash] ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## sha256 - -Given an array of bytes, returns the resulting sha256 hash. - -```rust -fn sha256(_input : [u8]) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::sha256(x); -} -``` - - - -## blake2s - -Given an array of bytes, returns an array with the Blake2 hash - -```rust -fn blake2s(_input : [u8]) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::blake2s(x); -} -``` - - - -## pedersen_hash - -Given an array of Fields, returns the Pedersen hash. - -```rust -fn pedersen_hash(_input : [Field]) -> Field -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::pedersen_hash(x); -} -``` - - - - - -## pedersen_commitment - -Given an array of Fields, returns the Pedersen commitment. - -```rust -fn pedersen_commitment(_input : [Field]) -> [Field; 2] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let commitment = std::hash::pedersen_commitment(x); -} -``` - - - -## keccak256 - -Given an array of bytes (`u8`), returns the resulting keccak hash as an array of 32 bytes -(`[u8; 32]`). Specify a message_size to hash only the first `message_size` bytes -of the input. - -```rust -fn keccak256(_input : [u8; N], _message_size: u32) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let message_size = 4; - let hash = std::hash::keccak256(x, message_size); -} -``` - - - -## poseidon - -Given an array of Fields, returns a new Field with the Poseidon Hash. Mind that you need to specify -how many inputs are there to your Poseidon function. - -```rust -// example for hash_1, hash_2 accepts an array of length 2, etc -fn hash_1(input: [Field; 1]) -> Field -``` - -example: - -```rust -fn main() -{ - let hash1 = std::hash::poseidon::bn254::hash_2([1, 2]); - assert(hash1 == 0x115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189a); -} -``` - -## mimc_bn254 and mimc - -`mimc_bn254` is `mimc`, but with hardcoded parameters for the BN254 curve. You can use it by -providing an array of Fields, and it returns a Field with the hash. You can use the `mimc` method if -you're willing to input your own constants: - -```rust -fn mimc(x: Field, k: Field, constants: [Field; N], exp : Field) -> Field -``` - -otherwise, use the `mimc_bn254` method: - -```rust -fn mimc_bn254(array: [Field; N]) -> Field -``` - -example: - -```rust - -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::mimc::mimc_bn254(x); -} -``` - -## hash_to_field - -```rust -fn hash_to_field(_input : [Field; N]) -> Field {} -``` - -Calculates the `blake2s` hash of the inputs and returns the hash modulo the field modulus to return -a value which can be represented as a `Field`. - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/01_scalar.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/01_scalar.mdx deleted file mode 100644 index c7eed820a80..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/01_scalar.mdx +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: Scalar multiplication -description: See how you can perform scalar multiplications over a fixed base in Noir -keywords: [cryptographic primitives, Noir project, scalar multiplication] ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## scalar_mul::fixed_base_embedded_curve - -Performs scalar multiplication over the embedded curve whose coordinates are defined by the -configured noir field. For the BN254 scalar field, this is BabyJubJub or Grumpkin. - -```rust -fn fixed_base_embedded_curve(_input : Field) -> [Field; 2] -``` - -example - -```rust -fn main(x : Field) { - let scal = std::scalar_mul::fixed_base_embedded_curve(x); - std::println(scal); -} -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/02_schnorr.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/02_schnorr.mdx deleted file mode 100644 index c184ce28120..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/02_schnorr.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: Schnorr Signatures -description: Learn how you can verify Schnorr signatures using Noir -keywords: [cryptographic primitives, Noir project, schnorr, signatures] ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## schnorr::verify_signature - -Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin). - -```rust -fn verify_signature(_public_key_x: Field, _public_key_y: Field, _signature: [u8; 64], _message: [u8]) -> bool -``` - -where `_signature` can be generated like so using the npm package -[@noir-lang/barretenberg](https://www.npmjs.com/package/@noir-lang/barretenberg) - -```js -const { BarretenbergWasm } = require('@noir-lang/barretenberg/dest/wasm'); -const { Schnorr } = require('@noir-lang/barretenberg/dest/crypto/schnorr'); - -... - -const barretenberg = await BarretenbergWasm.new(); -const schnorr = new Schnorr(barretenberg); -const pubKey = schnorr.computePublicKey(privateKey); -const message = ... -const signature = Array.from( - schnorr.constructSignature(hash, privateKey).toBuffer() -); - -... -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx deleted file mode 100644 index 72bce984821..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: ECDSA Signature Verification -description: Learn about the cryptographic primitives regarding ECDSA over the secp256k1 and secp256r1 curves -keywords: [cryptographic primitives, Noir project, ecdsa, secp256k1, secp256r1, signatures] ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -Noir supports ECDSA signatures verification over the secp256k1 and secp256r1 curves. - -## ecdsa_secp256k1::verify_signature - -Verifier for ECDSA Secp256k1 signatures - -```rust -fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message: [u8]) -> bool -``` - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - -## ecdsa_secp256r1::verify_signature - -Verifier for ECDSA Secp256r1 signatures - -```rust -fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message: [u8]) -> bool -``` - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/04_ec_primitives.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/04_ec_primitives.md deleted file mode 100644 index 6f69e468402..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/04_ec_primitives.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -title: Elliptic Curve Primitives -keywords: [cryptographic primitives, Noir project] ---- - -Data structures and methods on them that allow you to carry out computations involving elliptic -curves over the (mathematical) field corresponding to `Field`. For the field currently at our -disposal, applications would involve a curve embedded in BN254, e.g. the -[Baby Jubjub curve](https://eips.ethereum.org/EIPS/eip-2494). - -## Data structures - -### Elliptic curve configurations - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Curve`), i.e. the specific elliptic -curve you want to use, which would be specified using any one of the methods -`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::new` which take the coefficients in the -defining equation together with a generator point as parameters. You can find more detail in the -comments in -[`noir_stdlib/src/ec.nr`](https://github.com/noir-lang/noir/blob/v0.19.4/noir_stdlib/src/ec.nr), but -the gist of it is that the elliptic curves of interest are usually expressed in one of the standard -forms implemented here (Twisted Edwards, Montgomery and Short Weierstraß), and in addition to that, -you could choose to use `affine` coordinates (Cartesian coordinates - the usual (x,y) - possibly -together with a point at infinity) or `curvegroup` coordinates (some form of projective coordinates -requiring more coordinates but allowing for more efficient implementations of elliptic curve -operations). Conversions between all of these forms are provided, and under the hood these -conversions are done whenever an operation is more efficient in a different representation (or a -mixed coordinate representation is employed). - -### Points - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Point`), i.e. points lying on the -elliptic curve. For a curve configuration `c` and a point `p`, it may be checked that `p` -does indeed lie on `c` by calling `c.contains(p1)`. - -## Methods - -(given a choice of curve representation, e.g. use `std::ec::tecurve::affine::Curve` and use -`std::ec::tecurve::affine::Point`) - -- The **zero element** is given by `Point::zero()`, and we can verify whether a point `p: Point` is - zero by calling `p.is_zero()`. -- **Equality**: Points `p1: Point` and `p2: Point` may be checked for equality by calling - `p1.eq(p2)`. -- **Addition**: For `c: Curve` and points `p1: Point` and `p2: Point` on the curve, adding these two - points is accomplished by calling `c.add(p1,p2)`. -- **Negation**: For a point `p: Point`, `p.negate()` is its negation. -- **Subtraction**: For `c` and `p1`, `p2` as above, subtracting `p2` from `p1` is accomplished by - calling `c.subtract(p1,p2)`. -- **Scalar multiplication**: For `c` as above, `p: Point` a point on the curve and `n: Field`, - scalar multiplication is given by `c.mul(n,p)`. If instead `n :: [u1; N]`, i.e. `n` is a bit - array, the `bit_mul` method may be used instead: `c.bit_mul(n,p)` -- **Multi-scalar multiplication**: For `c` as above and arrays `n: [Field; N]` and `p: [Point; N]`, - multi-scalar multiplication is given by `c.msm(n,p)`. -- **Coordinate representation conversions**: The `into_group` method converts a point or curve - configuration in the affine representation to one in the CurveGroup representation, and - `into_affine` goes in the other direction. -- **Curve representation conversions**: `tecurve` and `montcurve` curves and points are equivalent - and may be converted between one another by calling `into_montcurve` or `into_tecurve` on their - configurations or points. `swcurve` is more general and a curve c of one of the other two types - may be converted to this representation by calling `c.into_swcurve()`, whereas a point `p` lying - on the curve given by `c` may be mapped to its corresponding `swcurve` point by calling - `c.map_into_swcurve(p)`. -- **Map-to-curve methods**: The Elligator 2 method of mapping a field element `n: Field` into a - `tecurve` or `montcurve` with configuration `c` may be called as `c.elligator2_map(n)`. For all of - the curve configurations, the SWU map-to-curve method may be called as `c.swu_map(z,n)`, where - `z: Field` depends on `Field` and `c` and must be chosen by the user (the conditions it needs to - satisfy are specified in the comments - [here](https://github.com/noir-lang/noir/blob/v0.19.4/noir_stdlib/src/ec.nr). - -## Examples - -The -[ec_baby_jubjub test](https://github.com/noir-lang/noir/blob/master/test_programs/compile_success_empty/ec_baby_jubjub/src/main.nr) -illustrates all of the above primitives on various forms of the Baby Jubjub curve. A couple of more -interesting examples in Noir would be: - -Public-key cryptography: Given an elliptic curve and a 'base point' on it, determine the public key -from the private key. This is a matter of using scalar multiplication. In the case of Baby Jubjub, -for example, this code would do: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; - -fn bjj_pub_key(priv_key: Field) -> Point -{ - - let bjj = Curve::new(168700, 168696, G::new(995203441582195749578291179787384436505546430278305826713579947235728471134,5472060717959818805561601436314318772137091100104008585924551046643952123905)); - - let base_pt = Point::new(5299619240641551281634865583518297030282874472190772894086521144482721001553, 16950150798460657717958625567821834550301663161624707787222815936182638968203); - - bjj.mul(priv_key,base_pt) -} -``` - -This would come in handy in a Merkle proof. - -- EdDSA signature verification: This is a matter of combining these primitives with a suitable hash - function. See - [feat(stdlib): EdDSA sig verification noir#1136](https://github.com/noir-lang/noir/pull/1136) for - the case of Baby Jubjub and the Poseidon hash function. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/05_eddsa.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/05_eddsa.mdx deleted file mode 100644 index 9a5beb55ee9..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/05_eddsa.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: EdDSA Verification -description: Learn about the cryptographic primitives regarding EdDSA -keywords: [cryptographic primitives, Noir project, eddsa, signatures] ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## eddsa::eddsa_poseidon_verify - -Verifier for EdDSA signatures - -```rust -fn eddsa_poseidon_verify(public_key_x : Field, public_key_y : Field, signature_s: Field, signature_r8_x: Field, signature_r8_y: Field, message: Field) -> bool -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/logging.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/logging.md deleted file mode 100644 index 4ba0fe0e656..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/logging.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -title: Logging -description: - Learn how to use the println statement for debugging in Noir with this tutorial. Understand the - basics of logging in Noir and how to implement it in your code. -keywords: - [ - noir logging, - println statement, - debugging in noir, - noir std library, - logging tutorial, - basic logging in noir, - noir logging implementation, - noir debugging techniques, - rust, - ] ---- - -The standard library provides a familiar `println` statement you can use. Despite being a limited -implementation of rust's `println!` macro, this construct can be useful for debugging. - -You can print the output of println statements in your Noir code by using the `nargo execute` command or the `--show-output` flag when using `nargo test` (provided there are println statements in your tests). - -It is recommended to use `nargo execute` if you want to debug failing constraints with `println` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). `println` will not work for failed constraints caught at compile time. - -The `println` statement is unconstrained, so it works for outputting integers, fields, strings, and even structs or expressions. For example: - -```rust -use dep::std; - -struct Person { - age : Field, - height : Field, -} - -fn main(age : Field, height : Field) { - let person = Person { age : age, height : height }; - std::println(person); - std::println(age + height); - std::println("Hello world!"); -} - -``` - -You can print multiple different types in the same statement and string as well as a new "fmtstr" type. A `fmtstr` can be specified in the same way as a normal string it just should be prepended with an "f" character: - -```rust - let fmt_str = f"i: {i}, j: {j}"; - std::println(fmt_str); - - let s = myStruct { y: x, x: y }; - std::println(s); - - std::println(f"i: {i}, s: {s}"); - - std::println(x); - std::println([x, y]); - - let foo = fooStruct { my_struct: s, foo: 15 }; - std::println(f"s: {s}, foo: {foo}"); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/merkle_trees.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/merkle_trees.md deleted file mode 100644 index dc383a1426b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/merkle_trees.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: Merkle Trees -description: Learn about Merkle Trees in Noir with this tutorial. Explore the basics of computing a merkle root using a proof, with examples. -keywords: - [ - Merkle trees in Noir, - Noir programming language, - check membership, - computing root from leaf, - Noir Merkle tree implementation, - Merkle tree tutorial, - Merkle tree code examples, - Noir libraries, - pedersen hash., - ] ---- - -## compute_merkle_root - -Returns the root of the tree from the provided leaf and its hash path, using a [Pedersen hash](cryptographic_primitives/00_hashes.mdx#pedersen_hash). - -```rust -fn compute_merkle_root(leaf : Field, index : Field, hash_path: [Field]) -> Field -``` - -example: - -```rust -/** - // these values are for this example only - index = "0" - priv_key = "0x000000000000000000000000000000000000000000000000000000616c696365" - secret = "0x1929ea3ab8d9106a899386883d9428f8256cfedb3c4f6b66bf4aa4d28a79988f" - note_hash_path = [ - "0x1e61bdae0f027b1b2159e1f9d3f8d00fa668a952dddd822fda80dc745d6f65cc", - "0x0e4223f3925f98934393c74975142bd73079ab0621f4ee133cee050a3c194f1a", - "0x2fd7bb412155bf8693a3bd2a3e7581a679c95c68a052f835dddca85fa1569a40" - ] - */ -fn main(index: Field, priv_key: Field, secret: Field, note_hash_path: [Field; 3]) { - - let pubkey = std::scalar_mul::fixed_base_embedded_curve(priv_key); - let pubkey_x = pubkey[0]; - let pubkey_y = pubkey[1]; - let note_commitment = std::hash::pedersen([pubkey_x, pubkey_y, secret]); - - let root = std::merkle::compute_merkle_root(note_commitment[0], index, note_hash_path); - std::println(root); -} -``` - -To check merkle tree membership: - -1. Include a merkle root as a program input. -2. Compute the merkle root of a given leaf, index and hash path. -3. Assert the merkle roots are equal. - -For more info about merkle trees, see the Wikipedia [page](https://en.wikipedia.org/wiki/Merkle_tree). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/options.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/options.md deleted file mode 100644 index 3d3139fb98b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/options.md +++ /dev/null @@ -1,99 +0,0 @@ ---- -title: Option Type ---- - -The `Option` type is a way to express that a value might be present (`Some(T))` or absent (`None`). It's a safer way to handle potential absence of values, compared to using nulls in many other languages. - -```rust -struct Option { - None, - Some(T), -} -``` - -You can import the Option type into your Noir program like so: - -```rust -use dep::std::option::Option; - -fn main() { - let none = Option::none(); - let some = Option::some(3); -} -``` - -See [this test](https://github.com/noir-lang/noir/blob/5cbfb9c4a06c8865c98ff2b594464b037d821a5c/crates/nargo_cli/tests/test_data/option/src/main.nr) for a more comprehensive set of examples of each of the methods described below. - -## Methods - -### none - -Constructs a none value. - -### some - -Constructs a some wrapper around a given value. - -### is_none - -Returns true if the Option is None. - -### is_some - -Returns true of the Option is Some. - -### unwrap - -Asserts `self.is_some()` and returns the wrapped value. - -### unwrap_unchecked - -Returns the inner value without asserting `self.is_some()`. This method can be useful within an if condition when we already know that `option.is_some()`. If the option is None, there is no guarantee what value will be returned, only that it will be of type T for an `Option`. - -### unwrap_or - -Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value. - -### unwrap_or_else - -Returns the wrapped value if `self.is_some()`. Otherwise, calls the given function to return a default value. - -### map - -If self is `Some(x)`, this returns `Some(f(x))`. Otherwise, this returns `None`. - -### map_or - -If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns the given default value. - -### map_or_else - -If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns `default()`. - -### and - -Returns None if self is None. Otherwise, this returns `other`. - -### and_then - -If self is None, this returns None. Otherwise, this calls the given function with the Some value contained within self, and returns the result of that call. In some languages this function is called `flat_map` or `bind`. - -### or - -If self is Some, return self. Otherwise, return `other`. - -### or_else - -If self is Some, return self. Otherwise, return `default()`. - -### xor - -If only one of the two Options is Some, return that option. Otherwise, if both options are Some or both are None, None is returned. - -### filter - -Returns `Some(x)` if self is `Some(x)` and `predicate(x)` is true. Otherwise, this returns `None`. - -### flatten - -Flattens an `Option>` into a `Option`. This returns `None` if the outer Option is None. Otherwise, this returns the inner Option. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/recursion.md deleted file mode 100644 index 5e592a2fd89..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/recursion.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: Recursive Proofs -description: Learn about how to write recursive proofs in Noir. -keywords: [recursion, recursive proofs, verification_key, aggregation object, verify_proof] ---- - -Noir supports recursively verifying proofs, meaning you verify the proof of a Noir program in another Noir program. This enables creating proofs of arbitrary size by doing step-wise verification of smaller components of a large proof. - -The `verify_proof` function takes a verification key, proof and public inputs for a zk program, as well as a key hash and an input aggregation object. The key hash is used to check the validity of the verification key and the input aggregation object is required by some proving systems. The `verify_proof` function returns an output aggregation object that can then be fed into future iterations of the proof verification if required. - -```rust -#[foreign(verify_proof)] -fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : Field, _key_hash : Field, _input_aggregation_object : [Field]) -> [Field] {} -``` - -:::info - -This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. - -::: - -## Aggregation Object - -The purpose of the input aggregation object is a little less clear though (and the output aggregation object that is returned from the `std::verify_proof` method). Recursive zkSNARK schemes do not necessarily "verify a proof" in the sense that you expect a true or false to be spit out by the verifier. Rather an aggregation object is built over the public inputs. In the case of PLONK the recursive aggregation object is two G1 points (expressed as 16 witness values). The final verifier (in our case this is most often the smart contract verifier) has to be aware of this aggregation object to execute a pairing and check the validity of these points (thus completing the recursive verification). - -So for example in this circuit: - -```rust -use dep::std; - -fn main( - verification_key : [Field; 114], - proof : [Field; 94], - public_inputs : [Field; 1], - key_hash : Field, - input_aggregation_object : [Field; 16], - proof_b : [Field; 94], -) -> pub [Field; 16] { - let output_aggregation_object_a = std::verify_proof( - verification_key, - proof, - public_inputs, - key_hash, - input_aggregation_object - ); - - let output_aggregation_object = std::verify_proof( - verification_key, - proof_b, - public_inputs, - key_hash, - output_aggregation_object_a - ); - - let mut output = [0; 16]; - for i in 0..16 { - output[i] = output_aggregation_object[i]; - } - output -} -``` - -In this example we have a circuit, that generates proofs A and B, that is being verified in circuit C. Assuming that the proof being passed in is not already a recursive proof, the `input_aggregation_object` will be all zeros. It will then generate an `output_aggregation_object`. This blob of data then becomes the `input_aggregation_object` of the next recursive aggregation we wish to compute. We can see here as the same public inputs, verification key, and key hash are used that we are verifying two proofs generated from the same circuit in this single circuit. `std::verify_proof` returns a `[Field]` because the size of an aggregation object is proof system dependent--in barretenberg, aggregation objects are two G1 points, while in Halo2, the aggregation object is a list of G1 points that is log the circuit size. So for the final step we convert the slice into an array of size 16 because we are generating proofs using UltraPlonk. - -## Parameters - -### `verification_key` - -The verification key for the zk program that is being verified. - -### `proof` - -The proof for the zk program that is being verified. - -### `public_inputs` - -These represent the public inputs of the proof we are verifying. They should be checked against in the circuit after construction of a new aggregation state. - -### `key_hash` - -A key hash is used to check the validity of the verification key. The circuit implementing this opcode can use this hash to ensure that the key provided to the circuit matches the key produced by the circuit creator. - -### `input_aggregation_object` - -An aggregation object is blob of data that the top-level verifier must run some proof system specific algorithm on to complete verification. The size is proof system specific and will be set by the backend integrating this opcode. The input aggregation object is only not `None` when we are verifying a previous recursive aggregation in the current circuit. If this is the first recursive aggregation there is no input aggregation object. It is left to the backend to determine how to handle when there is no input aggregation object. - -## Return value - -### `output_aggregation_object` - -This is the result of a recursive aggregation and is what will be fed into the next verifier. -The next verifier can either perform a final verification (returning true or false) or perform another recursive aggregation where this output aggregation object will be the input aggregation object of the next recursive aggregation. - -## Example - -You can see an example of how to do recursive proofs in [this example recursion demo repo](https://github.com/noir-lang/noir-examples/tree/master/recursion). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/zeroed.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/zeroed.md deleted file mode 100644 index 97dab02dac2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/zeroed.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: Zeroed Function -description: - The zeroed function returns a zeroed value of any type. -keywords: - [ - zeroed - ] ---- - -Implements `fn zeroed() -> T` to return a zeroed value of any type. This function is generally unsafe to use as the zeroed bit pattern is not guaranteed to be valid for all types. It can however, be useful in cases when the value is guaranteed not to be used such as in a BoundedVec library implementing a growable vector, up to a certain length, backed by an array. The array can be initialized with zeroed values which are guaranteed to be inaccessible until the vector is pushed to. Similarly, enumerations in noir can be implemented using this method by providing zeroed values for the unused variants. - -You can access the function at `std::unsafe::zeroed`. - -This function currently supports the following types: - -- Field -- Bool -- Uint -- Array -- String -- Tuple -- Function - -Using it on other types could result in unexpected behavior. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/explainers/explainer-recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/explainers/explainer-recursion.md deleted file mode 100644 index 9357d3c7341..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/explainers/explainer-recursion.md +++ /dev/null @@ -1,175 +0,0 @@ ---- -title: Recursive proofs -description: Explore the concept of recursive proofs in Zero-Knowledge programming. Understand how recursion works in Noir, a language for writing smart contracts on the EVM blockchain. Learn through practical examples like Alice and Bob's guessing game, Charlie's recursive merkle tree, and Daniel's reusable components. Discover how to use recursive proofs to optimize computational resources and improve efficiency. - -keywords: - [ - "Recursive Proofs", - "Zero-Knowledge Programming", - "Noir", - "EVM Blockchain", - "Smart Contracts", - "Recursion in Noir", - "Alice and Bob Guessing Game", - "Recursive Merkle Tree", - "Reusable Components", - "Optimizing Computational Resources", - "Improving Efficiency", - "Verification Key", - "Aggregation Objects", - "Recursive zkSNARK schemes", - "PLONK", - "Proving and Verification Keys" - ] -sidebar_position: 1 ---- - -In programming, we tend to think of recursion as something calling itself. A classic example would be the calculation of the factorial of a number: - -```js -function factorial(n) { - if (n === 0 || n === 1) { - return 1; - } else { - return n * factorial(n - 1); - } -} -``` - -In this case, while `n` is not `1`, this function will keep calling itself until it hits the base case, bubbling up the result on the call stack: - -```md - Is `n` 1? <--------- - /\ / - / \ n = n -1 - / \ / - Yes No -------- -``` - -In Zero-Knowledge, recursion has some similarities. - -It is not a Noir function calling itself, but a proof being used as an input to another circuit. In short, you verify one proof *inside* another proof, returning the proof that both proofs are valid. - -This means that, given enough computational resources, you can prove the correctness of any arbitrary number of proofs in a single proof. This could be useful to design state channels (for which a common example would be [Bitcoin's Lightning Network](https://en.wikipedia.org/wiki/Lightning_Network)), to save on gas costs by settling one proof on-chain, or simply to make business logic less dependent on a consensus mechanism. - -## Examples - -Let us look at some of these examples - -### Alice and Bob - Guessing game - -Alice and Bob are friends, and they like guessing games. They want to play a guessing game online, but for that, they need a trusted third-party that knows both of their secrets and finishes the game once someone wins. - -So, they use zero-knowledge proofs. Alice tries to guess Bob's number, and Bob will generate a ZK proof stating whether she succeeded or failed. - -This ZK proof can go on a smart contract, revealing the winner and even giving prizes. However, this means every turn needs to be verified on-chain. This incurs some cost and waiting time that may simply make the game too expensive or time-consuming to be worth it. - -So, Alice started thinking: "what if Bob generates his proof, and instead of sending it on-chain, I verify it *within* my own proof before playing my own turn?". She can then generate a proof that she verified his proof, and so on. - -```md - Did you fail? <-------------------------- - / \ / - / \ n = n -1 - / \ / - Yes No / - | | / - | | / - | You win / - | / - | / -Generate proof of that / - + / - my own guess ---------------- -``` - -### Charlie - Recursive merkle tree - -Charlie is a concerned citizen, and wants to be sure his vote in an election is accounted for. He votes with a ZK proof, but he has no way of knowing that his ZK proof was included in the total vote count! - -So, the tallier puts all the votes in a merkle tree, and everyone can also prove the verification of two proofs within one proof, as such: - -```md - abcd - __________|______________ - | | - ab cd - _____|_____ ______|______ - | | | | - alice bob charlie daniel -``` - -Doing this recursively allows us to arrive on a final proof `abcd` which if true, verifies the correctness of all the votes. - -### Daniel - Reusable components - -Daniel has a big circuit and a big headache. A part of his circuit is a setup phase that finishes with some assertions that need to be made. But that section alone takes most of the proving time, and is largely independent of the rest of the circuit. - -He could find it more efficient to generate a proof for that setup phase separately, and verifying it in his actual business logic section of the circuit. This will allow for parallelization of both proofs, which results in a considerable speedup. - -## What params do I need - -As you can see in the [recursion reference](noir/standard_library/recursion.md), a simple recursive proof requires: - -- The proof to verify -- The Verification Key of the circuit that generated the proof -- A hash of this verification key, as it's needed for some backends -- The public inputs for the proof -- The input aggregation object - -It also returns the `output aggregation object`. These aggregation objects can be confusing at times, so let's dive in a little bit. - -### Aggregation objects - -Recursive zkSNARK schemes do not necessarily "verify a proof" in the sense that you expect a true or false to be spit out by the verifier. Rather an aggregation object is built over the public inputs. - -In the case of PLONK the recursive aggregation object is two G1 points (expressed as 16 witness values). The final verifier (in our case this is most often the smart contract verifier) has to be aware of this aggregation object to execute a pairing and check the validity of these points. - -So, taking the example of Alice and Bob and their guessing game: - -- Alice makes her guess. Her proof is *not* recursive: it doesn't verify any proof within it! It's just a standard `assert(x != y)` circuit -- Bob verifies Alice's proof and makes his own guess. In this circuit, he is verifying a proof, so it needs to output an `aggregation object`: he is generating a recursive proof! -- Alice verifies Bob's *recursive proof*, and uses Bob's `output aggregation object` as the `input aggregation object` in her proof... Which in turn, generates another `output aggregation object`. - -One should notice that when Bob generates his first proof, he has no input aggregation object. Because he is not verifying an recursive proof, he has no `input aggregation object`. In this case, he may use zeros instead. - -We can imagine the `aggregation object` as the baton in a [relay race](https://en.wikipedia.org/wiki/Relay_race). The first runner doesn't have to receive the baton from anyone else, as he/she already starts with it. But when his/her turn is over, the next runner needs to receive it, run a bit more, and pass it along. Even though every runner could theoretically verify the baton mid-run (why not? 🏃🔍), only at the end of the race does the referee verify that the whole race is valid. - -## Some architecture - -As with everything in computer science, there's no one-size-fits all. But there are some patterns that could help understanding and implementing them. To give three examples: - -### Adding some logic to a proof verification - -This would be an approach for something like our guessing game, where proofs are sent back and forth and are verified by each opponent. This circuit would be divided in two sections: - -- A `recursive verification` section, which would be just the call to `std::verify_proof`, and that would be skipped on the first move (since there's no proof to verify) -- A `guessing` section, which is basically the logic part where the actual guessing happens - -In such a situation, and assuming Alice is first, she would skip the first part and try to guess Bob's number. Bob would then verify her proof on the first section of his run, and try to guess Alice's number on the second part, and so on. - -### Aggregating proofs - -In some one-way interaction situations, recursion would allow for aggregation of simple proofs that don't need to be immediately verified on-chain or elsewhere. - -To give a practical example, a barman wouldn't need to verify a "proof-of-age" on-chain every time he serves alcohol to a customer. Instead, the architecture would comprise two circuits: - -- A `main`, non-recursive circuit with some logic -- A `recursive` circuit meant to verify two proofs in one proof - -The customer's proofs would be intermediate, and made on their phones, and the barman could just verify them locally. He would then aggregate them into a final proof sent on-chain (or elsewhere) at the end of the day. - -### Recursively verifying different circuits - -Nothing prevents you from verifying different circuits in a recursive proof, for example: - -- A `circuit1` circuit -- A `circuit2` circuit -- A `recursive` circuit - -In this example, a regulator could verify that taxes were paid for a specific purchase by aggregating both a `payer` circuit (proving that a purchase was made and taxes were paid), and a `receipt` circuit (proving that the payment was received) - -## How fast is it - -At the time of writing, verifying recursive proofs is surprisingly fast. This is because most of the time is spent on generating the verification key that will be used to generate the next proof. So you are able to cache the verification key and reuse it later. - -Currently, Noir JS packages don't expose the functionality of loading proving and verification keys, but that feature exists in the underlying `bb.js` package. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/explanations/noir/traits.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/explanations/noir/traits.md deleted file mode 100644 index 7ba07e74f40..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/explanations/noir/traits.md +++ /dev/null @@ -1,348 +0,0 @@ ---- -title: Traits -description: - Traits in Noir can be used to abstract out a common interface for functions across - several data types. -keywords: [noir programming language, traits, interfaces, generic, protocol] ---- - -## Overview - -Traits in Noir are a useful abstraction similar to interfaces or protocols in other languages. Each trait defines -the interface of several methods contained within the trait. Types can then implement this trait by providing -implementations for these methods. For example in the program: - -```rust -struct Rectangle { - width: Field, - height: Field, -} - -impl Rectangle { - fn area(self) -> Field { - self.width * self.height - } -} - -fn log_area(r: Rectangle) { - println(r.area()); -} -``` - -We have a function `log_area` to log the area of a `Rectangle`. Now how should we change the program if we want this -function to work on `Triangle`s as well?: - -```rust -struct Triangle { - width: Field, - height: Field, -} - -impl Triangle { - fn area(self) -> Field { - self.width * self.height / 2 - } -} -``` - -Making `log_area` generic over all types `T` would be invalid since not all types have an `area` method. Instead, we can -introduce a new `Area` trait and make `log_area` generic over all types `T` that implement `Area`: - -```rust -trait Area { - fn area(self) -> Field; -} - -fn log_area(shape: T) where T: Area { - println(shape.area()); -} -``` - -We also need to explicitly implement `Area` for `Rectangle` and `Triangle`. We can do that by changing their existing -impls slightly. Note that the parameter types and return type of each of our `area` methods must match those defined -by the `Area` trait. - -```rust -impl Area for Rectangle { - fn area(self) -> Field { - self.width * self.height - } -} - -impl Area for Triangle { - fn area(self) -> Field { - self.width * self.height / 2 - } -} -``` - -Now we have a working program that is generic over any type of Shape that is used! Others can even use this program -as a library with their own types - such as `Circle` - as long as they also implement `Area` for these types. - -## Where Clauses - -As seen in `log_area` above, when we want to create a function or method that is generic over any type that implements -a trait, we can add a where clause to the generic function. - -```rust -fn log_area(shape: T) where T: Area { - println(shape.area()); -} -``` - -It is also possible to apply multiple trait constraints on the same variable at once by combining traits with the `+` -operator. Similarly, we can have multiple trait constraints by separating each with a comma: - -```rust -fn foo(elements: [T], thing: U) where - T: Default + Add + Eq, - U: Bar, -{ - let mut sum = T::default(); - - for element in elements { - sum += element; - } - - if sum == T::default() { - thing.bar(); - } -} -``` - -## Generic Implementations - -You can add generics to a trait implementation by adding the generic list after the `impl` keyword: - -```rust -trait Second { - fn second(self) -> Field; -} - -impl Second for (T, Field) { - fn second(self) -> Field { - self.1 - } -} -``` - -You can also implement a trait for every type this way: - -```rust -trait Debug { - fn debug(self); -} - -impl Debug for T { - fn debug(self) { - println(self); - } -} - -fn main() { - 1.debug(); -} -``` - -### Generic Trait Implementations With Where Clauses - -Where clauses can also be placed on trait implementations themselves to restrict generics in a similar way. -For example, while `impl Foo for T` implements the trait `Foo` for every type, `impl Foo for T where T: Bar` -will implement `Foo` only for types that also implement `Bar`. This is often used for implementing generic types. -For example, here is the implementation for array equality: - -```rust -impl Eq for [T; N] where T: Eq { - // Test if two arrays have the same elements. - // Because both arrays must have length N, we know their lengths already match. - fn eq(self, other: Self) -> bool { - let mut result = true; - - for i in 0 .. self.len() { - // The T: Eq constraint is needed to call == on the array elements here - result &= self[i] == other[i]; - } - - result - } -} -``` - -## Trait Methods With No `self` - -A trait can contain any number of methods, each of which have access to the `Self` type which represents each type -that eventually implements the trait. Similarly, the `self` variable is available as well but is not required to be used. -For example, we can define a trait to create a default value for a type. This trait will need to return the `Self` type -but doesn't need to take any parameters: - -```rust -trait Default { - fn default() -> Self; -} -``` - -Implementing this trait can be done similarly to any other trait: - -```rust -impl Default for Field { - fn default() -> Field { - 0 - } -} - -struct MyType {} - -impl Default for MyType { - fn default() -> Field { - MyType {} - } -} -``` - -However, since there is no `self` parameter, we cannot call it via the method call syntax `object.method()`. -Instead, we'll need to refer to the function directly. This can be done either by referring to the -specific impl `MyType::default()` or referring to the trait itself `Default::default()`. In the later -case, type inference determines the impl that is selected. - -```rust -let my_struct = MyStruct::default(); - -let x: Field = Default::default(); -let result = x + Default::default(); -``` - -:::warning - -```rust -let _ = Default::default(); -``` - -If type inference cannot select which impl to use because of an ambiguous `Self` type, an impl will be -arbitrarily selected. This occurs most often when the result of a trait function call with no parameters -is unused. To avoid this, when calling a trait function with no `self` or `Self` parameters or return type, -always refer to it via the implementation type's namespace - e.g. `MyType::default()`. -This is set to change to an error in future Noir versions. - -::: - -## Default Method Implementations - -A trait can also have default implementations of its methods by giving a body to the desired functions. -Note that this body must be valid for all types that may implement the trait. As a result, the only -valid operations on `self` will be operations valid for any type or other operations on the trait itself. - -```rust -trait Numeric { - fn add(self, other: Self) -> Self; - - // Default implementation of double is (self + self) - fn double(self) -> Self { - self.add(self) - } -} -``` - -When implementing a trait with default functions, a type may choose to implement only the required functions: - -```rust -impl Numeric for Field { - fn add(self, other: Field) -> Field { - self + other - } -} -``` - -Or it may implement the optional methods as well: - -```rust -impl Numeric for u32 { - fn add(self, other: u32) -> u32 { - self + other - } - - fn double(self) -> u32 { - self * 2 - } -} -``` - -## Impl Specialization - -When implementing traits for a generic type it is possible to implement the trait for only a certain combination -of generics. This can be either as an optimization or because those specific generics are required to implement the trait. - -```rust -trait Sub { - fn sub(self, other: Self) -> Self; -} - -struct NonZero { - value: T, -} - -impl Sub for NonZero { - fn sub(self, other: Self) -> Self { - let value = self.value - other.value; - assert(value != 0); - NonZero { value } - } -} -``` - -## Overlapping Implementations - -Overlapping implementations are disallowed by Noir to ensure Noir's decision on which impl to select is never ambiguous. -This means if a trait `Foo` is already implemented -by a type `Bar` for all `T`, then we cannot also have a separate impl for `Bar` (or any other -type argument). Similarly, if there is an impl for all `T` such as `impl Debug for T`, we cannot create -any more impls to `Debug` for other types since it would be ambiguous which impl to choose for any given -method call. - -```rust -trait Trait {} - -// Previous impl defined here -impl Trait for (A, B) {} - -// error: Impl for type `(Field, Field)` overlaps with existing impl -impl Trait for (Field, Field) {} -``` - -## Trait Coherence - -Another restriction on trait implementations is coherence. This restriction ensures other crates cannot create -impls that may overlap with other impls, even if several unrelated crates are used as dependencies in the same -program. - -The coherence restriction is: to implement a trait, either the trait itself or the object type must be declared -in the crate the impl is in. - -In practice this often comes up when using types provided by libraries. If a library provides a type `Foo` that does -not implement a trait in the standard library such as `Default`, you may not `impl Default for Foo` in your own crate. -While restrictive, this prevents later issues or silent changes in the program if the `Foo` library later added its -own impl for `Default`. If you are a user of the `Foo` library in this scenario and need a trait not implemented by the -library your choices are to either submit a patch to the library or use the newtype pattern. - -### The Newtype Pattern - -The newtype pattern gets around the coherence restriction by creating a new wrapper type around the library type -that we cannot create `impl`s for. Since the new wrapper type is defined in our current crate, we can create -impls for any trait we need on it. - -```rust -struct Wrapper { - foo: dep::some_library::Foo, -} - -impl Default for Wrapper { - fn default() -> Wrapper { - Wrapper { - foo: dep::some_library::Foo::new(), - } - } -} -``` - -Since we have an impl for our own type, the behavior of this code will not change even if `some_library` is updated -to provide its own `impl Default for Foo`. The downside of this pattern is that it requires extra wrapping and -unwrapping of values when converting to and from the `Wrapper` and `Foo` types. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/explanations/standard_library/traits.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/explanations/standard_library/traits.md deleted file mode 100644 index 63b4f3d6f0b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/explanations/standard_library/traits.md +++ /dev/null @@ -1,140 +0,0 @@ ---- -title: Traits -description: Noir's stdlib provides a few commonly used traits. -keywords: [traits, trait, interface, protocol, default, add, eq] ---- - -## `std::default` - -### `std::default::Default` - -```rust -trait Default { - fn default() -> Self; -} -``` - -Constructs a default value of a type. - -Implementations: -```rust -impl Default for Field { .. } - -impl Default for i8 { .. } -impl Default for i16 { .. } -impl Default for i32 { .. } -impl Default for i64 { .. } - -impl Default for u8 { .. } -impl Default for u16 { .. } -impl Default for u32 { .. } -impl Default for u64 { .. } - -impl Default for () { .. } -impl Default for bool { .. } - -impl Default for [T; N] - where T: Default { .. } - -impl Default for (A, B) - where A: Default, B: Default { .. } - -impl Default for (A, B, C) - where A: Default, B: Default, C: Default { .. } - -impl Default for (A, B, C, D) - where A: Default, B: Default, C: Default, D: Default { .. } - -impl Default for (A, B, C, D, E) - where A: Default, B: Default, C: Default, D: Default, E: Default { .. } -``` - -For primitive integer types, the return value of `default` is `0`. Container -types such as arrays are filled with default values of their element type. - -## `std::ops` - -### `std::ops::Eq` - -```rust -trait Eq { - fn eq(self, other: Self) -> bool; -} -``` -Returns `true` if `self` is equal to `other`. - -Implementations: -```rust -impl Eq for Field { .. } - -impl Eq for i8 { .. } -impl Eq for i16 { .. } -impl Eq for i32 { .. } -impl Eq for i64 { .. } - -impl Eq for u8 { .. } -impl Eq for u16 { .. } -impl Eq for u32 { .. } -impl Eq for u64 { .. } - -impl Eq for () { .. } -impl Eq for bool { .. } - -impl Eq for [T; N] - where T: Eq { .. } - -impl Eq for (A, B) - where A: Eq, B: Eq { .. } - -impl Eq for (A, B, C) - where A: Eq, B: Eq, C: Eq { .. } - -impl Eq for (A, B, C, D) - where A: Eq, B: Eq, C: Eq, D: Eq { .. } - -impl Eq for (A, B, C, D, E) - where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq { .. } -``` - -### `std::ops::Add`, `std::ops::Sub`, `std::ops::Mul`, and `std::ops::Div` - -These traits abstract over addition, subtraction, multiplication, and division respectively. -Although Noir does not currently have operator overloading, in the future implementing these -traits for a given type will also allow that type to be used with the corresponding operator -for that trait (`+` for Add, etc) in addition to the normal method names. - -```rust -trait Add { - fn add(self, other: Self) -> Self; -} - -trait Sub { - fn sub(self, other: Self) -> Self; -} - -trait Mul { - fn mul(self, other: Self) -> Self; -} - -trait Div { - fn div(self, other: Self) -> Self; -} -``` - -The implementations block below is given for the `Add` trait, but the same types that implement -`Add` also implement `Sub`, `Mul`, and `Div`. - -Implementations: -```rust -impl Add for Field { .. } - -impl Add for i8 { .. } -impl Add for i16 { .. } -impl Add for i32 { .. } -impl Add for i64 { .. } - -impl Add for u8 { .. } -impl Add for u16 { .. } -impl Add for u32 { .. } -impl Add for u64 { .. } -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/getting_started/create_a_project.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/getting_started/create_a_project.md deleted file mode 100644 index f10916c39c5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/getting_started/create_a_project.md +++ /dev/null @@ -1,142 +0,0 @@ ---- -title: Creating A Project -description: - Learn how to create and verify your first Noir program using Nargo, a programming language for - zero-knowledge proofs. -keywords: - [ - Nargo, - Noir, - zero-knowledge proofs, - programming language, - create Noir program, - verify Noir program, - step-by-step guide, - ] -sidebar_position: 1 - ---- - -Now that we have installed Nargo, it is time to make our first hello world program! - -## Create a Project Directory - -Noir code can live anywhere on your computer. Let us create a _projects_ folder in the home -directory to house our Noir programs. - -For Linux, macOS, and Windows PowerShell, create the directory and change directory into it by -running: - -```sh -mkdir ~/projects -cd ~/projects -``` - -## Create Our First Nargo Project - -Now that we are in the projects directory, create a new Nargo project by running: - -```sh -nargo new hello_world -``` - -> **Note:** `hello_world` can be any arbitrary project name, we are simply using `hello_world` for -> demonstration. -> -> In production, the common practice is to name the project folder as `circuits` for better -> identifiability when sitting alongside other folders in the codebase (e.g. `contracts`, `scripts`, -> `test`). - -A `hello_world` folder would be created. Similar to Rust, the folder houses _src/main.nr_ and -_Nargo.toml_ that contains the source code and environmental options of your Noir program -respectively. - -### Intro to Noir Syntax - -Let us take a closer look at _main.nr_. The default _main.nr_ generated should look like this: - -```rust -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` - -The first line of the program specifies the program's inputs: - -```rust -x : Field, y : pub Field -``` - -Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the -keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](../noir/syntax/data_types/index.md) section. - -The next line of the program specifies its body: - -```rust -assert(x != y); -``` - -The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. - -For more Noir syntax, check the [Language Concepts](../noir/syntax/comments.md) chapter. - -## Build In/Output Files - -Change directory into _hello_world_ and build in/output files for your Noir program by running: - -```sh -cd hello_world -nargo check -``` - -Two additional files would be generated in your project directory: - -_Prover.toml_ houses input values, and _Verifier.toml_ houses public values. - -## Prove Our Noir Program - -Now that the project is set up, we can create a proof of correct execution on our Noir program. - -Fill in input values for execution in the _Prover.toml_ file. For example: - -```toml -x = "1" -y = "2" -``` - -Prove the valid execution of your Noir program: - -```sh -nargo prove -``` - -A new folder _proofs_ would then be generated in your project directory, containing the proof file -`.proof`, where the project name is defined in Nargo.toml. - -The _Verifier.toml_ file would also be updated with the public values computed from program -execution (in this case the value of `y`): - -```toml -y = "0x0000000000000000000000000000000000000000000000000000000000000002" -``` - -> **Note:** Values in _Verifier.toml_ are computed as 32-byte hex values. - -## Verify Our Noir Program - -Once a proof is generated, we can verify correct execution of our Noir program by verifying the -proof file. - -Verify your proof by running: - -```sh -nargo verify -``` - -The verification will complete in silence if it is successful. If it fails, it will log the -corresponding error instead. - -Congratulations, you have now created and verified a proof for your very first Noir program! - -In the [next section](./project_breakdown.md), we will go into more detail on each step performed. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/getting_started/installation/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/getting_started/installation/index.md deleted file mode 100644 index ddb8a250eb4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/getting_started/installation/index.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Nargo Installation -description: - nargo is a command line tool for interacting with Noir programs. This page is a quick guide on how to install Nargo though the most common and easy method, noirup -keywords: [ - Nargo - Noir - Rust - Cargo - Noirup - Installation - Terminal Commands - Version Check - Nightlies - Specific Versions - Branches - Noirup Repository -] ---- - -`nargo` is the one-stop-shop for almost everything related with Noir. The name comes from our love for Rust and its package manager `cargo`. - -With `nargo`, you can start new projects, compile, execute, prove, verify, test, generate solidity contracts, and do pretty much all that is available in Noir. - -Similarly to `rustup`, we also maintain an easy installation method that covers most machines: `noirup`. - -## Installing Noirup - -Open a terminal on your machine, and write: - -```bash -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -Close the terminal, open another one, and run - -```bash -noirup -``` - -Done. That's it. You should have the latest version working. You can check with `nargo --version`. - -You can also install nightlies, specific versions -or branches, check out the [noirup repository](https://github.com/noir-lang/noirup) for more -information. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/getting_started/installation/other_install_methods.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/getting_started/installation/other_install_methods.md deleted file mode 100644 index a532f83750e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/getting_started/installation/other_install_methods.md +++ /dev/null @@ -1,190 +0,0 @@ ---- -title: Alternative Install Methods -description: - There are different ways to install Nargo, the one-stop shop and command-line tool for developing Noir programs. This guide explains other methods that don't rely on noirup, such as compiling from source, installing from binaries, and using WSL for windows -keywords: [ - Installation - Nargo - Noirup - Binaries - Compiling from Source - WSL for Windows - macOS - Linux - Nix - Direnv - Shell & editor experience - Building and testing - Uninstalling Nargo - Noir vs code extension -] -sidebar_position: 1 ---- - - -## Installation - -The most common method of installing Nargo is through [Noirup](./index.md) - -However, there are other methods for installing Nargo: - -- [Binaries](#binaries) -- [Compiling from Source](#compile-from-source) -- [WSL for Windows](#wsl-for-windows) - -### Binaries - -See [GitHub Releases](https://github.com/noir-lang/noir/releases) for the latest and previous -platform specific binaries. - -#### Step 1 - -Paste and run the following in the terminal to extract and install the binary: - -> **macOS / Linux:** If you are prompted with `Permission denied` when running commands, prepend -> `sudo` and re-run it. - -##### macOS (Apple Silicon) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-aarch64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### macOS (Intel) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### Linux (Bash) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-unknown-linux-gnu.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -C $HOME/.nargo/bin/ && \ -echo -e '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.bashrc && \ -source ~/.bashrc -``` - -#### Step 2 - -Check if the installation was successful by running `nargo --version`. You should get a version number. - -> **macOS:** If you are prompted with an OS alert, right-click and open the _nargo_ executable from -> Finder. Close the new terminal popped up and `nargo` should now be accessible. - -### Option 3: Compile from Source - -Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. It helps mitigating issues commonly associated with dependency management, such as conflicts between required package versions for different projects (often referred to as "dependency hell"). - -Combined with direnv, which automatically sets or clears environment variables based on the directory, it further simplifies the development process by seamlessly integrating with the developer's shell, facilitating an efficient and reliable workflow for managing and deploying Noir projects with multiple dependencies. - -#### Setting up your environment - -For the best experience, please follow these instructions to setup your environment: - -1. Install Nix following [their guide](https://nixos.org/download.html) for your operating system. -2. Create the file `~/.config/nix/nix.conf` with the contents: - -```ini -experimental-features = nix-command -extra-experimental-features = flakes -``` - -3. Install direnv into your Nix profile by running: - -```sh -nix profile install nixpkgs#direnv -``` - -4. Add direnv to your shell following [their guide](https://direnv.net/docs/hook.html). - 1. For bash or zshell, add `eval "$(direnv hook bash)"` or `eval "$(direnv hook zsh)"` to your ~/.bashrc or ~/.zshrc file, respectively. -5. Restart your shell. - -#### Shell & editor experience - -Now that your environment is set up, you can get to work on the project. - -1. Clone the repository, such as: - -```sh -git clone git@github.com:noir-lang/noir -``` - -> Replacing `noir` with whichever repository you want to work on. - -2. Navigate to the directory: - -```sh -cd noir -``` - -> Replacing `noir` with whichever repository you cloned. - -3. You should see a **direnv error** because projects aren't allowed by default. Make sure you've reviewed and trust our `.envrc` file, then you need to run: - -```sh -direnv allow -``` - -4. Now, wait awhile for all the native dependencies to be built. This will take some time and direnv will warn you that it is taking a long time, but we just need to let it run. - -5. Once you are presented with your prompt again, you can start your editor within the project directory (we recommend [VSCode](https://code.visualstudio.com/)): - -```sh -code . -``` - -6. (Recommended) When launching VSCode for the first time, you should be prompted to install our recommended plugins. We highly recommend installing these for the best development experience. - -#### Building and testing - -Assuming you are using `direnv` to populate your environment, building and testing the project can be done -with the typical `cargo build`, `cargo test`, and `cargo clippy` commands. You'll notice that the `cargo` version matches the version we specify in `rust-toolchain.toml`, which is 1.71.1 at the time of this writing. - -If you want to build the entire project in an isolated sandbox, you can use Nix commands: - -1. `nix build .` (or `nix build . -L` for verbose output) to build the project in a Nix sandbox. -2. `nix flake check` (or `nix flake check -L` for verbose output) to run clippy and tests in a Nix sandbox. - -#### Without `direnv` - -If you have hesitations with using direnv, you can launch a subshell with `nix develop` and then launch your editor from within the subshell. However, if VSCode was already launched in the project directory, the environment won't be updated. - -Advanced: If you aren't using direnv nor launching your editor within the subshell, you can try to install Barretenberg and other global dependencies the package needs. This is an advanced workflow and likely won't receive support! - -### Option 4: WSL (for Windows) - -The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed natively. However, it is available by using Windows Subsystem for Linux (WSL). - -Step 1: Follow the instructions [here](https://learn.microsoft.com/en-us/windows/wsl/install) to install and run WSL. - -step 2: Follow the [Noirup instructions](./index.md). - -## Uninstalling Nargo - -### Noirup - -If you installed Noir with `noirup`, you can uninstall Noir by removing the files in `~/.nargo`, `~/nargo` and `~/noir_cache`. - -```bash -rm -r ~/.nargo -rm -r ~/nargo -rm -r ~/noir_cache -``` - -### Nix - -If you installed Noir with Nix or from source, you can remove the binary located at `~/.nix-profile/bin/nargo`. - -```bash -rm ~/.nix-profile/bin/nargo -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/getting_started/project_breakdown.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/getting_started/project_breakdown.md deleted file mode 100644 index c4e2a9ae003..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/getting_started/project_breakdown.md +++ /dev/null @@ -1,199 +0,0 @@ ---- -title: Project Breakdown -description: - Learn about the anatomy of a Nargo project, including the purpose of the Prover and Verifier TOML - files, and how to prove and verify your program. -keywords: - [Nargo, Nargo project, Prover.toml, Verifier.toml, proof verification, private asset transfer] -sidebar_position: 2 ---- - -This section breaks down our hello world program in section _1.2_. We elaborate on the project -structure and what the `prove` and `verify` commands did in the previous section. - -## Anatomy of a Nargo Project - -Upon creating a new project with `nargo new` and building the in/output files with `nargo check` -commands, you would get a minimal Nargo project of the following structure: - - - src - - Prover.toml - - Verifier.toml - - Nargo.toml - -The source directory _src_ holds the source code for your Noir program. By default only a _main.nr_ -file will be generated within it. - -### Prover.toml - -_Prover.toml_ is used for specifying the input values for executing and proving the program. You can specify `toml` files with different names by using the `--prover-name` or `-p` flags, see the [Prover](#provertoml) section below. Optionally you may specify expected output values for prove-time checking as well. - -### Verifier.toml - -_Verifier.toml_ contains public in/output values computed when executing the Noir program. - -### Nargo.toml - -_Nargo.toml_ contains the environmental options of your project. It contains a "package" section and a "dependencies" section. - -Example Nargo.toml: - -```toml -[package] -name = "noir_starter" -type = "bin" -authors = ["Alice"] -compiler_version = "0.9.0" -description = "Getting started with Noir" -entry = "circuit/main.nr" -license = "MIT" - -[dependencies] -ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} -``` - -Nargo.toml for a [workspace](../noir/modules_packages_crates/workspaces.md) will look a bit different. For example: - -```toml -[workspace] -members = ["crates/a", "crates/b"] -default-member = "crates/a" -``` - -#### Package section - -The package section requires a number of fields including: - -- `name` (**required**) - the name of the package -- `type` (**required**) - can be "bin", "lib", or "contract" to specify whether its a binary, library or Aztec contract -- `authors` (optional) - authors of the project -- `compiler_version` - specifies the version of the compiler to use. This is enforced by the compiler and follow's [Rust's versioning](https://doc.rust-lang.org/cargo/reference/manifest.html#the-version-field), so a `compiler_version = 0.18.0` will enforce Nargo version 0.18.0, `compiler_version = ^0.18.0` will enforce anything above 0.18.0 but below 0.19.0, etc. For more information, see how [Rust handles these operators](https://docs.rs/semver/latest/semver/enum.Op.html) -- `description` (optional) -- `entry` (optional) - a relative filepath to use as the entry point into your package (overrides the default of `src/lib.nr` or `src/main.nr`) -- `backend` (optional) -- `license` (optional) - -#### Dependencies section - -This is where you will specify any dependencies for your project. See the [Dependencies page](../noir/modules_packages_crates/dependencies.md) for more info. - -`./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or -verifier contract respectively. - -### main.nr - -The _main.nr_ file contains a `main` method, this method is the entry point into your Noir program. - -In our sample program, _main.nr_ looks like this: - -```rust -fn main(x : Field, y : Field) { - assert(x != y); -} -``` - -The parameters `x` and `y` can be seen as the API for the program and must be supplied by the -prover. Since neither `x` nor `y` is marked as public, the verifier does not supply any inputs, when -verifying the proof. - -The prover supplies the values for `x` and `y` in the _Prover.toml_ file. - -As for the program body, `assert` ensures the satisfaction of the condition (e.g. `x != y`) is -constrained by the proof of the execution of said program (i.e. if the condition was not met, the -verifier would reject the proof as an invalid proof). - -### Prover.toml - -The _Prover.toml_ file is a file which the prover uses to supply his witness values(both private and -public). - -In our hello world program the _Prover.toml_ file looks like this: - -```toml -x = "1" -y = "2" -``` - -When the command `nargo prove` is executed, two processes happen: - -1. Noir creates a proof that `x` which holds the value of `1` and `y` which holds the value of `2` - is not equal. This not equal constraint is due to the line `assert(x != y)`. - -2. Noir creates and stores the proof of this statement in the _proofs_ directory in a file called your-project.proof. So if your project is named "private_voting" (defined in the project Nargo.toml), the proof will be saved at `./proofs/private_voting.proof`. Opening this file will display the proof in hex format. - -#### Arrays of Structs - -The following code shows how to pass an array of structs to a Noir program to generate a proof. - -```rust -// main.nr -struct Foo { - bar: Field, - baz: Field, -} - -fn main(foos: [Foo; 3]) -> pub Field { - foos[2].bar + foos[2].baz -} -``` - -Prover.toml: - -```toml -[[foos]] # foos[0] -bar = 0 -baz = 0 - -[[foos]] # foos[1] -bar = 0 -baz = 0 - -[[foos]] # foos[2] -bar = 1 -baz = 2 -``` - -#### Custom toml files - -You can specify a `toml` file with a different name to use for proving by using the `--prover-name` or `-p` flags. - -This command looks for proof inputs in the default **Prover.toml** and generates the proof and saves it at `./proofs/.proof`: - -```bash -nargo prove -``` - -This command looks for proof inputs in the custom **OtherProver.toml** and generates proof and saves it at `./proofs/.proof`: - -```bash -nargo prove -p OtherProver -``` - -## Verifying a Proof - -When the command `nargo verify` is executed, two processes happen: - -1. Noir checks in the _proofs_ directory for a proof file with the project name (eg. test_project.proof) - -2. If that file is found, the proof's validity is checked - -> **Note:** The validity of the proof is linked to the current Noir program; if the program is -> changed and the verifier verifies the proof, it will fail because the proof is not valid for the -> _modified_ Noir program. - -In production, the prover and the verifier are usually two separate entities. A prover would -retrieve the necessary inputs, execute the Noir program, generate a proof and pass it to the -verifier. The verifier would then retrieve the public inputs from usually external sources and -verifies the validity of the proof against it. - -Take a private asset transfer as an example: - -A user on browser as the prover would retrieve private inputs (e.g. the user's private key) and -public inputs (e.g. the user's encrypted balance on-chain), compute the transfer, generate a proof -and submit it to the verifier smart contract. - -The verifier contract would then draw the user's encrypted balance directly from the blockchain and -verify the proof submitted against it. If the verification passes, additional functions in the -verifier contract could trigger (e.g. approve the asset transfer). - -Now that you understand the concepts, you'll probably want some editor feedback while you are writing more complex code. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/getting_started/tooling/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/getting_started/tooling/_category_.json deleted file mode 100644 index dff520ebc41..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/getting_started/tooling/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "position": 3, - "label": "Tooling", - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/getting_started/tooling/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/getting_started/tooling/index.md deleted file mode 100644 index 16f5f3ca45e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/getting_started/tooling/index.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: Tooling -Description: This section provides information about the various tools and utilities available for Noir development. It covers IDE tools, Codespaces, and community projects. -Keywords: [Noir, Development, Playground, IDE Tools, Language Service Provider, VS Code Extension, Codespaces, noir-starter, Community Projects, Awesome Noir Repository, Developer Tooling] ---- - -Noir is meant to be easy to develop with. For that reason, a number of utilities have been put together to ease the development process as much as feasible in the zero-knowledge world. - -## IDE tools - -When you install Nargo, you're also installing a Language Service Provider (LSP), which can be used by IDEs to provide syntax highlighting, codelens, warnings, and more. - -The easiest way to use these tools is by installing the [Noir VS Code extension](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). - -## Codespaces - -Some Noir repos have leveraged Codespaces in order to ease the development process. You can visit the [noir-starter](https://github.com/noir-lang/noir-starter) for an example. - -## GitHub Actions - -You can use `noirup` with GitHub Actions for CI/CD and automated testing. It is as simple as -installing `noirup` and running tests in your GitHub Action `yml` file. - -See the -[config file in the Noir repo](https://github.com/TomAFrench/noir-hashes/blob/master/.github/workflows/noir.yml) for an example usage. - -## Community projects - -As an open-source project, Noir has received many contributions over time. Some of them are related with developer tooling, and you can see some of them in [Awesome Noir repository](https://github.com/noir-lang/awesome-noir#dev-tools) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/how_to/how-to-recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/how_to/how-to-recursion.md deleted file mode 100644 index 2f7be604401..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/how_to/how-to-recursion.md +++ /dev/null @@ -1,184 +0,0 @@ ---- -title: How to use recursion on NoirJS -description: Learn how to implement recursion with NoirJS, a powerful tool for creating smart contracts on the EVM blockchain. This guide assumes familiarity with NoirJS, solidity verifiers, and the Barretenberg proving backend. Discover how to generate both final and intermediate proofs using `noir_js` and `backend_barretenberg`. -keywords: - [ - "NoirJS", - "EVM blockchain", - "smart contracts", - "recursion", - "solidity verifiers", - "Barretenberg backend", - "noir_js", - "backend_barretenberg", - "intermediate proofs", - "final proofs", - "nargo compile", - "json import", - "recursive circuit", - "recursive app" - ] -sidebar_position: 1 ---- - -This guide shows you how to use recursive proofs in your NoirJS app. For the sake of clarity, it is assumed that: - -- You already have a NoirJS app. If you don't, please visit the [NoirJS tutorial](../tutorials/noirjs_app.md) and the [reference](../reference/NoirJS/noir_js/index.md). -- You are familiar with what are recursive proofs and you have read the [recursion explainer](../explainers/explainer-recursion.md) -- You already built a recursive circuit following [the reference](../noir/standard_library/recursion.md), and understand how it works. - -It is also assumed that you're not using `noir_wasm` for compilation, and instead you've used [`nargo compile`](../reference/nargo_commands.md) to generate the `json` you're now importing into your project. However, the guide should work just the same if you're using `noir_wasm`. - -:::info - -As you've read in the [explainer](../explainers/explainer-recursion.md), a recursive proof is an intermediate proof. Meaning it doesn't necessarily generate the final step that makes it verifiable in a smart contract. However, it is easy to verify within another circuit. - -While "standard" usage of NoirJS packages abstracts final proofs, it currently lacks the necessary interface to abstract away intermediate proofs. Which means these proofs need to be created by using the backend directly. - -In short: - -- `noir_js` generates *only* final proofs -- `backend_barretenberg` generates both types of proofs - -::: - -In a standard recursive app, you're also dealing with at least two circuits. For the purpose of this guide, we will assume these two: - -- `main`: a circuit of type `assert(x != y)` -- `recursive`: a circuit that verifies `main` - -For a full example on how recursive proofs work, please refer to the [noir-examples](https://github.com/noir-lang/noir-examples) repository. We will *not* be using it as a reference for this guide. - -## Step 1: Setup - -In a common NoirJS app, you need to instantiate a backend with something like `const backend = new Backend(circuit)`. Then you feed it to the `noir_js` interface. - -For recursion, this doesn't happen, and the only need for `noir_js` is only to `execute` a circuit and get its witness and return value. Everything else is not interfaced, so it needs to happen on the `backend` object. - -It is also recommended that you instantiate the backend with as many threads as possible, to allow for maximum concurrency: - -```js -const backend = new Backend(circuit, { threads: 8 }) -``` - -:::tip -You can use the [`os.cpus()`](https://nodejs.org/api/os.html#oscpus) object in `nodejs` or [`navigator.hardwareConcurrency`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/hardwareConcurrency) on the browser to make the most out of those glorious cpu cores -::: - -## Step 2: Generating the witness and the proof for `main` - -After instantiating the backend, you should also instantiate `noir_js`. We will use it to execute the circuit and get the witness. - -```js -const noir = new Noir(circuit, backend) -const { witness } = noir.execute(input) -``` - -With this witness, you are now able to generate the intermediate proof for the main circuit: - -```js -const { proof, publicInputs } = await backend.generateIntermediateProof(witness) -``` - -:::warning - -Always keep in mind what is actually happening on your development process, otherwise you'll quickly become confused about what circuit are we actually running and why! - -In this case, you can imagine that Alice (running the `main` circuit) is proving something to Bob (running the `recursive` circuit), and Bob is verifying her proof within his proof. - -With this in mind, it becomes clear that our intermediate proof is the one *meant to be verified within another circuit*. So it is Alice's. Actually, the only final proof in this theoretical scenario would be the last one, sent on-chain. - -::: - -## Step 3 - Verification and proof artifacts - -Optionally, you are able to verify the intermediate proof: - -```js -const verified = await backend.verifyIntermediateProof({ proof, publicInputs }) -``` - -This can be useful to make sure our intermediate proof was correctly generated. But the real goal is to do it within another circuit. For that, we need to generate the intermediate artifacts: - -```js -const { proofAsFields, vkAsFields, vkHash } = await backend.generateIntermediateProofArtifacts( { publicInputs, proof }, publicInputsCount) -``` - -This call takes the public inputs and the proof, but also the public inputs count. While this is easily retrievable by simply counting the `publicInputs` length, the backend interface doesn't currently abstract it away. - -:::info - -The `proofAsFields` has a constant size `[Field; 93]`. However, currently the backend doesn't remove the public inputs from the proof when converting it. - -This means that if your `main` circuit has two public inputs, then you should also modify the recursive circuit to accept a proof with the public inputs appended. This means that in our example, since `y` is a public input, our `proofAsFields` is of type `[Field; 94]`. - -Verification keys in Barretenberg are always of size 114. - -::: - -:::warning - -One common mistake is to forget *who* makes this call. - -In a situation where Alice is generating the `main` proof, if she generates the proof artifacts and sends them to Bob, which gladly takes them as true, this would mean Alice could prove anything! - -Instead, Bob needs to make sure *he* extracts the proof artifacts, using his own instance of the `main` circuit backend. This way, Alice has to provide a valid proof for the correct `main` circuit. - -::: - -## Step 4 - Recursive proof generation - -With the artifacts, generating a recursive proof is no different from a normal proof. You simply use the `backend` (with the recursive circuit) to generate it: - -```js -const recursiveInputs = { - verification_key: vkAsFields, // array of length 114 - proof: proofAsFields, // array of length 93 + size of public inputs - publicInputs: [mainInput.y], // using the example above, where `y` is the only public input - key_hash: vkHash, - input_aggregation_object: Array(16).fill(0) // this circuit is verifying a non-recursive proof, so there's no input aggregation object: just use zero -} - -const { witness, returnValue } = noir.execute(recursiveInputs) // we're executing the recursive circuit now! -const { proof, publicInputs } = backend.generateFinalProof(witness) -const verified = backend.verifyFinalProof({ proof, publicInputs }) -``` - -You can obviously chain this proof into another proof. In fact, if you're using recursive proofs, you're probably interested of using them this way! In that case, you should keep in mind the `returnValue`, as it will contain the `input_aggregation_object` for the next proof. - -:::tip - -Managing circuits and "who does what" can be confusing. To make sure your naming is consistent, you can keep them in an object. For example: - -```js -const circuits = { -main: mainJSON, -recursive: recursiveJSON -} -const backends = { -main: new BarretenbergBackend(circuits.main), -recursive: new BarretenbergBackend(circuits.recursive) -} -const noir_programs = { -main: new Noir(circuits.main, backends.main), -recursive: new Noir(circuits.recursive, backends.recursive) -} -``` - -This allows you to neatly call exactly the method you want without conflicting names: - -```js -// Alice runs this 👇 -const { witness: mainWitness } = await noir_programs.main.execute(input) -const proof = await backends.main.generateIntermediateProof(mainWitness) - -// Bob runs this 👇 -const verified = await backends.main.verifyIntermediateProof(proof) -const { proofAsFields, vkAsFields, vkHash } = await backends.main.generateIntermediateProofArtifacts( - proof, - numPublicInputs, -); -const recursiveProof = await noir_programs.recursive.generateFinalProof(recursiveInputs) -``` - -::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/how_to/merkle-proof.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/how_to/merkle-proof.mdx deleted file mode 100644 index 34074659ac1..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/how_to/merkle-proof.mdx +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Prove Merkle Tree Membership -description: - Learn how to use merkle membership proof in Noir to prove that a given leaf is a member of a - merkle tree with a specified root, at a given index. -keywords: - [merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree] ---- - -Let's walk through an example of a merkle membership proof in Noir that proves that a given leaf is -in a merkle tree. - -```rust -use dep::std; - -fn main(message : [Field; 62], index : Field, hashpath : [Field; 40], root : Field) { - let leaf = std::hash::hash_to_field(message); - let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); - assert(merkle_root == root); -} - -``` - -The message is hashed using `hash_to_field`. The specific hash function that is being used is chosen -by the backend. The only requirement is that this hash function can heuristically be used as a -random oracle. If only collision resistance is needed, then one can call `std::hash::pedersen_hash` -instead. - -```rust -let leaf = std::hash::hash_to_field(message); -``` - -The leaf is then passed to a compute_merkle_root function with the root, index and hashpath. The returned root can then be asserted to be the same as the provided root. - -```rust -let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); -assert (merkle_root == root); -``` - -> **Note:** It is possible to re-implement the merkle tree implementation without standard library. -> However, for most usecases, it is enough. In general, the standard library will always opt to be -> as conservative as possible, while striking a balance with efficiency. - -An example, the merkle membership proof, only requires a hash function that has collision -resistance, hence a hash function like Pedersen is allowed, which in most cases is more efficient -than the even more conservative sha256. - -[View an example on the starter repo](https://github.com/noir-lang/noir-examples/blob/3ea09545cabfa464124ec2f3ea8e60c608abe6df/stealthdrop/circuits/src/main.nr#L20) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/how_to/solidity_verifier.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/how_to/solidity_verifier.md deleted file mode 100644 index 6aaad542ee0..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/how_to/solidity_verifier.md +++ /dev/null @@ -1,131 +0,0 @@ ---- -title: Generate a Solidity Verifier -description: - Learn how to run the verifier as a smart contract on the blockchain. Compile a Solidity verifier - contract for your Noir program and deploy it on any EVM blockchain acting as a verifier smart - contract. Read more to find out -keywords: - [ - solidity verifier, - smart contract, - blockchain, - compiler, - plonk_vk.sol, - EVM blockchain, - verifying Noir programs, - proving backend, - Barretenberg, - ] -sidebar_position: 0 ---- - -For certain applications, it may be desirable to run the verifier as a smart contract instead of on -a local machine. - -Compile a Solidity verifier contract for your Noir program by running: - -```sh -nargo codegen-verifier -``` - -A new `contract` folder would then be generated in your project directory, containing the Solidity -file `plonk_vk.sol`. It can be deployed on any EVM blockchain acting as a verifier smart contract. - -> **Note:** It is possible to compile verifier contracts of Noir programs for other smart contract -> platforms as long as the proving backend supplies an implementation. -> -> Barretenberg, the default proving backend for Nargo, supports compilation of verifier contracts in -> Solidity only for the time being. - -## Verify - -To verify a proof using the Solidity verifier contract, call the `verify` function with the -following signature: - -```solidity -function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) -``` - -You can see an example of how the `verify` function is called in the example zk voting application [here](https://github.com/noir-lang/noir-examples/blob/33e598c257e2402ea3a6b68dd4c5ad492bce1b0a/foundry-voting/src/zkVote.sol#L35): - -```solidity -function castVote(bytes calldata proof, uint proposalId, uint vote, bytes32 nullifierHash) public returns (bool) { - // ... - bytes32[] memory publicInputs = new bytes32[](4); - publicInputs[0] = merkleRoot; - publicInputs[1] = bytes32(proposalId); - publicInputs[2] = bytes32(vote); - publicInputs[3] = nullifierHash; - require(verifier.verify(proof, publicInputs), "Invalid proof"); -``` - -### Public Inputs - -:::tip - -A circuit doesn't have the concept of a return value. Return values are just syntactic sugar in -Noir. - -Under the hood, the return value is passed as an input to the circuit and is checked at the end of -the circuit program. - -::: - -The verifier contract uses the output (return) value of a Noir program as a public input. So if you -have the following function - -```rust -fn main( - // Public inputs - pubkey_x: pub Field, - pubkey_y: pub Field, - // Private inputs - priv_key: Field, -) -> pub Field -``` - -then `verify` in `plonk_vk.sol` will expect 3 public inputs. Passing two inputs will result in an -error like `Reason: PUBLIC_INPUT_COUNT_INVALID(3, 2)`. - -In this case the 3 inputs to `verify` would be ordered as `[pubkey_x, pubkey_y, return]`. - -#### Struct inputs - -Consider the following program: - -```rust -struct Type1 { - val1: Field, - val2: Field, -} - -struct Nested { - t1: Type1, - is_true: bool, -} - -fn main(x: pub Field, nested: pub Nested, y: pub Field) { - //... -} -``` - -Structs will be flattened so that the array of inputs is 1-dimensional array. The order of these inputs would be flattened to: `[x, nested.t1.val1, nested.t1.val2, nested.is_true, y]` - -## Noir for EVM chains - -You can currently deploy the Solidity verifier contracts to most EVM compatible chains. EVM chains that have been tested and are known to work include: - -- Optimism -- Arbitrum -- Polygon PoS -- Scroll -- Celo -- Taiko - -Other EVM chains should work, but have not been tested directly by our team. If you test any other chains, please open a PR on this page to update the list. See [this doc](https://github.com/noir-lang/noir-starter/tree/main/with-foundry#testing-on-chain) for more info about testing verifier contracts on different EVM chains. - -### Unsupported chains - -Unfortunately not all "EVM" chains are supported. - -**zkSync** and the **Polygon zkEVM** do _not_ currently support proof verification via Solidity verifier contracts. They are missing the bn256 precompile contract that the verifier contract requires. Once these chains support this precompile, they may work. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/index.md deleted file mode 100644 index eaf8c59f935..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/index.md +++ /dev/null @@ -1,84 +0,0 @@ ---- -title: Noir -description: - Learn about the public alpha release of Noir, a domain specific language heavily influenced by Rust that compiles to - an intermediate language which can be compiled to an arithmetic circuit or a rank-1 constraint system. -keywords: - [ - Noir, - Domain Specific Language, - Rust, - Intermediate Language, - Arithmetic Circuit, - Rank-1 Constraint System, - Ethereum Developers, - Protocol Developers, - Blockchain Developers, - Proving System, - Smart Contract Language, - ] -sidebar_position: 0 ---- - -## What's new about Noir? - -Noir, a domain-specific language crafted for SNARK proving systems, stands out with its simplicity, flexibility, -and robust capabilities. Unlike conventional approaches that compile directly to a fixed NP-complete language, -Noir takes a two-pronged path. It first compiles to an adaptable intermediate language known as ACIR. From there, -depending on the project's needs, ACIR can be further compiled into an arithmetic circuit for integration with Aztec's -barretenberg backend or transformed into a rank-1 constraint system suitable for R1CS backends like Arkworks' Marlin -backend, among others. - -This innovative design introduces unique challenges, yet it strategically separates the programming language from the -backend. Noir's approach echoes the modular philosophy of LLVM, offering developers a versatile toolkit for cryptographic -programming. - -## Who is Noir for? - -### Solidity Developers - -Noir streamlines the creation of Solidity contracts that interface with SNARK systems. -[`Utilize the nargo codegen-verifier`](./reference/nargo_commands.md#nargo-codegen-verifier) command to construct verifier -contracts efficiently. While the current alpha version offers this as a direct feature, future updates aim -to modularize this process for even greater ease of use. - -Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will be -modularized in the future; however, as of the alpha, you can use the `nargo codegen-verifier` command to create a verifier contract. - -### Protocol Developers - -Should the Aztec backend not align with your existing tech stack, or if you're inclined to integrate alternative -proving systems, Noir's agnostic compilation to a proof-agnostic intermediate language offers unmatched flexibility. -This allows protocol engineers the freedom to substitute the default PLONK-based system with an alternative of their -choice, tailoring the proving system to their specific needs. - -### Blockchain developers - -Blockchain developers often face environmental constraints, such as predetermined proving systems and smart contract -languages. Noir addresses this by enabling the implementation of custom proving system backends and smart contract -interfaces, ensuring seamless integration with your blockchain's architecture, and expanding the horizons for innovation -within your projects. - -## Libraries - -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the -[awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). - -Some libraries that are available today include: - -- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library -- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains - the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage - proof verification (or verification of any trie proof involving 32-byte long keys) -- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing - for computations on large unsigned integers -- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and - return the source Ethereum address -- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of - sparse Merkle trees -- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data - type, allowing access to negative numbers on Noir -- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, - allowing results that aren't whole numbers - -See the section on [dependencies](noir/modules_packages_crates/dependencies.md) for more information. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/migration_notes.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/migration_notes.md deleted file mode 100644 index 9c1809fd609..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/migration_notes.md +++ /dev/null @@ -1,105 +0,0 @@ ---- -title: Migration notes -description: Read about migration notes from previous versions, which could solve problems while updating -keywords: [Noir, notes, migration, updating, upgrading] ---- - -Noir is in full-speed development. Things break fast, wild, and often. This page attempts to leave some notes on errors you might encounter when upgrading and how to resolve them until proper patches are built. - -### `backend encountered an error: libc++.so.1` - -Depending on your OS, you may encounter the following error when running `nargo prove` for the first time: - -```text -The backend encountered an error: "/home/codespace/.nargo/backends/acvm-backend-barretenberg/backend_binary: error while loading shared libraries: libc++.so.1: cannot open shared object file: No such file or directory\n" -``` - -Install the `libc++-dev` library with: - -```bash -sudo apt install libc++-dev -``` - -## ≥0.19 - -### Enforcing `compiler_version` - -From this version on, the compiler will check for the `compiler_version` field in `Nargo.toml`, and will error if it doesn't match the current Nargo version in use. - -To update, please make sure this field in `Nargo.toml` matches the output of `nargo --version`. - -## ≥0.14 - -The index of the [for loops](noir/syntax/control_flow.md#loops) is now of type `u64` instead of `Field`. An example refactor would be: - -```rust -for i in 0..10 { - let i = i as Field; -} -``` - -## ≥v0.11.0 and Nargo backend - -From this version onwards, Nargo starts managing backends through the `nargo backend` command. Upgrading to the versions per usual steps might lead to: - -### `backend encountered an error` - -This is likely due to the existing locally installed version of proving backend (e.g. barretenberg) is incompatible with the version of Nargo in use. - -To fix the issue: - -1. Uninstall the existing backend - -```bash -nargo backend uninstall acvm-backend-barretenberg -``` - -You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. - -2. Reinstall a compatible version of the proving backend. - -If you are using the default barretenberg backend, simply run: - -``` -nargo prove -``` - -with your Noir program. - -This will trigger the download and installation of the latest version of barretenberg compatible with your Nargo in use. - -### `backend encountered an error: illegal instruction` - -On certain Intel-based systems, an `illegal instruction` error may arise due to incompatibility of barretenberg with certain CPU instructions. - -To fix the issue: - -1. Uninstall the existing backend - -```bash -nargo backend uninstall acvm-backend-barretenberg -``` - -You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. - -2. Reinstall a compatible version of the proving backend. - -If you are using the default barretenberg backend, simply run: - -``` -nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/barretenberg-js-binary/raw/master/run-bb.tar.gz -``` - -This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. - -The gzipped file is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. - -Then run: - -``` -DESIRED_BINARY_VERSION=0.8.1 nargo info -``` - -This overrides the bb native binary with a bb.js node application instead, which should be compatible with most if not all hardware. This does come with the drawback of being generally slower than native binary. - -0.8.1 indicates bb.js version 0.8.1, so if you change that it will update to a different version or the default version in the script if none was supplied. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/dependencies.md deleted file mode 100644 index d9d21ef0485..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/dependencies.md +++ /dev/null @@ -1,124 +0,0 @@ ---- -title: Dependencies -description: - Learn how to specify and manage dependencies in Nargo, allowing you to upload packages to GitHub - and use them easily in your project. -keywords: [Nargo, dependencies, GitHub, package management, versioning] -sidebar_position: 1 ---- - -Nargo allows you to upload packages to GitHub and use them as dependencies. - -## Specifying a dependency - -Specifying a dependency requires a tag to a specific commit and the git url to the url containing -the package. - -Currently, there are no requirements on the tag contents. If requirements are added, it would follow -semver 2.0 guidelines. - -> Note: Without a `tag` , there would be no versioning and dependencies would change each time you -> compile your project. - -For example, to add the [ecrecover-noir library](https://github.com/colinnielsen/ecrecover-noir) to your project, add it to `Nargo.toml`: - -```toml -# Nargo.toml - -[dependencies] -ecrecover = {tag = "v0.8.0", git = "https://github.com/colinnielsen/ecrecover-noir"} -``` - -If the module is in a subdirectory, you can define a subdirectory in your git repository, for example: - -```toml -# Nargo.toml - -[dependencies] -easy_private_token_contract = {tag ="v0.1.0-alpha62", git = "https://github.com/AztecProtocol/aztec-packages", directory = "yarn-project/noir-contracts/contracts/easy_private_token_contract"} -``` - -## Specifying a local dependency - -You can also specify dependencies that are local to your machine. - -For example, this file structure has a library and binary crate - -```tree -├── binary_crate -│   ├── Nargo.toml -│   └── src -│   └── main.nr -└── lib_a - ├── Nargo.toml - └── src - └── lib.nr -``` - -Inside of the binary crate, you can specify: - -```toml -# Nargo.toml - -[dependencies] -lib_a = { path = "../lib_a" } -``` - -## Importing dependencies - -You can import a dependency to a Noir file using the following syntax. For example, to import the -ecrecover-noir library and local lib_a referenced above: - -```rust -use dep::ecrecover; -use dep::lib_a; -``` - -You can also import only the specific parts of dependency that you want to use, like so: - -```rust -use dep::std::hash::sha256; -use dep::std::scalar_mul::fixed_base_embedded_curve; -``` - -Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you -can import multiple items in the same line by enclosing them in curly braces: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; -``` - -We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. - -Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. - -## Dependencies of Dependencies - -Note that when you import a dependency, you also get access to all of the dependencies of that package. - -For example, the [phy_vector](https://github.com/resurgencelabs/phy_vector) library imports an [fraction](https://github.com/resurgencelabs/fraction) library. If you're importing the phy_vector library, then you can access the functions in fractions library like so: - -```rust -use dep::phy_vector; - -fn main(x : Field, y : pub Field) { - //... - let f = phy_vector::fraction::toFraction(true, 2, 1); - //... -} -``` - -## Available Libraries - -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). - -Some libraries that are available today include: - -- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library -- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) -- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers -- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address -- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees -- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir -- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/black_box_fns.md deleted file mode 100644 index 985bb7c879d..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/black_box_fns.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: Black Box Functions -description: Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. -keywords: [noir, black box functions] ---- - -Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. This makes certain zk-snark unfriendly computations cheaper than if they were implemented in Noir. - -:::warning - -It is likely that not all backends will support a particular black box function. - -::: - -Because it is not guaranteed that all backends will support black box functions, it is possible that certain Noir programs won't compile against a particular backend if they use an unsupported black box function. It is possible to fallback to less efficient implementations written in Noir/ACIR in some cases. - -Black box functions are specified with the `#[foreign(black_box_fn)]` attribute. For example, the SHA256 function in the Noir [source code](https://github.com/noir-lang/noir/blob/v0.5.1/noir_stdlib/src/hash.nr) looks like: - -```rust -#[foreign(sha256)] -fn sha256(_input : [u8; N]) -> [u8; 32] {} -``` - -## Function list - -Here is a list of the current black box functions that are supported by UltraPlonk: - -- AES -- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) -- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) -- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash) -- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment) -- [HashToField128Security](./cryptographic_primitives/hashes.mdx#hash_to_field) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx) -- [Compute merkle root](./merkle_trees.md#compute_merkle_root) -- AND -- XOR -- RANGE -- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion.md) - -Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. - -You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/noir/blob/master/acvm-repo/acir/src/circuit/black_box_functions.rs). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/ec_primitives.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/ec_primitives.md deleted file mode 100644 index fc8ed59f09d..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/ec_primitives.md +++ /dev/null @@ -1,102 +0,0 @@ ---- -title: Elliptic Curve Primitives -keywords: [cryptographic primitives, Noir project] -sidebar_position: 4 ---- - -Data structures and methods on them that allow you to carry out computations involving elliptic -curves over the (mathematical) field corresponding to `Field`. For the field currently at our -disposal, applications would involve a curve embedded in BN254, e.g. the -[Baby Jubjub curve](https://eips.ethereum.org/EIPS/eip-2494). - -## Data structures - -### Elliptic curve configurations - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Curve`), i.e. the specific elliptic -curve you want to use, which would be specified using any one of the methods -`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::new` which take the coefficients in the -defining equation together with a generator point as parameters. You can find more detail in the -comments in -[`noir_stdlib/src/ec.nr`](https://github.com/noir-lang/noir/blob/v0.22.0/noir_stdlib/src/ec.nr), but -the gist of it is that the elliptic curves of interest are usually expressed in one of the standard -forms implemented here (Twisted Edwards, Montgomery and Short Weierstraß), and in addition to that, -you could choose to use `affine` coordinates (Cartesian coordinates - the usual (x,y) - possibly -together with a point at infinity) or `curvegroup` coordinates (some form of projective coordinates -requiring more coordinates but allowing for more efficient implementations of elliptic curve -operations). Conversions between all of these forms are provided, and under the hood these -conversions are done whenever an operation is more efficient in a different representation (or a -mixed coordinate representation is employed). - -### Points - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Point`), i.e. points lying on the -elliptic curve. For a curve configuration `c` and a point `p`, it may be checked that `p` -does indeed lie on `c` by calling `c.contains(p1)`. - -## Methods - -(given a choice of curve representation, e.g. use `std::ec::tecurve::affine::Curve` and use -`std::ec::tecurve::affine::Point`) - -- The **zero element** is given by `Point::zero()`, and we can verify whether a point `p: Point` is - zero by calling `p.is_zero()`. -- **Equality**: Points `p1: Point` and `p2: Point` may be checked for equality by calling - `p1.eq(p2)`. -- **Addition**: For `c: Curve` and points `p1: Point` and `p2: Point` on the curve, adding these two - points is accomplished by calling `c.add(p1,p2)`. -- **Negation**: For a point `p: Point`, `p.negate()` is its negation. -- **Subtraction**: For `c` and `p1`, `p2` as above, subtracting `p2` from `p1` is accomplished by - calling `c.subtract(p1,p2)`. -- **Scalar multiplication**: For `c` as above, `p: Point` a point on the curve and `n: Field`, - scalar multiplication is given by `c.mul(n,p)`. If instead `n :: [u1; N]`, i.e. `n` is a bit - array, the `bit_mul` method may be used instead: `c.bit_mul(n,p)` -- **Multi-scalar multiplication**: For `c` as above and arrays `n: [Field; N]` and `p: [Point; N]`, - multi-scalar multiplication is given by `c.msm(n,p)`. -- **Coordinate representation conversions**: The `into_group` method converts a point or curve - configuration in the affine representation to one in the CurveGroup representation, and - `into_affine` goes in the other direction. -- **Curve representation conversions**: `tecurve` and `montcurve` curves and points are equivalent - and may be converted between one another by calling `into_montcurve` or `into_tecurve` on their - configurations or points. `swcurve` is more general and a curve c of one of the other two types - may be converted to this representation by calling `c.into_swcurve()`, whereas a point `p` lying - on the curve given by `c` may be mapped to its corresponding `swcurve` point by calling - `c.map_into_swcurve(p)`. -- **Map-to-curve methods**: The Elligator 2 method of mapping a field element `n: Field` into a - `tecurve` or `montcurve` with configuration `c` may be called as `c.elligator2_map(n)`. For all of - the curve configurations, the SWU map-to-curve method may be called as `c.swu_map(z,n)`, where - `z: Field` depends on `Field` and `c` and must be chosen by the user (the conditions it needs to - satisfy are specified in the comments - [here](https://github.com/noir-lang/noir/blob/v0.22.0/noir_stdlib/src/ec.nr). - -## Examples - -The -[ec_baby_jubjub test](https://github.com/noir-lang/noir/blob/master/test_programs/compile_success_empty/ec_baby_jubjub/src/main.nr) -illustrates all of the above primitives on various forms of the Baby Jubjub curve. A couple of more -interesting examples in Noir would be: - -Public-key cryptography: Given an elliptic curve and a 'base point' on it, determine the public key -from the private key. This is a matter of using scalar multiplication. In the case of Baby Jubjub, -for example, this code would do: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; - -fn bjj_pub_key(priv_key: Field) -> Point -{ - - let bjj = Curve::new(168700, 168696, G::new(995203441582195749578291179787384436505546430278305826713579947235728471134,5472060717959818805561601436314318772137091100104008585924551046643952123905)); - - let base_pt = Point::new(5299619240641551281634865583518297030282874472190772894086521144482721001553, 16950150798460657717958625567821834550301663161624707787222815936182638968203); - - bjj.mul(priv_key,base_pt) -} -``` - -This would come in handy in a Merkle proof. - -- EdDSA signature verification: This is a matter of combining these primitives with a suitable hash - function. See - [feat(stdlib): EdDSA sig verification noir#1136](https://github.com/noir-lang/noir/pull/1136) for - the case of Baby Jubjub and the Poseidon hash function. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx deleted file mode 100644 index 1376c51dfde..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: ECDSA Signature Verification -description: Learn about the cryptographic primitives regarding ECDSA over the secp256k1 and secp256r1 curves -keywords: [cryptographic primitives, Noir project, ecdsa, secp256k1, secp256r1, signatures] -sidebar_position: 3 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -Noir supports ECDSA signatures verification over the secp256k1 and secp256r1 curves. - -## ecdsa_secp256k1::verify_signature - -Verifier for ECDSA Secp256k1 signatures - -```rust -fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message: [u8]) -> bool -``` - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - -## ecdsa_secp256r1::verify_signature - -Verifier for ECDSA Secp256r1 signatures - -```rust -fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message: [u8]) -> bool -``` - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/eddsa.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/eddsa.mdx deleted file mode 100644 index a9c10da6c06..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/eddsa.mdx +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: EdDSA Verification -description: Learn about the cryptographic primitives regarding EdDSA -keywords: [cryptographic primitives, Noir project, eddsa, signatures] -sidebar_position: 5 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## eddsa::eddsa_poseidon_verify - -Verifier for EdDSA signatures - -```rust -fn eddsa_poseidon_verify(public_key_x : Field, public_key_y : Field, signature_s: Field, signature_r8_x: Field, signature_r8_y: Field, message: Field) -> bool -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/hashes.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/hashes.mdx deleted file mode 100644 index 9250cb4a0c0..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/hashes.mdx +++ /dev/null @@ -1,168 +0,0 @@ ---- -title: Hash methods -description: - Learn about the cryptographic primitives ready to use for any Noir project, including sha256, - blake2s, pedersen, mimc_bn254 and mimc -keywords: - [cryptographic primitives, Noir project, sha256, blake2s, pedersen, mimc_bn254, mimc, hash] -sidebar_position: 0 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## sha256 - -Given an array of bytes, returns the resulting sha256 hash. - -```rust -fn sha256(_input : [u8]) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::sha256(x); -} -``` - - - -## blake2s - -Given an array of bytes, returns an array with the Blake2 hash - -```rust -fn blake2s(_input : [u8]) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::blake2s(x); -} -``` - - - -## pedersen_hash - -Given an array of Fields, returns the Pedersen hash. - -```rust -fn pedersen_hash(_input : [Field]) -> Field -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::pedersen_hash(x); -} -``` - - - - - -## pedersen_commitment - -Given an array of Fields, returns the Pedersen commitment. - -```rust -fn pedersen_commitment(_input : [Field]) -> [Field; 2] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let commitment = std::hash::pedersen_commitment(x); -} -``` - - - -## keccak256 - -Given an array of bytes (`u8`), returns the resulting keccak hash as an array of 32 bytes -(`[u8; 32]`). Specify a message_size to hash only the first `message_size` bytes -of the input. - -```rust -fn keccak256(_input : [u8; N], _message_size: u32) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let message_size = 4; - let hash = std::hash::keccak256(x, message_size); -} -``` - - - -## poseidon - -Given an array of Fields, returns a new Field with the Poseidon Hash. Mind that you need to specify -how many inputs are there to your Poseidon function. - -```rust -// example for hash_1, hash_2 accepts an array of length 2, etc -fn hash_1(input: [Field; 1]) -> Field -``` - -example: - -```rust -fn main() -{ - let hash_2 = std::hash::poseidon::bn254::hash_2([1, 2]); - assert(hash2 == 0x115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189a); -} -``` - -## mimc_bn254 and mimc - -`mimc_bn254` is `mimc`, but with hardcoded parameters for the BN254 curve. You can use it by -providing an array of Fields, and it returns a Field with the hash. You can use the `mimc` method if -you're willing to input your own constants: - -```rust -fn mimc(x: Field, k: Field, constants: [Field; N], exp : Field) -> Field -``` - -otherwise, use the `mimc_bn254` method: - -```rust -fn mimc_bn254(array: [Field; N]) -> Field -``` - -example: - -```rust - -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::mimc::mimc_bn254(x); -} -``` - -## hash_to_field - -```rust -fn hash_to_field(_input : [Field; N]) -> Field {} -``` - -Calculates the `blake2s` hash of the inputs and returns the hash modulo the field modulus to return -a value which can be represented as a `Field`. - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/scalar.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/scalar.mdx deleted file mode 100644 index 1e686303c18..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/scalar.mdx +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: Scalar multiplication -description: See how you can perform scalar multiplications over a fixed base in Noir -keywords: [cryptographic primitives, Noir project, scalar multiplication] -sidebar_position: 1 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## scalar_mul::fixed_base_embedded_curve - -Performs scalar multiplication over the embedded curve whose coordinates are defined by the -configured noir field. For the BN254 scalar field, this is BabyJubJub or Grumpkin. - -```rust -fn fixed_base_embedded_curve(_input : Field) -> [Field; 2] -``` - -example - -```rust -fn main(x : Field) { - let scal = std::scalar_mul::fixed_base_embedded_curve(x); - std::println(scal); -} -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/schnorr.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/schnorr.mdx deleted file mode 100644 index 7a2c9c20226..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/schnorr.mdx +++ /dev/null @@ -1,38 +0,0 @@ ---- -title: Schnorr Signatures -description: Learn how you can verify Schnorr signatures using Noir -keywords: [cryptographic primitives, Noir project, schnorr, signatures] -sidebar_position: 2 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## schnorr::verify_signature - -Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin). - -```rust -fn verify_signature(_public_key_x: Field, _public_key_y: Field, _signature: [u8; 64], _message: [u8]) -> bool -``` - -where `_signature` can be generated like so using the npm package -[@noir-lang/barretenberg](https://www.npmjs.com/package/@noir-lang/barretenberg) - -```js -const { BarretenbergWasm } = require('@noir-lang/barretenberg/dest/wasm'); -const { Schnorr } = require('@noir-lang/barretenberg/dest/crypto/schnorr'); - -... - -const barretenberg = await BarretenbergWasm.new(); -const schnorr = new Schnorr(barretenberg); -const pubKey = schnorr.computePublicKey(privateKey); -const message = ... -const signature = Array.from( - schnorr.constructSignature(hash, privateKey).toBuffer() -); - -... -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/logging.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/logging.md deleted file mode 100644 index 2e163b52ab3..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/logging.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -title: Logging -description: - Learn how to use the println statement for debugging in Noir with this tutorial. Understand the - basics of logging in Noir and how to implement it in your code. -keywords: - [ - noir logging, - println statement, - print statement, - debugging in noir, - noir std library, - logging tutorial, - basic logging in noir, - noir logging implementation, - noir debugging techniques, - rust, - ] ---- - -The standard library provides two familiar statements you can use: `println` and `print`. Despite being a limited implementation of rust's `println!` and `print!` macros, these constructs can be useful for debugging. - -You can print the output of both statements in your Noir code by using the `nargo execute` command or the `--show-output` flag when using `nargo test` (provided there are print statements in your tests). - -It is recommended to use `nargo execute` if you want to debug failing constraints with `println` or `print` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). Neither `println`, nor `print` are callable for failed constraints caught at compile time. - -Both `print` and `println` are generic functions which can work on integers, fields, strings, and even structs or expressions. Note however, that slices are currently unsupported. For example: - -```rust -use dep::std; - -struct Person { - age : Field, - height : Field, -} - -fn main(age : Field, height : Field) { - let person = Person { age : age, height : height }; - std::println(person); - std::println(age + height); - std::println("Hello world!"); -} -``` - -You can print different types in the same statement (including strings) with a type called `fmtstr`. It can be specified in the same way as a normal string, just prepended with an "f" character: - -```rust - let fmt_str = f"i: {i}, j: {j}"; - std::println(fmt_str); - - let s = myStruct { y: x, x: y }; - std::println(s); - - std::println(f"i: {i}, s: {s}"); - - std::println(x); - std::println([x, y]); - - let foo = fooStruct { my_struct: s, foo: 15 }; - std::println(f"s: {s}, foo: {foo}"); - - std::println(15); // prints 0x0f, implicit Field - std::println(-1 as u8); // prints 255 - std::println(-1 as i8); // prints -1 -``` - -Examples shown above are interchangeable between the two `print` statements: - -```rust -let person = Person { age : age, height : height }; - -std::println(person); -std::print(person); - -std::println("Hello world!"); // Prints with a newline at the end of the input -std::print("Hello world!"); // Prints the input and keeps cursor on the same line -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/merkle_trees.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/merkle_trees.md deleted file mode 100644 index 5b45617812a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/merkle_trees.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: Merkle Trees -description: Learn about Merkle Trees in Noir with this tutorial. Explore the basics of computing a merkle root using a proof, with examples. -keywords: - [ - Merkle trees in Noir, - Noir programming language, - check membership, - computing root from leaf, - Noir Merkle tree implementation, - Merkle tree tutorial, - Merkle tree code examples, - Noir libraries, - pedersen hash., - ] ---- - -## compute_merkle_root - -Returns the root of the tree from the provided leaf and its hash path, using a [Pedersen hash](./cryptographic_primitives/hashes.mdx#pedersen_hash). - -```rust -fn compute_merkle_root(leaf : Field, index : Field, hash_path: [Field]) -> Field -``` - -example: - -```rust -/** - // these values are for this example only - index = "0" - priv_key = "0x000000000000000000000000000000000000000000000000000000616c696365" - secret = "0x1929ea3ab8d9106a899386883d9428f8256cfedb3c4f6b66bf4aa4d28a79988f" - note_hash_path = [ - "0x1e61bdae0f027b1b2159e1f9d3f8d00fa668a952dddd822fda80dc745d6f65cc", - "0x0e4223f3925f98934393c74975142bd73079ab0621f4ee133cee050a3c194f1a", - "0x2fd7bb412155bf8693a3bd2a3e7581a679c95c68a052f835dddca85fa1569a40" - ] - */ -fn main(index: Field, priv_key: Field, secret: Field, note_hash_path: [Field; 3]) { - - let pubkey = std::scalar_mul::fixed_base_embedded_curve(priv_key); - let pubkey_x = pubkey[0]; - let pubkey_y = pubkey[1]; - let note_commitment = std::hash::pedersen([pubkey_x, pubkey_y, secret]); - - let root = std::merkle::compute_merkle_root(note_commitment[0], index, note_hash_path); - std::println(root); -} -``` - -To check merkle tree membership: - -1. Include a merkle root as a program input. -2. Compute the merkle root of a given leaf, index and hash path. -3. Assert the merkle roots are equal. - -For more info about merkle trees, see the Wikipedia [page](https://en.wikipedia.org/wiki/Merkle_tree). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/options.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/options.md deleted file mode 100644 index 3d3139fb98b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/options.md +++ /dev/null @@ -1,99 +0,0 @@ ---- -title: Option Type ---- - -The `Option` type is a way to express that a value might be present (`Some(T))` or absent (`None`). It's a safer way to handle potential absence of values, compared to using nulls in many other languages. - -```rust -struct Option { - None, - Some(T), -} -``` - -You can import the Option type into your Noir program like so: - -```rust -use dep::std::option::Option; - -fn main() { - let none = Option::none(); - let some = Option::some(3); -} -``` - -See [this test](https://github.com/noir-lang/noir/blob/5cbfb9c4a06c8865c98ff2b594464b037d821a5c/crates/nargo_cli/tests/test_data/option/src/main.nr) for a more comprehensive set of examples of each of the methods described below. - -## Methods - -### none - -Constructs a none value. - -### some - -Constructs a some wrapper around a given value. - -### is_none - -Returns true if the Option is None. - -### is_some - -Returns true of the Option is Some. - -### unwrap - -Asserts `self.is_some()` and returns the wrapped value. - -### unwrap_unchecked - -Returns the inner value without asserting `self.is_some()`. This method can be useful within an if condition when we already know that `option.is_some()`. If the option is None, there is no guarantee what value will be returned, only that it will be of type T for an `Option`. - -### unwrap_or - -Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value. - -### unwrap_or_else - -Returns the wrapped value if `self.is_some()`. Otherwise, calls the given function to return a default value. - -### map - -If self is `Some(x)`, this returns `Some(f(x))`. Otherwise, this returns `None`. - -### map_or - -If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns the given default value. - -### map_or_else - -If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns `default()`. - -### and - -Returns None if self is None. Otherwise, this returns `other`. - -### and_then - -If self is None, this returns None. Otherwise, this calls the given function with the Some value contained within self, and returns the result of that call. In some languages this function is called `flat_map` or `bind`. - -### or - -If self is Some, return self. Otherwise, return `other`. - -### or_else - -If self is Some, return self. Otherwise, return `default()`. - -### xor - -If only one of the two Options is Some, return that option. Otherwise, if both options are Some or both are None, None is returned. - -### filter - -Returns `Some(x)` if self is `Some(x)` and `predicate(x)` is true. Otherwise, this returns `None`. - -### flatten - -Flattens an `Option>` into a `Option`. This returns `None` if the outer Option is None. Otherwise, this returns the inner Option. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/recursion.md deleted file mode 100644 index 4a004fd3664..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/recursion.md +++ /dev/null @@ -1,90 +0,0 @@ ---- -title: Recursive Proofs -description: Learn about how to write recursive proofs in Noir. -keywords: [recursion, recursive proofs, verification_key, aggregation object, verify_proof] ---- - -Noir supports recursively verifying proofs, meaning you verify the proof of a Noir program in another Noir program. This enables creating proofs of arbitrary size by doing step-wise verification of smaller components of a large proof. - -The `verify_proof` function takes a verification key, proof and public inputs for a zk program, as well as a key hash and an input aggregation object. The key hash is used to check the validity of the verification key and the input aggregation object is required by some proving systems. The `verify_proof` function returns an output aggregation object that can then be fed into future iterations of the proof verification if required. - -```rust -#[foreign(verify_proof)] -fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : Field, _key_hash : Field, _input_aggregation_object : [Field]) -> [Field] {} -``` - -:::info - -This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. - -::: - -## Example usage - -```rust -use dep::std; - -fn main( - verification_key : [Field; 114], - proof : [Field; 94], - public_inputs : [Field; 1], - key_hash : Field, - input_aggregation_object : [Field; 16], - proof_b : [Field; 94], -) -> pub [Field; 16] { - let output_aggregation_object_a = std::verify_proof( - verification_key.as_slice(), - proof.as_slice(), - public_inputs.as_slice(), - key_hash, - input_aggregation_object - ); - - let output_aggregation_object = std::verify_proof( - verification_key.as_slice(), - proof_b.as_slice(), - public_inputs.as_slice(), - key_hash, - output_aggregation_object_a - ); - - let mut output = [0; 16]; - for i in 0..16 { - output[i] = output_aggregation_object[i]; - } - output -} -``` - -## Parameters - -### `verification_key` - -The verification key for the zk program that is being verified. - -### `proof` - -The proof for the zk program that is being verified. - -### `public_inputs` - -These represent the public inputs of the proof we are verifying. They should be checked against in the circuit after construction of a new aggregation state. - -### `key_hash` - -A key hash is used to check the validity of the verification key. The circuit implementing this opcode can use this hash to ensure that the key provided to the circuit matches the key produced by the circuit creator. - -### `input_aggregation_object` - -An aggregation object is blob of data that the top-level verifier must run some proof system specific algorithm on to complete verification. The size is proof system specific and will be set by the backend integrating this opcode. The input aggregation object is only not `None` when we are verifying a previous recursive aggregation in the current circuit. If this is the first recursive aggregation there is no input aggregation object. It is left to the backend to determine how to handle when there is no input aggregation object. - -## Return value - -### `output_aggregation_object` - -This is the result of a recursive aggregation and is what will be fed into the next verifier. -The next verifier can either perform a final verification (returning true or false) or perform another recursive aggregation where this output aggregation object will be the input aggregation object of the next recursive aggregation. - -## Example - -You can see an example of how to do recursive proofs in [this example recursion demo repo](https://github.com/noir-lang/noir-examples/tree/master/recursion). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/zeroed.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/zeroed.md deleted file mode 100644 index 97dab02dac2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/zeroed.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: Zeroed Function -description: - The zeroed function returns a zeroed value of any type. -keywords: - [ - zeroed - ] ---- - -Implements `fn zeroed() -> T` to return a zeroed value of any type. This function is generally unsafe to use as the zeroed bit pattern is not guaranteed to be valid for all types. It can however, be useful in cases when the value is guaranteed not to be used such as in a BoundedVec library implementing a growable vector, up to a certain length, backed by an array. The array can be initialized with zeroed values which are guaranteed to be inaccessible until the vector is pushed to. Similarly, enumerations in noir can be implemented using this method by providing zeroed values for the unused variants. - -You can access the function at `std::unsafe::zeroed`. - -This function currently supports the following types: - -- Field -- Bool -- Uint -- Array -- String -- Tuple -- Function - -Using it on other types could result in unexpected behavior. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/_category_.json deleted file mode 100644 index 666b691ae91..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Syntax", - "position": 0, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/assert.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/assert.md deleted file mode 100644 index c5f9aff139c..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/assert.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: Assert Function -description: - Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or - comparison expression that follows to be true, and what happens if the expression is false at - runtime. -keywords: [Noir programming language, assert statement, predicate expression, comparison expression] -sidebar_position: 4 ---- - -Noir includes a special `assert` function which will explicitly constrain the predicate/comparison -expression that follows to be true. If this expression is false at runtime, the program will fail to -be proven. Example: - -```rust -fn main(x : Field, y : Field) { - assert(x == y); -} -``` - -You can optionally provide a message to be logged when the assertion fails: - -```rust -assert(x == y, "x and y are not equal"); -``` - -> Assertions only work for predicate operations, such as `==`. If there's any ambiguity on the operation, the program will fail to compile. For example, it is unclear if `assert(x + y)` would check for `x + y == 0` or simply would return `true`. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/comments.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/comments.md deleted file mode 100644 index f76ab49094b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/comments.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Comments -description: - Learn how to write comments in Noir programming language. A comment is a line of code that is - ignored by the compiler, but it can be read by programmers. Single-line and multi-line comments - are supported in Noir. -keywords: [Noir programming language, comments, single-line comments, multi-line comments] -sidebar_position: 9 ---- - -A comment is a line in your codebase which the compiler ignores, however it can be read by -programmers. - -Here is a single line comment: - -```rust -// This is a comment and is ignored -``` - -`//` is used to tell the compiler to ignore the rest of the line. - -Noir also supports multi-line block comments. Start a block comment with `/*` and end the block with `*/`. - -Noir does not natively support doc comments. You may be able to use [Rust doc comments](https://doc.rust-lang.org/reference/comments.html) in your code to leverage some Rust documentation build tools with Noir code. - -```rust -/* - This is a block comment describing a complex function. -*/ -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/control_flow.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/control_flow.md deleted file mode 100644 index 4ce65236db3..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/control_flow.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Control Flow -description: - Learn how to use loops and if expressions in the Noir programming language. Discover the syntax - and examples for for loops and if-else statements. -keywords: [Noir programming language, loops, for loop, if-else statements, Rust syntax] -sidebar_position: 2 ---- - -## Loops - -Noir has one kind of loop: the `for` loop. `for` loops allow you to repeat a block of code multiple -times. - -The following block of code between the braces is run 10 times. - -```rust -for i in 0..10 { - // do something -}; -``` - -The index for loops is of type `u64`. - -## If Expressions - -Noir supports `if-else` statements. The syntax is most similar to Rust's where it is not required -for the statement's conditional to be surrounded by parentheses. - -```rust -let a = 0; -let mut x: u32 = 0; - -if a == 0 { - if a != 0 { - x = 6; - } else { - x = 2; - } -} else { - x = 5; - assert(x == 5); -} -assert(x == 2); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_bus.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_bus.md deleted file mode 100644 index 6c7e9b60891..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_bus.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: Data Bus -sidebar_position: 12 ---- -**Disclaimer** this feature is experimental, do not use it! - -The data bus is an optimization that the backend can use to make recursion more efficient. -In order to use it, you must define some inputs of the program entry points (usually the `main()` -function) with the `call_data` modifier, and the return values with the `return_data` modifier. -These modifiers are incompatible with `pub` and `mut` modifiers. - -## Example - -```rust -fn main(mut x: u32, y: call_data u32, z: call_data [u32;4] ) -> return_data u32 { - let a = z[x]; - a+y -} -``` - -As a result, both call_data and return_data will be treated as private inputs and encapsulated into a read-only array each, for the backend to process. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/arrays.md deleted file mode 100644 index addda1da8bc..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/arrays.md +++ /dev/null @@ -1,245 +0,0 @@ ---- -title: Arrays -description: - Dive into the Array data type in Noir. Grasp its methods, practical examples, and best practices for efficiently using Arrays in your Noir code. -keywords: - [ - noir, - array type, - methods, - examples, - indexing, - ] -sidebar_position: 4 ---- - -An array is one way of grouping together values into one compound type. Array types can be inferred -or explicitly specified via the syntax `[; ]`: - -```rust -fn main(x : Field, y : Field) { - let my_arr = [x, y]; - let your_arr: [Field; 2] = [x, y]; -} -``` - -Here, both `my_arr` and `your_arr` are instantiated as an array containing two `Field` elements. - -Array elements can be accessed using indexing: - -```rust -fn main() { - let a = [1, 2, 3, 4, 5]; - - let first = a[0]; - let second = a[1]; -} -``` - -All elements in an array must be of the same type (i.e. homogeneous). That is, an array cannot group -a `Field` value and a `u8` value together for example. - -You can write mutable arrays, like: - -```rust -fn main() { - let mut arr = [1, 2, 3, 4, 5]; - assert(arr[0] == 1); - - arr[0] = 42; - assert(arr[0] == 42); -} -``` - -You can instantiate a new array of a fixed size with the same value repeated for each element. The following example instantiates an array of length 32 where each element is of type Field and has the value 0. - -```rust -let array: [Field; 32] = [0; 32]; -``` - -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: - -```rust -let array: [Field; 32] = [0; 32]; -let sl = array.as_slice() -``` - -You can define multidimensional arrays: - -```rust -let array : [[Field; 2]; 2]; -let element = array[0][0]; -``` - -## Types - -You can create arrays of primitive types or structs. There is not yet support for nested arrays -(arrays of arrays) or arrays of structs that contain arrays. - -## Methods - -For convenience, the STD provides some ready-to-use, common methods for arrays: - -### len - -Returns the length of an array - -```rust -fn len(_array: [T; N]) -> comptime Field -``` - -example - -```rust -fn main() { - let array = [42, 42]; - assert(array.len() == 2); -} -``` - -### sort - -Returns a new sorted array. The original array remains untouched. Notice that this function will -only work for arrays of fields or integers, not for any arbitrary type. This is because the sorting -logic it uses internally is optimized specifically for these values. If you need a sort function to -sort any type, you should use the function `sort_via` described below. - -```rust -fn sort(_array: [T; N]) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32]; - let sorted = arr.sort(); - assert(sorted == [32, 42]); -} -``` - -### sort_via - -Sorts the array with a custom comparison function - -```rust -fn sort_via(mut a: [T; N], ordering: fn(T, T) -> bool) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32] - let sorted_ascending = arr.sort_via(|a, b| a <= b); - assert(sorted_ascending == [32, 42]); // verifies - - let sorted_descending = arr.sort_via(|a, b| a >= b); - assert(sorted_descending == [32, 42]); // does not verify -} -``` - -### map - -Applies a function to each element of the array, returning a new array containing the mapped elements. - -```rust -fn map(f: fn(T) -> U) -> [U; N] -``` - -example - -```rust -let a = [1, 2, 3]; -let b = a.map(|a| a * 2); // b is now [2, 4, 6] -``` - -### fold - -Applies a function to each element of the array, returning the final accumulated value. The first -parameter is the initial value. - -```rust -fn fold(mut accumulator: U, f: fn(U, T) -> U) -> U -``` - -This is a left fold, so the given function will be applied to the accumulator and first element of -the array, then the second, and so on. For a given call the expected result would be equivalent to: - -```rust -let a1 = [1]; -let a2 = [1, 2]; -let a3 = [1, 2, 3]; - -let f = |a, b| a - b; -a1.fold(10, f) //=> f(10, 1) -a2.fold(10, f) //=> f(f(10, 1), 2) -a3.fold(10, f) //=> f(f(f(10, 1), 2), 3) -``` - -example: - -```rust - -fn main() { - let arr = [2, 2, 2, 2, 2]; - let folded = arr.fold(0, |a, b| a + b); - assert(folded == 10); -} - -``` - -### reduce - -Same as fold, but uses the first element as starting element. - -```rust -fn reduce(f: fn(T, T) -> T) -> T -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let reduced = arr.reduce(|a, b| a + b); - assert(reduced == 10); -} -``` - -### all - -Returns true if all the elements satisfy the given predicate - -```rust -fn all(predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let all = arr.all(|a| a == 2); - assert(all); -} -``` - -### any - -Returns true if any of the elements satisfy the given predicate - -```rust -fn any(predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 5]; - let any = arr.any(|a| a == 5); - assert(any); -} - -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/booleans.md deleted file mode 100644 index 7211716f63e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/booleans.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Booleans -description: - Delve into the Boolean data type in Noir. Understand its methods, practical examples, and best practices for using Booleans in your Noir programs. -keywords: - [ - noir, - boolean type, - methods, - examples, - logical operations, - ] -sidebar_position: 2 ---- - - -The `bool` type in Noir has two possible values: `true` and `false`: - -```rust -fn main() { - let t = true; - let f: bool = false; -} -``` - -> **Note:** When returning a boolean value, it will show up as a value of 1 for `true` and 0 for -> `false` in _Verifier.toml_. - -The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and -[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/fields.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/fields.md deleted file mode 100644 index a1c67945d66..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/fields.md +++ /dev/null @@ -1,166 +0,0 @@ ---- -title: Fields -description: - Dive deep into the Field data type in Noir. Understand its methods, practical examples, and best practices to effectively use Fields in your Noir programs. -keywords: - [ - noir, - field type, - methods, - examples, - best practices, - ] -sidebar_position: 0 ---- - -The field type corresponds to the native field type of the proving backend. - -The size of a Noir field depends on the elliptic curve's finite field for the proving backend -adopted. For example, a field would be a 254-bit integer when paired with the default backend that -spans the Grumpkin curve. - -Fields support integer arithmetic and are often used as the default numeric type in Noir: - -```rust -fn main(x : Field, y : Field) { - let z = x + y; -} -``` - -`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new -private value `z` constrained to be equal to `x + y`. - -If proving efficiency is of priority, fields should be used as a default for solving problems. -Smaller integer types (e.g. `u64`) incur extra range constraints. - -## Methods - -After declaring a Field, you can use these common methods on it: - -### to_le_bits - -Transforms the field into an array of bits, Little Endian. - -```rust -fn to_le_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_le_bits(32); -} -``` - -### to_be_bits - -Transforms the field into an array of bits, Big Endian. - -```rust -fn to_be_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_be_bits(32); -} -``` - -### to_le_bytes - -Transforms into an array of bytes, Little Endian - -```rust -fn to_le_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_le_bytes(4); -} -``` - -### to_be_bytes - -Transforms into an array of bytes, Big Endian - -```rust -fn to_be_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_be_bytes(4); -} -``` - -### to_le_radix - -Decomposes into a vector over the specified base, Little Endian - -```rust -fn to_le_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_le_radix(256, 4); -} -``` - -### to_be_radix - -Decomposes into a vector over the specified base, Big Endian - -```rust -fn to_be_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_be_radix(256, 4); -} -``` - -### pow_32 - -Returns the value to the power of the specified exponent - -```rust -fn pow_32(self, exponent: Field) -> Field -``` - -example: - -```rust -fn main() { - let field = 2 - let pow = field.pow_32(4); - assert(pow == 16); -} -``` - -### sgn0 - -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. - -```rust -fn sgn0(self) -> u1 -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/index.md deleted file mode 100644 index f09bca0ee04..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/index.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: Data Types -description: - Get a clear understanding of the two categories of Noir data types - primitive types and compound - types. Learn about their characteristics, differences, and how to use them in your Noir - programming. -keywords: - [ - noir, - data types, - primitive types, - compound types, - private types, - public types, - ] ---- - -Every value in Noir has a type, which determines which operations are valid for it. - -All values in Noir are fundamentally composed of `Field` elements. For a more approachable -developing experience, abstractions are added on top to introduce different data types in Noir. - -Noir has two category of data types: primitive types (e.g. `Field`, integers, `bool`) and compound -types that group primitive types (e.g. arrays, tuples, structs). Each value can either be private or -public. - -## Private & Public Types - -A **private value** is known only to the Prover, while a **public value** is known by both the -Prover and Verifier. Mark values as `private` when the value should only be known to the prover. All -primitive types (including individual fields of compound types) in Noir are private by default, and -can be marked public when certain values are intended to be revealed to the Verifier. - -> **Note:** For public values defined in Noir programs paired with smart contract verifiers, once -> the proofs are verified on-chain the values can be considered known to everyone that has access to -> that blockchain. - -Public data types are treated no differently to private types apart from the fact that their values -will be revealed in proofs generated. Simply changing the value of a public type will not change the -circuit (where the same goes for changing values of private types as well). - -_Private values_ are also referred to as _witnesses_ sometimes. - -> **Note:** The terms private and public when applied to a type (e.g. `pub Field`) have a different -> meaning than when applied to a function (e.g. `pub fn foo() {}`). -> -> The former is a visibility modifier for the Prover to interpret if a value should be made known to -> the Verifier, while the latter is a visibility modifier for the compiler to interpret if a -> function should be made accessible to external Noir programs like in other languages. - -### pub Modifier - -All data types in Noir are private by default. Types are explicitly declared as public using the -`pub` modifier: - -```rust -fn main(x : Field, y : pub Field) -> pub Field { - x + y -} -``` - -In this example, `x` is **private** while `y` and `x + y` (the return value) are **public**. Note -that visibility is handled **per variable**, so it is perfectly valid to have one input that is -private and another that is public. - -> **Note:** Public types can only be declared through parameters on `main`. - -## Type Aliases - -A type alias is a new name for an existing type. Type aliases are declared with the keyword `type`: - -```rust -type Id = u8; - -fn main() { - let id: Id = 1; - let zero: u8 = 0; - assert(zero + 1 == id); -} -``` - -Type aliases can also be used with [generics](../generics.md): - -```rust -type Id = Size; - -fn main() { - let id: Id = 1; - let zero: u32 = 0; - assert(zero + 1 == id); -} -``` - -### BigInt - -You can achieve BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/integers.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/integers.md deleted file mode 100644 index baf5f4742c4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/integers.md +++ /dev/null @@ -1,113 +0,0 @@ ---- -title: Integers -description: Explore the Integer data type in Noir. Learn about its methods, see real-world examples, and grasp how to efficiently use Integers in your Noir code. -keywords: [noir, integer types, methods, examples, arithmetic] -sidebar_position: 1 ---- - -An integer type is a range constrained field type. The Noir frontend supports arbitrarily-sized, both unsigned and signed integer types. - -:::info - -When an integer is defined in Noir without a specific type, it will default to `Field`. - -The one exception is for loop indices which default to `u64` since comparisons on `Field`s are not possible. - -::: - -## Unsigned Integers - -An unsigned integer type is specified first with the letter `u` (indicating its unsigned nature) followed by its bit size (e.g. `8`): - -```rust -fn main() { - let x: u8 = 1; - let y: u8 = 1; - let z = x + y; - assert (z == 2); -} -``` - -The bit size determines the maximum value the integer type can store. For example, a `u8` variable can store a value in the range of 0 to 255 (i.e. $\\2^{8}-1\\$). - -## Signed Integers - -A signed integer type is specified first with the letter `i` (which stands for integer) followed by its bit size (e.g. `8`): - -```rust -fn main() { - let x: i8 = -1; - let y: i8 = -1; - let z = x + y; - assert (z == -2); -} -``` - -The bit size determines the maximum and minimum range of value the integer type can store. For example, an `i8` variable can store a value in the range of -128 to 127 (i.e. $\\-2^{7}\\$ to $\\2^{7}-1\\$). - -:::tip - -If you are using the default proving backend with Noir, both even (e.g. _u2_, _i2_) and odd (e.g. _u3_, _i3_) arbitrarily-sized integer types up to 127 bits (i.e. _u127_ and _i127_) are supported. - -::: - -## Overflows - -Computations that exceed the type boundaries will result in overflow errors. This happens with both signed and unsigned integers. For example, attempting to prove: - -```rust -fn main(x: u8, y: u8) { - let z = x + y; -} -``` - -With: - -```toml -x = "255" -y = "1" -``` - -Would result in: - -``` -$ nargo prove -error: Assertion failed: 'attempt to add with overflow' -┌─ ~/src/main.nr:9:13 -│ -│ let z = x + y; -│ ----- -│ -= Call stack: - ... -``` - -A similar error would happen with signed integers: - -```rust -fn main() { - let x: i8 = -118; - let y: i8 = -11; - let z = x + y; -} -``` - -### Wrapping methods - -Although integer overflow is expected to error, some use-cases rely on wrapping. For these use-cases, the standard library provides `wrapping` variants of certain common operations: - -```rust -fn wrapping_add(x: T, y: T) -> T; -fn wrapping_sub(x: T, y: T) -> T; -fn wrapping_mul(x: T, y: T) -> T; -``` - -Example of how it is used: - -```rust -use dep::std; - -fn main(x: u8, y: u8) -> pub u8 { - std::wrapping_add(x, y) -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/slices.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/slices.mdx deleted file mode 100644 index 4a6ee816aa2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/slices.mdx +++ /dev/null @@ -1,147 +0,0 @@ ---- -title: Slices -description: Explore the Slice data type in Noir. Understand its methods, see real-world examples, and learn how to effectively use Slices in your Noir programs. -keywords: [noir, slice type, methods, examples, subarrays] -sidebar_position: 5 ---- - -import Experimental from '@site/src/components/Notes/_experimental.mdx'; - - - -A slice is a dynamically-sized view into a sequence of elements. They can be resized at runtime, but because they don't own the data, they cannot be returned from a circuit. You can treat slices as arrays without a constrained size. - -```rust -use dep::std::slice; - -fn main() -> pub Field { - let mut slice: [Field] = [0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -View the corresponding test file [here][test-file]. - -[test-file]: https://github.com/noir-lang/noir/blob/f387ec1475129732f72ba294877efdf6857135ac/crates/nargo_cli/tests/test_data_ssa_refactor/slices/src/main.nr - -## Methods - -For convenience, the STD provides some ready-to-use, common methods for slices: - -### push_back - -Pushes a new element to the end of the slice, returning a new slice with a length one greater than the original unmodified slice. - -```rust -fn push_back(_self: [T], _elem: T) -> [T] -``` - -example: - -```rust -fn main() -> pub Field { - let mut slice: [Field] = [0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -View the corresponding test file [here][test-file]. - -### push_front - -Returns a new array with the specified element inserted at index 0. The existing elements indexes are incremented by 1. - -```rust -fn push_front(_self: Self, _elem: T) -> Self -``` - -Example: - -```rust -let mut new_slice: [Field] = []; -new_slice = new_slice.push_front(20); -assert(new_slice[0] == 20); // returns true -``` - -View the corresponding test file [here][test-file]. - -### pop_front - -Returns a tuple of two items, the first element of the array and the rest of the array. - -```rust -fn pop_front(_self: Self) -> (T, Self) -``` - -Example: - -```rust -let (first_elem, rest_of_slice) = slice.pop_front(); -``` - -View the corresponding test file [here][test-file]. - -### pop_back - -Returns a tuple of two items, the beginning of the array with the last element omitted and the last element. - -```rust -fn pop_back(_self: Self) -> (Self, T) -``` - -Example: - -```rust -let (popped_slice, last_elem) = slice.pop_back(); -``` - -View the corresponding test file [here][test-file]. - -### append - -Loops over a slice and adds it to the end of another. - -```rust -fn append(mut self, other: Self) -> Self -``` - -Example: - -```rust -let append = [1, 2].append([3, 4, 5]); -``` - -### insert - -Inserts an element at a specified index and shifts all following elements by 1. - -```rust -fn insert(_self: Self, _index: Field, _elem: T) -> Self -``` - -Example: - -```rust -new_slice = rest_of_slice.insert(2, 100); -assert(new_slice[2] == 100); -``` - -View the corresponding test file [here][test-file]. - -### remove - -Remove an element at a specified index, shifting all elements after it to the left, returning the altered slice and the removed element. - -```rust -fn remove(_self: Self, _index: Field) -> (Self, T) -``` - -Example: - -```rust -let (remove_slice, removed_elem) = slice.remove(3); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/strings.md deleted file mode 100644 index dd6c844f6ae..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/strings.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: Strings -description: - Discover the String data type in Noir. Learn about its methods, see real-world examples, and understand how to effectively manipulate and use Strings in Noir. -keywords: - [ - noir, - string type, - methods, - examples, - concatenation, - ] -sidebar_position: 3 ---- - - -The string type is a fixed length value defined with `str`. - -You can use strings in `assert()` functions or print them with -`std::println()`. See more about [Logging](../../standard_library/logging.md). - -```rust -use dep::std; - -fn main(message : pub str<11>, hex_as_string : str<4>) { - std::println(message); - assert(message == "hello world"); - assert(hex_as_string == "0x41"); -} -``` - -You can convert a `str` to a byte array by calling `as_bytes()` -or a vector by calling `as_bytes_vec()`. - -```rust -fn main() { - let message = "hello world"; - let message_bytes = message.as_bytes(); - let mut message_vec = message.as_bytes_vec(); - assert(message_bytes.len() == 11); - assert(message_bytes[0] == 104); - assert(message_bytes[0] == message_vec.get(0)); -} -``` - -## Escape characters - -You can use escape characters for your strings: - -| Escape Sequence | Description | -|-----------------|-----------------| -| `\r` | Carriage Return | -| `\n` | Newline | -| `\t` | Tab | -| `\0` | Null Character | -| `\"` | Double Quote | -| `\\` | Backslash | - -Example: - -```rust -let s = "Hello \"world" // prints "Hello "world" -let s = "hey \tyou"; // prints "hey you" -``` - -## Raw strings - -A raw string begins with the letter `r` and is optionally delimited by a number of hashes `#`. - -Escape characters are *not* processed within raw strings. All contents are interpreted literally. - -Example: - -```rust -let s = r"Hello world"; -let s = r#"Simon says "hello world""#; - -// Any number of hashes may be used (>= 1) as long as the string also terminates with the same number of hashes -let s = r#####"One "#, Two "##, Three "###, Four "####, Five will end the string."#####; -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/vectors.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/vectors.mdx deleted file mode 100644 index 10e35711b74..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/vectors.mdx +++ /dev/null @@ -1,173 +0,0 @@ ---- -title: Vectors -description: Delve into the Vector data type in Noir. Learn about its methods, practical examples, and best practices for using Vectors in your Noir code. -keywords: [noir, vector type, methods, examples, dynamic arrays] -sidebar_position: 6 ---- - -import Experimental from '@site/src/components/Notes/_experimental.mdx'; - - - -A vector is a collection type similar to Rust's Vector type. It's convenient way to use slices as mutable arrays. - -Example: - -```rust -use dep::std::collections::vec::Vec; - -let mut vector: Vec = Vec::new(); -for i in 0..5 { - vector.push(i); -} -assert(vector.len() == 5); -``` - -## Methods - -### new - -Creates a new, empty vector. - -```rust -pub fn new() -> Self { - Self { slice: [] } -} -``` - -Example: - -```rust -let empty_vector: Vec = Vec::new(); -assert(empty_vector.len() == 0); -``` - -### from_slice - -Creates a vector containing each element from a given slice. Mutations to the resulting vector will not affect the original slice. - -```rust -pub fn from_slice(slice: [T]) -> Self { - Self { slice } -} -``` - -Example: - -```rust -let arr: [Field] = [1, 2, 3]; -let vector_from_slice = Vec::from_slice(arr); -assert(vector_from_slice.len() == 3); -``` - -### get - -Retrieves an element from the vector at a given index. Panics if the index points beyond the vector's end. - -```rust -pub fn get(self, index: Field) -> T { - self.slice[index] -} -``` - -Example: - -```rust -let vector: Vec = Vec::from_slice([10, 20, 30]); -assert(vector.get(1) == 20); -``` - -### push - -Adds a new element to the vector's end, returning a new vector with a length one greater than the original unmodified vector. - -```rust -pub fn push(&mut self, elem: T) { - self.slice = self.slice.push_back(elem); -} -``` - -Example: - -```rust -let mut vector: Vec = Vec::new(); -vector.push(10); -assert(vector.len() == 1); -``` - -### pop - -Removes an element from the vector's end, returning a new vector with a length one less than the original vector, along with the removed element. Panics if the vector's length is zero. - -```rust -pub fn pop(&mut self) -> T { - let (popped_slice, last_elem) = self.slice.pop_back(); - self.slice = popped_slice; - last_elem -} -``` - -Example: - -```rust -let mut vector = Vec::from_slice([10, 20]); -let popped_elem = vector.pop(); -assert(popped_elem == 20); -assert(vector.len() == 1); -``` - -### insert - -Inserts an element at a specified index, shifting subsequent elements to the right. - -```rust -pub fn insert(&mut self, index: Field, elem: T) { - self.slice = self.slice.insert(index, elem); -} -``` - -Example: - -```rust -let mut vector = Vec::from_slice([10, 30]); -vector.insert(1, 20); -assert(vector.get(1) == 20); -``` - -### remove - -Removes an element at a specified index, shifting subsequent elements to the left, and returns the removed element. - -```rust -pub fn remove(&mut self, index: Field) -> T { - let (new_slice, elem) = self.slice.remove(index); - self.slice = new_slice; - elem -} -``` - -Example: - -```rust -let mut vector = Vec::from_slice([10, 20, 30]); -let removed_elem = vector.remove(1); -assert(removed_elem == 20); -assert(vector.len() == 2); -``` - -### len - -Returns the number of elements in the vector. - -```rust -pub fn len(self) -> Field { - self.slice.len() -} -``` - -Example: - -```rust -let empty_vector: Vec = Vec::new(); -assert(empty_vector.len() == 0); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/distinct.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/distinct.md deleted file mode 100644 index b59e0296b23..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/distinct.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: Distinct Witnesses -sidebar_position: 10 ---- - -The `distinct` keyword prevents repetitions of witness indices in the program's ABI. This ensures -that the witnesses being returned as public inputs are all unique. - -The `distinct` keyword is only used for return values on program entry points (usually the `main()` -function). - -When using `distinct` and `pub` simultaneously, `distinct` comes first. See the example below. - -You can read more about the problem this solves -[here](https://github.com/noir-lang/noir/issues/1183). - -## Example - -Without the `distinct` keyword, the following program - -```rust -fn main(x : pub Field, y : pub Field) -> pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - "return_witnesses": [3, 2, 4, 4] - } -} -``` - -Whereas (with the `distinct` keyword) - -```rust -fn main(x : pub Field, y : pub Field) -> distinct pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - //... - "return_witnesses": [3, 4, 5, 6] - } -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/functions.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/functions.md deleted file mode 100644 index 48aba9cd058..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/functions.md +++ /dev/null @@ -1,226 +0,0 @@ ---- -title: Functions -description: - Learn how to declare functions and methods in Noir, a programming language with Rust semantics. - This guide covers parameter declaration, return types, call expressions, and more. -keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] -sidebar_position: 1 ---- - -Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. - -To declare a function the `fn` keyword is used. - -```rust -fn foo() {} -``` - -By default, functions are visible only within the package they are defined. To make them visible outside of that package (for example, as part of a [library](../modules_packages_crates/crates_and_packages.md#libraries)), you should mark them as `pub`: - -```rust -pub fn foo() {} -``` - -You can also restrict the visibility of the function to only the crate it was defined in, by specifying `pub(crate)`: - -```rust -pub(crate) fn foo() {} //foo can only be called within its crate -``` - -All parameters in a function must have a type and all types are known at compile time. The parameter -is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. - -```rust -fn foo(x : Field, y : Field){} -``` - -The return type of a function can be stated by using the `->` arrow notation. The function below -states that the foo function must return a `Field`. If the function returns no value, then the arrow -is omitted. - -```rust -fn foo(x : Field, y : Field) -> Field { - x + y -} -``` - -Note that a `return` keyword is unneeded in this case - the last expression in a function's body is -returned. - -## Main function - -If you're writing a binary, the `main` function is the starting point of your program. You can pass all types of expressions to it, as long as they have a fixed size at compile time: - -```rust -fn main(x : Field) // this is fine: passing a Field -fn main(x : [Field; 2]) // this is also fine: passing a Field with known size at compile-time -fn main(x : (Field, bool)) // 👌: passing a (Field, bool) tuple means size 2 -fn main(x : str<5>) // this is fine, as long as you pass a string of size 5 - -fn main(x : Vec) // can't compile, has variable size -fn main(x : [Field]) // can't compile, has variable size -fn main(....// i think you got it by now -``` - -Keep in mind [tests](../../getting_started/tooling/testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: - -```rust -fn main(x : [Field]) { - assert(x[0] == 1); -} - -#[test] -fn test_one() { - main([1, 2]); -} -``` - -```bash -$ nargo test -[testing] Running 1 test functions -[testing] Testing test_one... ok -[testing] All tests passed - -$ nargo check -The application panicked (crashed). -Message: Cannot have variable sized arrays as a parameter to main -``` - -## Call Expressions - -Calling a function in Noir is executed by using the function name and passing in the necessary -arguments. - -Below we show how to call the `foo` function from the `main` function using a call expression: - -```rust -fn main(x : Field, y : Field) { - let z = foo(x); -} - -fn foo(x : Field) -> Field { - x + x -} -``` - -## Methods - -You can define methods in Noir on any struct type in scope. - -```rust -struct MyStruct { - foo: Field, - bar: Field, -} - -impl MyStruct { - fn new(foo: Field) -> MyStruct { - MyStruct { - foo, - bar: 2, - } - } - - fn sum(self) -> Field { - self.foo + self.bar - } -} - -fn main() { - let s = MyStruct::new(40); - assert(s.sum() == 42); -} -``` - -Methods are just syntactic sugar for functions, so if we wanted to we could also call `sum` as -follows: - -```rust -assert(MyStruct::sum(s) == 42); -``` - -It is also possible to specialize which method is chosen depending on the [generic](./generics.md) type that is used. In this example, the `foo` function returns different values depending on its type: - -```rust -struct Foo {} - -impl Foo { - fn foo(self) -> Field { 1 } -} - -impl Foo { - fn foo(self) -> Field { 2 } -} - -fn main() { - let f1: Foo = Foo{}; - let f2: Foo = Foo{}; - assert(f1.foo() + f2.foo() == 3); -} -``` - -Also note that impls with the same method name defined in them cannot overlap. For example, if we already have `foo` defined for `Foo` and `Foo` like we do above, we cannot also define `foo` in an `impl Foo` since it would be ambiguous which version of `foo` to choose. - -```rust -// Including this impl in the same project as the above snippet would -// cause an overlapping impls error -impl Foo { - fn foo(self) -> Field { 3 } -} -``` - -## Lambdas - -Lambdas are anonymous functions. They follow the syntax of Rust - `|arg1, arg2, ..., argN| return_expression`. - -```rust -let add_50 = |val| val + 50; -assert(add_50(100) == 150); -``` - -See [Lambdas](./lambdas.md) for more details. - -## Attributes - -Attributes are metadata that can be applied to a function, using the following syntax: `#[attribute(value)]`. - -Supported attributes include: - -- **builtin**: the function is implemented by the compiler, for efficiency purposes. -- **deprecated**: mark the function as _deprecated_. Calling the function will generate a warning: `warning: use of deprecated function` -- **field**: Used to enable conditional compilation of code depending on the field size. See below for more details -- **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./unconstrained.md) and [NoirJS](../../reference/NoirJS/noir_js/index.md) for more details. -- **test**: mark the function as unit tests. See [Tests](../../getting_started/tooling/testing.md) for more details - -### Field Attribute - -The field attribute defines which field the function is compatible for. The function is conditionally compiled, under the condition that the field attribute matches the Noir native field. -The field can be defined implicitly, by using the name of the elliptic curve usually associated to it - for instance bn254, bls12_381 - or explicitly by using the field (prime) order, in decimal or hexadecimal form. -As a result, it is possible to define multiple versions of a function with each version specialized for a different field attribute. This can be useful when a function requires different parameters depending on the underlying elliptic curve. - -Example: we define the function `foo()` three times below. Once for the default Noir bn254 curve, once for the field $\mathbb F_{23}$, which will normally never be used by Noir, and once again for the bls12_381 curve. - -```rust -#[field(bn254)] -fn foo() -> u32 { - 1 -} - -#[field(23)] -fn foo() -> u32 { - 2 -} - -// This commented code would not compile as foo would be defined twice because it is the same field as bn254 -// #[field(21888242871839275222246405745257275088548364400416034343698204186575808495617)] -// fn foo() -> u32 { -// 2 -// } - -#[field(bls12_381)] -fn foo() -> u32 { - 3 -} -``` - -If the field name is not known to Noir, it will discard the function. Field names are case insensitive. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/generics.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/generics.md deleted file mode 100644 index d59e4c5d7c6..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/generics.md +++ /dev/null @@ -1,114 +0,0 @@ ---- -title: Generics -description: Learn how to use Generics in Noir -keywords: [Noir, Rust, generics, functions, structs] -sidebar_position: 6 ---- - -Generics allow you to use the same functions with multiple different concrete data types. You can -read more about the concept of generics in the Rust documentation -[here](https://doc.rust-lang.org/book/ch10-01-syntax.html). - -Here is a trivial example showing the identity function that supports any type. In Rust, it is -common to refer to the most general type as `T`. We follow the same convention in Noir. - -```rust -fn id(x: T) -> T { - x -} -``` - -## In Structs - -Generics are useful for specifying types in structs. For example, we can specify that a field in a -struct will be of a certain generic type. In this case `value` is of type `T`. - -```rust -struct RepeatedValue { - value: T, - count: Field, -} - -impl RepeatedValue { - fn new(value: T) -> Self { - Self { value, count: 1 } - } - - fn increment(mut repeated: Self) -> Self { - repeated.count += 1; - repeated - } - - fn print(self) { - for _i in 0 .. self.count { - dep::std::println(self.value); - } - } -} - -fn main() { - let mut repeated = RepeatedValue::new("Hello!"); - repeated = repeated.increment(); - repeated.print(); -} -``` - -The `print` function will print `Hello!` an arbitrary number of times, twice in this case. - -If we want to be generic over array lengths (which are type-level integers), we can use numeric -generics. Using these looks just like using regular generics, but these generics can resolve to -integers at compile-time, rather than resolving to types. Here's an example of a struct that is -generic over the size of the array it contains internally: - -```rust -struct BigInt { - limbs: [u32; N], -} - -impl BigInt { - // `N` is in scope of all methods in the impl - fn first(first: BigInt, second: BigInt) -> Self { - assert(first.limbs != second.limbs); - first - - fn second(first: BigInt, second: Self) -> Self { - assert(first.limbs != second.limbs); - second - } -} -``` - -## Calling functions on generic parameters - -Unlike Rust, Noir does not have traits, so how can one translate the equivalent of a trait bound in -Rust into Noir? That is, how can we write a function that is generic over some type `T`, while also -requiring there is a function like `eq: fn(T, T) -> bool` that works on the type? - -The answer is that we can translate this by passing in the function manually. Here's an example of -implementing array equality in Noir: - -```rust -fn array_eq(array1: [T; N], array2: [T; N], elem_eq: fn(T, T) -> bool) -> bool { - if array1.len() != array2.len() { - false - } else { - let mut result = true; - for i in 0 .. array1.len() { - result &= elem_eq(array1[i], array2[i]); - } - result - } -} - -fn main() { - assert(array_eq([1, 2, 3], [1, 2, 3], |a, b| a == b)); - - // We can use array_eq even for arrays of structs, as long as we have - // an equality function for these structs we can pass in - let array = [MyStruct::new(), MyStruct::new()]; - assert(array_eq(array, array, MyStruct::eq)); -} -``` - -You can see an example of generics in the tests -[here](https://github.com/noir-lang/noir/blob/master/test_programs/execution_success/generics/src/main.nr). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/lambdas.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/lambdas.md deleted file mode 100644 index e0a267adfda..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/lambdas.md +++ /dev/null @@ -1,81 +0,0 @@ ---- -title: Lambdas -description: Learn how to use anonymous functions in Noir programming language. -keywords: [Noir programming language, lambda, closure, function, anonymous function] -sidebar_position: 8 ---- - -## Introduction - -Lambdas are anonymous functions. The syntax is `|arg1, arg2, ..., argN| return_expression`. - -```rust -let add_50 = |val| val + 50; -assert(add_50(100) == 150); -``` - -A block can be used as the body of a lambda, allowing you to declare local variables inside it: - -```rust -let cool = || { - let x = 100; - let y = 100; - x + y -} - -assert(cool() == 200); -``` - -## Closures - -Inside the body of a lambda, you can use variables defined in the enclosing function. Such lambdas are called **closures**. In this example `x` is defined inside `main` and is accessed from within the lambda: - -```rust -fn main() { - let x = 100; - let closure = || x + 150; - assert(closure() == 250); -} -``` - -## Passing closures to higher-order functions - -It may catch you by surprise that the following code fails to compile: - -```rust -fn foo(f: fn () -> Field) -> Field { - f() -} - -fn main() { - let (x, y) = (50, 50); - assert(foo(|| x + y) == 100); // error :( -} -``` - -The reason is that the closure's capture environment affects its type - we have a closure that captures two Fields and `foo` -expects a regular function as an argument - those are incompatible. -:::note - -Variables contained within the `||` are the closure's parameters, and the expression that follows it is the closure's body. The capture environment is comprised of any variables used in the closure's body that are not parameters. - -E.g. in |x| x + y, y would be a captured variable, but x would not be, since it is a parameter of the closure. - -::: -The syntax for the type of a closure is `fn[env](args) -> ret_type`, where `env` is the capture environment of the closure - -in this example that's `(Field, Field)`. - -The best solution in our case is to make `foo` generic over the environment type of its parameter, so that it can be called -with closures with any environment, as well as with regular functions: - -```rust -fn foo(f: fn[Env]() -> Field) -> Field { - f() -} - -fn main() { - let (x, y) = (50, 50); - assert(foo(|| x + y) == 100); // compiles fine - assert(foo(|| 60) == 60); // compiles fine -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/mutability.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/mutability.md deleted file mode 100644 index 6abfae3cfa7..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/mutability.md +++ /dev/null @@ -1,93 +0,0 @@ ---- -title: Mutability -description: - Learn about mutable variables, constants, and globals in Noir programming language. Discover how - to declare, modify, and use them in your programs. -keywords: [noir programming language, mutability in noir, mutable variables, constants, globals] -sidebar_position: 7 ---- - -Variables in noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned -to via an assignment expression. - -```rust -let x = 2; -x = 3; // error: x must be mutable to be assigned to - -let mut y = 3; -let y = 4; // OK -``` - -The `mut` modifier can also apply to patterns: - -```rust -let (a, mut b) = (1, 2); -a = 11; // error: a must be mutable to be assigned to -b = 12; // OK - -let mut (c, d) = (3, 4); -c = 13; // OK -d = 14; // OK - -// etc. -let MyStruct { x: mut y } = MyStruct { x: a }; -// y is now in scope -``` - -Note that mutability in noir is local and everything is passed by value, so if a called function -mutates its parameters then the parent function will keep the old value of the parameters. - -```rust -fn main() -> pub Field { - let x = 3; - helper(x); - x // x is still 3 -} - -fn helper(mut x: i32) { - x = 4; -} -``` - -## Comptime Values - -:::warning - -The 'comptime' keyword was removed in version 0.10. The comptime keyword and syntax are currently still kept and parsed for backwards compatibility, but are now deprecated and will issue a warning when used. `comptime` has been removed because it is no longer needed for accessing arrays. - -::: - -## Globals - -Noir also supports global variables. However, they must be known at compile-time. The global type can also be inferred by the compiler entirely. Globals can also be used to specify array -annotations for function parameters and can be imported from submodules. - -```rust -global N: Field = 5; // Same as `global N: Field = 5` - -fn main(x : Field, y : [Field; N]) { - let res = x * N; - - assert(res == y[0]); - - let res2 = x * my_submodule::N; - assert(res != res2); -} - -mod my_submodule { - use dep::std; - - global N: Field = 10; - - fn my_helper() -> Field { - let x = N; - x - } -} -``` - -## Why only local mutability? - -Witnesses in a proving system are immutable in nature. Noir aims to _closely_ mirror this setting -without applying additional overhead to the user. Modeling a mutable reference is not as -straightforward as on conventional architectures and would incur some possibly unexpected overhead. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/ops.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/ops.md deleted file mode 100644 index 60425cb8994..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/ops.md +++ /dev/null @@ -1,98 +0,0 @@ ---- -title: Logical Operations -description: - Learn about the supported arithmetic and logical operations in the Noir programming language. - Discover how to perform operations on private input types, integers, and booleans. -keywords: - [ - Noir programming language, - supported operations, - arithmetic operations, - logical operations, - predicate operators, - bitwise operations, - short-circuiting, - backend, - ] -sidebar_position: 3 ---- - -# Operations - -## Table of Supported Operations - -| Operation | Description | Requirements | -| :-------- | :------------------------------------------------------------: | -------------------------------------: | -| + | Adds two private input types together | Types must be private input | -| - | Subtracts two private input types together | Types must be private input | -| \* | Multiplies two private input types together | Types must be private input | -| / | Divides two private input types together | Types must be private input | -| ^ | XOR two private input types together | Types must be integer | -| & | AND two private input types together | Types must be integer | -| \| | OR two private input types together | Types must be integer | -| \<\< | Left shift an integer by another integer amount | Types must be integer | -| >> | Right shift an integer by another integer amount | Types must be integer | -| ! | Bitwise not of a value | Type must be integer or boolean | -| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | -| > | returns a bool if one value is more than the other | Upper bound must have a known bit size | -| >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | -| == | returns a bool if one value is equal to the other | Both types must not be constants | -| != | returns a bool if one value is not equal to the other | Both types must not be constants | - -### Predicate Operators - -`<,<=, !=, == , >, >=` are known as predicate/comparison operations because they compare two values. -This differs from the operations such as `+` where the operands are used in _computation_. - -### Bitwise Operations Example - -```rust -fn main(x : Field) { - let y = x as u32; - let z = y & y; -} -``` - -`z` is implicitly constrained to be the result of `y & y`. The `&` operand is used to denote bitwise -`&`. - -> `x & x` would not compile as `x` is a `Field` and not an integer type. - -### Logical Operators - -Noir has no support for the logical operators `||` and `&&`. This is because encoding the -short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can -use the bitwise operators `|` and `&` which operate identically for booleans, just without the -short-circuiting. - -```rust -let my_val = 5; - -let mut flag = 1; -if (my_val > 6) | (my_val == 0) { - flag = 0; -} -assert(flag == 1); - -if (my_val != 10) & (my_val < 50) { - flag = 0; -} -assert(flag == 0); -``` - -### Shorthand operators - -Noir shorthand operators for most of the above operators, namely `+=, -=, *=, /=, %=, &=, |=, ^=, <<=`, and `>>=`. These allow for more concise syntax. For example: - -```rust -let mut i = 0; -i = i + 1; -``` - -could be written as: - -```rust -let mut i = 0; -i += 1; -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/shadowing.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/shadowing.md deleted file mode 100644 index b5a6b6b38b9..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/shadowing.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Shadowing -sidebar_position: 11 ---- - -Noir allows for inheriting variables' values and re-declaring them with the same name similar to Rust, known as shadowing. - -For example, the following function is valid in Noir: - -```rust -fn main() { - let x = 5; - - { - let x = x * 2; - assert (x == 10); - } - - assert (x == 5); -} -``` - -In this example, a variable x is first defined with the value 5. - -The local scope that follows shadows the original x, i.e. creates a local mutable x based on the value of the original x. It is given a value of 2 times the original x. - -When we return to the main scope, x once again refers to just the original x, which stays at the value of 5. - -## Temporal mutability - -One way that shadowing is useful, in addition to ergonomics across scopes, is for temporarily mutating variables. - -```rust -fn main() { - let age = 30; - // age = age + 5; // Would error as `age` is immutable by default. - - let mut age = age + 5; // Temporarily mutates `age` with a new value. - - let age = age; // Locks `age`'s mutability again. - - assert (age == 35); -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/unconstrained.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/unconstrained.md deleted file mode 100644 index 6b3424f7993..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/unconstrained.md +++ /dev/null @@ -1,95 +0,0 @@ ---- -title: Unconstrained Functions -description: "Learn about what unconstrained functions in Noir are, how to use them and when you'd want to." - -keywords: [Noir programming language, unconstrained, open] -sidebar_position: 5 ---- - -Unconstrained functions are functions which do not constrain any of the included computation and allow for non-deterministic computation. - -## Why? - -Zero-knowledge (ZK) domain-specific languages (DSL) enable developers to generate ZK proofs from their programs by compiling code down to the constraints of an NP complete language (such as R1CS or PLONKish languages). However, the hard bounds of a constraint system can be very limiting to the functionality of a ZK DSL. - -Enabling a circuit language to perform unconstrained execution is a powerful tool. Said another way, unconstrained execution lets developers generate witnesses from code that does not generate any constraints. Being able to execute logic outside of a circuit is critical for both circuit performance and constructing proofs on information that is external to a circuit. - -Fetching information from somewhere external to a circuit can also be used to enable developers to improve circuit efficiency. - -A ZK DSL does not just prove computation, but proves that some computation was handled correctly. Thus, it is necessary that when we switch from performing some operation directly inside of a circuit to inside of an unconstrained environment that the appropriate constraints are still laid down elsewhere in the circuit. - -## Example - -An in depth example might help drive the point home. This example comes from the excellent [post](https://discord.com/channels/1113924620781883405/1124022445054111926/1128747641853972590) by Tom in the Noir Discord. - -Let's look at how we can optimize a function to turn a `u72` into an array of `u8`s. - -```rust -fn main(num: u72) -> pub [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8)) as u72 & 0xff) as u8; - } - - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 91 -Backend circuit size: 3619 -``` - -A lot of the operations in this function are optimized away by the compiler (all the bit-shifts turn into divisions by constants). However we can save a bunch of gates by casting to u8 a bit earlier. This automatically truncates the bit-shifted value to fit in a u8 which allows us to remove the XOR against 0xff. This saves us ~480 gates in total. - -```rust -fn main(num: u72) -> pub [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8)) as u8; - } - - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 75 -Backend circuit size: 3143 -``` - -Those are some nice savings already but we can do better. This code is all constrained so we're proving every step of calculating out using num, but we don't actually care about how we calculate this, just that it's correct. This is where brillig comes in. - -It turns out that truncating a u72 into a u8 is hard to do inside a snark, each time we do as u8 we lay down 4 ACIR opcodes which get converted into multiple gates. It's actually much easier to calculate num from out than the other way around. All we need to do is multiply each element of out by a constant and add them all together, both relatively easy operations inside a snark. - -We can then run u72_to_u8 as unconstrained brillig code in order to calculate out, then use that result in our constrained function and assert that if we were to do the reverse calculation we'd get back num. This looks a little like the below: - -```rust -fn main(num: u72) -> pub [u8; 8] { - let out = u72_to_u8(num); - - let mut reconstructed_num: u72 = 0; - for i in 0..8 { - reconstructed_num += (out[i] as u72 << (56 - (8 * i))); - } - assert(num == reconstructed_num); - out -} - -unconstrained fn u72_to_u8(num: u72) -> [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8))) as u8; - } - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 78 -Backend circuit size: 2902 -``` - -This ends up taking off another ~250 gates from our circuit! We've ended up with more ACIR opcodes than before but they're easier for the backend to prove (resulting in fewer gates). - -Generally we want to use brillig whenever there's something that's easy to verify but hard to compute within the circuit. For example, if you wanted to calculate a square root of a number it'll be a much better idea to calculate this in brillig and then assert that if you square the result you get back your number. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/.nojekyll deleted file mode 100644 index e2ac6616add..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md deleted file mode 100644 index 5cbe9421b92..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md +++ /dev/null @@ -1,185 +0,0 @@ -# BarretenbergBackend - -## Implements - -- [`Backend`](../interfaces/Backend.md) - -## Constructors - -### new BarretenbergBackend(acirCircuit, options) - -```ts -new BarretenbergBackend(acirCircuit, options): BarretenbergBackend -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `acirCircuit` | [`CompiledCircuit`](../type-aliases/CompiledCircuit.md) | -| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | - -#### Returns - -[`BarretenbergBackend`](BarretenbergBackend.md) - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`destroy`](../interfaces/Backend.md#destroy) - -#### Description - -Destroys the backend - -*** - -### generateFinalProof() - -```ts -generateFinalProof(decompressedWitness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `decompressedWitness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`generateFinalProof`](../interfaces/Backend.md#generatefinalproof) - -#### Description - -Generates a final proof (not meant to be verified in another circuit) - -*** - -### generateIntermediateProof() - -```ts -generateIntermediateProof(witness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `witness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`generateIntermediateProof`](../interfaces/Backend.md#generateintermediateproof) - -#### Example - -```typescript -const intermediateProof = await backend.generateIntermediateProof(witness); -``` - -*** - -### generateIntermediateProofArtifacts() - -```ts -generateIntermediateProofArtifacts(proofData, numOfPublicInputs): Promise -``` - -#### Parameters - -| Parameter | Type | Default value | -| :------ | :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | `undefined` | -| `numOfPublicInputs` | `number` | `0` | - -#### Returns - -`Promise`\<`object`\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`generateIntermediateProofArtifacts`](../interfaces/Backend.md#generateintermediateproofartifacts) - -#### Example - -```typescript -const artifacts = await backend.generateIntermediateProofArtifacts(proof, numOfPublicInputs); -``` - -*** - -### verifyFinalProof() - -```ts -verifyFinalProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`verifyFinalProof`](../interfaces/Backend.md#verifyfinalproof) - -#### Description - -Verifies a final proof - -*** - -### verifyIntermediateProof() - -```ts -verifyIntermediateProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`verifyIntermediateProof`](../interfaces/Backend.md#verifyintermediateproof) - -#### Example - -```typescript -const isValidIntermediate = await backend.verifyIntermediateProof(proof); -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/index.md deleted file mode 100644 index bfbecb52864..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/index.md +++ /dev/null @@ -1,45 +0,0 @@ -# backend_barretenberg - -## Exports - -### Classes - -| Class | Description | -| :------ | :------ | -| [BarretenbergBackend](classes/BarretenbergBackend.md) | - | - -### Interfaces - -| Interface | Description | -| :------ | :------ | -| [Backend](interfaces/Backend.md) | - | - -### Type Aliases - -| Type alias | Description | -| :------ | :------ | -| [BackendOptions](type-aliases/BackendOptions.md) | - | -| [CompiledCircuit](type-aliases/CompiledCircuit.md) | - | -| [ProofData](type-aliases/ProofData.md) | - | - -## Functions - -### flattenPublicInputs() - -```ts -flattenPublicInputs(publicInputs): string[] -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `publicInputs` | `WitnessMap` | - -#### Returns - -`string`[] - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/interfaces/Backend.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/interfaces/Backend.md deleted file mode 100644 index 3eb9645c8d2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/interfaces/Backend.md +++ /dev/null @@ -1,132 +0,0 @@ -# Backend - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Description - -Destroys the backend - -*** - -### generateFinalProof() - -```ts -generateFinalProof(decompressedWitness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `decompressedWitness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Description - -Generates a final proof (not meant to be verified in another circuit) - -*** - -### generateIntermediateProof() - -```ts -generateIntermediateProof(decompressedWitness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `decompressedWitness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Description - -Generates an intermediate proof (meant to be verified in another circuit) - -*** - -### generateIntermediateProofArtifacts() - -```ts -generateIntermediateProofArtifacts(proofData, numOfPublicInputs): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | -| `numOfPublicInputs` | `number` | - -#### Returns - -`Promise`\<`object`\> - -#### Description - -Retrieves the artifacts from a proof in the Field format - -*** - -### verifyFinalProof() - -```ts -verifyFinalProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Verifies a final proof - -*** - -### verifyIntermediateProof() - -```ts -verifyIntermediateProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Verifies an intermediate proof - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md deleted file mode 100644 index 266ade75d17..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md +++ /dev/null @@ -1,19 +0,0 @@ -# BackendOptions - -```ts -type BackendOptions: object; -``` - -## Description - -An options object, currently only used to specify the number of threads to use. - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `threads` | `number` | **Description**

Number of threads | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit.md deleted file mode 100644 index 34e0dd04205..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit.md +++ /dev/null @@ -1,20 +0,0 @@ -# CompiledCircuit - -```ts -type CompiledCircuit: object; -``` - -## Description - -The representation of a compiled circuit - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `abi` | `Abi` | **Description**

ABI representation of the circuit | -| `bytecode` | `string` | **Description**

The bytecode of the circuit | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/type-aliases/ProofData.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/type-aliases/ProofData.md deleted file mode 100644 index 3eb360a78f1..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/type-aliases/ProofData.md +++ /dev/null @@ -1,20 +0,0 @@ -# ProofData - -```ts -type ProofData: object; -``` - -## Description - -The representation of a proof - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `proof` | `Uint8Array` | **Description**

An byte array representing the proof | -| `publicInputs` | `WitnessMap` | **Description**

Public inputs of a proof | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs deleted file mode 100644 index 2aaa55bccf6..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend","label":"BarretenbergBackend"}]},{"type":"category","label":"Interfaces","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/interfaces/Backend","label":"Backend"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions","label":"BackendOptions"},{"type":"doc","id":"reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit","label":"CompiledCircuit"},{"type":"doc","id":"reference/NoirJS/backend_barretenberg/type-aliases/ProofData","label":"ProofData"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/.nojekyll deleted file mode 100644 index e2ac6616add..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/classes/Noir.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/classes/Noir.md deleted file mode 100644 index 34e20d99684..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/classes/Noir.md +++ /dev/null @@ -1,132 +0,0 @@ -# Noir - -## Constructors - -### new Noir(circuit, backend) - -```ts -new Noir(circuit, backend?): Noir -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `circuit` | [`CompiledCircuit`](../type-aliases/CompiledCircuit.md) | -| `backend`? | `Backend` | - -#### Returns - -[`Noir`](Noir.md) - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Description - -Destroys the underlying backend instance. - -#### Example - -```typescript -await noir.destroy(); -``` - -*** - -### execute() - -```ts -execute(inputs, foreignCallHandler?): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `inputs` | [`InputMap`](../type-aliases/InputMap.md) | -| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | - -#### Returns - -`Promise`\<`object`\> - -#### Description - -Allows to execute a circuit to get its witness and return value. - -#### Example - -```typescript -async execute(inputs) -``` - -*** - -### generateFinalProof() - -```ts -generateFinalProof(inputs, foreignCallHandler?): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `inputs` | [`InputMap`](../type-aliases/InputMap.md) | -| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Description - -Generates a witness and a proof given an object as input. - -#### Example - -```typescript -async generateFinalProof(input) -``` - -*** - -### verifyFinalProof() - -```ts -verifyFinalProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Instantiates the verification key and verifies a proof. - -#### Example - -```typescript -async verifyFinalProof(proof) -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/and.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/and.md deleted file mode 100644 index c783283e396..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/and.md +++ /dev/null @@ -1,22 +0,0 @@ -# and() - -```ts -and(lhs, rhs): string -``` - -Performs a bitwise AND operation between `lhs` and `rhs` - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `lhs` | `string` | | -| `rhs` | `string` | | - -## Returns - -`string` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/blake2s256.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/blake2s256.md deleted file mode 100644 index 7882d0da8d5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/blake2s256.md +++ /dev/null @@ -1,21 +0,0 @@ -# blake2s256() - -```ts -blake2s256(inputs): Uint8Array -``` - -Calculates the Blake2s256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md deleted file mode 100644 index 0ba5783f0d5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md +++ /dev/null @@ -1,29 +0,0 @@ -# ecdsa\_secp256k1\_verify() - -```ts -ecdsa_secp256k1_verify( - hashed_msg, - public_key_x_bytes, - public_key_y_bytes, - signature): boolean -``` - -Calculates the Blake2s256 hash of the input bytes and represents these as a single field element. -Verifies a ECDSA signature over the secp256k1 curve. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `hashed_msg` | `Uint8Array` | | -| `public_key_x_bytes` | `Uint8Array` | | -| `public_key_y_bytes` | `Uint8Array` | | -| `signature` | `Uint8Array` | | - -## Returns - -`boolean` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md deleted file mode 100644 index 0b20ff68957..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md +++ /dev/null @@ -1,28 +0,0 @@ -# ecdsa\_secp256r1\_verify() - -```ts -ecdsa_secp256r1_verify( - hashed_msg, - public_key_x_bytes, - public_key_y_bytes, - signature): boolean -``` - -Verifies a ECDSA signature over the secp256r1 curve. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `hashed_msg` | `Uint8Array` | | -| `public_key_x_bytes` | `Uint8Array` | | -| `public_key_y_bytes` | `Uint8Array` | | -| `signature` | `Uint8Array` | | - -## Returns - -`boolean` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/keccak256.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/keccak256.md deleted file mode 100644 index d10f155ce86..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/keccak256.md +++ /dev/null @@ -1,21 +0,0 @@ -# keccak256() - -```ts -keccak256(inputs): Uint8Array -``` - -Calculates the Keccak256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/sha256.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/sha256.md deleted file mode 100644 index 6ba4ecac022..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/sha256.md +++ /dev/null @@ -1,21 +0,0 @@ -# sha256() - -```ts -sha256(inputs): Uint8Array -``` - -Calculates the SHA256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/xor.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/xor.md deleted file mode 100644 index 8d762b895d3..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/xor.md +++ /dev/null @@ -1,22 +0,0 @@ -# xor() - -```ts -xor(lhs, rhs): string -``` - -Performs a bitwise XOR operation between `lhs` and `rhs` - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `lhs` | `string` | | -| `rhs` | `string` | | - -## Returns - -`string` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/index.md deleted file mode 100644 index 8b9e35bc9a1..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/index.md +++ /dev/null @@ -1,37 +0,0 @@ -# noir_js - -## Exports - -### Classes - -| Class | Description | -| :------ | :------ | -| [Noir](classes/Noir.md) | - | - -### Type Aliases - -| Type alias | Description | -| :------ | :------ | -| [CompiledCircuit](type-aliases/CompiledCircuit.md) | - | -| [ForeignCallHandler](type-aliases/ForeignCallHandler.md) | A callback which performs an foreign call and returns the response. | -| [ForeignCallInput](type-aliases/ForeignCallInput.md) | - | -| [ForeignCallOutput](type-aliases/ForeignCallOutput.md) | - | -| [InputMap](type-aliases/InputMap.md) | - | -| [ProofData](type-aliases/ProofData.md) | - | -| [WitnessMap](type-aliases/WitnessMap.md) | - | - -### Functions - -| Function | Description | -| :------ | :------ | -| [and](functions/and.md) | Performs a bitwise AND operation between `lhs` and `rhs` | -| [blake2s256](functions/blake2s256.md) | Calculates the Blake2s256 hash of the input bytes | -| [ecdsa\_secp256k1\_verify](functions/ecdsa_secp256k1_verify.md) | Calculates the Blake2s256 hash of the input bytes and represents these as a single field element. | -| [ecdsa\_secp256r1\_verify](functions/ecdsa_secp256r1_verify.md) | Verifies a ECDSA signature over the secp256r1 curve. | -| [keccak256](functions/keccak256.md) | Calculates the Keccak256 hash of the input bytes | -| [sha256](functions/sha256.md) | Calculates the SHA256 hash of the input bytes | -| [xor](functions/xor.md) | Performs a bitwise XOR operation between `lhs` and `rhs` | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/CompiledCircuit.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/CompiledCircuit.md deleted file mode 100644 index 34e0dd04205..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/CompiledCircuit.md +++ /dev/null @@ -1,20 +0,0 @@ -# CompiledCircuit - -```ts -type CompiledCircuit: object; -``` - -## Description - -The representation of a compiled circuit - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `abi` | `Abi` | **Description**

ABI representation of the circuit | -| `bytecode` | `string` | **Description**

The bytecode of the circuit | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md deleted file mode 100644 index 812b8b16481..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md +++ /dev/null @@ -1,24 +0,0 @@ -# ForeignCallHandler - -```ts -type ForeignCallHandler: (name, inputs) => Promise; -``` - -A callback which performs an foreign call and returns the response. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `name` | `string` | The identifier for the type of foreign call being performed. | -| `inputs` | [`ForeignCallInput`](ForeignCallInput.md)[] | An array of hex encoded inputs to the foreign call. | - -## Returns - -`Promise`\<[`ForeignCallOutput`](ForeignCallOutput.md)[]\> - -outputs - An array of hex encoded outputs containing the results of the foreign call. - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md deleted file mode 100644 index dd95809186a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md +++ /dev/null @@ -1,9 +0,0 @@ -# ForeignCallInput - -```ts -type ForeignCallInput: string[]; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md deleted file mode 100644 index b71fb78a946..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md +++ /dev/null @@ -1,9 +0,0 @@ -# ForeignCallOutput - -```ts -type ForeignCallOutput: string | string[]; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/InputMap.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/InputMap.md deleted file mode 100644 index c714e999d93..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/InputMap.md +++ /dev/null @@ -1,13 +0,0 @@ -# InputMap - -```ts -type InputMap: object; -``` - -## Index signature - - \[`key`: `string`\]: `InputValue` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/ProofData.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/ProofData.md deleted file mode 100644 index 3eb360a78f1..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/ProofData.md +++ /dev/null @@ -1,20 +0,0 @@ -# ProofData - -```ts -type ProofData: object; -``` - -## Description - -The representation of a proof - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `proof` | `Uint8Array` | **Description**

An byte array representing the proof | -| `publicInputs` | `WitnessMap` | **Description**

Public inputs of a proof | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md deleted file mode 100644 index 258c46f9d0c..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md +++ /dev/null @@ -1,9 +0,0 @@ -# WitnessMap - -```ts -type WitnessMap: Map; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs deleted file mode 100644 index fe2629ddc9f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/noir_js/classes/Noir","label":"Noir"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/CompiledCircuit","label":"CompiledCircuit"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallHandler","label":"ForeignCallHandler"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallInput","label":"ForeignCallInput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallOutput","label":"ForeignCallOutput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/InputMap","label":"InputMap"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ProofData","label":"ProofData"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/WitnessMap","label":"WitnessMap"}]},{"type":"category","label":"Functions","items":[{"type":"doc","id":"reference/NoirJS/noir_js/functions/and","label":"and"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/blake2s256","label":"blake2s256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify","label":"ecdsa_secp256k1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify","label":"ecdsa_secp256r1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/keccak256","label":"keccak256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/sha256","label":"sha256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/xor","label":"xor"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/nargo_commands.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/nargo_commands.md deleted file mode 100644 index ff3dee8973f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/nargo_commands.md +++ /dev/null @@ -1,250 +0,0 @@ ---- -title: Nargo -description: - Noir CLI Commands for Noir Prover and Verifier to create, execute, prove and verify programs, - generate Solidity verifier smart contract and compile into JSON file containing ACIR - representation and ABI of circuit. -keywords: - [ - Nargo, - Noir CLI, - Noir Prover, - Noir Verifier, - generate Solidity verifier, - compile JSON file, - ACIR representation, - ABI of circuit, - TypeScript, - ] -sidebar_position: 0 ---- - -## General options - -| Option | Description | -| -------------------- | -------------------------------------------------- | -| `--show-ssa` | Emit debug information for the intermediate SSA IR | -| `--deny-warnings` | Quit execution when warnings are emitted | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo help [subcommand]` - -Prints the list of available commands or specific information of a subcommand. - -_Arguments_ - -| Argument | Description | -| -------------- | -------------------------------------------- | -| `` | The subcommand whose help message to display | - -## `nargo backend` - -Installs and selects custom backends used to generate and verify proofs. - -### Commands - -| Command | Description | -| ----------- | --------------------------------------------------------- | -| `current` | Prints the name of the currently active backend | -| `ls` | Prints the list of currently installed backends | -| `use` | Select the backend to use | -| `install` | Install a new backend from a URL | -| `uninstall` | Uninstalls a backend | -| `help` | Print this message or the help of the given subcommand(s) | - -### Options - -| Option | Description | -| ------------ | ----------- | -| `-h, --help` | Print help | - -## `nargo check` - -Generate the `Prover.toml` and `Verifier.toml` files for specifying prover and verifier in/output -values of the Noir program respectively. - -### Options - -| Option | Description | -| --------------------- | ------------------------------------- | -| `--package ` | The name of the package to check | -| `--workspace` | Check all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -### `nargo codegen-verifier` - -Generate a Solidity verifier smart contract for the program. - -### Options - -| Option | Description | -| --------------------- | ------------------------------------- | -| `--package ` | The name of the package to codegen | -| `--workspace` | Codegen all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo compile` - -Compile the program into a JSON build artifact file containing the ACIR representation and the ABI -of the circuit. This build artifact can then be used to generate and verify proofs. - -You can also use "build" as an alias for compile (e.g. `nargo build`). - -### Options - -| Option | Description | -| --------------------- | ------------------------------------------------------------ | -| `--package ` | The name of the package to compile | -| `--workspace` | Compile all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo new ` - -Creates a new Noir project in a new folder. - -**Arguments** - -| Argument | Description | -| -------- | -------------------------------- | -| `` | The path to save the new project | - -### Options - -| Option | Description | -| --------------- | ----------------------------------------------------- | -| `--name ` | Name of the package [default: package directory name] | -| `--lib` | Use a library template | -| `--bin` | Use a binary template [default] | -| `--contract` | Use a contract template | -| `-h, --help` | Print help | - -## `nargo init` - -Creates a new Noir project in the current directory. - -### Options - -| Option | Description | -| --------------- | ----------------------------------------------------- | -| `--name ` | Name of the package [default: current directory name] | -| `--lib` | Use a library template | -| `--bin` | Use a binary template [default] | -| `--contract` | Use a contract template | -| `-h, --help` | Print help | - -## `nargo execute [WITNESS_NAME]` - -Runs the Noir program and prints its return value. - -**Arguments** - -| Argument | Description | -| ---------------- | ----------------------------------------- | -| `[WITNESS_NAME]` | Write the execution witness to named file | - -### Options - -| Option | Description | -| --------------------------------- | ------------------------------------------------------------------------------------ | -| `-p, --prover-name ` | The name of the toml file which contains the inputs for the prover [default: Prover] | -| `--package ` | The name of the package to execute | -| `--workspace` | Execute all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -_Usage_ - -The inputs to the circuit are read from the `Prover.toml` file generated by `nargo check`, which -must be filled in. - -To save the witness to file, run the command with a value for the `WITNESS_NAME` argument. A -`.tr` file will then be saved in the `./target` folder. - -## `nargo prove` - -Creates a proof for the program. - -### Options - -| Option | Description | -| ------------------------------------- | ---------------------------------------------------------------------------------------- | -| `-p, --prover-name ` | The name of the toml file which contains the inputs for the prover [default: Prover] | -| `-v, --verifier-name ` | The name of the toml file which contains the inputs for the verifier [default: Verifier] | -| `--verify` | Verify proof after proving | -| `--package ` | The name of the package to prove | -| `--workspace` | Prove all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo verify` - -Given a proof and a program, verify whether the proof is valid. - -### Options - -| Option | Description | -| ------------------------------------- | ---------------------------------------------------------------------------------------- | -| `-v, --verifier-name ` | The name of the toml file which contains the inputs for the verifier [default: Verifier] | -| `--package ` | The name of the package to verify | -| `--workspace` | Verify all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo test [TEST_NAME]` - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. To print `println` statements in tests, use the `--show-output` flag. - -Takes an optional `--exact` flag which allows you to select tests based on an exact name. - -See an example on the [testing page](../getting_started/tooling/testing.md). - -### Options - -| Option | Description | -| --------------------- | -------------------------------------- | -| `--show-output` | Display output of `println` statements | -| `--exact` | Only run tests that match exactly | -| `--package ` | The name of the package to test | -| `--workspace` | Test all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo info` - -Prints a table containing the information of the package. - -Currently the table provide - -1. The number of ACIR opcodes -2. The final number gates in the circuit used by a backend - -If the file contains a contract the table will provide the -above information about each function of the contract. - -## `nargo lsp` - -Start a long-running Language Server process that communicates over stdin/stdout. -Usually this command is not run by a user, but instead will be run by a Language Client, such as [vscode-noir](https://github.com/noir-lang/vscode-noir). - -## `nargo fmt` - -Automatically formats your Noir source code based on the default formatting settings. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/tutorials/noirjs_app.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/tutorials/noirjs_app.md deleted file mode 100644 index 516e07c89fd..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/tutorials/noirjs_app.md +++ /dev/null @@ -1,261 +0,0 @@ ---- -title: Tiny NoirJS app -description: Learn how to setup a new app that uses Noir to generate and verify zero-knowledge SNARK proofs in a typescript or javascript environment -keywords: [how to, guide, javascript, typescript, noir, barretenberg, zero-knowledge, proofs] -sidebar_position: 0 ---- - -NoirJS works both on the browser and on the server, and works for both ESM and CJS module systems. In this page, we will learn how can we write a simple test and a simple web app to verify the standard Noir example. - -You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). - -## Before we start - -:::note - -Feel free to use whatever versions, just keep in mind that Nargo and the NoirJS packages are meant to be in sync. For example, Nargo 0.18.x matches `noir_js@0.18.x`, etc. - -In this guide, we will be pinned to 0.17.0. - -::: - -Make sure you have Node installed on your machine by opening a terminal and executing `node --version`. If you don't see a version, you should install [node](https://github.com/nvm-sh/nvm). You can also use `yarn` if you prefer that package manager over npm (which comes with node). - -First of all, follow the [Nargo guide](../getting_started/installation/index.md) to install nargo version 0.17.0 and create a new project with `nargo new circuit`. Once there, `cd` into the `circuit` folder. You should then be able to compile your circuit into `json` format and see it inside the `target` folder: - -```bash -nargo compile -``` - -Your folder structure should look like: - -```tree -. -└── circuit - ├── Nargo.toml - ├── src - │ └── main.nr - └── target - └── circuit.json -``` - -## Starting a new project - -Go back to the previous folder and start a new project by running run `npm init`. You can configure your project or just leave the defaults, and see a `package.json` appear in your root folder. - -## Installing dependencies - -We'll need two `npm` packages. These packages will provide us the methods we need to run and verify proofs: - -```bash -npm i @noir-lang/backend_barretenberg@^0.17.0 @noir-lang/noir_js@^0.17.0 -``` - -To serve our page, we can use a build tool such as `vite`. Because we're gonna use some `wasm` files, we need to install a plugin as well. Run: - -```bash -npm i --save-dev vite rollup-plugin-copy -``` - -Since we're on the dependency world, we may as well define a nice starting script. Vite makes it easy. Just open `package.json`, find the block "scripts" and add this just below the line with `"test" : "echo......."`: - -```json - "start": "vite --open" -``` - -If you want do build a static website, you can also add some build and preview scripts: - -```json - "build": "vite build", - "preview": "vite preview" -``` - -## Vite plugins - -Vite is great, but support from `wasm` doesn't work out-of-the-box. We're gonna write a quick plugin and use another one. Just copy and paste this into a file named `vite.config.js`. You don't need to understand it, just trust me bro. - -```js -import { defineConfig } from 'vite'; -import copy from 'rollup-plugin-copy'; -import fs from 'fs'; -import path from 'path'; - -const wasmContentTypePlugin = { - name: 'wasm-content-type-plugin', - configureServer(server) { - server.middlewares.use(async (req, res, next) => { - if (req.url.endsWith('.wasm')) { - res.setHeader('Content-Type', 'application/wasm'); - const newPath = req.url.replace('deps', 'dist'); - const targetPath = path.join(__dirname, newPath); - const wasmContent = fs.readFileSync(targetPath); - return res.end(wasmContent); - } - next(); - }); - }, -}; - -export default defineConfig(({ command }) => { - if (command === 'serve') { - return { - plugins: [ - copy({ - targets: [{ src: 'node_modules/**/*.wasm', dest: 'node_modules/.vite/dist' }], - copySync: true, - hook: 'buildStart', - }), - command === 'serve' ? wasmContentTypePlugin : [], - ], - }; - } - - return {}; -}); -``` - -## HTML - -Here's the simplest HTML with some terrible UI. Create a file called `index.html` and paste this: - -```html - - - - - - -

Very basic Noir app

-
-

Logs

-

Proof

-
- - -``` - -## Some good old vanilla Javascript - -Create a new file `app.js`, which is where our javascript code will live. Let's start with this code inside: - -```js -document.addEventListener('DOMContentLoaded', async () => { - // here's where the magic happens -}); - -function display(container, msg) { - const c = document.getElementById(container); - const p = document.createElement('p'); - p.textContent = msg; - c.appendChild(p); -} -``` - -We can manipulate our website with this little function, so we can see our website working. - -## Adding Noir - -If you come from the previous page, your folder structure should look like this: - -```tree -├── app.js -├── circuit -│ ├── Nargo.toml -│ ├── src -│ │ └── main.nr -│ └── target -│ └── circuit.json -├── index.html -├── package.json -└── vite.config.js -``` - -You'll see other files and folders showing up (like `package-lock.json`, `yarn.lock`, `node_modules`) but you shouldn't have to care about those. - -## Importing our dependencies - -We're starting with the good stuff now. At the top of the new javascript file, import the packages: - -```ts -import { BarretenbergBackend } from '@noir-lang/backend_barretenberg'; -import { Noir } from '@noir-lang/noir_js'; -``` - -We also need to import the `circuit` JSON file we created. If you have the suggested folder structure, you can add this line: - -```ts -import circuit from './circuit/target/circuit.json'; -``` - -## Write code - -:::note - -We're gonna be adding code inside the `document.addEventListener...etc` block: - -```js -// forget stuff here -document.addEventListener('DOMContentLoaded', async () => { - // here's where the magic happens -}); -// forget stuff here -``` - -::: - -Our dependencies exported two classes: `BarretenbergBackend` and `Noir`. Let's `init` them and add some logs, just to flex: - -```ts -const backend = new BarretenbergBackend(circuit); -const noir = new Noir(circuit, backend); -``` - -## Proving - -Now we're ready to prove stuff! Let's feed some inputs to our circuit and calculate the proof: - -```js -const input = { x: 1, y: 2 }; -display('logs', 'Generating proof... ⌛'); -const proof = await noir.generateFinalProof(input); -display('logs', 'Generating proof... ✅'); -display('results', proof.proof); -``` - -You're probably eager to see stuff happening, so go and run your app now! - -From your terminal, run `npm start` (or `yarn start`). If it doesn't open a browser for you, just visit `localhost:5173`. On a modern laptop, proof will generate in less than 100ms, and you'll see this: - -![Getting Started 0](@site/static/img/noir_getting_started_1.png) - -If you're human, you shouldn't be able to understand anything on the "proof" box. That's OK. We like you, human. - -In any case, this means your proof was generated! But you shouldn't trust me just yet. Add these lines to see it being verified: - -```js -display('logs', 'Verifying proof... ⌛'); -const verification = await noir.verifyFinalProof(proof); -if (verification) display('logs', 'Verifying proof... ✅'); -``` - -By saving, your app will refresh and here's our complete Tiny Noir App! - -You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). - -## Further Reading - -You can see how noirjs is used in a full stack Next.js hardhat application in the [noir-starter repo here](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat). The example shows how to calculate a proof in the browser and verify it with a deployed Solidity verifier contract from noirjs. - -You should also check out the more advanced examples in the [noir-examples repo](https://github.com/noir-lang/noir-examples), where you'll find reference usage for some cool apps. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/_category_.json deleted file mode 100644 index 5d694210bbf..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 0, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/hello_noir/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/hello_noir/_category_.json deleted file mode 100644 index 23b560f610b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/hello_noir/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 1, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/hello_noir/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/hello_noir/index.md deleted file mode 100644 index 743c4d8d634..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/hello_noir/index.md +++ /dev/null @@ -1,142 +0,0 @@ ---- -title: Creating a Project -description: - Learn how to create and verify your first Noir program using Nargo, a programming language for - zero-knowledge proofs. -keywords: - [ - Nargo, - Noir, - zero-knowledge proofs, - programming language, - create Noir program, - verify Noir program, - step-by-step guide, - ] -sidebar_position: 1 - ---- - -Now that we have installed Nargo, it is time to make our first hello world program! - -## Create a Project Directory - -Noir code can live anywhere on your computer. Let us create a _projects_ folder in the home -directory to house our Noir programs. - -For Linux, macOS, and Windows PowerShell, create the directory and change directory into it by -running: - -```sh -mkdir ~/projects -cd ~/projects -``` - -## Create Our First Nargo Project - -Now that we are in the projects directory, create a new Nargo project by running: - -```sh -nargo new hello_world -``` - -> **Note:** `hello_world` can be any arbitrary project name, we are simply using `hello_world` for -> demonstration. -> -> In production, the common practice is to name the project folder as `circuits` for better -> identifiability when sitting alongside other folders in the codebase (e.g. `contracts`, `scripts`, -> `test`). - -A `hello_world` folder would be created. Similar to Rust, the folder houses _src/main.nr_ and -_Nargo.toml_ which contain the source code and environmental options of your Noir program -respectively. - -### Intro to Noir Syntax - -Let us take a closer look at _main.nr_. The default _main.nr_ generated should look like this: - -```rust -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` - -The first line of the program specifies the program's inputs: - -```rust -x : Field, y : pub Field -``` - -Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the -keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](../../noir/concepts/data_types/index.md) section. - -The next line of the program specifies its body: - -```rust -assert(x != y); -``` - -The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. - -For more Noir syntax, check the [Language Concepts](../../noir/concepts/comments.md) chapter. - -## Build In/Output Files - -Change directory into _hello_world_ and build in/output files for your Noir program by running: - -```sh -cd hello_world -nargo check -``` - -Two additional files would be generated in your project directory: - -_Prover.toml_ houses input values, and _Verifier.toml_ houses public values. - -## Prove Our Noir Program - -Now that the project is set up, we can create a proof of correct execution of our Noir program. - -Fill in input values for execution in the _Prover.toml_ file. For example: - -```toml -x = "1" -y = "2" -``` - -Prove the valid execution of your Noir program: - -```sh -nargo prove -``` - -A new folder _proofs_ would then be generated in your project directory, containing the proof file -`.proof`, where the project name is defined in Nargo.toml. - -The _Verifier.toml_ file would also be updated with the public values computed from program -execution (in this case the value of `y`): - -```toml -y = "0x0000000000000000000000000000000000000000000000000000000000000002" -``` - -> **Note:** Values in _Verifier.toml_ are computed as 32-byte hex values. - -## Verify Our Noir Program - -Once a proof is generated, we can verify correct execution of our Noir program by verifying the -proof file. - -Verify your proof by running: - -```sh -nargo verify -``` - -The verification will complete in silence if it is successful. If it fails, it will log the -corresponding error instead. - -Congratulations, you have now created and verified a proof for your very first Noir program! - -In the [next section](./project_breakdown.md), we will go into more detail on each step performed. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/hello_noir/project_breakdown.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/hello_noir/project_breakdown.md deleted file mode 100644 index 6160a102c6c..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/hello_noir/project_breakdown.md +++ /dev/null @@ -1,199 +0,0 @@ ---- -title: Project Breakdown -description: - Learn about the anatomy of a Nargo project, including the purpose of the Prover and Verifier TOML - files, and how to prove and verify your program. -keywords: - [Nargo, Nargo project, Prover.toml, Verifier.toml, proof verification, private asset transfer] -sidebar_position: 2 ---- - -This section breaks down our hello world program from the previous section. We elaborate on the project -structure and what the `prove` and `verify` commands did. - -## Anatomy of a Nargo Project - -Upon creating a new project with `nargo new` and building the in/output files with `nargo check` -commands, you would get a minimal Nargo project of the following structure: - - - src - - Prover.toml - - Verifier.toml - - Nargo.toml - -The source directory _src_ holds the source code for your Noir program. By default only a _main.nr_ -file will be generated within it. - -### Prover.toml - -_Prover.toml_ is used for specifying the input values for executing and proving the program. You can specify `toml` files with different names by using the `--prover-name` or `-p` flags, see the [Prover](#provertoml) section below. Optionally you may specify expected output values for prove-time checking as well. - -### Verifier.toml - -_Verifier.toml_ contains public in/output values computed when executing the Noir program. - -### Nargo.toml - -_Nargo.toml_ contains the environmental options of your project. It contains a "package" section and a "dependencies" section. - -Example Nargo.toml: - -```toml -[package] -name = "noir_starter" -type = "bin" -authors = ["Alice"] -compiler_version = "0.9.0" -description = "Getting started with Noir" -entry = "circuit/main.nr" -license = "MIT" - -[dependencies] -ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} -``` - -Nargo.toml for a [workspace](../../noir/modules_packages_crates/workspaces.md) will look a bit different. For example: - -```toml -[workspace] -members = ["crates/a", "crates/b"] -default-member = "crates/a" -``` - -#### Package section - -The package section defines a number of fields including: - -- `name` (**required**) - the name of the package -- `type` (**required**) - can be "bin", "lib", or "contract" to specify whether its a binary, library or Aztec contract -- `authors` (optional) - authors of the project -- `compiler_version` - specifies the version of the compiler to use. This is enforced by the compiler and follow's [Rust's versioning](https://doc.rust-lang.org/cargo/reference/manifest.html#the-version-field), so a `compiler_version = 0.18.0` will enforce Nargo version 0.18.0, `compiler_version = ^0.18.0` will enforce anything above 0.18.0 but below 0.19.0, etc. For more information, see how [Rust handles these operators](https://docs.rs/semver/latest/semver/enum.Op.html) -- `description` (optional) -- `entry` (optional) - a relative filepath to use as the entry point into your package (overrides the default of `src/lib.nr` or `src/main.nr`) -- `backend` (optional) -- `license` (optional) - -#### Dependencies section - -This is where you will specify any dependencies for your project. See the [Dependencies page](../../noir/modules_packages_crates/dependencies.md) for more info. - -`./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or -verifier contract respectively. - -### main.nr - -The _main.nr_ file contains a `main` method, this method is the entry point into your Noir program. - -In our sample program, _main.nr_ looks like this: - -```rust -fn main(x : Field, y : Field) { - assert(x != y); -} -``` - -The parameters `x` and `y` can be seen as the API for the program and must be supplied by the -prover. Since neither `x` nor `y` is marked as public, the verifier does not supply any inputs, when -verifying the proof. - -The prover supplies the values for `x` and `y` in the _Prover.toml_ file. - -As for the program body, `assert` ensures that the condition to be satisfied (e.g. `x != y`) is -constrained by the proof of the execution of said program (i.e. if the condition was not met, the -verifier would reject the proof as an invalid proof). - -### Prover.toml - -The _Prover.toml_ file is a file which the prover uses to supply his witness values(both private and -public). - -In our hello world program the _Prover.toml_ file looks like this: - -```toml -x = "1" -y = "2" -``` - -When the command `nargo prove` is executed, two processes happen: - -1. Noir creates a proof that `x`, which holds the value of `1`, and `y`, which holds the value of `2`, - is not equal. This inequality constraint is due to the line `assert(x != y)`. - -2. Noir creates and stores the proof of this statement in the _proofs_ directory in a file called your-project.proof. So if your project is named "private_voting" (defined in the project Nargo.toml), the proof will be saved at `./proofs/private_voting.proof`. Opening this file will display the proof in hex format. - -#### Arrays of Structs - -The following code shows how to pass an array of structs to a Noir program to generate a proof. - -```rust -// main.nr -struct Foo { - bar: Field, - baz: Field, -} - -fn main(foos: [Foo; 3]) -> pub Field { - foos[2].bar + foos[2].baz -} -``` - -Prover.toml: - -```toml -[[foos]] # foos[0] -bar = 0 -baz = 0 - -[[foos]] # foos[1] -bar = 0 -baz = 0 - -[[foos]] # foos[2] -bar = 1 -baz = 2 -``` - -#### Custom toml files - -You can specify a `toml` file with a different name to use for proving by using the `--prover-name` or `-p` flags. - -This command looks for proof inputs in the default **Prover.toml** and generates the proof and saves it at `./proofs/.proof`: - -```bash -nargo prove -``` - -This command looks for proof inputs in the custom **OtherProver.toml** and generates proof and saves it at `./proofs/.proof`: - -```bash -nargo prove -p OtherProver -``` - -## Verifying a Proof - -When the command `nargo verify` is executed, two processes happen: - -1. Noir checks in the _proofs_ directory for a proof file with the project name (eg. test_project.proof) - -2. If that file is found, the proof's validity is checked - -> **Note:** The validity of the proof is linked to the current Noir program; if the program is -> changed and the verifier verifies the proof, it will fail because the proof is not valid for the -> _modified_ Noir program. - -In production, the prover and the verifier are usually two separate entities. A prover would -retrieve the necessary inputs, execute the Noir program, generate a proof and pass it to the -verifier. The verifier would then retrieve the public inputs, usually from external sources, and -verify the validity of the proof against it. - -Take a private asset transfer as an example: - -A person using a browser as the prover would retrieve private inputs locally (e.g. the user's private key) and -public inputs (e.g. the user's encrypted balance on-chain), compute the transfer, generate a proof -and submit it to the verifier smart contract. - -The verifier contract would then draw the user's encrypted balance directly from the blockchain and -verify the proof submitted against it. If the verification passes, additional functions in the -verifier contract could trigger (e.g. approve the asset transfer). - -Now that you understand the concepts, you'll probably want some editor feedback while you are writing more complex code. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/installation/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/installation/_category_.json deleted file mode 100644 index 0c02fb5d4d7..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/installation/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "position": 0, - "label": "Install Nargo", - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/installation/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/installation/index.md deleted file mode 100644 index 4ef86aa5914..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/installation/index.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Nargo Installation -description: - nargo is a command line tool for interacting with Noir programs. This page is a quick guide on how to install Nargo through the most common and easy method, noirup -keywords: [ - Nargo - Noir - Rust - Cargo - Noirup - Installation - Terminal Commands - Version Check - Nightlies - Specific Versions - Branches - Noirup Repository -] -pagination_next: getting_started/hello_noir/index ---- - -`nargo` is the one-stop-shop for almost everything related with Noir. The name comes from our love for Rust and its package manager `cargo`. - -With `nargo`, you can start new projects, compile, execute, prove, verify, test, generate solidity contracts, and do pretty much all that is available in Noir. - -Similarly to `rustup`, we also maintain an easy installation method that covers most machines: `noirup`. - -## Installing Noirup - -Open a terminal on your machine, and write: - -```bash -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -Close the terminal, open another one, and run - -```bash -noirup -``` - -Done. That's it. You should have the latest version working. You can check with `nargo --version`. - -You can also install nightlies, specific versions -or branches. Check out the [noirup repository](https://github.com/noir-lang/noirup) for more -information. - -Now we're ready to start working on [our first Noir program!](../hello_noir/index.md) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/installation/other_install_methods.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/installation/other_install_methods.md deleted file mode 100644 index 746633b628d..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/installation/other_install_methods.md +++ /dev/null @@ -1,190 +0,0 @@ ---- -title: Alternative Install Methods -description: - There are different ways to install Nargo, the one-stop shop and command-line tool for developing Noir programs. This guide explains other methods that don't rely on noirup, such as compiling from source, installing from binaries, and using WSL for windows -keywords: [ - Installation - Nargo - Noirup - Binaries - Compiling from Source - WSL for Windows - macOS - Linux - Nix - Direnv - Shell & editor experience - Building and testing - Uninstalling Nargo - Noir vs code extension -] -sidebar_position: 1 ---- - - -## Installation - -The most common method of installing Nargo is through [Noirup](./index.md) - -However, there are other methods for installing Nargo: - -- [Binaries](#binaries) -- [Compiling from Source](#compile-from-source) -- [WSL for Windows](#wsl-for-windows) - -### Binaries - -See [GitHub Releases](https://github.com/noir-lang/noir/releases) for the latest and previous -platform specific binaries. - -#### Step 1 - -Paste and run the following in the terminal to extract and install the binary: - -> **macOS / Linux:** If you are prompted with `Permission denied` when running commands, prepend -> `sudo` and re-run it. - -##### macOS (Apple Silicon) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.23.0/nargo-aarch64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### macOS (Intel) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.23.0/nargo-x86_64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### Linux (Bash) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.23.0/nargo-x86_64-unknown-linux-gnu.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -C $HOME/.nargo/bin/ && \ -echo -e '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.bashrc && \ -source ~/.bashrc -``` - -#### Step 2 - -Check if the installation was successful by running `nargo --version`. You should get a version number. - -> **macOS:** If you are prompted with an OS alert, right-click and open the _nargo_ executable from -> Finder. Close the new terminal popped up and `nargo` should now be accessible. - -### Option 3: Compile from Source - -Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. It helps mitigating issues commonly associated with dependency management, such as conflicts between required package versions for different projects (often referred to as "dependency hell"). - -Combined with direnv, which automatically sets or clears environment variables based on the directory, it further simplifies the development process by seamlessly integrating with the developer's shell, facilitating an efficient and reliable workflow for managing and deploying Noir projects with multiple dependencies. - -#### Setting up your environment - -For the best experience, please follow these instructions to setup your environment: - -1. Install Nix following [their guide](https://nixos.org/download.html) for your operating system. -2. Create the file `~/.config/nix/nix.conf` with the contents: - -```ini -experimental-features = nix-command -extra-experimental-features = flakes -``` - -3. Install direnv into your Nix profile by running: - -```sh -nix profile install nixpkgs#direnv -``` - -4. Add direnv to your shell following [their guide](https://direnv.net/docs/hook.html). - 1. For bash or zshell, add `eval "$(direnv hook bash)"` or `eval "$(direnv hook zsh)"` to your ~/.bashrc or ~/.zshrc file, respectively. -5. Restart your shell. - -#### Shell & editor experience - -Now that your environment is set up, you can get to work on the project. - -1. Clone the repository, such as: - -```sh -git clone git@github.com:noir-lang/noir -``` - -> Replacing `noir` with whichever repository you want to work on. - -2. Navigate to the directory: - -```sh -cd noir -``` - -> Replacing `noir` with whichever repository you cloned. - -3. You should see a **direnv error** because projects aren't allowed by default. Make sure you've reviewed and trust our `.envrc` file, then you need to run: - -```sh -direnv allow -``` - -4. Now, wait awhile for all the native dependencies to be built. This will take some time and direnv will warn you that it is taking a long time, but we just need to let it run. - -5. Once you are presented with your prompt again, you can start your editor within the project directory (we recommend [VSCode](https://code.visualstudio.com/)): - -```sh -code . -``` - -6. (Recommended) When launching VSCode for the first time, you should be prompted to install our recommended plugins. We highly recommend installing these for the best development experience. - -#### Building and testing - -Assuming you are using `direnv` to populate your environment, building and testing the project can be done -with the typical `cargo build`, `cargo test`, and `cargo clippy` commands. You'll notice that the `cargo` version matches the version we specify in `rust-toolchain.toml`, which is 1.71.1 at the time of this writing. - -If you want to build the entire project in an isolated sandbox, you can use Nix commands: - -1. `nix build .` (or `nix build . -L` for verbose output) to build the project in a Nix sandbox. -2. `nix flake check` (or `nix flake check -L` for verbose output) to run clippy and tests in a Nix sandbox. - -#### Without `direnv` - -If you have hesitations with using direnv, you can launch a subshell with `nix develop` and then launch your editor from within the subshell. However, if VSCode was already launched in the project directory, the environment won't be updated. - -Advanced: If you aren't using direnv nor launching your editor within the subshell, you can try to install Barretenberg and other global dependencies the package needs. This is an advanced workflow and likely won't receive support! - -### Option 4: WSL (for Windows) - -The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed natively. However, it is available by using Windows Subsystem for Linux (WSL). - -Step 1: Follow the instructions [here](https://learn.microsoft.com/en-us/windows/wsl/install) to install and run WSL. - -step 2: Follow the [Noirup instructions](./index.md). - -## Uninstalling Nargo - -### Noirup - -If you installed Noir with `noirup`, you can uninstall Noir by removing the files in `~/.nargo`, `~/nargo` and `~/noir_cache`. - -```bash -rm -r ~/.nargo -rm -r ~/nargo -rm -r ~/noir_cache -``` - -### Nix - -If you installed Noir with Nix or from source, you can remove the binary located at `~/.nix-profile/bin/nargo`. - -```bash -rm ~/.nix-profile/bin/nargo -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/tooling/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/tooling/_category_.json deleted file mode 100644 index 55804c03a71..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/tooling/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "position": 2, - "label": "Tooling", - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/tooling/index.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/tooling/index.mdx deleted file mode 100644 index ec9ccea4115..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/tooling/index.mdx +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: Tooling -Description: This section provides information about the various tools and utilities available for Noir development. It covers IDE tools, Codespaces, and community projects. -Keywords: [Noir, Development, Playground, IDE Tools, Language Service Provider, VS Code Extension, Codespaces, noir-starter, Community Projects, Awesome Noir Repository, Developer Tooling] ---- - -Noir is meant to be easy to develop with. For that reason, a number of utilities have been put together to ease the development process as much as feasible in the zero-knowledge world. - -## IDE tools - -When you install Nargo, you're also installing a Language Service Provider (LSP), which can be used by IDEs to provide syntax highlighting, codelens, warnings, and more. - -The easiest way to use these tools is by installing the [Noir VS Code extension](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). - -## Codespaces - -Some Noir repos have leveraged Codespaces in order to ease the development process. You can visit the [noir-starter](https://github.com/noir-lang/noir-starter) for an example. - - - -## GitHub Actions - -You can use `noirup` with GitHub Actions for CI/CD and automated testing. It is as simple as -installing `noirup` and running tests in your GitHub Action `yml` file. - -See the -[config file in the Noir repo](https://github.com/TomAFrench/noir-hashes/blob/master/.github/workflows/noir.yml) for an example usage. - -## Community projects - -As an open-source project, Noir has received many contributions over time. Some of them are related with developer tooling, and you can see some of them in [Awesome Noir repository](https://github.com/noir-lang/awesome-noir#dev-tools) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/tooling/language_server.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/tooling/language_server.md deleted file mode 100644 index 81e0356ef8a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/tooling/language_server.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Language Server -description: Learn about the Noir Language Server, how to install the components, and configuration that may be required. -keywords: [Nargo, Language Server, LSP, VSCode, Visual Studio Code] -sidebar_position: 0 ---- - -This section helps you install and configure the Noir Language Server. - -The Language Server Protocol (LSP) has two components, the [Server](#language-server) and the [Client](#language-client). Below we describe each in the context of Noir. - -## Language Server - -The Server component is provided by the Nargo command line tool that you installed at the beginning of this guide. -As long as Nargo is installed and you've used it to run other commands in this guide, it should be good to go! - -If you'd like to verify that the `nargo lsp` command is available, you can run `nargo --help` and look for `lsp` in the list of commands. If you see it, you're using a version of Noir with LSP support. - -## Language Client - -The Client component is usually an editor plugin that launches the Server. It communicates LSP messages between the editor and the Server. For example, when you save a file, the Client will alert the Server, so it can try to compile the project and report any errors. - -Currently, Noir provides a Language Client for Visual Studio Code via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). - -> **Note:** Noir's Language Server Protocol support currently assumes users' VSCode workspace root to be the same as users' Noir project root (i.e. where Nargo.toml lies). -> -> If LSP features seem to be missing / malfunctioning, make sure you are opening your Noir project directly (instead of as a sub-folder) in your VSCode instance. - -When your language server is running correctly and the VSCode plugin is installed, you should see handy codelens buttons for compilation, measuring circuit size, execution, and tests: - -![Compile and Execute](@site/static/img/codelens_compile_execute.png) -![Run test](@site/static/img/codelens_run_test.png) - -You should also see your tests in the `testing` panel: - -![Testing panel](@site/static/img/codelens_testing_panel.png) - -### Configuration - -- **Noir: Enable LSP** - If checked, the extension will launch the Language Server via `nargo lsp` and communicate with it. -- **Noir: Nargo Flags** - Additional flags may be specified if you require them to be added when the extension calls `nargo lsp`. -- **Noir: Nargo Path** - An absolute path to a Nargo binary with the `lsp` command. This may be useful if Nargo is not within the `PATH` of your editor. -- **Noir > Trace: Server** - Setting this to `"messages"` or `"verbose"` will log LSP messages between the Client and Server. Useful for debugging. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/tooling/testing.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/tooling/testing.md deleted file mode 100644 index d3e0c522473..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/tooling/testing.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -title: Testing in Noir -description: Learn how to use Nargo to test your Noir program in a quick and easy way -keywords: [Nargo, testing, Noir, compile, test] -sidebar_position: 1 ---- - -You can test your Noir programs using Noir circuits. - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. - -For example if you have a program like: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test] -fn test_add() { - assert(add(2,2) == 4); - assert(add(0,1) == 1); - assert(add(1,0) == 1); -} -``` - -Running `nargo test` will test that the `test_add` function can be executed while satisfying all -the constraints which allows you to test that add returns the expected values. Test functions can't -have any arguments currently. - -### Test fail - -You can write tests that are expected to fail by using the decorator `#[test(should_fail)]`. For example: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test(should_fail)] -fn test_add() { - assert(add(2,2) == 5); -} -``` - -You can be more specific and make it fail with a specific reason by using `should_fail_with = "`: - -```rust -fn main(african_swallow_avg_speed : Field) { - assert(african_swallow_avg_speed == 65, "What is the airspeed velocity of an unladen swallow"); -} - -#[test] -fn test_king_arthur() { - main(65); -} - -#[test(should_fail_with = "What is the airspeed velocity of an unladen swallow")] -fn test_bridgekeeper() { - main(32); -} - -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/how_to/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/how_to/_category_.json deleted file mode 100644 index 23b560f610b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/how_to/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 1, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/how_to/how-to-oracles.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/how_to/how-to-oracles.md deleted file mode 100644 index 0d84d992320..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/how_to/how-to-oracles.md +++ /dev/null @@ -1,280 +0,0 @@ ---- -title: How to use Oracles -description: Learn how to use oracles in your Noir program with examples in both Nargo and NoirJS. This guide also covers writing a JSON RPC server and providing custom foreign call handlers for NoirJS. -keywords: - - Noir Programming - - Oracles - - Nargo - - NoirJS - - JSON RPC Server - - Foreign Call Handlers -sidebar_position: 1 ---- - -This guide shows you how to use oracles in your Noir program. For the sake of clarity, it assumes that: - -- You have read the [explainer on Oracles](../explainers/explainer-oracle.md) and are comfortable with the concept. -- You have a Noir program to add oracles to. You can create one using the [vite-hardhat starter](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat) as a boilerplate. -- You understand the concept of a JSON-RPC server. Visit the [JSON-RPC website](https://www.jsonrpc.org/) if you need a refresher. -- You are comfortable with server-side JavaScript (e.g. Node.js, managing packages, etc.). - -For reference, you can find the snippets used in this tutorial on the [Aztec DevRel Repository](https://github.com/AztecProtocol/dev-rel/tree/main/code-snippets/how-to-oracles). - -## Rundown - -This guide has 3 major steps: - -1. How to modify our Noir program to make use of oracle calls as unconstrained functions -2. How to write a JSON RPC Server to resolve these oracle calls with Nargo -3. How to use them in Nargo and how to provide a custom resolver in NoirJS - -## Step 1 - Modify your Noir program - -An oracle is defined in a Noir program by defining two methods: - -- An unconstrained method - This tells the compiler that it is executing an [unconstrained functions](../noir/concepts//unconstrained.md). -- A decorated oracle method - This tells the compiler that this method is an RPC call. - -An example of an oracle that returns a `Field` would be: - -```rust -#[oracle(getSqrt)] -unconstrained fn sqrt(number: Field) -> Field { } - -unconstrained fn get_sqrt(number: Field) -> Field { - sqrt(number) -} -``` - -In this example, we're wrapping our oracle function in a unconstrained method, and decorating it with `oracle(getSqrt)`. We can then call the unconstrained function as we would call any other function: - -```rust -fn main(input: Field) { - let sqrt = get_sqrt(input); -} -``` - -In the next section, we will make this `getSqrt` (defined on the `sqrt` decorator) be a method of the RPC server Noir will use. - -:::danger - -As explained in the [Oracle Explainer](../explainers/explainer-oracle.md), this `main` function is unsafe unless you constrain its return value. For example: - -```rust -fn main(input: Field) { - let sqrt = get_sqrt(input); - assert(sqrt.pow_32(2) as u64 == input as u64); // <---- constrain the return of an oracle! -} -``` - -::: - -:::info - -Currently, oracles only work with single params or array params. For example: - -```rust -#[oracle(getSqrt)] -unconstrained fn sqrt([Field; 2]) -> [Field; 2] { } -``` - -::: - -## Step 2 - Write an RPC server - -Brillig will call *one* RPC server. Most likely you will have to write your own, and you can do it in whatever language you prefer. In this guide, we will do it in Javascript. - -Let's use the above example of an oracle that consumes an array with two `Field` and returns their square roots: - -```rust -#[oracle(getSqrt)] -unconstrained fn sqrt(input: [Field; 2]) -> [Field; 2] { } - -unconstrained fn get_sqrt(input: [Field; 2]) -> [Field; 2] { - sqrt(input) -} - -fn main(input: [Field; 2]) { - let sqrt = get_sqrt(input); - assert(sqrt[0].pow_32(2) as u64 == input[0] as u64); - assert(sqrt[1].pow_32(2) as u64 == input[1] as u64); -} -``` - -:::info - -Why square root? - -In general, computing square roots is computationally more expensive than multiplications, which takes a toll when speaking about ZK applications. In this case, instead of calculating the square root in Noir, we are using our oracle to offload that computation to be made in plain. In our circuit we can simply multiply the two values. - -::: - -Now, we should write the correspondent RPC server, starting with the [default JSON-RPC 2.0 boilerplate](https://www.npmjs.com/package/json-rpc-2.0#example): - -```js -import { JSONRPCServer } from "json-rpc-2.0"; -import express from "express"; -import bodyParser from "body-parser"; - -const app = express(); -app.use(bodyParser.json()); - -const server = new JSONRPCServer(); -app.post("/", (req, res) => { - const jsonRPCRequest = req.body; - server.receive(jsonRPCRequest).then((jsonRPCResponse) => { - if (jsonRPCResponse) { - res.json(jsonRPCResponse); - } else { - res.sendStatus(204); - } - }); -}); - -app.listen(5555); -``` - -Now, we will add our `getSqrt` method, as expected by the `#[oracle(getSqrt)]` decorator in our Noir code. It maps through the params array and returns their square roots: - -```js -server.addMethod("getSqrt", async (params) => { - const values = params[0].Array.map(({ inner }) => { - return { inner: `${Math.sqrt(parseInt(inner, 16))}` }; - }); - return { values: [{ Array: values }] }; -}); -``` - -:::tip - -Brillig expects an object with an array of values. Each value is an object declaring to be `Single` or `Array` and returning a `inner` property *as a string*. For example: - -```json -{ "values": [{ "Array": [{ "inner": "1" }, { "inner": "2"}]}]} -{ "values": [{ "Single": { "inner": "1" }}]} -{ "values": [{ "Single": { "inner": "1" }}, { "Array": [{ "inner": "1", { "inner": "2" }}]}]} -``` - -If you're using Typescript, the following types may be helpful in understanding the expected return value and making sure they're easy to follow: - -```js -interface Value { - inner: string, -} - -interface SingleForeignCallParam { - Single: Value, -} - -interface ArrayForeignCallParam { - Array: Value[], -} - -type ForeignCallParam = SingleForeignCallParam | ArrayForeignCallParam; - -interface ForeignCallResult { - values: ForeignCallParam[], -} -``` - -::: - -## Step 3 - Usage with Nargo - -Using the [`nargo` CLI tool](../getting_started/installation/index.md), you can use oracles in the `nargo test`, `nargo execute` and `nargo prove` commands by passing a value to `--oracle-resolver`. For example: - -```bash -nargo test --oracle-resolver http://localhost:5555 -``` - -This tells `nargo` to use your RPC Server URL whenever it finds an oracle decorator. - -## Step 4 - Usage with NoirJS - -In a JS environment, an RPC server is not strictly necessary, as you may want to resolve your oracles without needing any JSON call at all. NoirJS simply expects that you pass a callback function when you generate proofs, and that callback function can be anything. - -For example, if your Noir program expects the host machine to provide CPU pseudo-randomness, you could simply pass it as the `foreignCallHandler`. You don't strictly need to create an RPC server to serve pseudo-randomness, as you may as well get it directly in your app: - -```js -const foreignCallHandler = (name, inputs) => crypto.randomBytes(16) // etc - -await noir.generateFinalProof(inputs, foreignCallHandler) -``` - -As one can see, in NoirJS, the [`foreignCallHandler`](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) function simply means "a callback function that returns a value of type [`ForeignCallOutput`](../reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md). It doesn't have to be an RPC call like in the case for Nargo. - -:::tip - -Does this mean you don't have to write an RPC server like in [Step #2](#step-2---write-an-rpc-server)? - -You don't technically have to, but then how would you run `nargo test` or `nargo prove`? To use both `Nargo` and `NoirJS` in your development flow, you will have to write a JSON RPC server. - -::: - -In this case, let's make `foreignCallHandler` call the JSON RPC Server we created in [Step #2](#step-2---write-an-rpc-server), by making it a JSON RPC Client. - -For example, using the same `getSqrt` program in [Step #1](#step-1---modify-your-noir-program) (comments in the code): - -```js -import { JSONRPCClient } from "json-rpc-2.0"; - -// declaring the JSONRPCClient -const client = new JSONRPCClient((jsonRPCRequest) => { -// hitting the same JSON RPC Server we coded above - return fetch("http://localhost:5555", { - method: "POST", - headers: { - "content-type": "application/json", - }, - body: JSON.stringify(jsonRPCRequest), - }).then((response) => { - if (response.status === 200) { - return response - .json() - .then((jsonRPCResponse) => client.receive(jsonRPCResponse)); - } else if (jsonRPCRequest.id !== undefined) { - return Promise.reject(new Error(response.statusText)); - } - }); -}); - -// declaring a function that takes the name of the foreign call (getSqrt) and the inputs -const foreignCallHandler = async (name, input) => { - // notice that the "inputs" parameter contains *all* the inputs - // in this case we to make the RPC request with the first parameter "numbers", which would be input[0] - const oracleReturn = await client.request(name, [ - { Array: input[0].map((i) => ({ inner: i.toString("hex") })) }, - ]); - return [oracleReturn.values[0].Array.map((x) => x.inner)]; -}; - -// the rest of your NoirJS code -const input = { input: [4, 16] }; -const { witness } = await noir.execute(numbers, foreignCallHandler); -``` - -:::tip - -If you're in a NoirJS environment running your RPC server together with a frontend app, you'll probably hit a familiar problem in full-stack development: requests being blocked by [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) policy. For development only, you can simply install and use the [`cors` npm package](https://www.npmjs.com/package/cors) to get around the problem: - -```bash -yarn add cors -``` - -and use it as a middleware: - -```js -import cors from "cors"; - -const app = express(); -app.use(cors()) -``` - -::: - -## Conclusion - -Hopefully by the end of this guide, you should be able to: - -- Write your own logic around Oracles and how to write a JSON RPC server to make them work with your Nargo commands. -- Provide custom foreign call handlers for NoirJS. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/how_to/how-to-recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/how_to/how-to-recursion.md deleted file mode 100644 index f34647a99d5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/how_to/how-to-recursion.md +++ /dev/null @@ -1,179 +0,0 @@ ---- -title: How to use recursion on NoirJS -description: Learn how to implement recursion with NoirJS, a powerful tool for creating smart contracts on the EVM blockchain. This guide assumes familiarity with NoirJS, solidity verifiers, and the Barretenberg proving backend. Discover how to generate both final and intermediate proofs using `noir_js` and `backend_barretenberg`. -keywords: - [ - "NoirJS", - "EVM blockchain", - "smart contracts", - "recursion", - "solidity verifiers", - "Barretenberg backend", - "noir_js", - "backend_barretenberg", - "intermediate proofs", - "final proofs", - "nargo compile", - "json import", - "recursive circuit", - "recursive app" - ] -sidebar_position: 1 ---- - -This guide shows you how to use recursive proofs in your NoirJS app. For the sake of clarity, it is assumed that: - -- You already have a NoirJS app. If you don't, please visit the [NoirJS tutorial](../tutorials/noirjs_app.md) and the [reference](../reference/NoirJS/noir_js/index.md). -- You are familiar with what are recursive proofs and you have read the [recursion explainer](../explainers/explainer-recursion.md) -- You already built a recursive circuit following [the reference](../noir/standard_library/recursion.md), and understand how it works. - -It is also assumed that you're not using `noir_wasm` for compilation, and instead you've used [`nargo compile`](../reference/nargo_commands.md) to generate the `json` you're now importing into your project. However, the guide should work just the same if you're using `noir_wasm`. - -:::info - -As you've read in the [explainer](../explainers/explainer-recursion.md), a recursive proof is an intermediate proof. This means that it doesn't necessarily generate the final step that makes it verifiable in a smart contract. However, it is easy to verify within another circuit. - -While "standard" usage of NoirJS packages abstracts final proofs, it currently lacks the necessary interface to abstract away intermediate proofs. This means that these proofs need to be created by using the backend directly. - -In short: - -- `noir_js` generates *only* final proofs -- `backend_barretenberg` generates both types of proofs - -::: - -In a standard recursive app, you're also dealing with at least two circuits. For the purpose of this guide, we will assume these two: - -- `main`: a circuit of type `assert(x != y)` -- `recursive`: a circuit that verifies `main` - -For a full example on how recursive proofs work, please refer to the [noir-examples](https://github.com/noir-lang/noir-examples) repository. We will *not* be using it as a reference for this guide. - -## Step 1: Setup - -In a common NoirJS app, you need to instantiate a backend with something like `const backend = new Backend(circuit)`. Then you feed it to the `noir_js` interface. - -For recursion, this doesn't happen, and the only need for `noir_js` is only to `execute` a circuit and get its witness and return value. Everything else is not interfaced, so it needs to happen on the `backend` object. - -It is also recommended that you instantiate the backend with as many threads as possible, to allow for maximum concurrency: - -```js -const backend = new Backend(circuit, { threads: 8 }) -``` - -:::tip -You can use the [`os.cpus()`](https://nodejs.org/api/os.html#oscpus) object in `nodejs` or [`navigator.hardwareConcurrency`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/hardwareConcurrency) on the browser to make the most out of those glorious cpu cores -::: - -## Step 2: Generating the witness and the proof for `main` - -After instantiating the backend, you should also instantiate `noir_js`. We will use it to execute the circuit and get the witness. - -```js -const noir = new Noir(circuit, backend) -const { witness } = noir.execute(input) -``` - -With this witness, you are now able to generate the intermediate proof for the main circuit: - -```js -const { proof, publicInputs } = await backend.generateIntermediateProof(witness) -``` - -:::warning - -Always keep in mind what is actually happening on your development process, otherwise you'll quickly become confused about what circuit we are actually running and why! - -In this case, you can imagine that Alice (running the `main` circuit) is proving something to Bob (running the `recursive` circuit), and Bob is verifying her proof within his proof. - -With this in mind, it becomes clear that our intermediate proof is the one *meant to be verified within another circuit*, so it must be Alice's. Actually, the only final proof in this theoretical scenario would be the last one, sent on-chain. - -::: - -## Step 3 - Verification and proof artifacts - -Optionally, you are able to verify the intermediate proof: - -```js -const verified = await backend.verifyIntermediateProof({ proof, publicInputs }) -``` - -This can be useful to make sure our intermediate proof was correctly generated. But the real goal is to do it within another circuit. For that, we need to generate the intermediate artifacts: - -```js -const { proofAsFields, vkAsFields, vkHash } = await backend.generateIntermediateProofArtifacts( { publicInputs, proof }, publicInputsCount) -``` - -This call takes the public inputs and the proof, but also the public inputs count. While this is easily retrievable by simply counting the `publicInputs` length, the backend interface doesn't currently abstract it away. - -:::info - -The `proofAsFields` has a constant size `[Field; 93]` and verification keys in Barretenberg are always `[Field; 114]`. - -::: - -:::warning - -One common mistake is to forget *who* makes this call. - -In a situation where Alice is generating the `main` proof, if she generates the proof artifacts and sends them to Bob, which gladly takes them as true, this would mean Alice could prove anything! - -Instead, Bob needs to make sure *he* extracts the proof artifacts, using his own instance of the `main` circuit backend. This way, Alice has to provide a valid proof for the correct `main` circuit. - -::: - -## Step 4 - Recursive proof generation - -With the artifacts, generating a recursive proof is no different from a normal proof. You simply use the `backend` (with the recursive circuit) to generate it: - -```js -const recursiveInputs = { - verification_key: vkAsFields, // array of length 114 - proof: proofAsFields, // array of length 93 + size of public inputs - publicInputs: [mainInput.y], // using the example above, where `y` is the only public input - key_hash: vkHash, -} - -const { witness, returnValue } = noir.execute(recursiveInputs) // we're executing the recursive circuit now! -const { proof, publicInputs } = backend.generateFinalProof(witness) -const verified = backend.verifyFinalProof({ proof, publicInputs }) -``` - -You can obviously chain this proof into another proof. In fact, if you're using recursive proofs, you're probably interested of using them this way! - -:::tip - -Managing circuits and "who does what" can be confusing. To make sure your naming is consistent, you can keep them in an object. For example: - -```js -const circuits = { - main: mainJSON, - recursive: recursiveJSON -} -const backends = { - main: new BarretenbergBackend(circuits.main), - recursive: new BarretenbergBackend(circuits.recursive) -} -const noir_programs = { - main: new Noir(circuits.main, backends.main), - recursive: new Noir(circuits.recursive, backends.recursive) -} -``` - -This allows you to neatly call exactly the method you want without conflicting names: - -```js -// Alice runs this 👇 -const { witness: mainWitness } = await noir_programs.main.execute(input) -const proof = await backends.main.generateIntermediateProof(mainWitness) - -// Bob runs this 👇 -const verified = await backends.main.verifyIntermediateProof(proof) -const { proofAsFields, vkAsFields, vkHash } = await backends.main.generateIntermediateProofArtifacts( - proof, - numPublicInputs, -); -const recursiveProof = await noir_programs.recursive.generateFinalProof(recursiveInputs) -``` - -::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/how_to/how-to-solidity-verifier.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/how_to/how-to-solidity-verifier.md deleted file mode 100644 index e3c7c1065da..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/how_to/how-to-solidity-verifier.md +++ /dev/null @@ -1,231 +0,0 @@ ---- -title: Generate a Solidity Verifier -description: - Learn how to run the verifier as a smart contract on the blockchain. Compile a Solidity verifier - contract for your Noir program and deploy it on any EVM blockchain acting as a verifier smart - contract. Read more to find out -keywords: - [ - solidity verifier, - smart contract, - blockchain, - compiler, - plonk_vk.sol, - EVM blockchain, - verifying Noir programs, - proving backend, - Barretenberg, - ] -sidebar_position: 0 -pagination_next: tutorials/noirjs_app ---- - -Noir has the ability to generate a verifier contract in Solidity, which can be deployed in many EVM-compatible blockchains such as Ethereum. - -This allows for a powerful feature set, as one can make use of the conciseness and the privacy provided by Noir in an immutable ledger. Applications can range from simple P2P guessing games, to complex private DeFi interactions. - -This guide shows you how to generate a Solidity Verifier and deploy it on the [Remix IDE](https://remix.ethereum.org/). It is assumed that: - -- You are comfortable with the Solidity programming language and understand how contracts are deployed on the Ethereum network -- You have Noir installed and you have a Noir program. If you don't, [get started](../getting_started/installation/index.md) with Nargo and the example Hello Noir circuit -- You are comfortable navigating RemixIDE. If you aren't or you need a refresher, you can find some video tutorials [here](https://www.youtube.com/channel/UCjTUPyFEr2xDGN6Cg8nKDaA) that could help you. - -## Rundown - -Generating a Solidity Verifier contract is actually a one-command process. However, compiling it and deploying it can have some caveats. Here's the rundown of this guide: - -1. How to generate a solidity smart contract -2. How to compile the smart contract in the RemixIDE -3. How to deploy it to a testnet - -## Step 1 - Generate a contract - -This is by far the most straight-forward step. Just run: - -```sh -nargo codegen-verifier -``` - -A new `contract` folder would then be generated in your project directory, containing the Solidity -file `plonk_vk.sol`. It can be deployed to any EVM blockchain acting as a verifier smart contract. - -:::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. - -Barretenberg, the default proving backend for Nargo, supports generation of verifier contracts, for the time being these are only in Solidity. -::: - -## Step 2 - Compiling - -We will mostly skip the details of RemixIDE, as the UI can change from version to version. For now, we can just open -Remix and create a blank workspace. - -![Create Workspace](@site/static/img/how-tos/solidity_verifier_1.png) - -We will create a new file to contain the contract Nargo generated, and copy-paste its content. - -:::warning - -You'll likely see a warning advising you to not trust pasted code. While it is an important warning, it is irrelevant in the context of this guide and can be ignored. We will not be deploying anywhere near a mainnet. - -::: - -To compile our the verifier, we can navigate to the compilation tab: - -![Compilation Tab](@site/static/img/how-tos/solidity_verifier_2.png) - -Remix should automatically match a suitable compiler version. However, hitting the "Compile" button will most likely generate a "Stack too deep" error: - -![Stack too deep](@site/static/img/how-tos/solidity_verifier_3.png) - -This is due to the verify function needing to put many variables on the stack, but enabling the optimizer resolves the issue. To do this, let's open the "Advanced Configurations" tab and enable optimization. The default 200 runs will suffice. - -:::info - -This time we will see a warning about an unused function parameter. This is expected, as the `verify` function doesn't use the `_proof` parameter inside a solidity block, it is loaded from calldata and used in assembly. - -::: - -![Compilation success](@site/static/img/how-tos/solidity_verifier_4.png) - -## Step 3 - Deploying - -At this point we should have a compiled contract read to deploy. If we navigate to the deploy section in Remix, we will see many different environments we can deploy to. The steps to deploy on each environment would be out-of-scope for this guide, so we will just use the default Remix VM. - -Looking closely, we will notice that our "Solidity Verifier" is actually three contracts working together: - -- An `UltraVerificationKey` library which simply stores the verification key for our circuit. -- An abstract contract `BaseUltraVerifier` containing most of the verifying logic. -- A main `UltraVerifier` contract that inherits from the Base and uses the Key contract. - -Remix will take care of the dependencies for us so we can simply deploy the UltraVerifier contract by selecting it and hitting "deploy": - -![Deploying UltraVerifier](@site/static/img/how-tos/solidity_verifier_5.png) - -A contract will show up in the "Deployed Contracts" section, where we can retrieve the Verification Key Hash. This is particularly useful for double-checking the deployer contract is the correct one. - -:::note - -Why "UltraVerifier"? - -To be precise, the Noir compiler (`nargo`) doesn't generate the verifier contract directly. It compiles the Noir code into an intermediate language (ACIR), which is then executed by the backend. So it is the backend that returns the verifier smart contract, not Noir. - -In this case, the Barretenberg Backend uses the UltraPlonk proving system, hence the "UltraVerifier" name. - -::: - -## Step 4 - Verifying - -To verify a proof using the Solidity verifier contract, we call the `verify` function in this extended contract: - -```solidity -function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) -``` - -When using the default example in the [Hello Noir](../getting_started/hello_noir/index.md) guide, the easiest way to confirm that the verifier contract is doing its job is by calling the `verify` function via remix with the required parameters. For `_proof`, run `nargo prove` and use the string in `proof/.proof` (adding the hex `0x` prefix). We can also copy the public input from `Verifier.toml`, as it will be properly formatted as 32-byte strings: - -``` -0x...... , [0x0000.....02] -``` - -A programmatic example of how the `verify` function is called can be seen in the example zk voting application [here](https://github.com/noir-lang/noir-examples/blob/33e598c257e2402ea3a6b68dd4c5ad492bce1b0a/foundry-voting/src/zkVote.sol#L35): - -```solidity -function castVote(bytes calldata proof, uint proposalId, uint vote, bytes32 nullifierHash) public returns (bool) { - // ... - bytes32[] memory publicInputs = new bytes32[](4); - publicInputs[0] = merkleRoot; - publicInputs[1] = bytes32(proposalId); - publicInputs[2] = bytes32(vote); - publicInputs[3] = nullifierHash; - require(verifier.verify(proof, publicInputs), "Invalid proof"); -``` - -:::info[Return Values] - -A circuit doesn't have the concept of a return value. Return values are just syntactic sugar in -Noir. - -Under the hood, the return value is passed as an input to the circuit and is checked at the end of -the circuit program. - -For example, if you have Noir program like this: - -```rust -fn main( - // Public inputs - pubkey_x: pub Field, - pubkey_y: pub Field, - // Private inputs - priv_key: Field, -) -> pub Field -``` - -the `verify` function will expect the public inputs array (second function parameter) to be of length 3, the two inputs and the return value. Like before, these values are populated in Verifier.toml after running `nargo prove`. - -Passing only two inputs will result in an error such as `PUBLIC_INPUT_COUNT_INVALID(3, 2)`. - -In this case, the inputs parameter to `verify` would be an array ordered as `[pubkey_x, pubkey_y, return]`. - -::: - -:::tip[Structs] - -You can pass structs to the verifier contract. They will be flattened so that the array of inputs is 1-dimensional array. - -For example, consider the following program: - -```rust -struct Type1 { - val1: Field, - val2: Field, -} - -struct Nested { - t1: Type1, - is_true: bool, -} - -fn main(x: pub Field, nested: pub Nested, y: pub Field) { - //... -} -``` - -The order of these inputs would be flattened to: `[x, nested.t1.val1, nested.t1.val2, nested.is_true, y]` - -::: - -The other function you can call is our entrypoint `verify` function, as defined above. - -:::tip - -It's worth noticing that the `verify` function is actually a `view` function. A `view` function does not alter the blockchain state, so it doesn't need to be distributed (i.e. it will run only on the executing node), and therefore doesn't cost any gas. - -This can be particularly useful in some situations. If Alice generated a proof and wants Bob to verify its correctness, Bob doesn't need to run Nargo, NoirJS, or any Noir specific infrastructure. He can simply make a call to the blockchain with the proof and verify it is correct without paying any gas. - -It would be incorrect to say that a Noir proof verification costs any gas at all. However, most of the time the result of `verify` is used to modify state (for example, to update a balance, a game state, etc). In that case the whole network needs to execute it, which does incur gas costs (calldata and execution, but not storage). - -::: - -## A Note on EVM chains - -ZK-SNARK verification depends on some precompiled cryptographic primitives such as Elliptic Curve Pairings (if you like complex math, you can read about EC Pairings [here](https://medium.com/@VitalikButerin/exploring-elliptic-curve-pairings-c73c1864e627)). Not all EVM chains support EC Pairings, notably some of the ZK-EVMs. This means that you won't be able to use the verifier contract in all of them. - -For example, chains like `zkSync ERA` and `Polygon zkEVM` do not currently support these precompiles, so proof verification via Solidity verifier contracts won't work. Here's a quick list of EVM chains that have been tested and are known to work: - -- Optimism -- Arbitrum -- Polygon PoS -- Scroll -- Celo - -If you test any other chains, please open a PR on this page to update the list. See [this doc](https://github.com/noir-lang/noir-starter/tree/main/with-foundry#testing-on-chain) for more info about testing verifier contracts on different EVM chains. - -## What's next - -Now that you know how to call a Noir Solidity Verifier on a smart contract using Remix, you should be comfortable with using it with some programmatic frameworks, such as [hardhat](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat) and [foundry](https://github.com/noir-lang/noir-starter/tree/main/with-foundry). - -You can find other tools, examples, boilerplates and libraries in the [awesome-noir](https://github.com/noir-lang/awesome-noir) repository. - -You should also be ready to write and deploy your first NoirJS app and start generating proofs on websites, phones, and NodeJS environments! Head on to the [NoirJS tutorial](../tutorials/noirjs_app.md) to learn how to do that. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/how_to/merkle-proof.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/how_to/merkle-proof.mdx deleted file mode 100644 index 34074659ac1..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/how_to/merkle-proof.mdx +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Prove Merkle Tree Membership -description: - Learn how to use merkle membership proof in Noir to prove that a given leaf is a member of a - merkle tree with a specified root, at a given index. -keywords: - [merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree] ---- - -Let's walk through an example of a merkle membership proof in Noir that proves that a given leaf is -in a merkle tree. - -```rust -use dep::std; - -fn main(message : [Field; 62], index : Field, hashpath : [Field; 40], root : Field) { - let leaf = std::hash::hash_to_field(message); - let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); - assert(merkle_root == root); -} - -``` - -The message is hashed using `hash_to_field`. The specific hash function that is being used is chosen -by the backend. The only requirement is that this hash function can heuristically be used as a -random oracle. If only collision resistance is needed, then one can call `std::hash::pedersen_hash` -instead. - -```rust -let leaf = std::hash::hash_to_field(message); -``` - -The leaf is then passed to a compute_merkle_root function with the root, index and hashpath. The returned root can then be asserted to be the same as the provided root. - -```rust -let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); -assert (merkle_root == root); -``` - -> **Note:** It is possible to re-implement the merkle tree implementation without standard library. -> However, for most usecases, it is enough. In general, the standard library will always opt to be -> as conservative as possible, while striking a balance with efficiency. - -An example, the merkle membership proof, only requires a hash function that has collision -resistance, hence a hash function like Pedersen is allowed, which in most cases is more efficient -than the even more conservative sha256. - -[View an example on the starter repo](https://github.com/noir-lang/noir-examples/blob/3ea09545cabfa464124ec2f3ea8e60c608abe6df/stealthdrop/circuits/src/main.nr#L20) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/index.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/index.mdx deleted file mode 100644 index 75086ddcdde..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/index.mdx +++ /dev/null @@ -1,67 +0,0 @@ ---- -title: Noir Lang -hide_title: true -description: - Learn about the public alpha release of Noir, a domain specific language heavily influenced by Rust that compiles to - an intermediate language which can be compiled to an arithmetic circuit or a rank-1 constraint system. -keywords: - [Noir, - Domain Specific Language, - Rust, - Intermediate Language, - Arithmetic Circuit, - Rank-1 Constraint System, - Ethereum Developers, - Protocol Developers, - Blockchain Developers, - Proving System, - Smart Contract Language] -sidebar_position: 0 ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -Noir Logo - -Noir is a Domain-Specific Language for SNARK proving systems developed by [Aztec Labs](https://aztec.network/). It allows you to generate complex Zero-Knowledge Programs (ZKP) by using simple and flexible syntax, requiring no previous knowledge on the underlying mathematics or cryptography. - -ZK programs are programs that can generate short proofs of a certain statement without revealing some details about it. You can read more about ZKPs [here](https://dev.to/spalladino/a-beginners-intro-to-coding-zero-knowledge-proofs-c56). - -## What's new about Noir? - -Noir works differently from most ZK languages by taking a two-pronged path. First, it compiles the program to an adaptable intermediate language known as ACIR. From there, depending on a given project's needs, ACIR can be further compiled into an arithmetic circuit for integration with the proving backend. - -:::info - -Noir is backend agnostic, which means it makes no assumptions on which proving backend powers the ZK proof. Being the language that powers [Aztec Contracts](https://docs.aztec.network/developers/contracts/main), it defaults to Aztec's Barretenberg proving backend. - -However, the ACIR output can be transformed to be compatible with other PLONK-based backends, or into a [rank-1 constraint system](https://www.rareskills.io/post/rank-1-constraint-system) suitable for backends such as Arkwork's Marlin. - -::: - -## Who is Noir for? - -Noir can be used both in complex cloud-based backends and in user's smartphones, requiring no knowledge on the underlying math or cryptography. From authorization systems that keep a password in the user's device, to complex on-chain verification of recursive proofs, Noir is designed to abstract away complexity without any significant overhead. Here are some examples of situations where Noir can be used: - - - - Noir Logo - - Aztec Contracts leverage Noir to allow for the storage and execution of private information. Writing an Aztec Contract is as easy as writing Noir, and Aztec developers can easily interact with the network storage and execution through the [Aztec.nr](https://docs.aztec.network/developers/contracts/main) library. - - - Soliditry Verifier Example - Noir can auto-generate Solidity verifier contracts that verify Noir proofs. This allows for non-interactive verification of proofs containing private information in an immutable system. This feature powers a multitude of use-case scenarios, from P2P chess tournaments, to [Aztec Layer-2 Blockchain](https://docs.aztec.network/) - - - Aztec Labs developed NoirJS, an easy interface to generate and verify Noir proofs in a Javascript environment. This allows for Noir to be used in webpages, mobile apps, games, and any other environment supporting JS execution in a standalone manner. - - - - -## Libraries - -Noir is meant to be easy to extend by simply importing Noir libraries just like in Rust. -The [awesome-noir repo](https://github.com/noir-lang/awesome-noir#libraries) is a collection of libraries developed by the Noir community. -Writing a new library is easy and makes code be composable and easy to reuse. See the section on [dependencies](noir/modules_packages_crates/dependencies.md) for more information. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/migration_notes.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/migration_notes.md deleted file mode 100644 index 68acd5e566e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/migration_notes.md +++ /dev/null @@ -1,107 +0,0 @@ ---- -title: Migration notes -description: Read about migration notes from previous versions, which could solve problems while updating -keywords: [Noir, notes, migration, updating, upgrading] ---- - -Noir is in full-speed development. Things break fast, wild, and often. This page attempts to leave some notes on errors you might encounter when upgrading and how to resolve them until proper patches are built. - -## 0.22.0 - -### `backend encountered an error: libc++.so.1` - -Depending on your OS, you may encounter the following error when running `nargo prove` for the first time: - -```text -The backend encountered an error: "/home/codespace/.nargo/backends/acvm-backend-barretenberg/backend_binary: error while loading shared libraries: libc++.so.1: cannot open shared object file: No such file or directory\n" -``` - -Install the `libc++-dev` library with: - -```bash -sudo apt install libc++-dev -``` - -## ≥0.19 - -### Enforcing `compiler_version` - -From this version on, the compiler will check for the `compiler_version` field in `Nargo.toml`, and will error if it doesn't match the current Nargo version in use. - -To update, please make sure this field in `Nargo.toml` matches the output of `nargo --version`. - -## ≥0.14 - -The index of the [for loops](noir/concepts/control_flow.md#loops) is now of type `u64` instead of `Field`. An example refactor would be: - -```rust -for i in 0..10 { - let i = i as Field; -} -``` - -## ≥v0.11.0 and Nargo backend - -From this version onwards, Nargo starts managing backends through the `nargo backend` command. Upgrading to the versions per usual steps might lead to: - -### `backend encountered an error` - -This is likely due to the existing locally installed version of proving backend (e.g. barretenberg) is incompatible with the version of Nargo in use. - -To fix the issue: - -1. Uninstall the existing backend - -```bash -nargo backend uninstall acvm-backend-barretenberg -``` - -You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. - -2. Reinstall a compatible version of the proving backend. - -If you are using the default barretenberg backend, simply run: - -``` -nargo prove -``` - -with your Noir program. - -This will trigger the download and installation of the latest version of barretenberg compatible with your Nargo in use. - -### `backend encountered an error: illegal instruction` - -On certain Intel-based systems, an `illegal instruction` error may arise due to incompatibility of barretenberg with certain CPU instructions. - -To fix the issue: - -1. Uninstall the existing backend - -```bash -nargo backend uninstall acvm-backend-barretenberg -``` - -You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. - -2. Reinstall a compatible version of the proving backend. - -If you are using the default barretenberg backend, simply run: - -``` -nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/barretenberg-js-binary/raw/master/run-bb.tar.gz -``` - -This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. - -The gzipped file is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. - -Then run: - -``` -DESIRED_BINARY_VERSION=0.8.1 nargo info -``` - -This overrides the bb native binary with a bb.js node application instead, which should be compatible with most if not all hardware. This does come with the drawback of being generally slower than native binary. - -0.8.1 indicates bb.js version 0.8.1, so if you change that it will update to a different version or the default version in the script if none was supplied. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/assert.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/assert.md deleted file mode 100644 index c5f9aff139c..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/assert.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: Assert Function -description: - Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or - comparison expression that follows to be true, and what happens if the expression is false at - runtime. -keywords: [Noir programming language, assert statement, predicate expression, comparison expression] -sidebar_position: 4 ---- - -Noir includes a special `assert` function which will explicitly constrain the predicate/comparison -expression that follows to be true. If this expression is false at runtime, the program will fail to -be proven. Example: - -```rust -fn main(x : Field, y : Field) { - assert(x == y); -} -``` - -You can optionally provide a message to be logged when the assertion fails: - -```rust -assert(x == y, "x and y are not equal"); -``` - -> Assertions only work for predicate operations, such as `==`. If there's any ambiguity on the operation, the program will fail to compile. For example, it is unclear if `assert(x + y)` would check for `x + y == 0` or simply would return `true`. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/control_flow.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/control_flow.md deleted file mode 100644 index 4ce65236db3..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/control_flow.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Control Flow -description: - Learn how to use loops and if expressions in the Noir programming language. Discover the syntax - and examples for for loops and if-else statements. -keywords: [Noir programming language, loops, for loop, if-else statements, Rust syntax] -sidebar_position: 2 ---- - -## Loops - -Noir has one kind of loop: the `for` loop. `for` loops allow you to repeat a block of code multiple -times. - -The following block of code between the braces is run 10 times. - -```rust -for i in 0..10 { - // do something -}; -``` - -The index for loops is of type `u64`. - -## If Expressions - -Noir supports `if-else` statements. The syntax is most similar to Rust's where it is not required -for the statement's conditional to be surrounded by parentheses. - -```rust -let a = 0; -let mut x: u32 = 0; - -if a == 0 { - if a != 0 { - x = 6; - } else { - x = 2; - } -} else { - x = 5; - assert(x == 5); -} -assert(x == 2); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_bus.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_bus.md deleted file mode 100644 index e54fc861257..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_bus.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: Data Bus -sidebar_position: 13 ---- -**Disclaimer** this feature is experimental, do not use it! - -The data bus is an optimization that the backend can use to make recursion more efficient. -In order to use it, you must define some inputs of the program entry points (usually the `main()` -function) with the `call_data` modifier, and the return values with the `return_data` modifier. -These modifiers are incompatible with `pub` and `mut` modifiers. - -## Example - -```rust -fn main(mut x: u32, y: call_data u32, z: call_data [u32;4] ) -> return_data u32 { - let a = z[x]; - a+y -} -``` - -As a result, both call_data and return_data will be treated as private inputs and encapsulated into a read-only array each, for the backend to process. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/_category_.json deleted file mode 100644 index 5d694210bbf..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 0, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/arrays.md deleted file mode 100644 index fb81dcc3970..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/arrays.md +++ /dev/null @@ -1,251 +0,0 @@ ---- -title: Arrays -description: - Dive into the Array data type in Noir. Grasp its methods, practical examples, and best practices for efficiently using Arrays in your Noir code. -keywords: - [ - noir, - array type, - methods, - examples, - indexing, - ] -sidebar_position: 4 ---- - -An array is one way of grouping together values into one compound type. Array types can be inferred -or explicitly specified via the syntax `[; ]`: - -```rust -fn main(x : Field, y : Field) { - let my_arr = [x, y]; - let your_arr: [Field; 2] = [x, y]; -} -``` - -Here, both `my_arr` and `your_arr` are instantiated as an array containing two `Field` elements. - -Array elements can be accessed using indexing: - -```rust -fn main() { - let a = [1, 2, 3, 4, 5]; - - let first = a[0]; - let second = a[1]; -} -``` - -All elements in an array must be of the same type (i.e. homogeneous). That is, an array cannot group -a `Field` value and a `u8` value together for example. - -You can write mutable arrays, like: - -```rust -fn main() { - let mut arr = [1, 2, 3, 4, 5]; - assert(arr[0] == 1); - - arr[0] = 42; - assert(arr[0] == 42); -} -``` - -You can instantiate a new array of a fixed size with the same value repeated for each element. The following example instantiates an array of length 32 where each element is of type Field and has the value 0. - -```rust -let array: [Field; 32] = [0; 32]; -``` - -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: - -```rust -let array: [Field; 32] = [0; 32]; -let sl = array.as_slice() -``` - -You can define multidimensional arrays: - -```rust -let array : [[Field; 2]; 2]; -let element = array[0][0]; -``` - -However, multidimensional slices are not supported. For example, the following code will error at compile time: - -```rust -let slice : [[Field]] = []; -``` - -## Types - -You can create arrays of primitive types or structs. There is not yet support for nested arrays -(arrays of arrays) or arrays of structs that contain arrays. - -## Methods - -For convenience, the STD provides some ready-to-use, common methods for arrays: - -### len - -Returns the length of an array - -```rust -fn len(_array: [T; N]) -> comptime Field -``` - -example - -```rust -fn main() { - let array = [42, 42]; - assert(array.len() == 2); -} -``` - -### sort - -Returns a new sorted array. The original array remains untouched. Notice that this function will -only work for arrays of fields or integers, not for any arbitrary type. This is because the sorting -logic it uses internally is optimized specifically for these values. If you need a sort function to -sort any type, you should use the function `sort_via` described below. - -```rust -fn sort(_array: [T; N]) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32]; - let sorted = arr.sort(); - assert(sorted == [32, 42]); -} -``` - -### sort_via - -Sorts the array with a custom comparison function - -```rust -fn sort_via(mut a: [T; N], ordering: fn(T, T) -> bool) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32] - let sorted_ascending = arr.sort_via(|a, b| a <= b); - assert(sorted_ascending == [32, 42]); // verifies - - let sorted_descending = arr.sort_via(|a, b| a >= b); - assert(sorted_descending == [32, 42]); // does not verify -} -``` - -### map - -Applies a function to each element of the array, returning a new array containing the mapped elements. - -```rust -fn map(f: fn(T) -> U) -> [U; N] -``` - -example - -```rust -let a = [1, 2, 3]; -let b = a.map(|a| a * 2); // b is now [2, 4, 6] -``` - -### fold - -Applies a function to each element of the array, returning the final accumulated value. The first -parameter is the initial value. - -```rust -fn fold(mut accumulator: U, f: fn(U, T) -> U) -> U -``` - -This is a left fold, so the given function will be applied to the accumulator and first element of -the array, then the second, and so on. For a given call the expected result would be equivalent to: - -```rust -let a1 = [1]; -let a2 = [1, 2]; -let a3 = [1, 2, 3]; - -let f = |a, b| a - b; -a1.fold(10, f) //=> f(10, 1) -a2.fold(10, f) //=> f(f(10, 1), 2) -a3.fold(10, f) //=> f(f(f(10, 1), 2), 3) -``` - -example: - -```rust - -fn main() { - let arr = [2, 2, 2, 2, 2]; - let folded = arr.fold(0, |a, b| a + b); - assert(folded == 10); -} - -``` - -### reduce - -Same as fold, but uses the first element as starting element. - -```rust -fn reduce(f: fn(T, T) -> T) -> T -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let reduced = arr.reduce(|a, b| a + b); - assert(reduced == 10); -} -``` - -### all - -Returns true if all the elements satisfy the given predicate - -```rust -fn all(predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let all = arr.all(|a| a == 2); - assert(all); -} -``` - -### any - -Returns true if any of the elements satisfy the given predicate - -```rust -fn any(predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 5]; - let any = arr.any(|a| a == 5); - assert(any); -} - -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/booleans.md deleted file mode 100644 index 7211716f63e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/booleans.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Booleans -description: - Delve into the Boolean data type in Noir. Understand its methods, practical examples, and best practices for using Booleans in your Noir programs. -keywords: - [ - noir, - boolean type, - methods, - examples, - logical operations, - ] -sidebar_position: 2 ---- - - -The `bool` type in Noir has two possible values: `true` and `false`: - -```rust -fn main() { - let t = true; - let f: bool = false; -} -``` - -> **Note:** When returning a boolean value, it will show up as a value of 1 for `true` and 0 for -> `false` in _Verifier.toml_. - -The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and -[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/fields.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/fields.md deleted file mode 100644 index 99b4aa63549..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/fields.md +++ /dev/null @@ -1,192 +0,0 @@ ---- -title: Fields -description: - Dive deep into the Field data type in Noir. Understand its methods, practical examples, and best practices to effectively use Fields in your Noir programs. -keywords: - [ - noir, - field type, - methods, - examples, - best practices, - ] -sidebar_position: 0 ---- - -The field type corresponds to the native field type of the proving backend. - -The size of a Noir field depends on the elliptic curve's finite field for the proving backend -adopted. For example, a field would be a 254-bit integer when paired with the default backend that -spans the Grumpkin curve. - -Fields support integer arithmetic and are often used as the default numeric type in Noir: - -```rust -fn main(x : Field, y : Field) { - let z = x + y; -} -``` - -`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new -private value `z` constrained to be equal to `x + y`. - -If proving efficiency is of priority, fields should be used as a default for solving problems. -Smaller integer types (e.g. `u64`) incur extra range constraints. - -## Methods - -After declaring a Field, you can use these common methods on it: - -### to_le_bits - -Transforms the field into an array of bits, Little Endian. - -```rust -fn to_le_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_le_bits(32); -} -``` - -### to_be_bits - -Transforms the field into an array of bits, Big Endian. - -```rust -fn to_be_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_be_bits(32); -} -``` - -### to_le_bytes - -Transforms into an array of bytes, Little Endian - -```rust -fn to_le_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_le_bytes(4); -} -``` - -### to_be_bytes - -Transforms into an array of bytes, Big Endian - -```rust -fn to_be_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_be_bytes(4); -} -``` - -### to_le_radix - -Decomposes into a vector over the specified base, Little Endian - -```rust -fn to_le_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_le_radix(256, 4); -} -``` - -### to_be_radix - -Decomposes into a vector over the specified base, Big Endian - -```rust -fn to_be_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_be_radix(256, 4); -} -``` - -### pow_32 - -Returns the value to the power of the specified exponent - -```rust -fn pow_32(self, exponent: Field) -> Field -``` - -example: - -```rust -fn main() { - let field = 2 - let pow = field.pow_32(4); - assert(pow == 16); -} -``` - -### assert_max_bit_size - -Adds a constraint to specify that the field can be represented with `bit_size` number of bits - -```rust -fn assert_max_bit_size(self, bit_size: u32) -``` - -example: - -```rust -fn main() { - let field = 2 - field.assert_max_bit_size(32); -} -``` - -### sgn0 - -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. - -```rust -fn sgn0(self) -> u1 -``` - - -### lt - -Returns true if the field is less than the other field - -```rust -pub fn lt(self, another: Field) -> bool -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/function_types.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/function_types.md deleted file mode 100644 index f6121af17e2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/function_types.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Function types -sidebar_position: 10 ---- - -Noir supports higher-order functions. The syntax for a function type is as follows: - -```rust -fn(arg1_type, arg2_type, ...) -> return_type -``` - -Example: - -```rust -fn assert_returns_100(f: fn() -> Field) { // f takes no args and returns a Field - assert(f() == 100); -} - -fn main() { - assert_returns_100(|| 100); // ok - assert_returns_100(|| 150); // fails -} -``` - -A function type also has an optional capture environment - this is necessary to support closures. -See [Lambdas](../lambdas.md) for more details. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/index.md deleted file mode 100644 index f09bca0ee04..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/index.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: Data Types -description: - Get a clear understanding of the two categories of Noir data types - primitive types and compound - types. Learn about their characteristics, differences, and how to use them in your Noir - programming. -keywords: - [ - noir, - data types, - primitive types, - compound types, - private types, - public types, - ] ---- - -Every value in Noir has a type, which determines which operations are valid for it. - -All values in Noir are fundamentally composed of `Field` elements. For a more approachable -developing experience, abstractions are added on top to introduce different data types in Noir. - -Noir has two category of data types: primitive types (e.g. `Field`, integers, `bool`) and compound -types that group primitive types (e.g. arrays, tuples, structs). Each value can either be private or -public. - -## Private & Public Types - -A **private value** is known only to the Prover, while a **public value** is known by both the -Prover and Verifier. Mark values as `private` when the value should only be known to the prover. All -primitive types (including individual fields of compound types) in Noir are private by default, and -can be marked public when certain values are intended to be revealed to the Verifier. - -> **Note:** For public values defined in Noir programs paired with smart contract verifiers, once -> the proofs are verified on-chain the values can be considered known to everyone that has access to -> that blockchain. - -Public data types are treated no differently to private types apart from the fact that their values -will be revealed in proofs generated. Simply changing the value of a public type will not change the -circuit (where the same goes for changing values of private types as well). - -_Private values_ are also referred to as _witnesses_ sometimes. - -> **Note:** The terms private and public when applied to a type (e.g. `pub Field`) have a different -> meaning than when applied to a function (e.g. `pub fn foo() {}`). -> -> The former is a visibility modifier for the Prover to interpret if a value should be made known to -> the Verifier, while the latter is a visibility modifier for the compiler to interpret if a -> function should be made accessible to external Noir programs like in other languages. - -### pub Modifier - -All data types in Noir are private by default. Types are explicitly declared as public using the -`pub` modifier: - -```rust -fn main(x : Field, y : pub Field) -> pub Field { - x + y -} -``` - -In this example, `x` is **private** while `y` and `x + y` (the return value) are **public**. Note -that visibility is handled **per variable**, so it is perfectly valid to have one input that is -private and another that is public. - -> **Note:** Public types can only be declared through parameters on `main`. - -## Type Aliases - -A type alias is a new name for an existing type. Type aliases are declared with the keyword `type`: - -```rust -type Id = u8; - -fn main() { - let id: Id = 1; - let zero: u8 = 0; - assert(zero + 1 == id); -} -``` - -Type aliases can also be used with [generics](../generics.md): - -```rust -type Id = Size; - -fn main() { - let id: Id = 1; - let zero: u32 = 0; - assert(zero + 1 == id); -} -``` - -### BigInt - -You can achieve BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/integers.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/integers.md deleted file mode 100644 index 30135d76e4a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/integers.md +++ /dev/null @@ -1,162 +0,0 @@ ---- -title: Integers -description: Explore the Integer data type in Noir. Learn about its methods, see real-world examples, and grasp how to efficiently use Integers in your Noir code. -keywords: [noir, integer types, methods, examples, arithmetic] -sidebar_position: 1 ---- - -An integer type is a range constrained field type. The Noir frontend supports arbitrarily-sized, both unsigned and signed integer types. - -:::info - -When an integer is defined in Noir without a specific type, it will default to `Field`. - -The one exception is for loop indices which default to `u64` since comparisons on `Field`s are not possible. - -::: - -## Unsigned Integers - -An unsigned integer type is specified first with the letter `u` (indicating its unsigned nature) followed by its bit size (e.g. `8`): - -```rust -fn main() { - let x: u8 = 1; - let y: u8 = 1; - let z = x + y; - assert (z == 2); -} -``` - -The bit size determines the maximum value the integer type can store. For example, a `u8` variable can store a value in the range of 0 to 255 (i.e. $\\2^{8}-1\\$). - -## Signed Integers - -A signed integer type is specified first with the letter `i` (which stands for integer) followed by its bit size (e.g. `8`): - -```rust -fn main() { - let x: i8 = -1; - let y: i8 = -1; - let z = x + y; - assert (z == -2); -} -``` - -The bit size determines the maximum and minimum range of value the integer type can store. For example, an `i8` variable can store a value in the range of -128 to 127 (i.e. $\\-2^{7}\\$ to $\\2^{7}-1\\$). - -:::tip - -If you are using the default proving backend with Noir, both even (e.g. _u2_, _i2_) and odd (e.g. _u3_, _i3_) arbitrarily-sized integer types up to 127 bits (i.e. _u127_ and _i127_) are supported. - -::: - - -## 128 bits Unsigned Integers - -The built-in structure `U128` allows you to use 128-bit unsigned integers almost like a native integer type. However, there are some differences to keep in mind: -- You cannot cast between a native integer and `U128` -- There is a higher performance cost when using `U128`, compared to a native type. - -Conversion between unsigned integer types and U128 are done through the use of `from_integer` and `to_integer` functions. - -```rust -fn main() { - let x = U128::from_integer(23); - let y = U128::from_hex("0x7"); - let z = x + y; - assert(z.to_integer() == 30); -} -``` - -`U128` is implemented with two 64 bits limbs, representing the low and high bits, which explains the performance cost. You should expect `U128` to be twice more costly for addition and four times more costly for multiplication. -You can construct a U128 from its limbs: -```rust -fn main(x: u64, y: u64) { - let x = U128::from_u64s_be(x,y); - assert(z.hi == x as Field); - assert(z.lo == y as Field); -} -``` - -Note that the limbs are stored as Field elements in order to avoid unnecessary conversions. -Apart from this, most operations will work as usual: - -```rust -fn main(x: U128, y: U128) { - // multiplication - let c = x * y; - // addition and subtraction - let c = c - x + y; - // division - let c = x / y; - // bit operation; - let c = x & y | y; - // bit shift - let c = x << y; - // comparisons; - let c = x < y; - let c = x == y; -} -``` - -## Overflows - -Computations that exceed the type boundaries will result in overflow errors. This happens with both signed and unsigned integers. For example, attempting to prove: - -```rust -fn main(x: u8, y: u8) { - let z = x + y; -} -``` - -With: - -```toml -x = "255" -y = "1" -``` - -Would result in: - -``` -$ nargo prove -error: Assertion failed: 'attempt to add with overflow' -┌─ ~/src/main.nr:9:13 -│ -│ let z = x + y; -│ ----- -│ -= Call stack: - ... -``` - -A similar error would happen with signed integers: - -```rust -fn main() { - let x: i8 = -118; - let y: i8 = -11; - let z = x + y; -} -``` - -### Wrapping methods - -Although integer overflow is expected to error, some use-cases rely on wrapping. For these use-cases, the standard library provides `wrapping` variants of certain common operations: - -```rust -fn wrapping_add(x: T, y: T) -> T; -fn wrapping_sub(x: T, y: T) -> T; -fn wrapping_mul(x: T, y: T) -> T; -``` - -Example of how it is used: - -```rust -use dep::std; - -fn main(x: u8, y: u8) -> pub u8 { - std::wrapping_add(x, y) -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/references.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/references.md deleted file mode 100644 index a5293d11cfb..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/references.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: References -sidebar_position: 9 ---- - -Noir supports first-class references. References are a bit like pointers: they point to a specific address that can be followed to access the data stored at that address. You can use Rust-like syntax to use pointers in Noir: the `&` operator references the variable, the `*` operator dereferences it. - -Example: - -```rust -fn main() { - let mut x = 2; - - // you can reference x as &mut and pass it to multiplyBy2 - multiplyBy2(&mut x); -} - -// you can access &mut here -fn multiplyBy2(x: &mut Field) { - // and dereference it with * - *x = *x * 2; -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/slices.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/slices.mdx deleted file mode 100644 index 4a6ee816aa2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/slices.mdx +++ /dev/null @@ -1,147 +0,0 @@ ---- -title: Slices -description: Explore the Slice data type in Noir. Understand its methods, see real-world examples, and learn how to effectively use Slices in your Noir programs. -keywords: [noir, slice type, methods, examples, subarrays] -sidebar_position: 5 ---- - -import Experimental from '@site/src/components/Notes/_experimental.mdx'; - - - -A slice is a dynamically-sized view into a sequence of elements. They can be resized at runtime, but because they don't own the data, they cannot be returned from a circuit. You can treat slices as arrays without a constrained size. - -```rust -use dep::std::slice; - -fn main() -> pub Field { - let mut slice: [Field] = [0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -View the corresponding test file [here][test-file]. - -[test-file]: https://github.com/noir-lang/noir/blob/f387ec1475129732f72ba294877efdf6857135ac/crates/nargo_cli/tests/test_data_ssa_refactor/slices/src/main.nr - -## Methods - -For convenience, the STD provides some ready-to-use, common methods for slices: - -### push_back - -Pushes a new element to the end of the slice, returning a new slice with a length one greater than the original unmodified slice. - -```rust -fn push_back(_self: [T], _elem: T) -> [T] -``` - -example: - -```rust -fn main() -> pub Field { - let mut slice: [Field] = [0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -View the corresponding test file [here][test-file]. - -### push_front - -Returns a new array with the specified element inserted at index 0. The existing elements indexes are incremented by 1. - -```rust -fn push_front(_self: Self, _elem: T) -> Self -``` - -Example: - -```rust -let mut new_slice: [Field] = []; -new_slice = new_slice.push_front(20); -assert(new_slice[0] == 20); // returns true -``` - -View the corresponding test file [here][test-file]. - -### pop_front - -Returns a tuple of two items, the first element of the array and the rest of the array. - -```rust -fn pop_front(_self: Self) -> (T, Self) -``` - -Example: - -```rust -let (first_elem, rest_of_slice) = slice.pop_front(); -``` - -View the corresponding test file [here][test-file]. - -### pop_back - -Returns a tuple of two items, the beginning of the array with the last element omitted and the last element. - -```rust -fn pop_back(_self: Self) -> (Self, T) -``` - -Example: - -```rust -let (popped_slice, last_elem) = slice.pop_back(); -``` - -View the corresponding test file [here][test-file]. - -### append - -Loops over a slice and adds it to the end of another. - -```rust -fn append(mut self, other: Self) -> Self -``` - -Example: - -```rust -let append = [1, 2].append([3, 4, 5]); -``` - -### insert - -Inserts an element at a specified index and shifts all following elements by 1. - -```rust -fn insert(_self: Self, _index: Field, _elem: T) -> Self -``` - -Example: - -```rust -new_slice = rest_of_slice.insert(2, 100); -assert(new_slice[2] == 100); -``` - -View the corresponding test file [here][test-file]. - -### remove - -Remove an element at a specified index, shifting all elements after it to the left, returning the altered slice and the removed element. - -```rust -fn remove(_self: Self, _index: Field) -> (Self, T) -``` - -Example: - -```rust -let (remove_slice, removed_elem) = slice.remove(3); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/strings.md deleted file mode 100644 index 8ab5825a4c4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/strings.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: Strings -description: - Discover the String data type in Noir. Learn about its methods, see real-world examples, and understand how to effectively manipulate and use Strings in Noir. -keywords: - [ - noir, - string type, - methods, - examples, - concatenation, - ] -sidebar_position: 3 ---- - - -The string type is a fixed length value defined with `str`. - -You can use strings in `assert()` functions or print them with -`println()`. See more about [Logging](../../standard_library/logging.md). - -```rust -use dep::std; - -fn main(message : pub str<11>, hex_as_string : str<4>) { - println(message); - assert(message == "hello world"); - assert(hex_as_string == "0x41"); -} -``` - -You can convert a `str` to a byte array by calling `as_bytes()` -or a vector by calling `as_bytes_vec()`. - -```rust -fn main() { - let message = "hello world"; - let message_bytes = message.as_bytes(); - let mut message_vec = message.as_bytes_vec(); - assert(message_bytes.len() == 11); - assert(message_bytes[0] == 104); - assert(message_bytes[0] == message_vec.get(0)); -} -``` - -## Escape characters - -You can use escape characters for your strings: - -| Escape Sequence | Description | -|-----------------|-----------------| -| `\r` | Carriage Return | -| `\n` | Newline | -| `\t` | Tab | -| `\0` | Null Character | -| `\"` | Double Quote | -| `\\` | Backslash | - -Example: - -```rust -let s = "Hello \"world" // prints "Hello "world" -let s = "hey \tyou"; // prints "hey you" -``` - -## Raw strings - -A raw string begins with the letter `r` and is optionally delimited by a number of hashes `#`. - -Escape characters are *not* processed within raw strings. All contents are interpreted literally. - -Example: - -```rust -let s = r"Hello world"; -let s = r#"Simon says "hello world""#; - -// Any number of hashes may be used (>= 1) as long as the string also terminates with the same number of hashes -let s = r#####"One "#, Two "##, Three "###, Four "####, Five will end the string."#####; -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/structs.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/structs.md deleted file mode 100644 index dbf68c99813..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/structs.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -title: Structs -description: - Explore the Struct data type in Noir. Learn about its methods, see real-world examples, and grasp how to effectively define and use Structs in your Noir programs. -keywords: - [ - noir, - struct type, - methods, - examples, - data structures, - ] -sidebar_position: 8 ---- - -A struct also allows for grouping multiple values of different types. Unlike tuples, we can also -name each field. - -> **Note:** The usage of _field_ here refers to each element of the struct and is unrelated to the -> field type of Noir. - -Defining a struct requires giving it a name and listing each field within as `: ` pairs: - -```rust -struct Animal { - hands: Field, - legs: Field, - eyes: u8, -} -``` - -An instance of a struct can then be created with actual values in `: ` pairs in any -order. Struct fields are accessible using their given names: - -```rust -fn main() { - let legs = 4; - - let dog = Animal { - eyes: 2, - hands: 0, - legs, - }; - - let zero = dog.hands; -} -``` - -Structs can also be destructured in a pattern, binding each field to a new variable: - -```rust -fn main() { - let Animal { hands, legs: feet, eyes } = get_octopus(); - - let ten = hands + feet + eyes as u8; -} - -fn get_octopus() -> Animal { - let octopus = Animal { - hands: 0, - legs: 8, - eyes: 2, - }; - - octopus -} -``` - -The new variables can be bound with names different from the original struct field names, as -showcased in the `legs --> feet` binding in the example above. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/tuples.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/tuples.md deleted file mode 100644 index 2ec5c9c4113..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/tuples.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Tuples -description: - Dive into the Tuple data type in Noir. Understand its methods, practical examples, and best practices for efficiently using Tuples in your Noir code. -keywords: - [ - noir, - tuple type, - methods, - examples, - multi-value containers, - ] -sidebar_position: 7 ---- - -A tuple collects multiple values like an array, but with the added ability to collect values of -different types: - -```rust -fn main() { - let tup: (u8, u64, Field) = (255, 500, 1000); -} -``` - -One way to access tuple elements is via destructuring using pattern matching: - -```rust -fn main() { - let tup = (1, 2); - - let (one, two) = tup; - - let three = one + two; -} -``` - -Another way to access tuple elements is via direct member access, using a period (`.`) followed by -the index of the element we want to access. Index `0` corresponds to the first tuple element, `1` to -the second and so on: - -```rust -fn main() { - let tup = (5, 6, 7, 8); - - let five = tup.0; - let eight = tup.3; -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/vectors.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/vectors.mdx deleted file mode 100644 index aed13183719..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/vectors.mdx +++ /dev/null @@ -1,171 +0,0 @@ ---- -title: Vectors -description: Delve into the Vector data type in Noir. Learn about its methods, practical examples, and best practices for using Vectors in your Noir code. -keywords: [noir, vector type, methods, examples, dynamic arrays] -sidebar_position: 6 ---- - -import Experimental from '@site/src/components/Notes/_experimental.mdx'; - - - -A vector is a collection type similar to Rust's Vector type. It's convenient way to use slices as mutable arrays. - -Example: - -```rust -let mut vector: Vec = Vec::new(); -for i in 0..5 { - vector.push(i); -} -assert(vector.len() == 5); -``` - -## Methods - -### new - -Creates a new, empty vector. - -```rust -pub fn new() -> Self { - Self { slice: [] } -} -``` - -Example: - -```rust -let empty_vector: Vec = Vec::new(); -assert(empty_vector.len() == 0); -``` - -### from_slice - -Creates a vector containing each element from a given slice. Mutations to the resulting vector will not affect the original slice. - -```rust -pub fn from_slice(slice: [T]) -> Self { - Self { slice } -} -``` - -Example: - -```rust -let arr: [Field] = [1, 2, 3]; -let vector_from_slice = Vec::from_slice(arr); -assert(vector_from_slice.len() == 3); -``` - -### get - -Retrieves an element from the vector at a given index. Panics if the index points beyond the vector's end. - -```rust -pub fn get(self, index: Field) -> T { - self.slice[index] -} -``` - -Example: - -```rust -let vector: Vec = Vec::from_slice([10, 20, 30]); -assert(vector.get(1) == 20); -``` - -### push - -Adds a new element to the vector's end, returning a new vector with a length one greater than the original unmodified vector. - -```rust -pub fn push(&mut self, elem: T) { - self.slice = self.slice.push_back(elem); -} -``` - -Example: - -```rust -let mut vector: Vec = Vec::new(); -vector.push(10); -assert(vector.len() == 1); -``` - -### pop - -Removes an element from the vector's end, returning a new vector with a length one less than the original vector, along with the removed element. Panics if the vector's length is zero. - -```rust -pub fn pop(&mut self) -> T { - let (popped_slice, last_elem) = self.slice.pop_back(); - self.slice = popped_slice; - last_elem -} -``` - -Example: - -```rust -let mut vector = Vec::from_slice([10, 20]); -let popped_elem = vector.pop(); -assert(popped_elem == 20); -assert(vector.len() == 1); -``` - -### insert - -Inserts an element at a specified index, shifting subsequent elements to the right. - -```rust -pub fn insert(&mut self, index: Field, elem: T) { - self.slice = self.slice.insert(index, elem); -} -``` - -Example: - -```rust -let mut vector = Vec::from_slice([10, 30]); -vector.insert(1, 20); -assert(vector.get(1) == 20); -``` - -### remove - -Removes an element at a specified index, shifting subsequent elements to the left, and returns the removed element. - -```rust -pub fn remove(&mut self, index: Field) -> T { - let (new_slice, elem) = self.slice.remove(index); - self.slice = new_slice; - elem -} -``` - -Example: - -```rust -let mut vector = Vec::from_slice([10, 20, 30]); -let removed_elem = vector.remove(1); -assert(removed_elem == 20); -assert(vector.len() == 2); -``` - -### len - -Returns the number of elements in the vector. - -```rust -pub fn len(self) -> Field { - self.slice.len() -} -``` - -Example: - -```rust -let empty_vector: Vec = Vec::new(); -assert(empty_vector.len() == 0); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/distinct.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/distinct.md deleted file mode 100644 index 6c993b8b5e0..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/distinct.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: Distinct Witnesses -sidebar_position: 11 ---- - -The `distinct` keyword prevents repetitions of witness indices in the program's ABI. This ensures -that the witnesses being returned as public inputs are all unique. - -The `distinct` keyword is only used for return values on program entry points (usually the `main()` -function). - -When using `distinct` and `pub` simultaneously, `distinct` comes first. See the example below. - -You can read more about the problem this solves -[here](https://github.com/noir-lang/noir/issues/1183). - -## Example - -Without the `distinct` keyword, the following program - -```rust -fn main(x : pub Field, y : pub Field) -> pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - "return_witnesses": [3, 2, 4, 4] - } -} -``` - -Whereas (with the `distinct` keyword) - -```rust -fn main(x : pub Field, y : pub Field) -> distinct pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - //... - "return_witnesses": [3, 4, 5, 6] - } -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/functions.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/functions.md deleted file mode 100644 index 48aba9cd058..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/functions.md +++ /dev/null @@ -1,226 +0,0 @@ ---- -title: Functions -description: - Learn how to declare functions and methods in Noir, a programming language with Rust semantics. - This guide covers parameter declaration, return types, call expressions, and more. -keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] -sidebar_position: 1 ---- - -Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. - -To declare a function the `fn` keyword is used. - -```rust -fn foo() {} -``` - -By default, functions are visible only within the package they are defined. To make them visible outside of that package (for example, as part of a [library](../modules_packages_crates/crates_and_packages.md#libraries)), you should mark them as `pub`: - -```rust -pub fn foo() {} -``` - -You can also restrict the visibility of the function to only the crate it was defined in, by specifying `pub(crate)`: - -```rust -pub(crate) fn foo() {} //foo can only be called within its crate -``` - -All parameters in a function must have a type and all types are known at compile time. The parameter -is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. - -```rust -fn foo(x : Field, y : Field){} -``` - -The return type of a function can be stated by using the `->` arrow notation. The function below -states that the foo function must return a `Field`. If the function returns no value, then the arrow -is omitted. - -```rust -fn foo(x : Field, y : Field) -> Field { - x + y -} -``` - -Note that a `return` keyword is unneeded in this case - the last expression in a function's body is -returned. - -## Main function - -If you're writing a binary, the `main` function is the starting point of your program. You can pass all types of expressions to it, as long as they have a fixed size at compile time: - -```rust -fn main(x : Field) // this is fine: passing a Field -fn main(x : [Field; 2]) // this is also fine: passing a Field with known size at compile-time -fn main(x : (Field, bool)) // 👌: passing a (Field, bool) tuple means size 2 -fn main(x : str<5>) // this is fine, as long as you pass a string of size 5 - -fn main(x : Vec) // can't compile, has variable size -fn main(x : [Field]) // can't compile, has variable size -fn main(....// i think you got it by now -``` - -Keep in mind [tests](../../getting_started/tooling/testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: - -```rust -fn main(x : [Field]) { - assert(x[0] == 1); -} - -#[test] -fn test_one() { - main([1, 2]); -} -``` - -```bash -$ nargo test -[testing] Running 1 test functions -[testing] Testing test_one... ok -[testing] All tests passed - -$ nargo check -The application panicked (crashed). -Message: Cannot have variable sized arrays as a parameter to main -``` - -## Call Expressions - -Calling a function in Noir is executed by using the function name and passing in the necessary -arguments. - -Below we show how to call the `foo` function from the `main` function using a call expression: - -```rust -fn main(x : Field, y : Field) { - let z = foo(x); -} - -fn foo(x : Field) -> Field { - x + x -} -``` - -## Methods - -You can define methods in Noir on any struct type in scope. - -```rust -struct MyStruct { - foo: Field, - bar: Field, -} - -impl MyStruct { - fn new(foo: Field) -> MyStruct { - MyStruct { - foo, - bar: 2, - } - } - - fn sum(self) -> Field { - self.foo + self.bar - } -} - -fn main() { - let s = MyStruct::new(40); - assert(s.sum() == 42); -} -``` - -Methods are just syntactic sugar for functions, so if we wanted to we could also call `sum` as -follows: - -```rust -assert(MyStruct::sum(s) == 42); -``` - -It is also possible to specialize which method is chosen depending on the [generic](./generics.md) type that is used. In this example, the `foo` function returns different values depending on its type: - -```rust -struct Foo {} - -impl Foo { - fn foo(self) -> Field { 1 } -} - -impl Foo { - fn foo(self) -> Field { 2 } -} - -fn main() { - let f1: Foo = Foo{}; - let f2: Foo = Foo{}; - assert(f1.foo() + f2.foo() == 3); -} -``` - -Also note that impls with the same method name defined in them cannot overlap. For example, if we already have `foo` defined for `Foo` and `Foo` like we do above, we cannot also define `foo` in an `impl Foo` since it would be ambiguous which version of `foo` to choose. - -```rust -// Including this impl in the same project as the above snippet would -// cause an overlapping impls error -impl Foo { - fn foo(self) -> Field { 3 } -} -``` - -## Lambdas - -Lambdas are anonymous functions. They follow the syntax of Rust - `|arg1, arg2, ..., argN| return_expression`. - -```rust -let add_50 = |val| val + 50; -assert(add_50(100) == 150); -``` - -See [Lambdas](./lambdas.md) for more details. - -## Attributes - -Attributes are metadata that can be applied to a function, using the following syntax: `#[attribute(value)]`. - -Supported attributes include: - -- **builtin**: the function is implemented by the compiler, for efficiency purposes. -- **deprecated**: mark the function as _deprecated_. Calling the function will generate a warning: `warning: use of deprecated function` -- **field**: Used to enable conditional compilation of code depending on the field size. See below for more details -- **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./unconstrained.md) and [NoirJS](../../reference/NoirJS/noir_js/index.md) for more details. -- **test**: mark the function as unit tests. See [Tests](../../getting_started/tooling/testing.md) for more details - -### Field Attribute - -The field attribute defines which field the function is compatible for. The function is conditionally compiled, under the condition that the field attribute matches the Noir native field. -The field can be defined implicitly, by using the name of the elliptic curve usually associated to it - for instance bn254, bls12_381 - or explicitly by using the field (prime) order, in decimal or hexadecimal form. -As a result, it is possible to define multiple versions of a function with each version specialized for a different field attribute. This can be useful when a function requires different parameters depending on the underlying elliptic curve. - -Example: we define the function `foo()` three times below. Once for the default Noir bn254 curve, once for the field $\mathbb F_{23}$, which will normally never be used by Noir, and once again for the bls12_381 curve. - -```rust -#[field(bn254)] -fn foo() -> u32 { - 1 -} - -#[field(23)] -fn foo() -> u32 { - 2 -} - -// This commented code would not compile as foo would be defined twice because it is the same field as bn254 -// #[field(21888242871839275222246405745257275088548364400416034343698204186575808495617)] -// fn foo() -> u32 { -// 2 -// } - -#[field(bls12_381)] -fn foo() -> u32 { - 3 -} -``` - -If the field name is not known to Noir, it will discard the function. Field names are case insensitive. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/generics.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/generics.md deleted file mode 100644 index 0c1c27a2221..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/generics.md +++ /dev/null @@ -1,106 +0,0 @@ ---- -title: Generics -description: Learn how to use Generics in Noir -keywords: [Noir, Rust, generics, functions, structs] -sidebar_position: 7 ---- - -Generics allow you to use the same functions with multiple different concrete data types. You can -read more about the concept of generics in the Rust documentation -[here](https://doc.rust-lang.org/book/ch10-01-syntax.html). - -Here is a trivial example showing the identity function that supports any type. In Rust, it is -common to refer to the most general type as `T`. We follow the same convention in Noir. - -```rust -fn id(x: T) -> T { - x -} -``` - -## In Structs - -Generics are useful for specifying types in structs. For example, we can specify that a field in a -struct will be of a certain generic type. In this case `value` is of type `T`. - -```rust -struct RepeatedValue { - value: T, - count: Field, -} - -impl RepeatedValue { - fn print(self) { - for _i in 0 .. self.count { - println(self.value); - } - } -} - -fn main() { - let repeated = RepeatedValue { value: "Hello!", count: 2 }; - repeated.print(); -} -``` - -The `print` function will print `Hello!` an arbitrary number of times, twice in this case. - -If we want to be generic over array lengths (which are type-level integers), we can use numeric -generics. Using these looks just like using regular generics, but these generics can resolve to -integers at compile-time, rather than resolving to types. Here's an example of a struct that is -generic over the size of the array it contains internally: - -```rust -struct BigInt { - limbs: [u32; N], -} - -impl BigInt { - // `N` is in scope of all methods in the impl - fn first(first: BigInt, second: BigInt) -> Self { - assert(first.limbs != second.limbs); - first - - fn second(first: BigInt, second: Self) -> Self { - assert(first.limbs != second.limbs); - second - } -} -``` - -## Calling functions on generic parameters - -Since a generic type `T` can represent any type, how can we call functions on the underlying type? -In other words, how can we go from "any type `T`" to "any type `T` that has certain methods available?" - -This is what [traits](../concepts/traits.md) are for in Noir. Here's an example of a function generic over -any type `T` that implements the `Eq` trait for equality: - -```rust -fn first_element_is_equal(array1: [T; N], array2: [T; N]) -> bool - where T: Eq -{ - if (array1.len() == 0) | (array2.len() == 0) { - true - } else { - array1[0] == array2[0] - } -} - -fn main() { - assert(first_element_is_equal([1, 2, 3], [1, 5, 6])); - - // We can use first_element_is_equal for arrays of any type - // as long as we have an Eq impl for the types we pass in - let array = [MyStruct::new(), MyStruct::new()]; - assert(array_eq(array, array, MyStruct::eq)); -} - -impl Eq for MyStruct { - fn eq(self, other: MyStruct) -> bool { - self.foo == other.foo - } -} -``` - -You can find more details on traits and trait implementations on the [traits page](../concepts/traits.md). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/mutability.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/mutability.md deleted file mode 100644 index 9cc10429cb4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/mutability.md +++ /dev/null @@ -1,93 +0,0 @@ ---- -title: Mutability -description: - Learn about mutable variables, constants, and globals in Noir programming language. Discover how - to declare, modify, and use them in your programs. -keywords: [noir programming language, mutability in noir, mutable variables, constants, globals] -sidebar_position: 8 ---- - -Variables in noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned -to via an assignment expression. - -```rust -let x = 2; -x = 3; // error: x must be mutable to be assigned to - -let mut y = 3; -let y = 4; // OK -``` - -The `mut` modifier can also apply to patterns: - -```rust -let (a, mut b) = (1, 2); -a = 11; // error: a must be mutable to be assigned to -b = 12; // OK - -let mut (c, d) = (3, 4); -c = 13; // OK -d = 14; // OK - -// etc. -let MyStruct { x: mut y } = MyStruct { x: a }; -// y is now in scope -``` - -Note that mutability in noir is local and everything is passed by value, so if a called function -mutates its parameters then the parent function will keep the old value of the parameters. - -```rust -fn main() -> pub Field { - let x = 3; - helper(x); - x // x is still 3 -} - -fn helper(mut x: i32) { - x = 4; -} -``` - -## Comptime Values - -:::warning - -The 'comptime' keyword was removed in version 0.10. The comptime keyword and syntax are currently still kept and parsed for backwards compatibility, but are now deprecated and will issue a warning when used. `comptime` has been removed because it is no longer needed for accessing arrays. - -::: - -## Globals - -Noir also supports global variables. However, they must be known at compile-time. The global type can also be inferred by the compiler entirely. Globals can also be used to specify array -annotations for function parameters and can be imported from submodules. - -```rust -global N: Field = 5; // Same as `global N: Field = 5` - -fn main(x : Field, y : [Field; N]) { - let res = x * N; - - assert(res == y[0]); - - let res2 = x * my_submodule::N; - assert(res != res2); -} - -mod my_submodule { - use dep::std; - - global N: Field = 10; - - fn my_helper() -> Field { - let x = N; - x - } -} -``` - -## Why only local mutability? - -Witnesses in a proving system are immutable in nature. Noir aims to _closely_ mirror this setting -without applying additional overhead to the user. Modeling a mutable reference is not as -straightforward as on conventional architectures and would incur some possibly unexpected overhead. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/ops.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/ops.md deleted file mode 100644 index 60425cb8994..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/ops.md +++ /dev/null @@ -1,98 +0,0 @@ ---- -title: Logical Operations -description: - Learn about the supported arithmetic and logical operations in the Noir programming language. - Discover how to perform operations on private input types, integers, and booleans. -keywords: - [ - Noir programming language, - supported operations, - arithmetic operations, - logical operations, - predicate operators, - bitwise operations, - short-circuiting, - backend, - ] -sidebar_position: 3 ---- - -# Operations - -## Table of Supported Operations - -| Operation | Description | Requirements | -| :-------- | :------------------------------------------------------------: | -------------------------------------: | -| + | Adds two private input types together | Types must be private input | -| - | Subtracts two private input types together | Types must be private input | -| \* | Multiplies two private input types together | Types must be private input | -| / | Divides two private input types together | Types must be private input | -| ^ | XOR two private input types together | Types must be integer | -| & | AND two private input types together | Types must be integer | -| \| | OR two private input types together | Types must be integer | -| \<\< | Left shift an integer by another integer amount | Types must be integer | -| >> | Right shift an integer by another integer amount | Types must be integer | -| ! | Bitwise not of a value | Type must be integer or boolean | -| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | -| > | returns a bool if one value is more than the other | Upper bound must have a known bit size | -| >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | -| == | returns a bool if one value is equal to the other | Both types must not be constants | -| != | returns a bool if one value is not equal to the other | Both types must not be constants | - -### Predicate Operators - -`<,<=, !=, == , >, >=` are known as predicate/comparison operations because they compare two values. -This differs from the operations such as `+` where the operands are used in _computation_. - -### Bitwise Operations Example - -```rust -fn main(x : Field) { - let y = x as u32; - let z = y & y; -} -``` - -`z` is implicitly constrained to be the result of `y & y`. The `&` operand is used to denote bitwise -`&`. - -> `x & x` would not compile as `x` is a `Field` and not an integer type. - -### Logical Operators - -Noir has no support for the logical operators `||` and `&&`. This is because encoding the -short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can -use the bitwise operators `|` and `&` which operate identically for booleans, just without the -short-circuiting. - -```rust -let my_val = 5; - -let mut flag = 1; -if (my_val > 6) | (my_val == 0) { - flag = 0; -} -assert(flag == 1); - -if (my_val != 10) & (my_val < 50) { - flag = 0; -} -assert(flag == 0); -``` - -### Shorthand operators - -Noir shorthand operators for most of the above operators, namely `+=, -=, *=, /=, %=, &=, |=, ^=, <<=`, and `>>=`. These allow for more concise syntax. For example: - -```rust -let mut i = 0; -i = i + 1; -``` - -could be written as: - -```rust -let mut i = 0; -i += 1; -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/oracles.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/oracles.md deleted file mode 100644 index 2e6a6818d48..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/oracles.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: Oracles -description: Dive into how Noir supports Oracles via RPC calls, and learn how to declare an Oracle in Noir with our comprehensive guide. -keywords: - - Noir - - Oracles - - RPC Calls - - Unconstrained Functions - - Programming - - Blockchain -sidebar_position: 6 ---- - -Noir has support for Oracles via RPC calls. This means Noir will make an RPC call and use the return value for proof generation. - -Since Oracles are not resolved by Noir, they are [`unconstrained` functions](./unconstrained.md) - -You can declare an Oracle through the `#[oracle()]` flag. Example: - -```rust -#[oracle(get_number_sequence)] -unconstrained fn get_number_sequence(_size: Field) -> [Field] {} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/traits.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/traits.md deleted file mode 100644 index ef1445a5907..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/traits.md +++ /dev/null @@ -1,389 +0,0 @@ ---- -title: Traits -description: - Traits in Noir can be used to abstract out a common interface for functions across - several data types. -keywords: [noir programming language, traits, interfaces, generic, protocol] -sidebar_position: 14 ---- - -## Overview - -Traits in Noir are a useful abstraction similar to interfaces or protocols in other languages. Each trait defines -the interface of several methods contained within the trait. Types can then implement this trait by providing -implementations for these methods. For example in the program: - -```rust -struct Rectangle { - width: Field, - height: Field, -} - -impl Rectangle { - fn area(self) -> Field { - self.width * self.height - } -} - -fn log_area(r: Rectangle) { - println(r.area()); -} -``` - -We have a function `log_area` to log the area of a `Rectangle`. Now how should we change the program if we want this -function to work on `Triangle`s as well?: - -```rust -struct Triangle { - width: Field, - height: Field, -} - -impl Triangle { - fn area(self) -> Field { - self.width * self.height / 2 - } -} -``` - -Making `log_area` generic over all types `T` would be invalid since not all types have an `area` method. Instead, we can -introduce a new `Area` trait and make `log_area` generic over all types `T` that implement `Area`: - -```rust -trait Area { - fn area(self) -> Field; -} - -fn log_area(shape: T) where T: Area { - println(shape.area()); -} -``` - -We also need to explicitly implement `Area` for `Rectangle` and `Triangle`. We can do that by changing their existing -impls slightly. Note that the parameter types and return type of each of our `area` methods must match those defined -by the `Area` trait. - -```rust -impl Area for Rectangle { - fn area(self) -> Field { - self.width * self.height - } -} - -impl Area for Triangle { - fn area(self) -> Field { - self.width * self.height / 2 - } -} -``` - -Now we have a working program that is generic over any type of Shape that is used! Others can even use this program -as a library with their own types - such as `Circle` - as long as they also implement `Area` for these types. - -## Where Clauses - -As seen in `log_area` above, when we want to create a function or method that is generic over any type that implements -a trait, we can add a where clause to the generic function. - -```rust -fn log_area(shape: T) where T: Area { - println(shape.area()); -} -``` - -It is also possible to apply multiple trait constraints on the same variable at once by combining traits with the `+` -operator. Similarly, we can have multiple trait constraints by separating each with a comma: - -```rust -fn foo(elements: [T], thing: U) where - T: Default + Add + Eq, - U: Bar, -{ - let mut sum = T::default(); - - for element in elements { - sum += element; - } - - if sum == T::default() { - thing.bar(); - } -} -``` - -## Generic Implementations - -You can add generics to a trait implementation by adding the generic list after the `impl` keyword: - -```rust -trait Second { - fn second(self) -> Field; -} - -impl Second for (T, Field) { - fn second(self) -> Field { - self.1 - } -} -``` - -You can also implement a trait for every type this way: - -```rust -trait Debug { - fn debug(self); -} - -impl Debug for T { - fn debug(self) { - println(self); - } -} - -fn main() { - 1.debug(); -} -``` - -### Generic Trait Implementations With Where Clauses - -Where clauses can also be placed on trait implementations themselves to restrict generics in a similar way. -For example, while `impl Foo for T` implements the trait `Foo` for every type, `impl Foo for T where T: Bar` -will implement `Foo` only for types that also implement `Bar`. This is often used for implementing generic types. -For example, here is the implementation for array equality: - -```rust -impl Eq for [T; N] where T: Eq { - // Test if two arrays have the same elements. - // Because both arrays must have length N, we know their lengths already match. - fn eq(self, other: Self) -> bool { - let mut result = true; - - for i in 0 .. self.len() { - // The T: Eq constraint is needed to call == on the array elements here - result &= self[i] == other[i]; - } - - result - } -} -``` - -## Generic Traits - -Traits themselves can also be generic by placing the generic arguments after the trait name. These generics are in -scope of every item within the trait. - -```rust -trait Into { - // Convert `self` to type `T` - fn into(self) -> T; -} -``` - -When implementing generic traits the generic arguments of the trait must be specified. This is also true anytime -when referencing a generic trait (e.g. in a `where` clause). - -```rust -struct MyStruct { - array: [Field; 2], -} - -impl Into<[Field; 2]> for MyStruct { - fn into(self) -> [Field; 2] { - self.array - } -} - -fn as_array(x: T) -> [Field; 2] - where T: Into<[Field; 2]> -{ - x.into() -} - -fn main() { - let array = [1, 2]; - let my_struct = MyStruct { array }; - - assert_eq(as_array(my_struct), array); -} -``` - -## Trait Methods With No `self` - -A trait can contain any number of methods, each of which have access to the `Self` type which represents each type -that eventually implements the trait. Similarly, the `self` variable is available as well but is not required to be used. -For example, we can define a trait to create a default value for a type. This trait will need to return the `Self` type -but doesn't need to take any parameters: - -```rust -trait Default { - fn default() -> Self; -} -``` - -Implementing this trait can be done similarly to any other trait: - -```rust -impl Default for Field { - fn default() -> Field { - 0 - } -} - -struct MyType {} - -impl Default for MyType { - fn default() -> Field { - MyType {} - } -} -``` - -However, since there is no `self` parameter, we cannot call it via the method call syntax `object.method()`. -Instead, we'll need to refer to the function directly. This can be done either by referring to the -specific impl `MyType::default()` or referring to the trait itself `Default::default()`. In the later -case, type inference determines the impl that is selected. - -```rust -let my_struct = MyStruct::default(); - -let x: Field = Default::default(); -let result = x + Default::default(); -``` - -:::warning - -```rust -let _ = Default::default(); -``` - -If type inference cannot select which impl to use because of an ambiguous `Self` type, an impl will be -arbitrarily selected. This occurs most often when the result of a trait function call with no parameters -is unused. To avoid this, when calling a trait function with no `self` or `Self` parameters or return type, -always refer to it via the implementation type's namespace - e.g. `MyType::default()`. -This is set to change to an error in future Noir versions. - -::: - -## Default Method Implementations - -A trait can also have default implementations of its methods by giving a body to the desired functions. -Note that this body must be valid for all types that may implement the trait. As a result, the only -valid operations on `self` will be operations valid for any type or other operations on the trait itself. - -```rust -trait Numeric { - fn add(self, other: Self) -> Self; - - // Default implementation of double is (self + self) - fn double(self) -> Self { - self.add(self) - } -} -``` - -When implementing a trait with default functions, a type may choose to implement only the required functions: - -```rust -impl Numeric for Field { - fn add(self, other: Field) -> Field { - self + other - } -} -``` - -Or it may implement the optional methods as well: - -```rust -impl Numeric for u32 { - fn add(self, other: u32) -> u32 { - self + other - } - - fn double(self) -> u32 { - self * 2 - } -} -``` - -## Impl Specialization - -When implementing traits for a generic type it is possible to implement the trait for only a certain combination -of generics. This can be either as an optimization or because those specific generics are required to implement the trait. - -```rust -trait Sub { - fn sub(self, other: Self) -> Self; -} - -struct NonZero { - value: T, -} - -impl Sub for NonZero { - fn sub(self, other: Self) -> Self { - let value = self.value - other.value; - assert(value != 0); - NonZero { value } - } -} -``` - -## Overlapping Implementations - -Overlapping implementations are disallowed by Noir to ensure Noir's decision on which impl to select is never ambiguous. -This means if a trait `Foo` is already implemented -by a type `Bar` for all `T`, then we cannot also have a separate impl for `Bar` (or any other -type argument). Similarly, if there is an impl for all `T` such as `impl Debug for T`, we cannot create -any more impls to `Debug` for other types since it would be ambiguous which impl to choose for any given -method call. - -```rust -trait Trait {} - -// Previous impl defined here -impl Trait for (A, B) {} - -// error: Impl for type `(Field, Field)` overlaps with existing impl -impl Trait for (Field, Field) {} -``` - -## Trait Coherence - -Another restriction on trait implementations is coherence. This restriction ensures other crates cannot create -impls that may overlap with other impls, even if several unrelated crates are used as dependencies in the same -program. - -The coherence restriction is: to implement a trait, either the trait itself or the object type must be declared -in the crate the impl is in. - -In practice this often comes up when using types provided by libraries. If a library provides a type `Foo` that does -not implement a trait in the standard library such as `Default`, you may not `impl Default for Foo` in your own crate. -While restrictive, this prevents later issues or silent changes in the program if the `Foo` library later added its -own impl for `Default`. If you are a user of the `Foo` library in this scenario and need a trait not implemented by the -library your choices are to either submit a patch to the library or use the newtype pattern. - -### The Newtype Pattern - -The newtype pattern gets around the coherence restriction by creating a new wrapper type around the library type -that we cannot create `impl`s for. Since the new wrapper type is defined in our current crate, we can create -impls for any trait we need on it. - -```rust -struct Wrapper { - foo: dep::some_library::Foo, -} - -impl Default for Wrapper { - fn default() -> Wrapper { - Wrapper { - foo: dep::some_library::Foo::new(), - } - } -} -``` - -Since we have an impl for our own type, the behavior of this code will not change even if `some_library` is updated -to provide its own `impl Default for Foo`. The downside of this pattern is that it requires extra wrapping and -unwrapping of values when converting to and from the `Wrapper` and `Foo` types. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/unconstrained.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/unconstrained.md deleted file mode 100644 index 6b3424f7993..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/unconstrained.md +++ /dev/null @@ -1,95 +0,0 @@ ---- -title: Unconstrained Functions -description: "Learn about what unconstrained functions in Noir are, how to use them and when you'd want to." - -keywords: [Noir programming language, unconstrained, open] -sidebar_position: 5 ---- - -Unconstrained functions are functions which do not constrain any of the included computation and allow for non-deterministic computation. - -## Why? - -Zero-knowledge (ZK) domain-specific languages (DSL) enable developers to generate ZK proofs from their programs by compiling code down to the constraints of an NP complete language (such as R1CS or PLONKish languages). However, the hard bounds of a constraint system can be very limiting to the functionality of a ZK DSL. - -Enabling a circuit language to perform unconstrained execution is a powerful tool. Said another way, unconstrained execution lets developers generate witnesses from code that does not generate any constraints. Being able to execute logic outside of a circuit is critical for both circuit performance and constructing proofs on information that is external to a circuit. - -Fetching information from somewhere external to a circuit can also be used to enable developers to improve circuit efficiency. - -A ZK DSL does not just prove computation, but proves that some computation was handled correctly. Thus, it is necessary that when we switch from performing some operation directly inside of a circuit to inside of an unconstrained environment that the appropriate constraints are still laid down elsewhere in the circuit. - -## Example - -An in depth example might help drive the point home. This example comes from the excellent [post](https://discord.com/channels/1113924620781883405/1124022445054111926/1128747641853972590) by Tom in the Noir Discord. - -Let's look at how we can optimize a function to turn a `u72` into an array of `u8`s. - -```rust -fn main(num: u72) -> pub [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8)) as u72 & 0xff) as u8; - } - - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 91 -Backend circuit size: 3619 -``` - -A lot of the operations in this function are optimized away by the compiler (all the bit-shifts turn into divisions by constants). However we can save a bunch of gates by casting to u8 a bit earlier. This automatically truncates the bit-shifted value to fit in a u8 which allows us to remove the XOR against 0xff. This saves us ~480 gates in total. - -```rust -fn main(num: u72) -> pub [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8)) as u8; - } - - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 75 -Backend circuit size: 3143 -``` - -Those are some nice savings already but we can do better. This code is all constrained so we're proving every step of calculating out using num, but we don't actually care about how we calculate this, just that it's correct. This is where brillig comes in. - -It turns out that truncating a u72 into a u8 is hard to do inside a snark, each time we do as u8 we lay down 4 ACIR opcodes which get converted into multiple gates. It's actually much easier to calculate num from out than the other way around. All we need to do is multiply each element of out by a constant and add them all together, both relatively easy operations inside a snark. - -We can then run u72_to_u8 as unconstrained brillig code in order to calculate out, then use that result in our constrained function and assert that if we were to do the reverse calculation we'd get back num. This looks a little like the below: - -```rust -fn main(num: u72) -> pub [u8; 8] { - let out = u72_to_u8(num); - - let mut reconstructed_num: u72 = 0; - for i in 0..8 { - reconstructed_num += (out[i] as u72 << (56 - (8 * i))); - } - assert(num == reconstructed_num); - out -} - -unconstrained fn u72_to_u8(num: u72) -> [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8))) as u8; - } - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 78 -Backend circuit size: 2902 -``` - -This ends up taking off another ~250 gates from our circuit! We've ended up with more ACIR opcodes than before but they're easier for the backend to prove (resulting in fewer gates). - -Generally we want to use brillig whenever there's something that's easy to verify but hard to compute within the circuit. For example, if you wanted to calculate a square root of a number it'll be a much better idea to calculate this in brillig and then assert that if you square the result you get back your number. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/_category_.json deleted file mode 100644 index 1debcfe7675..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Modules, Packages and Crates", - "position": 2, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/crates_and_packages.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/crates_and_packages.md deleted file mode 100644 index 95ee9f52ab2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/crates_and_packages.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Crates and Packages -description: Learn how to use Crates and Packages in your Noir project -keywords: [Nargo, dependencies, package management, crates, package] -sidebar_position: 0 ---- - -## Crates - -A crate is the smallest amount of code that the Noir compiler considers at a time. -Crates can contain modules, and the modules may be defined in other files that get compiled with the crate, as we’ll see in the coming sections. - -### Crate Types - -A Noir crate can come in several forms: binaries, libraries or contracts. - -#### Binaries - -_Binary crates_ are programs which you can compile to an ACIR circuit which you can then create proofs against. Each must have a function called `main` that defines the ACIR circuit which is to be proved. - -#### Libraries - -_Library crates_ don't have a `main` function and they don't compile down to ACIR. Instead they define functionality intended to be shared with multiple projects, and eventually included in a binary crate. - -#### Contracts - -Contract crates are similar to binary crates in that they compile to ACIR which you can create proofs against. They are different in that they do not have a single `main` function, but are a collection of functions to be deployed to the [Aztec network](https://aztec.network). You can learn more about the technical details of Aztec in the [monorepo](https://github.com/AztecProtocol/aztec-packages) or contract [examples](https://github.com/AztecProtocol/aztec-packages/tree/master/noir-projects/noir-contracts/contracts). - -### Crate Root - -Every crate has a root, which is the source file that the compiler starts, this is also known as the root module. The Noir compiler does not enforce any conditions on the name of the file which is the crate root, however if you are compiling via Nargo the crate root must be called `lib.nr` or `main.nr` for library or binary crates respectively. - -## Packages - -A Nargo _package_ is a collection of one of more crates that provides a set of functionality. A package must include a Nargo.toml file. - -A package _must_ contain either a library or a binary crate, but not both. - -### Differences from Cargo Packages - -One notable difference between Rust's Cargo and Noir's Nargo is that while Cargo allows a package to contain an unlimited number of binary crates and a single library crate, Nargo currently only allows a package to contain a single crate. - -In future this restriction may be lifted to allow a Nargo package to contain both a binary and library crate or multiple binary crates. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/dependencies.md deleted file mode 100644 index d9d21ef0485..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/dependencies.md +++ /dev/null @@ -1,124 +0,0 @@ ---- -title: Dependencies -description: - Learn how to specify and manage dependencies in Nargo, allowing you to upload packages to GitHub - and use them easily in your project. -keywords: [Nargo, dependencies, GitHub, package management, versioning] -sidebar_position: 1 ---- - -Nargo allows you to upload packages to GitHub and use them as dependencies. - -## Specifying a dependency - -Specifying a dependency requires a tag to a specific commit and the git url to the url containing -the package. - -Currently, there are no requirements on the tag contents. If requirements are added, it would follow -semver 2.0 guidelines. - -> Note: Without a `tag` , there would be no versioning and dependencies would change each time you -> compile your project. - -For example, to add the [ecrecover-noir library](https://github.com/colinnielsen/ecrecover-noir) to your project, add it to `Nargo.toml`: - -```toml -# Nargo.toml - -[dependencies] -ecrecover = {tag = "v0.8.0", git = "https://github.com/colinnielsen/ecrecover-noir"} -``` - -If the module is in a subdirectory, you can define a subdirectory in your git repository, for example: - -```toml -# Nargo.toml - -[dependencies] -easy_private_token_contract = {tag ="v0.1.0-alpha62", git = "https://github.com/AztecProtocol/aztec-packages", directory = "yarn-project/noir-contracts/contracts/easy_private_token_contract"} -``` - -## Specifying a local dependency - -You can also specify dependencies that are local to your machine. - -For example, this file structure has a library and binary crate - -```tree -├── binary_crate -│   ├── Nargo.toml -│   └── src -│   └── main.nr -└── lib_a - ├── Nargo.toml - └── src - └── lib.nr -``` - -Inside of the binary crate, you can specify: - -```toml -# Nargo.toml - -[dependencies] -lib_a = { path = "../lib_a" } -``` - -## Importing dependencies - -You can import a dependency to a Noir file using the following syntax. For example, to import the -ecrecover-noir library and local lib_a referenced above: - -```rust -use dep::ecrecover; -use dep::lib_a; -``` - -You can also import only the specific parts of dependency that you want to use, like so: - -```rust -use dep::std::hash::sha256; -use dep::std::scalar_mul::fixed_base_embedded_curve; -``` - -Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you -can import multiple items in the same line by enclosing them in curly braces: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; -``` - -We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. - -Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. - -## Dependencies of Dependencies - -Note that when you import a dependency, you also get access to all of the dependencies of that package. - -For example, the [phy_vector](https://github.com/resurgencelabs/phy_vector) library imports an [fraction](https://github.com/resurgencelabs/fraction) library. If you're importing the phy_vector library, then you can access the functions in fractions library like so: - -```rust -use dep::phy_vector; - -fn main(x : Field, y : pub Field) { - //... - let f = phy_vector::fraction::toFraction(true, 2, 1); - //... -} -``` - -## Available Libraries - -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). - -Some libraries that are available today include: - -- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library -- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) -- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers -- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address -- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees -- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir -- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/modules.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/modules.md deleted file mode 100644 index ae822a1cff4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/modules.md +++ /dev/null @@ -1,105 +0,0 @@ ---- -title: Modules -description: - Learn how to organize your files using modules in Noir, following the same convention as Rust's - module system. Examples included. -keywords: [Noir, Rust, modules, organizing files, sub-modules] -sidebar_position: 2 ---- - -Noir's module system follows the same convention as the _newer_ version of Rust's module system. - -## Purpose of Modules - -Modules are used to organize files. Without modules all of your code would need to live in a single -file. In Noir, the compiler does not automatically scan all of your files to detect modules. This -must be done explicitly by the developer. - -## Examples - -### Importing a module in the crate root - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::hello_world(); -} -``` - -Filename : `src/foo.nr` - -```rust -fn from_foo() {} -``` - -In the above snippet, the crate root is the `src/main.nr` file. The compiler sees the module -declaration `mod foo` which prompts it to look for a foo.nr file. - -Visually this module hierarchy looks like the following : - -``` -crate - ├── main - │ - └── foo - └── from_foo - -``` - -### Importing a module throughout the tree - -All modules are accessible from the `crate::` namespace. - -``` -crate - ├── bar - ├── foo - └── main - -``` - -In the above snippet, if `bar` would like to use functions in `foo`, it can do so by `use crate::foo::function_name`. - -### Sub-modules - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::from_foo(); -} -``` - -Filename : `src/foo.nr` - -```rust -mod bar; -fn from_foo() {} -``` - -Filename : `src/foo/bar.nr` - -```rust -fn from_bar() {} -``` - -In the above snippet, we have added an extra module to the module tree; `bar`. `bar` is a submodule -of `foo` hence we declare bar in `foo.nr` with `mod bar`. Since `foo` is not the crate root, the -compiler looks for the file associated with the `bar` module in `src/foo/bar.nr` - -Visually the module hierarchy looks as follows: - -``` -crate - ├── main - │ - └── foo - ├── from_foo - └── bar - └── from_bar -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/workspaces.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/workspaces.md deleted file mode 100644 index 513497f12bf..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/workspaces.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Workspaces -sidebar_position: 3 ---- - -Workspaces are a feature of nargo that allow you to manage multiple related Noir packages in a single repository. A workspace is essentially a group of related projects that share common build output directories and configurations. - -Each Noir project (with it's own Nargo.toml file) can be thought of as a package. Each package is expected to contain exactly one "named circuit", being the "name" defined in Nargo.toml with the program logic defined in `./src/main.nr`. - -For a project with the following structure: - -```tree -├── crates -│ ├── a -│ │ ├── Nargo.toml -│ │ └── Prover.toml -│ │ └── src -│ │ └── main.nr -│ └── b -│ ├── Nargo.toml -│ └── Prover.toml -│ └── src -│ └── main.nr -│ -└── Nargo.toml -``` - -You can define a workspace in Nargo.toml like so: - -```toml -[workspace] -members = ["crates/a", "crates/b"] -default-member = "crates/a" -``` - -`members` indicates which packages are included in the workspace. As such, all member packages of a workspace will be processed when the `--workspace` flag is used with various commands or if a `default-member` is not specified. - -`default-member` indicates which package various commands process by default. - -Libraries can be defined in a workspace. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. - -Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/_category_.json deleted file mode 100644 index af04c0933fd..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Standard Library", - "position": 1, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/black_box_fns.md deleted file mode 100644 index e8b62f21d4e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/black_box_fns.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Black Box Functions -description: Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. -keywords: [noir, black box functions] ---- - -Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. This makes certain zk-snark unfriendly computations cheaper than if they were implemented in Noir. - -The ACVM spec defines a set of blackbox functions which backends will be expected to implement. This allows backends to use optimized implementations of these constraints if they have them, however they may also fallback to less efficient naive implementations if not. - -## Function list - -Here is a list of the current black box functions: - -- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) -- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) -- [Blake3](./cryptographic_primitives/hashes.mdx#blake3) -- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash) -- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx) -- AND -- XOR -- RANGE -- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion.md) - -Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. - -You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/noir/blob/master/acvm-repo/acir/src/circuit/black_box_functions.rs). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/cryptographic_primitives/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/cryptographic_primitives/_category_.json deleted file mode 100644 index 5d694210bbf..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/cryptographic_primitives/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 0, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/cryptographic_primitives/ec_primitives.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/cryptographic_primitives/ec_primitives.md deleted file mode 100644 index 8067d38d465..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/cryptographic_primitives/ec_primitives.md +++ /dev/null @@ -1,102 +0,0 @@ ---- -title: Elliptic Curve Primitives -keywords: [cryptographic primitives, Noir project] -sidebar_position: 4 ---- - -Data structures and methods on them that allow you to carry out computations involving elliptic -curves over the (mathematical) field corresponding to `Field`. For the field currently at our -disposal, applications would involve a curve embedded in BN254, e.g. the -[Baby Jubjub curve](https://eips.ethereum.org/EIPS/eip-2494). - -## Data structures - -### Elliptic curve configurations - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Curve`), i.e. the specific elliptic -curve you want to use, which would be specified using any one of the methods -`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::new` which take the coefficients in the -defining equation together with a generator point as parameters. You can find more detail in the -comments in -[`noir_stdlib/src/ec.nr`](https://github.com/noir-lang/noir/blob/v0.23.0/noir_stdlib/src/ec.nr), but -the gist of it is that the elliptic curves of interest are usually expressed in one of the standard -forms implemented here (Twisted Edwards, Montgomery and Short Weierstraß), and in addition to that, -you could choose to use `affine` coordinates (Cartesian coordinates - the usual (x,y) - possibly -together with a point at infinity) or `curvegroup` coordinates (some form of projective coordinates -requiring more coordinates but allowing for more efficient implementations of elliptic curve -operations). Conversions between all of these forms are provided, and under the hood these -conversions are done whenever an operation is more efficient in a different representation (or a -mixed coordinate representation is employed). - -### Points - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Point`), i.e. points lying on the -elliptic curve. For a curve configuration `c` and a point `p`, it may be checked that `p` -does indeed lie on `c` by calling `c.contains(p1)`. - -## Methods - -(given a choice of curve representation, e.g. use `std::ec::tecurve::affine::Curve` and use -`std::ec::tecurve::affine::Point`) - -- The **zero element** is given by `Point::zero()`, and we can verify whether a point `p: Point` is - zero by calling `p.is_zero()`. -- **Equality**: Points `p1: Point` and `p2: Point` may be checked for equality by calling - `p1.eq(p2)`. -- **Addition**: For `c: Curve` and points `p1: Point` and `p2: Point` on the curve, adding these two - points is accomplished by calling `c.add(p1,p2)`. -- **Negation**: For a point `p: Point`, `p.negate()` is its negation. -- **Subtraction**: For `c` and `p1`, `p2` as above, subtracting `p2` from `p1` is accomplished by - calling `c.subtract(p1,p2)`. -- **Scalar multiplication**: For `c` as above, `p: Point` a point on the curve and `n: Field`, - scalar multiplication is given by `c.mul(n,p)`. If instead `n :: [u1; N]`, i.e. `n` is a bit - array, the `bit_mul` method may be used instead: `c.bit_mul(n,p)` -- **Multi-scalar multiplication**: For `c` as above and arrays `n: [Field; N]` and `p: [Point; N]`, - multi-scalar multiplication is given by `c.msm(n,p)`. -- **Coordinate representation conversions**: The `into_group` method converts a point or curve - configuration in the affine representation to one in the CurveGroup representation, and - `into_affine` goes in the other direction. -- **Curve representation conversions**: `tecurve` and `montcurve` curves and points are equivalent - and may be converted between one another by calling `into_montcurve` or `into_tecurve` on their - configurations or points. `swcurve` is more general and a curve c of one of the other two types - may be converted to this representation by calling `c.into_swcurve()`, whereas a point `p` lying - on the curve given by `c` may be mapped to its corresponding `swcurve` point by calling - `c.map_into_swcurve(p)`. -- **Map-to-curve methods**: The Elligator 2 method of mapping a field element `n: Field` into a - `tecurve` or `montcurve` with configuration `c` may be called as `c.elligator2_map(n)`. For all of - the curve configurations, the SWU map-to-curve method may be called as `c.swu_map(z,n)`, where - `z: Field` depends on `Field` and `c` and must be chosen by the user (the conditions it needs to - satisfy are specified in the comments - [here](https://github.com/noir-lang/noir/blob/v0.23.0/noir_stdlib/src/ec.nr). - -## Examples - -The -[ec_baby_jubjub test](https://github.com/noir-lang/noir/blob/master/test_programs/compile_success_empty/ec_baby_jubjub/src/main.nr) -illustrates all of the above primitives on various forms of the Baby Jubjub curve. A couple of more -interesting examples in Noir would be: - -Public-key cryptography: Given an elliptic curve and a 'base point' on it, determine the public key -from the private key. This is a matter of using scalar multiplication. In the case of Baby Jubjub, -for example, this code would do: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; - -fn bjj_pub_key(priv_key: Field) -> Point -{ - - let bjj = Curve::new(168700, 168696, G::new(995203441582195749578291179787384436505546430278305826713579947235728471134,5472060717959818805561601436314318772137091100104008585924551046643952123905)); - - let base_pt = Point::new(5299619240641551281634865583518297030282874472190772894086521144482721001553, 16950150798460657717958625567821834550301663161624707787222815936182638968203); - - bjj.mul(priv_key,base_pt) -} -``` - -This would come in handy in a Merkle proof. - -- EdDSA signature verification: This is a matter of combining these primitives with a suitable hash - function. See - [feat(stdlib): EdDSA sig verification noir#1136](https://github.com/noir-lang/noir/pull/1136) for - the case of Baby Jubjub and the Poseidon hash function. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx deleted file mode 100644 index 4bf09cef178..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx +++ /dev/null @@ -1,60 +0,0 @@ ---- -title: ECDSA Signature Verification -description: Learn about the cryptographic primitives regarding ECDSA over the secp256k1 and secp256r1 curves -keywords: [cryptographic primitives, Noir project, ecdsa, secp256k1, secp256r1, signatures] -sidebar_position: 3 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -Noir supports ECDSA signatures verification over the secp256k1 and secp256r1 curves. - -## ecdsa_secp256k1::verify_signature - -Verifier for ECDSA Secp256k1 signatures - -```rust title="ecdsa_secp256k1" showLineNumbers -pub fn verify_signature( - public_key_x: [u8; 32], - public_key_y: [u8; 32], - signature: [u8; 64], - message_hash: [u8; N] -) -> bool -``` -> Source code: noir_stdlib/src/ecdsa_secp256k1.nr#L2-L9 - - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - -## ecdsa_secp256r1::verify_signature - -Verifier for ECDSA Secp256r1 signatures - -```rust title="ecdsa_secp256r1" showLineNumbers -pub fn verify_signature( - public_key_x: [u8; 32], - public_key_y: [u8; 32], - signature: [u8; 64], - message_hash: [u8; N] -) -> bool -``` -> Source code: noir_stdlib/src/ecdsa_secp256r1.nr#L2-L9 - - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/cryptographic_primitives/eddsa.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/cryptographic_primitives/eddsa.mdx deleted file mode 100644 index a9c10da6c06..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/cryptographic_primitives/eddsa.mdx +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: EdDSA Verification -description: Learn about the cryptographic primitives regarding EdDSA -keywords: [cryptographic primitives, Noir project, eddsa, signatures] -sidebar_position: 5 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## eddsa::eddsa_poseidon_verify - -Verifier for EdDSA signatures - -```rust -fn eddsa_poseidon_verify(public_key_x : Field, public_key_y : Field, signature_s: Field, signature_r8_x: Field, signature_r8_y: Field, message: Field) -> bool -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/cryptographic_primitives/hashes.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/cryptographic_primitives/hashes.mdx deleted file mode 100644 index 730b6d4117f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/cryptographic_primitives/hashes.mdx +++ /dev/null @@ -1,234 +0,0 @@ ---- -title: Hash methods -description: - Learn about the cryptographic primitives ready to use for any Noir project, including sha256, - blake2s, pedersen, mimc_bn254 and mimc -keywords: - [cryptographic primitives, Noir project, sha256, blake2s, pedersen, mimc_bn254, mimc, hash] -sidebar_position: 0 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## sha256 - -Given an array of bytes, returns the resulting sha256 hash. - -```rust title="sha256" showLineNumbers -pub fn sha256(input: [u8; N]) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L5-L7 - - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::sha256(x); -} -``` - - - -## blake2s - -Given an array of bytes, returns an array with the Blake2 hash - -```rust title="blake2s" showLineNumbers -pub fn blake2s(input: [u8; N]) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L11-L13 - - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::blake2s(x); -} -``` - - - -## blake3 - -Given an array of bytes, returns an array with the Blake3 hash - -```rust title="blake3" showLineNumbers -pub fn blake3(input: [u8; N]) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L17-L19 - - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::blake3(x); -} -``` - - - -## pedersen_hash - -Given an array of Fields, returns the Pedersen hash. - -```rust title="pedersen_hash" showLineNumbers -pub fn pedersen_hash(input: [Field; N]) -> Field -``` -> Source code: noir_stdlib/src/hash.nr#L42-L44 - - -example: - -```rust title="pedersen-hash" showLineNumbers -use dep::std; - -fn main(x: Field, y: Field, expected_hash: Field) { - let hash = std::hash::pedersen_hash([x, y]); - assert_eq(hash, expected_hash); -} -``` -> Source code: test_programs/execution_success/pedersen_hash/src/main.nr#L1-L8 - - - - - -## pedersen_commitment - -Given an array of Fields, returns the Pedersen commitment. - -```rust title="pedersen_commitment" showLineNumbers -struct PedersenPoint { - x : Field, - y : Field, -} - -pub fn pedersen_commitment(input: [Field; N]) -> PedersenPoint -``` -> Source code: noir_stdlib/src/hash.nr#L22-L29 - - -example: - -```rust title="pedersen-commitment" showLineNumbers -use dep::std; - -fn main(x: Field, y: Field, expected_commitment: std::hash::PedersenPoint) { - let commitment = std::hash::pedersen_commitment([x, y]); - assert_eq(commitment.x, expected_commitment.x); - assert_eq(commitment.y, expected_commitment.y); -} -``` -> Source code: test_programs/execution_success/pedersen_commitment/src/main.nr#L1-L9 - - - - -## keccak256 - -Given an array of bytes (`u8`), returns the resulting keccak hash as an array of 32 bytes -(`[u8; 32]`). Specify a message_size to hash only the first `message_size` bytes -of the input. - -```rust title="keccak256" showLineNumbers -pub fn keccak256(input: [u8; N], message_size: u32) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L67-L69 - - -example: - -```rust title="keccak256" showLineNumbers -use dep::std; - -fn main(x: Field, result: [u8; 32]) { - // We use the `as` keyword here to denote the fact that we want to take just the first byte from the x Field - // The padding is taken care of by the program - let digest = std::hash::keccak256([x as u8], 1); - assert(digest == result); - - //#1399: variable message size - let message_size = 4; - let hash_a = std::hash::keccak256([1, 2, 3, 4], message_size); - let hash_b = std::hash::keccak256([1, 2, 3, 4, 0, 0, 0, 0], message_size); - - assert(hash_a == hash_b); - - let message_size_big = 8; - let hash_c = std::hash::keccak256([1, 2, 3, 4, 0, 0, 0, 0], message_size_big); - - assert(hash_a != hash_c); -} -``` -> Source code: test_programs/execution_success/keccak256/src/main.nr#L1-L22 - - - - -## poseidon - -Given an array of Fields, returns a new Field with the Poseidon Hash. Mind that you need to specify -how many inputs are there to your Poseidon function. - -```rust -// example for hash_1, hash_2 accepts an array of length 2, etc -fn hash_1(input: [Field; 1]) -> Field -``` - -example: - -```rust title="poseidon" showLineNumbers -use dep::std::hash::poseidon; - -fn main(x1: [Field; 2], y1: pub Field, x2: [Field; 4], y2: pub Field) { - let hash1 = poseidon::bn254::hash_2(x1); - assert(hash1 == y1); - - let hash2 = poseidon::bn254::hash_4(x2); - assert(hash2 == y2); -} -``` -> Source code: test_programs/execution_success/poseidon_bn254_hash/src/main.nr#L1-L11 - - -## mimc_bn254 and mimc - -`mimc_bn254` is `mimc`, but with hardcoded parameters for the BN254 curve. You can use it by -providing an array of Fields, and it returns a Field with the hash. You can use the `mimc` method if -you're willing to input your own constants: - -```rust -fn mimc(x: Field, k: Field, constants: [Field; N], exp : Field) -> Field -``` - -otherwise, use the `mimc_bn254` method: - -```rust -fn mimc_bn254(array: [Field; N]) -> Field -``` - -example: - -```rust - -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::mimc::mimc_bn254(x); -} -``` - -## hash_to_field - -```rust -fn hash_to_field(_input : [Field; N]) -> Field {} -``` - -Calculates the `blake2s` hash of the inputs and returns the hash modulo the field modulus to return -a value which can be represented as a `Field`. - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/cryptographic_primitives/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/cryptographic_primitives/index.md deleted file mode 100644 index 650f30165d5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/cryptographic_primitives/index.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Cryptographic Primitives -description: - Learn about the cryptographic primitives ready to use for any Noir project -keywords: - [ - cryptographic primitives, - Noir project, - ] ---- - -The Noir team is progressively adding new cryptographic primitives to the standard library. Reach out for news or if you would be interested in adding more of these calculations in Noir. - -Some methods are available thanks to the Aztec backend, not being performed using Noir. When using other backends, these methods may or may not be supplied. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/cryptographic_primitives/scalar.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/cryptographic_primitives/scalar.mdx deleted file mode 100644 index df411ca5443..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/cryptographic_primitives/scalar.mdx +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Scalar multiplication -description: See how you can perform scalar multiplications over a fixed base in Noir -keywords: [cryptographic primitives, Noir project, scalar multiplication] -sidebar_position: 1 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## scalar_mul::fixed_base_embedded_curve - -Performs scalar multiplication over the embedded curve whose coordinates are defined by the -configured noir field. For the BN254 scalar field, this is BabyJubJub or Grumpkin. - -```rust title="fixed_base_embedded_curve" showLineNumbers -pub fn fixed_base_embedded_curve( - low: Field, - high: Field -) -> [Field; 2] -``` -> Source code: noir_stdlib/src/scalar_mul.nr#L27-L32 - - -example - -```rust -fn main(x : Field) { - let scal = std::scalar_mul::fixed_base_embedded_curve(x); - println(scal); -} -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/cryptographic_primitives/schnorr.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/cryptographic_primitives/schnorr.mdx deleted file mode 100644 index ae12e6c12dc..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/cryptographic_primitives/schnorr.mdx +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Schnorr Signatures -description: Learn how you can verify Schnorr signatures using Noir -keywords: [cryptographic primitives, Noir project, schnorr, signatures] -sidebar_position: 2 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## schnorr::verify_signature - -Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin). - -```rust title="schnorr_verify" showLineNumbers -pub fn verify_signature( - public_key_x: Field, - public_key_y: Field, - signature: [u8; 64], - message: [u8; N] -) -> bool -``` -> Source code: noir_stdlib/src/schnorr.nr#L2-L9 - - -where `_signature` can be generated like so using the npm package -[@noir-lang/barretenberg](https://www.npmjs.com/package/@noir-lang/barretenberg) - -```js -const { BarretenbergWasm } = require('@noir-lang/barretenberg/dest/wasm'); -const { Schnorr } = require('@noir-lang/barretenberg/dest/crypto/schnorr'); - -... - -const barretenberg = await BarretenbergWasm.new(); -const schnorr = new Schnorr(barretenberg); -const pubKey = schnorr.computePublicKey(privateKey); -const message = ... -const signature = Array.from( - schnorr.constructSignature(hash, privateKey).toBuffer() -); - -... -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/merkle_trees.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/merkle_trees.md deleted file mode 100644 index fa488677884..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/merkle_trees.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: Merkle Trees -description: Learn about Merkle Trees in Noir with this tutorial. Explore the basics of computing a merkle root using a proof, with examples. -keywords: - [ - Merkle trees in Noir, - Noir programming language, - check membership, - computing root from leaf, - Noir Merkle tree implementation, - Merkle tree tutorial, - Merkle tree code examples, - Noir libraries, - pedersen hash., - ] ---- - -## compute_merkle_root - -Returns the root of the tree from the provided leaf and its hash path, using a [Pedersen hash](./cryptographic_primitives/hashes.mdx#pedersen_hash). - -```rust -fn compute_merkle_root(leaf : Field, index : Field, hash_path: [Field]) -> Field -``` - -example: - -```rust -/** - // these values are for this example only - index = "0" - priv_key = "0x000000000000000000000000000000000000000000000000000000616c696365" - secret = "0x1929ea3ab8d9106a899386883d9428f8256cfedb3c4f6b66bf4aa4d28a79988f" - note_hash_path = [ - "0x1e61bdae0f027b1b2159e1f9d3f8d00fa668a952dddd822fda80dc745d6f65cc", - "0x0e4223f3925f98934393c74975142bd73079ab0621f4ee133cee050a3c194f1a", - "0x2fd7bb412155bf8693a3bd2a3e7581a679c95c68a052f835dddca85fa1569a40" - ] - */ -fn main(index: Field, priv_key: Field, secret: Field, note_hash_path: [Field; 3]) { - - let pubkey = std::scalar_mul::fixed_base_embedded_curve(priv_key); - let pubkey_x = pubkey[0]; - let pubkey_y = pubkey[1]; - let note_commitment = std::hash::pedersen([pubkey_x, pubkey_y, secret]); - - let root = std::merkle::compute_merkle_root(note_commitment[0], index, note_hash_path); - println(root); -} -``` - -To check merkle tree membership: - -1. Include a merkle root as a program input. -2. Compute the merkle root of a given leaf, index and hash path. -3. Assert the merkle roots are equal. - -For more info about merkle trees, see the Wikipedia [page](https://en.wikipedia.org/wiki/Merkle_tree). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/options.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/options.md deleted file mode 100644 index 970c9cfbf11..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/options.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -title: Option Type ---- - -The `Option` type is a way to express that a value might be present (`Some(T))` or absent (`None`). It's a safer way to handle potential absence of values, compared to using nulls in many other languages. - -```rust -struct Option { - None, - Some(T), -} -``` - -The `Option` type, already imported into your Noir program, can be used directly: - -```rust -fn main() { - let none = Option::none(); - let some = Option::some(3); -} -``` - -See [this test](https://github.com/noir-lang/noir/blob/5cbfb9c4a06c8865c98ff2b594464b037d821a5c/crates/nargo_cli/tests/test_data/option/src/main.nr) for a more comprehensive set of examples of each of the methods described below. - -## Methods - -### none - -Constructs a none value. - -### some - -Constructs a some wrapper around a given value. - -### is_none - -Returns true if the Option is None. - -### is_some - -Returns true of the Option is Some. - -### unwrap - -Asserts `self.is_some()` and returns the wrapped value. - -### unwrap_unchecked - -Returns the inner value without asserting `self.is_some()`. This method can be useful within an if condition when we already know that `option.is_some()`. If the option is None, there is no guarantee what value will be returned, only that it will be of type T for an `Option`. - -### unwrap_or - -Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value. - -### unwrap_or_else - -Returns the wrapped value if `self.is_some()`. Otherwise, calls the given function to return a default value. - -### map - -If self is `Some(x)`, this returns `Some(f(x))`. Otherwise, this returns `None`. - -### map_or - -If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns the given default value. - -### map_or_else - -If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns `default()`. - -### and - -Returns None if self is None. Otherwise, this returns `other`. - -### and_then - -If self is None, this returns None. Otherwise, this calls the given function with the Some value contained within self, and returns the result of that call. In some languages this function is called `flat_map` or `bind`. - -### or - -If self is Some, return self. Otherwise, return `other`. - -### or_else - -If self is Some, return self. Otherwise, return `default()`. - -### xor - -If only one of the two Options is Some, return that option. Otherwise, if both options are Some or both are None, None is returned. - -### filter - -Returns `Some(x)` if self is `Some(x)` and `predicate(x)` is true. Otherwise, this returns `None`. - -### flatten - -Flattens an `Option>` into a `Option`. This returns `None` if the outer Option is None. Otherwise, this returns the inner Option. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/recursion.md deleted file mode 100644 index 4390bda4a26..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/recursion.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -title: Recursive Proofs -description: Learn about how to write recursive proofs in Noir. -keywords: [recursion, recursive proofs, verification_key, verify_proof] ---- - -Noir supports recursively verifying proofs, meaning you verify the proof of a Noir program in another Noir program. This enables creating proofs of arbitrary size by doing step-wise verification of smaller components of a large proof. - -Read [the explainer on recursion](../../explainers/explainer-recursion.md) to know more about this function and the [guide on how to use it.](../../how_to/how-to-recursion.md) - -```rust -#[foreign(verify_proof)] -fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : Field, _key_hash : Field) {} -``` - -:::info - -This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. - -::: - -## Example usage - -```rust -use dep::std; - -fn main( - verification_key : [Field; 114], - proof : [Field; 93], - public_inputs : [Field; 1], - key_hash : Field, - proof_b : [Field; 93], -) { - std::verify_proof( - verification_key.as_slice(), - proof.as_slice(), - public_inputs.as_slice(), - key_hash - ); - - std::verify_proof( - verification_key.as_slice(), - proof_b.as_slice(), - public_inputs.as_slice(), - key_hash - ); -} -``` - -You can see a full example of recursive proofs in [this example recursion demo repo](https://github.com/noir-lang/noir-examples/tree/master/recursion). - -## Parameters - -### `verification_key` - -The verification key for the zk program that is being verified. - -### `proof` - -The proof for the zk program that is being verified. - -### `public_inputs` - -These represent the public inputs of the proof we are verifying. - -### `key_hash` - -A key hash is used to check the validity of the verification key. The circuit implementing this opcode can use this hash to ensure that the key provided to the circuit matches the key produced by the circuit creator. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/traits.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/traits.md deleted file mode 100644 index f2960ca5080..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/traits.md +++ /dev/null @@ -1,284 +0,0 @@ ---- -title: Traits -description: Noir's stdlib provides a few commonly used traits. -keywords: [traits, trait, interface, protocol, default, add, eq] ---- - -## `std::default` - -### `std::default::Default` - -```rust -trait Default { - fn default() -> Self; -} -``` - -Constructs a default value of a type. - -Implementations: -```rust -impl Default for Field { .. } - -impl Default for i8 { .. } -impl Default for i16 { .. } -impl Default for i32 { .. } -impl Default for i64 { .. } - -impl Default for u8 { .. } -impl Default for u16 { .. } -impl Default for u32 { .. } -impl Default for u64 { .. } - -impl Default for () { .. } -impl Default for bool { .. } - -impl Default for [T; N] - where T: Default { .. } - -impl Default for (A, B) - where A: Default, B: Default { .. } - -impl Default for (A, B, C) - where A: Default, B: Default, C: Default { .. } - -impl Default for (A, B, C, D) - where A: Default, B: Default, C: Default, D: Default { .. } - -impl Default for (A, B, C, D, E) - where A: Default, B: Default, C: Default, D: Default, E: Default { .. } -``` - -For primitive integer types, the return value of `default` is `0`. Container -types such as arrays are filled with default values of their element type. - -## `std::cmp` - -### `std::cmp::Eq` - -```rust -trait Eq { - fn eq(self, other: Self) -> bool; -} -``` -Returns `true` if `self` is equal to `other`. Implementing this trait on a type -allows the type to be used with `==` and `!=`. - -Implementations: -```rust -impl Eq for Field { .. } - -impl Eq for i8 { .. } -impl Eq for i16 { .. } -impl Eq for i32 { .. } -impl Eq for i64 { .. } - -impl Eq for u8 { .. } -impl Eq for u16 { .. } -impl Eq for u32 { .. } -impl Eq for u64 { .. } - -impl Eq for () { .. } -impl Eq for bool { .. } - -impl Eq for [T; N] - where T: Eq { .. } - -impl Eq for (A, B) - where A: Eq, B: Eq { .. } - -impl Eq for (A, B, C) - where A: Eq, B: Eq, C: Eq { .. } - -impl Eq for (A, B, C, D) - where A: Eq, B: Eq, C: Eq, D: Eq { .. } - -impl Eq for (A, B, C, D, E) - where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq { .. } -``` - -### `std::cmp::Cmp` - -```rust -trait Cmp { - fn cmp(self, other: Self) -> Ordering; -} -``` - -`a.cmp(b)` compares two values returning `Ordering::less()` if `a < b`, -`Ordering::equal()` if `a == b`, or `Ordering::greater()` if `a > b`. -Implementing this trait on a type allows `<`, `<=`, `>`, and `>=` to be -used on values of the type. - -Implementations: - -```rust -impl Ord for u8 { .. } -impl Ord for u16 { .. } -impl Ord for u32 { .. } -impl Ord for u64 { .. } - -impl Ord for i8 { .. } -impl Ord for i16 { .. } -impl Ord for i32 { .. } - -impl Ord for i64 { .. } - -impl Ord for () { .. } -impl Ord for bool { .. } - -impl Ord for [T; N] - where T: Ord { .. } - -impl Ord for (A, B) - where A: Ord, B: Ord { .. } - -impl Ord for (A, B, C) - where A: Ord, B: Ord, C: Ord { .. } - -impl Ord for (A, B, C, D) - where A: Ord, B: Ord, C: Ord, D: Ord { .. } - -impl Ord for (A, B, C, D, E) - where A: Ord, B: Ord, C: Ord, D: Ord, E: Ord { .. } -``` - -## `std::ops` - -### `std::ops::Add`, `std::ops::Sub`, `std::ops::Mul`, and `std::ops::Div` - -These traits abstract over addition, subtraction, multiplication, and division respectively. -Implementing these traits for a given type will also allow that type to be used with the corresponding operator -for that trait (`+` for Add, etc) in addition to the normal method names. - -```rust -trait Add { - fn add(self, other: Self) -> Self; -} - -trait Sub { - fn sub(self, other: Self) -> Self; -} - -trait Mul { - fn mul(self, other: Self) -> Self; -} - -trait Div { - fn div(self, other: Self) -> Self; -} -``` - -The implementations block below is given for the `Add` trait, but the same types that implement -`Add` also implement `Sub`, `Mul`, and `Div`. - -Implementations: -```rust -impl Add for Field { .. } - -impl Add for i8 { .. } -impl Add for i16 { .. } -impl Add for i32 { .. } -impl Add for i64 { .. } - -impl Add for u8 { .. } -impl Add for u16 { .. } -impl Add for u32 { .. } -impl Add for u64 { .. } -``` - -### `std::ops::Rem` - -```rust -trait Rem { - fn rem(self, other: Self) -> Self; -} -``` - -`Rem::rem(a, b)` is the remainder function returning the result of what is -left after dividing `a` and `b`. Implementing `Rem` allows the `%` operator -to be used with the implementation type. - -Unlike other numeric traits, `Rem` is not implemented for `Field`. - -Implementations: -```rust -impl Rem for u8 { fn rem(self, other: u8) -> u8 { self % other } } -impl Rem for u16 { fn rem(self, other: u16) -> u16 { self % other } } -impl Rem for u32 { fn rem(self, other: u32) -> u32 { self % other } } -impl Rem for u64 { fn rem(self, other: u64) -> u64 { self % other } } - -impl Rem for i8 { fn rem(self, other: i8) -> i8 { self % other } } -impl Rem for i16 { fn rem(self, other: i16) -> i16 { self % other } } -impl Rem for i32 { fn rem(self, other: i32) -> i32 { self % other } } -impl Rem for i64 { fn rem(self, other: i64) -> i64 { self % other } } -``` - -### `std::ops::{ BitOr, BitAnd, BitXor }` - -```rust -trait BitOr { - fn bitor(self, other: Self) -> Self; -} - -trait BitAnd { - fn bitand(self, other: Self) -> Self; -} - -trait BitXor { - fn bitxor(self, other: Self) -> Self; -} -``` - -Traits for the bitwise operations `|`, `&`, and `^`. - -Implementing `BitOr`, `BitAnd` or `BitXor` for a type allows the `|`, `&`, or `^` operator respectively -to be used with the type. - -The implementations block below is given for the `BitOr` trait, but the same types that implement -`BitOr` also implement `BitAnd` and `BitXor`. - -Implementations: -```rust -impl BitOr for bool { fn bitor(self, other: bool) -> bool { self | other } } - -impl BitOr for u8 { fn bitor(self, other: u8) -> u8 { self | other } } -impl BitOr for u16 { fn bitor(self, other: u16) -> u16 { self | other } } -impl BitOr for u32 { fn bitor(self, other: u32) -> u32 { self | other } } -impl BitOr for u64 { fn bitor(self, other: u64) -> u64 { self | other } } - -impl BitOr for i8 { fn bitor(self, other: i8) -> i8 { self | other } } -impl BitOr for i16 { fn bitor(self, other: i16) -> i16 { self | other } } -impl BitOr for i32 { fn bitor(self, other: i32) -> i32 { self | other } } -impl BitOr for i64 { fn bitor(self, other: i64) -> i64 { self | other } } -``` - -### `std::ops::{ Shl, Shr }` - -```rust -trait Shl { - fn shl(self, other: Self) -> Self; -} - -trait Shr { - fn shr(self, other: Self) -> Self; -} -``` - -Traits for a bit shift left and bit shift right. - -Implementing `Shl` for a type allows the left shift operator (`<<`) to be used with the implementation type. -Similarly, implementing `Shr` allows the right shift operator (`>>`) to be used with the type. - -Note that bit shifting is not currently implemented for signed types. - -The implementations block below is given for the `Shl` trait, but the same types that implement -`Shl` also implement `Shr`. - -Implementations: -```rust -impl Shl for u8 { fn shl(self, other: u8) -> u8 { self << other } } -impl Shl for u16 { fn shl(self, other: u16) -> u16 { self << other } } -impl Shl for u32 { fn shl(self, other: u32) -> u32 { self << other } } -impl Shl for u64 { fn shl(self, other: u64) -> u64 { self << other } } -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/zeroed.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/zeroed.md deleted file mode 100644 index 97dab02dac2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/zeroed.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: Zeroed Function -description: - The zeroed function returns a zeroed value of any type. -keywords: - [ - zeroed - ] ---- - -Implements `fn zeroed() -> T` to return a zeroed value of any type. This function is generally unsafe to use as the zeroed bit pattern is not guaranteed to be valid for all types. It can however, be useful in cases when the value is guaranteed not to be used such as in a BoundedVec library implementing a growable vector, up to a certain length, backed by an array. The array can be initialized with zeroed values which are guaranteed to be inaccessible until the vector is pushed to. Similarly, enumerations in noir can be implemented using this method by providing zeroed values for the unused variants. - -You can access the function at `std::unsafe::zeroed`. - -This function currently supports the following types: - -- Field -- Bool -- Uint -- Array -- String -- Tuple -- Function - -Using it on other types could result in unexpected behavior. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/backend_barretenberg/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/backend_barretenberg/.nojekyll deleted file mode 100644 index e2ac6616add..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/backend_barretenberg/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/backend_barretenberg/classes/BarretenbergBackend.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/backend_barretenberg/classes/BarretenbergBackend.md deleted file mode 100644 index 5cbe9421b92..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/backend_barretenberg/classes/BarretenbergBackend.md +++ /dev/null @@ -1,185 +0,0 @@ -# BarretenbergBackend - -## Implements - -- [`Backend`](../interfaces/Backend.md) - -## Constructors - -### new BarretenbergBackend(acirCircuit, options) - -```ts -new BarretenbergBackend(acirCircuit, options): BarretenbergBackend -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `acirCircuit` | [`CompiledCircuit`](../type-aliases/CompiledCircuit.md) | -| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | - -#### Returns - -[`BarretenbergBackend`](BarretenbergBackend.md) - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`destroy`](../interfaces/Backend.md#destroy) - -#### Description - -Destroys the backend - -*** - -### generateFinalProof() - -```ts -generateFinalProof(decompressedWitness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `decompressedWitness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`generateFinalProof`](../interfaces/Backend.md#generatefinalproof) - -#### Description - -Generates a final proof (not meant to be verified in another circuit) - -*** - -### generateIntermediateProof() - -```ts -generateIntermediateProof(witness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `witness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`generateIntermediateProof`](../interfaces/Backend.md#generateintermediateproof) - -#### Example - -```typescript -const intermediateProof = await backend.generateIntermediateProof(witness); -``` - -*** - -### generateIntermediateProofArtifacts() - -```ts -generateIntermediateProofArtifacts(proofData, numOfPublicInputs): Promise -``` - -#### Parameters - -| Parameter | Type | Default value | -| :------ | :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | `undefined` | -| `numOfPublicInputs` | `number` | `0` | - -#### Returns - -`Promise`\<`object`\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`generateIntermediateProofArtifacts`](../interfaces/Backend.md#generateintermediateproofartifacts) - -#### Example - -```typescript -const artifacts = await backend.generateIntermediateProofArtifacts(proof, numOfPublicInputs); -``` - -*** - -### verifyFinalProof() - -```ts -verifyFinalProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`verifyFinalProof`](../interfaces/Backend.md#verifyfinalproof) - -#### Description - -Verifies a final proof - -*** - -### verifyIntermediateProof() - -```ts -verifyIntermediateProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`verifyIntermediateProof`](../interfaces/Backend.md#verifyintermediateproof) - -#### Example - -```typescript -const isValidIntermediate = await backend.verifyIntermediateProof(proof); -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/backend_barretenberg/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/backend_barretenberg/index.md deleted file mode 100644 index 93b248b0f65..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/backend_barretenberg/index.md +++ /dev/null @@ -1,45 +0,0 @@ -# Backend Barretenberg - -## Exports - -### Classes - -| Class | Description | -| :------ | :------ | -| [BarretenbergBackend](classes/BarretenbergBackend.md) | - | - -### Interfaces - -| Interface | Description | -| :------ | :------ | -| [Backend](interfaces/Backend.md) | - | - -### Type Aliases - -| Type alias | Description | -| :------ | :------ | -| [BackendOptions](type-aliases/BackendOptions.md) | - | -| [CompiledCircuit](type-aliases/CompiledCircuit.md) | - | -| [ProofData](type-aliases/ProofData.md) | - | - -## Functions - -### flattenPublicInputs() - -```ts -flattenPublicInputs(publicInputs): string[] -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `publicInputs` | `WitnessMap` | - -#### Returns - -`string`[] - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/backend_barretenberg/interfaces/Backend.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/backend_barretenberg/interfaces/Backend.md deleted file mode 100644 index 3eb9645c8d2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/backend_barretenberg/interfaces/Backend.md +++ /dev/null @@ -1,132 +0,0 @@ -# Backend - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Description - -Destroys the backend - -*** - -### generateFinalProof() - -```ts -generateFinalProof(decompressedWitness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `decompressedWitness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Description - -Generates a final proof (not meant to be verified in another circuit) - -*** - -### generateIntermediateProof() - -```ts -generateIntermediateProof(decompressedWitness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `decompressedWitness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Description - -Generates an intermediate proof (meant to be verified in another circuit) - -*** - -### generateIntermediateProofArtifacts() - -```ts -generateIntermediateProofArtifacts(proofData, numOfPublicInputs): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | -| `numOfPublicInputs` | `number` | - -#### Returns - -`Promise`\<`object`\> - -#### Description - -Retrieves the artifacts from a proof in the Field format - -*** - -### verifyFinalProof() - -```ts -verifyFinalProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Verifies a final proof - -*** - -### verifyIntermediateProof() - -```ts -verifyIntermediateProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Verifies an intermediate proof - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/backend_barretenberg/type-aliases/BackendOptions.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/backend_barretenberg/type-aliases/BackendOptions.md deleted file mode 100644 index 266ade75d17..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/backend_barretenberg/type-aliases/BackendOptions.md +++ /dev/null @@ -1,19 +0,0 @@ -# BackendOptions - -```ts -type BackendOptions: object; -``` - -## Description - -An options object, currently only used to specify the number of threads to use. - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `threads` | `number` | **Description**

Number of threads | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit.md deleted file mode 100644 index 34e0dd04205..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit.md +++ /dev/null @@ -1,20 +0,0 @@ -# CompiledCircuit - -```ts -type CompiledCircuit: object; -``` - -## Description - -The representation of a compiled circuit - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `abi` | `Abi` | **Description**

ABI representation of the circuit | -| `bytecode` | `string` | **Description**

The bytecode of the circuit | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/backend_barretenberg/type-aliases/ProofData.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/backend_barretenberg/type-aliases/ProofData.md deleted file mode 100644 index 3eb360a78f1..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/backend_barretenberg/type-aliases/ProofData.md +++ /dev/null @@ -1,20 +0,0 @@ -# ProofData - -```ts -type ProofData: object; -``` - -## Description - -The representation of a proof - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `proof` | `Uint8Array` | **Description**

An byte array representing the proof | -| `publicInputs` | `WitnessMap` | **Description**

Public inputs of a proof | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs deleted file mode 100644 index 04e662c845f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"noir_js/reference/backend_barretenberg/classes/BarretenbergBackend","label":"BarretenbergBackend"}]},{"type":"category","label":"Interfaces","items":[{"type":"doc","id":"noir_js/reference/backend_barretenberg/interfaces/Backend","label":"Backend"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"noir_js/reference/backend_barretenberg/type-aliases/BackendOptions","label":"BackendOptions"},{"type":"doc","id":"noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit","label":"CompiledCircuit"},{"type":"doc","id":"noir_js/reference/backend_barretenberg/type-aliases/ProofData","label":"ProofData"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/.nojekyll deleted file mode 100644 index e2ac6616add..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/classes/Noir.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/classes/Noir.md deleted file mode 100644 index c54468891af..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/classes/Noir.md +++ /dev/null @@ -1,131 +0,0 @@ -# Noir - -## Constructors - -### new Noir(circuit, backend) - -```ts -new Noir(circuit, backend?): Noir -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `circuit` | [`CompiledCircuit`](../type-aliases/CompiledCircuit.md) | -| `backend`? | `Backend` | - -#### Returns - -[`Noir`](Noir.md) - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Description - -Destroys the underlying backend instance. - -#### Example - -```typescript -await noir.destroy(); -``` - -*** - -### execute() - -```ts -execute(inputs, foreignCallHandler?): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `inputs` | [`InputMap`](../type-aliases/InputMap.md) | -| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | - -#### Returns - -`Promise`\<`object`\> - -#### Description - -Allows to execute a circuit to get its witness and return value. - -#### Example - -```typescript -async execute(inputs) -``` - -*** - -### generateFinalProof() - -```ts -generateFinalProof(inputs): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `inputs` | [`InputMap`](../type-aliases/InputMap.md) | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Description - -Generates a witness and a proof given an object as input. - -#### Example - -```typescript -async generateFinalProof(input) -``` - -*** - -### verifyFinalProof() - -```ts -verifyFinalProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Instantiates the verification key and verifies a proof. - -#### Example - -```typescript -async verifyFinalProof(proof) -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/functions/and.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/functions/and.md deleted file mode 100644 index c783283e396..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/functions/and.md +++ /dev/null @@ -1,22 +0,0 @@ -# and() - -```ts -and(lhs, rhs): string -``` - -Performs a bitwise AND operation between `lhs` and `rhs` - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `lhs` | `string` | | -| `rhs` | `string` | | - -## Returns - -`string` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/functions/blake2s256.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/functions/blake2s256.md deleted file mode 100644 index 7882d0da8d5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/functions/blake2s256.md +++ /dev/null @@ -1,21 +0,0 @@ -# blake2s256() - -```ts -blake2s256(inputs): Uint8Array -``` - -Calculates the Blake2s256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify.md deleted file mode 100644 index 0ba5783f0d5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify.md +++ /dev/null @@ -1,29 +0,0 @@ -# ecdsa\_secp256k1\_verify() - -```ts -ecdsa_secp256k1_verify( - hashed_msg, - public_key_x_bytes, - public_key_y_bytes, - signature): boolean -``` - -Calculates the Blake2s256 hash of the input bytes and represents these as a single field element. -Verifies a ECDSA signature over the secp256k1 curve. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `hashed_msg` | `Uint8Array` | | -| `public_key_x_bytes` | `Uint8Array` | | -| `public_key_y_bytes` | `Uint8Array` | | -| `signature` | `Uint8Array` | | - -## Returns - -`boolean` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify.md deleted file mode 100644 index 0b20ff68957..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify.md +++ /dev/null @@ -1,28 +0,0 @@ -# ecdsa\_secp256r1\_verify() - -```ts -ecdsa_secp256r1_verify( - hashed_msg, - public_key_x_bytes, - public_key_y_bytes, - signature): boolean -``` - -Verifies a ECDSA signature over the secp256r1 curve. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `hashed_msg` | `Uint8Array` | | -| `public_key_x_bytes` | `Uint8Array` | | -| `public_key_y_bytes` | `Uint8Array` | | -| `signature` | `Uint8Array` | | - -## Returns - -`boolean` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/functions/keccak256.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/functions/keccak256.md deleted file mode 100644 index d10f155ce86..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/functions/keccak256.md +++ /dev/null @@ -1,21 +0,0 @@ -# keccak256() - -```ts -keccak256(inputs): Uint8Array -``` - -Calculates the Keccak256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/functions/sha256.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/functions/sha256.md deleted file mode 100644 index 6ba4ecac022..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/functions/sha256.md +++ /dev/null @@ -1,21 +0,0 @@ -# sha256() - -```ts -sha256(inputs): Uint8Array -``` - -Calculates the SHA256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/functions/xor.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/functions/xor.md deleted file mode 100644 index 8d762b895d3..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/functions/xor.md +++ /dev/null @@ -1,22 +0,0 @@ -# xor() - -```ts -xor(lhs, rhs): string -``` - -Performs a bitwise XOR operation between `lhs` and `rhs` - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `lhs` | `string` | | -| `rhs` | `string` | | - -## Returns - -`string` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/index.md deleted file mode 100644 index 348453c0059..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/index.md +++ /dev/null @@ -1,37 +0,0 @@ -# Noir JS - -## Exports - -### Classes - -| Class | Description | -| :------ | :------ | -| [Noir](classes/Noir.md) | - | - -### Type Aliases - -| Type alias | Description | -| :------ | :------ | -| [CompiledCircuit](type-aliases/CompiledCircuit.md) | - | -| [ForeignCallHandler](type-aliases/ForeignCallHandler.md) | A callback which performs an foreign call and returns the response. | -| [ForeignCallInput](type-aliases/ForeignCallInput.md) | - | -| [ForeignCallOutput](type-aliases/ForeignCallOutput.md) | - | -| [InputMap](type-aliases/InputMap.md) | - | -| [ProofData](type-aliases/ProofData.md) | - | -| [WitnessMap](type-aliases/WitnessMap.md) | - | - -### Functions - -| Function | Description | -| :------ | :------ | -| [and](functions/and.md) | Performs a bitwise AND operation between `lhs` and `rhs` | -| [blake2s256](functions/blake2s256.md) | Calculates the Blake2s256 hash of the input bytes | -| [ecdsa\_secp256k1\_verify](functions/ecdsa_secp256k1_verify.md) | Calculates the Blake2s256 hash of the input bytes and represents these as a single field element. | -| [ecdsa\_secp256r1\_verify](functions/ecdsa_secp256r1_verify.md) | Verifies a ECDSA signature over the secp256r1 curve. | -| [keccak256](functions/keccak256.md) | Calculates the Keccak256 hash of the input bytes | -| [sha256](functions/sha256.md) | Calculates the SHA256 hash of the input bytes | -| [xor](functions/xor.md) | Performs a bitwise XOR operation between `lhs` and `rhs` | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/type-aliases/CompiledCircuit.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/type-aliases/CompiledCircuit.md deleted file mode 100644 index 34e0dd04205..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/type-aliases/CompiledCircuit.md +++ /dev/null @@ -1,20 +0,0 @@ -# CompiledCircuit - -```ts -type CompiledCircuit: object; -``` - -## Description - -The representation of a compiled circuit - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `abi` | `Abi` | **Description**

ABI representation of the circuit | -| `bytecode` | `string` | **Description**

The bytecode of the circuit | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/type-aliases/ForeignCallHandler.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/type-aliases/ForeignCallHandler.md deleted file mode 100644 index 812b8b16481..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/type-aliases/ForeignCallHandler.md +++ /dev/null @@ -1,24 +0,0 @@ -# ForeignCallHandler - -```ts -type ForeignCallHandler: (name, inputs) => Promise; -``` - -A callback which performs an foreign call and returns the response. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `name` | `string` | The identifier for the type of foreign call being performed. | -| `inputs` | [`ForeignCallInput`](ForeignCallInput.md)[] | An array of hex encoded inputs to the foreign call. | - -## Returns - -`Promise`\<[`ForeignCallOutput`](ForeignCallOutput.md)[]\> - -outputs - An array of hex encoded outputs containing the results of the foreign call. - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/type-aliases/ForeignCallInput.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/type-aliases/ForeignCallInput.md deleted file mode 100644 index dd95809186a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/type-aliases/ForeignCallInput.md +++ /dev/null @@ -1,9 +0,0 @@ -# ForeignCallInput - -```ts -type ForeignCallInput: string[]; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/type-aliases/ForeignCallOutput.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/type-aliases/ForeignCallOutput.md deleted file mode 100644 index b71fb78a946..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/type-aliases/ForeignCallOutput.md +++ /dev/null @@ -1,9 +0,0 @@ -# ForeignCallOutput - -```ts -type ForeignCallOutput: string | string[]; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/type-aliases/InputMap.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/type-aliases/InputMap.md deleted file mode 100644 index c714e999d93..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/type-aliases/InputMap.md +++ /dev/null @@ -1,13 +0,0 @@ -# InputMap - -```ts -type InputMap: object; -``` - -## Index signature - - \[`key`: `string`\]: `InputValue` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/type-aliases/ProofData.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/type-aliases/ProofData.md deleted file mode 100644 index 3eb360a78f1..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/type-aliases/ProofData.md +++ /dev/null @@ -1,20 +0,0 @@ -# ProofData - -```ts -type ProofData: object; -``` - -## Description - -The representation of a proof - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `proof` | `Uint8Array` | **Description**

An byte array representing the proof | -| `publicInputs` | `WitnessMap` | **Description**

Public inputs of a proof | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/type-aliases/WitnessMap.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/type-aliases/WitnessMap.md deleted file mode 100644 index 258c46f9d0c..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/type-aliases/WitnessMap.md +++ /dev/null @@ -1,9 +0,0 @@ -# WitnessMap - -```ts -type WitnessMap: Map; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/typedoc-sidebar.cjs deleted file mode 100644 index 077ebeb133e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir_js/reference/noir_js/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"noir_js/reference/noir_js/classes/Noir","label":"Noir"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/CompiledCircuit","label":"CompiledCircuit"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/ForeignCallHandler","label":"ForeignCallHandler"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/ForeignCallInput","label":"ForeignCallInput"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/ForeignCallOutput","label":"ForeignCallOutput"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/InputMap","label":"InputMap"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/ProofData","label":"ProofData"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/WitnessMap","label":"WitnessMap"}]},{"type":"category","label":"Functions","items":[{"type":"doc","id":"noir_js/reference/noir_js/functions/and","label":"and"},{"type":"doc","id":"noir_js/reference/noir_js/functions/blake2s256","label":"blake2s256"},{"type":"doc","id":"noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify","label":"ecdsa_secp256k1_verify"},{"type":"doc","id":"noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify","label":"ecdsa_secp256r1_verify"},{"type":"doc","id":"noir_js/reference/noir_js/functions/keccak256","label":"keccak256"},{"type":"doc","id":"noir_js/reference/noir_js/functions/sha256","label":"sha256"},{"type":"doc","id":"noir_js/reference/noir_js/functions/xor","label":"xor"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/backend_barretenberg/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/backend_barretenberg/.nojekyll deleted file mode 100644 index e2ac6616add..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/backend_barretenberg/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md deleted file mode 100644 index 5cbe9421b92..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md +++ /dev/null @@ -1,185 +0,0 @@ -# BarretenbergBackend - -## Implements - -- [`Backend`](../interfaces/Backend.md) - -## Constructors - -### new BarretenbergBackend(acirCircuit, options) - -```ts -new BarretenbergBackend(acirCircuit, options): BarretenbergBackend -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `acirCircuit` | [`CompiledCircuit`](../type-aliases/CompiledCircuit.md) | -| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | - -#### Returns - -[`BarretenbergBackend`](BarretenbergBackend.md) - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`destroy`](../interfaces/Backend.md#destroy) - -#### Description - -Destroys the backend - -*** - -### generateFinalProof() - -```ts -generateFinalProof(decompressedWitness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `decompressedWitness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`generateFinalProof`](../interfaces/Backend.md#generatefinalproof) - -#### Description - -Generates a final proof (not meant to be verified in another circuit) - -*** - -### generateIntermediateProof() - -```ts -generateIntermediateProof(witness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `witness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`generateIntermediateProof`](../interfaces/Backend.md#generateintermediateproof) - -#### Example - -```typescript -const intermediateProof = await backend.generateIntermediateProof(witness); -``` - -*** - -### generateIntermediateProofArtifacts() - -```ts -generateIntermediateProofArtifacts(proofData, numOfPublicInputs): Promise -``` - -#### Parameters - -| Parameter | Type | Default value | -| :------ | :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | `undefined` | -| `numOfPublicInputs` | `number` | `0` | - -#### Returns - -`Promise`\<`object`\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`generateIntermediateProofArtifacts`](../interfaces/Backend.md#generateintermediateproofartifacts) - -#### Example - -```typescript -const artifacts = await backend.generateIntermediateProofArtifacts(proof, numOfPublicInputs); -``` - -*** - -### verifyFinalProof() - -```ts -verifyFinalProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`verifyFinalProof`](../interfaces/Backend.md#verifyfinalproof) - -#### Description - -Verifies a final proof - -*** - -### verifyIntermediateProof() - -```ts -verifyIntermediateProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`verifyIntermediateProof`](../interfaces/Backend.md#verifyintermediateproof) - -#### Example - -```typescript -const isValidIntermediate = await backend.verifyIntermediateProof(proof); -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/backend_barretenberg/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/backend_barretenberg/index.md deleted file mode 100644 index e32501acb71..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/backend_barretenberg/index.md +++ /dev/null @@ -1,46 +0,0 @@ -# backend_barretenberg - -## Exports - -### Classes - -| Class | Description | -| :------ | :------ | -| [BarretenbergBackend](classes/BarretenbergBackend.md) | - | - -### Interfaces - -| Interface | Description | -| :------ | :------ | -| [Backend](interfaces/Backend.md) | - | - -### Type Aliases - -| Type alias | Description | -| :------ | :------ | -| [BackendOptions](type-aliases/BackendOptions.md) | - | -| [CompiledCircuit](type-aliases/CompiledCircuit.md) | - | -| [ProofData](type-aliases/ProofData.md) | - | - -## Functions - -### publicInputsToWitnessMap() - -```ts -publicInputsToWitnessMap(publicInputs, abi): WitnessMap -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `publicInputs` | `string`[] | -| `abi` | `Abi` | - -#### Returns - -`WitnessMap` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/backend_barretenberg/interfaces/Backend.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/backend_barretenberg/interfaces/Backend.md deleted file mode 100644 index 3eb9645c8d2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/backend_barretenberg/interfaces/Backend.md +++ /dev/null @@ -1,132 +0,0 @@ -# Backend - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Description - -Destroys the backend - -*** - -### generateFinalProof() - -```ts -generateFinalProof(decompressedWitness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `decompressedWitness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Description - -Generates a final proof (not meant to be verified in another circuit) - -*** - -### generateIntermediateProof() - -```ts -generateIntermediateProof(decompressedWitness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `decompressedWitness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Description - -Generates an intermediate proof (meant to be verified in another circuit) - -*** - -### generateIntermediateProofArtifacts() - -```ts -generateIntermediateProofArtifacts(proofData, numOfPublicInputs): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | -| `numOfPublicInputs` | `number` | - -#### Returns - -`Promise`\<`object`\> - -#### Description - -Retrieves the artifacts from a proof in the Field format - -*** - -### verifyFinalProof() - -```ts -verifyFinalProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Verifies a final proof - -*** - -### verifyIntermediateProof() - -```ts -verifyIntermediateProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Verifies an intermediate proof - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md deleted file mode 100644 index 266ade75d17..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md +++ /dev/null @@ -1,19 +0,0 @@ -# BackendOptions - -```ts -type BackendOptions: object; -``` - -## Description - -An options object, currently only used to specify the number of threads to use. - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `threads` | `number` | **Description**

Number of threads | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit.md deleted file mode 100644 index 34e0dd04205..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit.md +++ /dev/null @@ -1,20 +0,0 @@ -# CompiledCircuit - -```ts -type CompiledCircuit: object; -``` - -## Description - -The representation of a compiled circuit - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `abi` | `Abi` | **Description**

ABI representation of the circuit | -| `bytecode` | `string` | **Description**

The bytecode of the circuit | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/backend_barretenberg/type-aliases/ProofData.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/backend_barretenberg/type-aliases/ProofData.md deleted file mode 100644 index 05cebbc4e94..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/backend_barretenberg/type-aliases/ProofData.md +++ /dev/null @@ -1,20 +0,0 @@ -# ProofData - -```ts -type ProofData: object; -``` - -## Description - -The representation of a proof - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `proof` | `Uint8Array` | **Description**

An byte array representing the proof | -| `publicInputs` | `string`[] | **Description**

Public inputs of a proof | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs deleted file mode 100644 index 2aaa55bccf6..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend","label":"BarretenbergBackend"}]},{"type":"category","label":"Interfaces","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/interfaces/Backend","label":"Backend"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions","label":"BackendOptions"},{"type":"doc","id":"reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit","label":"CompiledCircuit"},{"type":"doc","id":"reference/NoirJS/backend_barretenberg/type-aliases/ProofData","label":"ProofData"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/.nojekyll deleted file mode 100644 index e2ac6616add..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/classes/Noir.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/classes/Noir.md deleted file mode 100644 index 34e20d99684..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/classes/Noir.md +++ /dev/null @@ -1,132 +0,0 @@ -# Noir - -## Constructors - -### new Noir(circuit, backend) - -```ts -new Noir(circuit, backend?): Noir -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `circuit` | [`CompiledCircuit`](../type-aliases/CompiledCircuit.md) | -| `backend`? | `Backend` | - -#### Returns - -[`Noir`](Noir.md) - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Description - -Destroys the underlying backend instance. - -#### Example - -```typescript -await noir.destroy(); -``` - -*** - -### execute() - -```ts -execute(inputs, foreignCallHandler?): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `inputs` | [`InputMap`](../type-aliases/InputMap.md) | -| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | - -#### Returns - -`Promise`\<`object`\> - -#### Description - -Allows to execute a circuit to get its witness and return value. - -#### Example - -```typescript -async execute(inputs) -``` - -*** - -### generateFinalProof() - -```ts -generateFinalProof(inputs, foreignCallHandler?): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `inputs` | [`InputMap`](../type-aliases/InputMap.md) | -| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Description - -Generates a witness and a proof given an object as input. - -#### Example - -```typescript -async generateFinalProof(input) -``` - -*** - -### verifyFinalProof() - -```ts -verifyFinalProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Instantiates the verification key and verifies a proof. - -#### Example - -```typescript -async verifyFinalProof(proof) -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/functions/and.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/functions/and.md deleted file mode 100644 index c783283e396..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/functions/and.md +++ /dev/null @@ -1,22 +0,0 @@ -# and() - -```ts -and(lhs, rhs): string -``` - -Performs a bitwise AND operation between `lhs` and `rhs` - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `lhs` | `string` | | -| `rhs` | `string` | | - -## Returns - -`string` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/functions/blake2s256.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/functions/blake2s256.md deleted file mode 100644 index 7882d0da8d5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/functions/blake2s256.md +++ /dev/null @@ -1,21 +0,0 @@ -# blake2s256() - -```ts -blake2s256(inputs): Uint8Array -``` - -Calculates the Blake2s256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md deleted file mode 100644 index 0b20ff68957..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md +++ /dev/null @@ -1,28 +0,0 @@ -# ecdsa\_secp256r1\_verify() - -```ts -ecdsa_secp256r1_verify( - hashed_msg, - public_key_x_bytes, - public_key_y_bytes, - signature): boolean -``` - -Verifies a ECDSA signature over the secp256r1 curve. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `hashed_msg` | `Uint8Array` | | -| `public_key_x_bytes` | `Uint8Array` | | -| `public_key_y_bytes` | `Uint8Array` | | -| `signature` | `Uint8Array` | | - -## Returns - -`boolean` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/functions/keccak256.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/functions/keccak256.md deleted file mode 100644 index d10f155ce86..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/functions/keccak256.md +++ /dev/null @@ -1,21 +0,0 @@ -# keccak256() - -```ts -keccak256(inputs): Uint8Array -``` - -Calculates the Keccak256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/functions/sha256.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/functions/sha256.md deleted file mode 100644 index 6ba4ecac022..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/functions/sha256.md +++ /dev/null @@ -1,21 +0,0 @@ -# sha256() - -```ts -sha256(inputs): Uint8Array -``` - -Calculates the SHA256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/functions/xor.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/functions/xor.md deleted file mode 100644 index 8d762b895d3..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/functions/xor.md +++ /dev/null @@ -1,22 +0,0 @@ -# xor() - -```ts -xor(lhs, rhs): string -``` - -Performs a bitwise XOR operation between `lhs` and `rhs` - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `lhs` | `string` | | -| `rhs` | `string` | | - -## Returns - -`string` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/index.md deleted file mode 100644 index d600e21b299..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/index.md +++ /dev/null @@ -1,37 +0,0 @@ -# noir_js - -## Exports - -### Classes - -| Class | Description | -| :------ | :------ | -| [Noir](classes/Noir.md) | - | - -### Type Aliases - -| Type alias | Description | -| :------ | :------ | -| [CompiledCircuit](type-aliases/CompiledCircuit.md) | - | -| [ForeignCallHandler](type-aliases/ForeignCallHandler.md) | A callback which performs an foreign call and returns the response. | -| [ForeignCallInput](type-aliases/ForeignCallInput.md) | - | -| [ForeignCallOutput](type-aliases/ForeignCallOutput.md) | - | -| [InputMap](type-aliases/InputMap.md) | - | -| [ProofData](type-aliases/ProofData.md) | - | -| [WitnessMap](type-aliases/WitnessMap.md) | - | - -### Functions - -| Function | Description | -| :------ | :------ | -| [and](functions/and.md) | Performs a bitwise AND operation between `lhs` and `rhs` | -| [blake2s256](functions/blake2s256.md) | Calculates the Blake2s256 hash of the input bytes | -| [ecdsa\_secp256k1\_verify](functions/ecdsa_secp256k1_verify.md) | Verifies a ECDSA signature over the secp256k1 curve. | -| [ecdsa\_secp256r1\_verify](functions/ecdsa_secp256r1_verify.md) | Verifies a ECDSA signature over the secp256r1 curve. | -| [keccak256](functions/keccak256.md) | Calculates the Keccak256 hash of the input bytes | -| [sha256](functions/sha256.md) | Calculates the SHA256 hash of the input bytes | -| [xor](functions/xor.md) | Performs a bitwise XOR operation between `lhs` and `rhs` | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/type-aliases/CompiledCircuit.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/type-aliases/CompiledCircuit.md deleted file mode 100644 index 34e0dd04205..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/type-aliases/CompiledCircuit.md +++ /dev/null @@ -1,20 +0,0 @@ -# CompiledCircuit - -```ts -type CompiledCircuit: object; -``` - -## Description - -The representation of a compiled circuit - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `abi` | `Abi` | **Description**

ABI representation of the circuit | -| `bytecode` | `string` | **Description**

The bytecode of the circuit | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md deleted file mode 100644 index 812b8b16481..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md +++ /dev/null @@ -1,24 +0,0 @@ -# ForeignCallHandler - -```ts -type ForeignCallHandler: (name, inputs) => Promise; -``` - -A callback which performs an foreign call and returns the response. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `name` | `string` | The identifier for the type of foreign call being performed. | -| `inputs` | [`ForeignCallInput`](ForeignCallInput.md)[] | An array of hex encoded inputs to the foreign call. | - -## Returns - -`Promise`\<[`ForeignCallOutput`](ForeignCallOutput.md)[]\> - -outputs - An array of hex encoded outputs containing the results of the foreign call. - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md deleted file mode 100644 index dd95809186a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md +++ /dev/null @@ -1,9 +0,0 @@ -# ForeignCallInput - -```ts -type ForeignCallInput: string[]; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md deleted file mode 100644 index b71fb78a946..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md +++ /dev/null @@ -1,9 +0,0 @@ -# ForeignCallOutput - -```ts -type ForeignCallOutput: string | string[]; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/type-aliases/InputMap.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/type-aliases/InputMap.md deleted file mode 100644 index c714e999d93..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/type-aliases/InputMap.md +++ /dev/null @@ -1,13 +0,0 @@ -# InputMap - -```ts -type InputMap: object; -``` - -## Index signature - - \[`key`: `string`\]: `InputValue` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/type-aliases/ProofData.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/type-aliases/ProofData.md deleted file mode 100644 index 05cebbc4e94..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/type-aliases/ProofData.md +++ /dev/null @@ -1,20 +0,0 @@ -# ProofData - -```ts -type ProofData: object; -``` - -## Description - -The representation of a proof - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `proof` | `Uint8Array` | **Description**

An byte array representing the proof | -| `publicInputs` | `string`[] | **Description**

Public inputs of a proof | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md deleted file mode 100644 index 258c46f9d0c..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md +++ /dev/null @@ -1,9 +0,0 @@ -# WitnessMap - -```ts -type WitnessMap: Map; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs deleted file mode 100644 index fe2629ddc9f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/noir_js/classes/Noir","label":"Noir"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/CompiledCircuit","label":"CompiledCircuit"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallHandler","label":"ForeignCallHandler"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallInput","label":"ForeignCallInput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallOutput","label":"ForeignCallOutput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/InputMap","label":"InputMap"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ProofData","label":"ProofData"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/WitnessMap","label":"WitnessMap"}]},{"type":"category","label":"Functions","items":[{"type":"doc","id":"reference/NoirJS/noir_js/functions/and","label":"and"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/blake2s256","label":"blake2s256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify","label":"ecdsa_secp256k1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify","label":"ecdsa_secp256r1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/keccak256","label":"keccak256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/sha256","label":"sha256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/xor","label":"xor"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_wasm/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_wasm/.nojekyll deleted file mode 100644 index e2ac6616add..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_wasm/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_wasm/functions/compile.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_wasm/functions/compile.md deleted file mode 100644 index 33eb434c3db..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_wasm/functions/compile.md +++ /dev/null @@ -1,51 +0,0 @@ -# compile() - -```ts -compile( - fileManager, - projectPath?, - logFn?, -debugLogFn?): Promise -``` - -Compiles a Noir project - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `fileManager` | `FileManager` | The file manager to use | -| `projectPath`? | `string` | The path to the project inside the file manager. Defaults to the root of the file manager | -| `logFn`? | `LogFn` | A logging function. If not provided, console.log will be used | -| `debugLogFn`? | `LogFn` | A debug logging function. If not provided, logFn will be used | - -## Returns - -`Promise`\<[`CompilationResult`](../type-aliases/CompilationResult.md)\> - -## Example - -```typescript -// Node.js - -import { compile, createFileManager } from '@noir-lang/noir_wasm'; - -const fm = createFileManager(myProjectPath); -const myCompiledCode = await compile(fm); -``` - -```typescript -// Browser - -import { compile, createFileManager } from '@noir-lang/noir_wasm'; - -const fm = createFileManager('/'); -for (const path of files) { - await fm.writeFile(path, await getFileAsStream(path)); -} -const myCompiledCode = await compile(fm); -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_wasm/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_wasm/index.md deleted file mode 100644 index 939f2481687..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_wasm/index.md +++ /dev/null @@ -1,21 +0,0 @@ -# noir_wasm - -## Exports - -### Type Aliases - -| Type alias | Description | -| :------ | :------ | -| [CompilationResult](type-aliases/CompilationResult.md) | output of Noir Wasm compilation, can be for a contract or lib/binary | - -### Functions - -| Function | Description | -| :------ | :------ | -| [compile](functions/compile.md) | Compiles a Noir project | -| [createFileManager](functions/createFileManager.md) | Creates a new FileManager instance based on fs in node and memfs in the browser (via webpack alias) | -| [inflateDebugSymbols](functions/inflateDebugSymbols.md) | Decompresses and decodes the debug symbols | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_wasm/type-aliases/CompilationResult.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_wasm/type-aliases/CompilationResult.md deleted file mode 100644 index 23cfbe6025d..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_wasm/type-aliases/CompilationResult.md +++ /dev/null @@ -1,11 +0,0 @@ -# CompilationResult - -```ts -type CompilationResult: ContractCompilationArtifacts | ProgramCompilationArtifacts; -``` - -output of Noir Wasm compilation, can be for a contract or lib/binary - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs deleted file mode 100644 index d7eba0db813..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"doc","id":"reference/NoirJS/noir_wasm/index","label":"API"},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/noir_wasm/type-aliases/CompilationResult","label":"CompilationResult"}]},{"type":"category","label":"Functions","items":[{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/compile","label":"compile"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/createFileManager","label":"createFileManager"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/inflateDebugSymbols","label":"inflateDebugSymbols"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/_category_.json deleted file mode 100644 index 5b6a20a609a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 4, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/nargo_commands.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/nargo_commands.md deleted file mode 100644 index fc2671b2bfc..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/nargo_commands.md +++ /dev/null @@ -1,253 +0,0 @@ ---- -title: Nargo -description: - Noir CLI Commands for Noir Prover and Verifier to create, execute, prove and verify programs, - generate Solidity verifier smart contract and compile into JSON file containing ACIR - representation and ABI of circuit. -keywords: - [ - Nargo, - Noir CLI, - Noir Prover, - Noir Verifier, - generate Solidity verifier, - compile JSON file, - ACIR representation, - ABI of circuit, - TypeScript, - ] -sidebar_position: 0 ---- - -## General options - -| Option | Description | -| -------------------- | -------------------------------------------------- | -| `--show-ssa` | Emit debug information for the intermediate SSA IR | -| `--deny-warnings` | Quit execution when warnings are emitted | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo help [subcommand]` - -Prints the list of available commands or specific information of a subcommand. - -_Arguments_ - -| Argument | Description | -| -------------- | -------------------------------------------- | -| `` | The subcommand whose help message to display | - -## `nargo backend` - -Installs and selects custom backends used to generate and verify proofs. - -### Commands - -| Command | Description | -| ----------- | --------------------------------------------------------- | -| `current` | Prints the name of the currently active backend | -| `ls` | Prints the list of currently installed backends | -| `use` | Select the backend to use | -| `install` | Install a new backend from a URL | -| `uninstall` | Uninstalls a backend | -| `help` | Print this message or the help of the given subcommand(s) | - -### Options - -| Option | Description | -| ------------ | ----------- | -| `-h, --help` | Print help | - -## `nargo check` - -Generate the `Prover.toml` and `Verifier.toml` files for specifying prover and verifier in/output -values of the Noir program respectively. - -### Options - -| Option | Description | -| --------------------- | ------------------------------------- | -| `--package ` | The name of the package to check | -| `--workspace` | Check all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -### `nargo codegen-verifier` - -Generate a Solidity verifier smart contract for the program. - -### Options - -| Option | Description | -| --------------------- | ------------------------------------- | -| `--package ` | The name of the package to codegen | -| `--workspace` | Codegen all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo compile` - -Compile the program into a JSON build artifact file containing the ACIR representation and the ABI -of the circuit. This build artifact can then be used to generate and verify proofs. - -You can also use "build" as an alias for compile (e.g. `nargo build`). - -### Options - -| Option | Description | -| --------------------- | ------------------------------------------------------------ | -| `--package ` | The name of the package to compile | -| `--workspace` | Compile all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo new ` - -Creates a new Noir project in a new folder. - -**Arguments** - -| Argument | Description | -| -------- | -------------------------------- | -| `` | The path to save the new project | - -### Options - -| Option | Description | -| --------------- | ----------------------------------------------------- | -| `--name ` | Name of the package [default: package directory name] | -| `--lib` | Use a library template | -| `--bin` | Use a binary template [default] | -| `--contract` | Use a contract template | -| `-h, --help` | Print help | - -## `nargo init` - -Creates a new Noir project in the current directory. - -### Options - -| Option | Description | -| --------------- | ----------------------------------------------------- | -| `--name ` | Name of the package [default: current directory name] | -| `--lib` | Use a library template | -| `--bin` | Use a binary template [default] | -| `--contract` | Use a contract template | -| `-h, --help` | Print help | - -## `nargo execute [WITNESS_NAME]` - -Runs the Noir program and prints its return value. - -**Arguments** - -| Argument | Description | -| ---------------- | ----------------------------------------- | -| `[WITNESS_NAME]` | Write the execution witness to named file | - -### Options - -| Option | Description | -| --------------------------------- | ------------------------------------------------------------------------------------ | -| `-p, --prover-name ` | The name of the toml file which contains the inputs for the prover [default: Prover] | -| `--package ` | The name of the package to execute | -| `--workspace` | Execute all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `--oracle-resolver` | JSON RPC url to solve oracle calls | -| `-h, --help` | Print help | - -_Usage_ - -The inputs to the circuit are read from the `Prover.toml` file generated by `nargo check`, which -must be filled in. - -To save the witness to file, run the command with a value for the `WITNESS_NAME` argument. A -`.tr` file will then be saved in the `./target` folder. - -## `nargo prove` - -Creates a proof for the program. - -### Options - -| Option | Description | -| ------------------------------------- | ---------------------------------------------------------------------------------------- | -| `-p, --prover-name ` | The name of the toml file which contains the inputs for the prover [default: Prover] | -| `-v, --verifier-name ` | The name of the toml file which contains the inputs for the verifier [default: Verifier] | -| `--verify` | Verify proof after proving | -| `--package ` | The name of the package to prove | -| `--workspace` | Prove all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `--oracle-resolver` | JSON RPC url to solve oracle calls | -| `-h, --help` | Print help | - -## `nargo verify` - -Given a proof and a program, verify whether the proof is valid. - -### Options - -| Option | Description | -| ------------------------------------- | ---------------------------------------------------------------------------------------- | -| `-v, --verifier-name ` | The name of the toml file which contains the inputs for the verifier [default: Verifier] | -| `--package ` | The name of the package to verify | -| `--workspace` | Verify all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -## `nargo test [TEST_NAME]` - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. To print `println` statements in tests, use the `--show-output` flag. - -Takes an optional `--exact` flag which allows you to select tests based on an exact name. - -See an example on the [testing page](../getting_started/tooling/testing.md). - -### Options - -| Option | Description | -| --------------------- | -------------------------------------- | -| `--show-output` | Display output of `println` statements | -| `--exact` | Only run tests that match exactly | -| `--package ` | The name of the package to test | -| `--workspace` | Test all packages in the workspace | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `--oracle-resolver` | JSON RPC url to solve oracle calls | -| `-h, --help` | Print help | - -## `nargo info` - -Prints a table containing the information of the package. - -Currently the table provide - -1. The number of ACIR opcodes -2. The final number gates in the circuit used by a backend - -If the file contains a contract the table will provide the -above information about each function of the contract. - -## `nargo lsp` - -Start a long-running Language Server process that communicates over stdin/stdout. -Usually this command is not run by a user, but instead will be run by a Language Client, such as [vscode-noir](https://github.com/noir-lang/vscode-noir). - -## `nargo fmt` - -Automatically formats your Noir source code based on the default formatting settings. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/tutorials/noirjs_app.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/tutorials/noirjs_app.md deleted file mode 100644 index e3bc8c58b24..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/tutorials/noirjs_app.md +++ /dev/null @@ -1,295 +0,0 @@ ---- -title: Building a web app with NoirJS -description: Learn how to setup a new app that uses Noir to generate and verify zero-knowledge SNARK proofs in a typescript or javascript environment. -keywords: [how to, guide, javascript, typescript, noir, barretenberg, zero-knowledge, proofs, app] -sidebar_position: 0 -pagination_next: noir/concepts/data_types/index ---- - -NoirJS is a set of packages meant to work both in a browser and a server environment. In this tutorial, we will build a simple web app using them. From here, you should get an idea on how to proceed with your own Noir projects! - -You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). - -## Setup - -:::note - -Feel free to use whatever versions, just keep in mind that Nargo and the NoirJS packages are meant to be in sync. For example, Nargo 0.23.x matches `noir_js@0.23.x`, etc. - -In this guide, we will be pinned to 0.23.0. - -::: - -Before we start, we want to make sure we have Node and Nargo installed. - -We start by opening a terminal and executing `node --version`. If we don't get an output like `v20.10.0`, that means node is not installed. Let's do that by following the handy [nvm guide](https://github.com/nvm-sh/nvm?tab=readme-ov-file#install--update-script). - -As for `Nargo`, we can follow the [Nargo guide](../getting_started/installation/index.md) to install it. If you're lazy, just paste this on a terminal and run `noirup`: - -```sh -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -Easy enough. Onwards! - -## Our project - -ZK is a powerful technology. An app that doesn't reveal one of the inputs to *anyone* is almost unbelievable, yet Noir makes it as easy as a single line of code. - -In fact, it's so simple that it comes nicely packaged in `nargo`. Let's do that! - -### Nargo - -Run: - -```nargo new circuit``` - -And... That's about it. Your program is ready to be compiled and run. - -To compile, let's `cd` into the `circuit` folder to enter our project, and call: - -```nargo compile``` - -This compiles our circuit into `json` format and add it to a new `target` folder. - -:::info - -At this point in the tutorial, your folder structure should look like this: - -```tree -. -└── circuit <---- our working directory - ├── Nargo.toml - ├── src - │ └── main.nr - └── target - └── circuit.json -``` - -::: - -### Node and Vite - -If you want to explore Nargo, feel free to go on a side-quest now and follow the steps in the -[getting started](../getting_started/hello_noir/index.md) guide. However, we want our app to run on the browser, so we need Vite. - -Vite is a powerful tool to generate static websites. While it provides all kinds of features, let's just go barebones with some good old vanilla JS. - -To do this this, go back to the previous folder (`cd ..`) and create a new vite project by running `npm create vite` and choosing "Vanilla" and "Javascript". - -You should see `vite-project` appear in your root folder. This seems like a good time to `cd` into it and install our NoirJS packages: - -```bash -npm i @noir-lang/backend_barretenberg@0.23.0 @noir-lang/noir_js@0.23.0 vite-plugin-top-level-await -``` - -:::info - -At this point in the tutorial, your folder structure should look like this: - -```tree -. -└── circuit - └── ...etc... -└── vite-project <---- our working directory - └── ...etc... -``` - -::: - -#### Some cleanup - -Add a `vite.config.js` file containing the following: - -```js -import { defineConfig } from 'vite'; -import topLevelAwait from "vite-plugin-top-level-await"; - -export default defineConfig({ - plugins: [ - topLevelAwait({ - promiseExportName: "__tla", - promiseImportName: i => `__tla_${i}` - }) - ] -}) -``` - -`npx create vite` is amazing but it creates a bunch of files we don't really need for our simple example. Actually, let's just delete everything except for `index.html`, `main.js` and `package.json`. I feel lighter already. - -![my heart is ready for you, noir.js](@site/static/img/memes/titanic.jpeg) - -## HTML - -Our app won't run like this, of course. We need some working HTML, at least. Let's open our broken-hearted `index.html` and replace everything with this code snippet: - -```html - - - - - - -

Noir app

-
- - -
-
-

Logs

-

Proof

-
- - -``` - -It *could* be a beautiful UI... Depending on which universe you live in. - -## Some good old vanilla Javascript - -Our love for Noir needs undivided attention, so let's just open `main.js` and delete everything (this is where the romantic scenery becomes a bit creepy). - -Start by pasting in this boilerplate code: - -```js -const setup = async () => { - await Promise.all([ - import("@noir-lang/noirc_abi").then(module => - module.default(new URL("@noir-lang/noirc_abi/web/noirc_abi_wasm_bg.wasm", import.meta.url).toString()) - ), - import("@noir-lang/acvm_js").then(module => - module.default(new URL("@noir-lang/acvm_js/web/acvm_js_bg.wasm", import.meta.url).toString()) - ) - ]); -} - -function display(container, msg) { - const c = document.getElementById(container); - const p = document.createElement('p'); - p.textContent = msg; - c.appendChild(p); -} - -document.getElementById('submitGuess').addEventListener('click', async () => { - try { - // here's where love happens - } catch(err) { - display("logs", "Oh 💔 Wrong guess") - } -}); - -``` - -The display function doesn't do much. We're simply manipulating our website to see stuff happening. For example, if the proof fails, it will simply log a broken heart 😢 - -As for the `setup` function, it's just a sad reminder that dealing with `wasm` on the browser is not as easy as it should. Just copy, paste, and forget. - -:::info - -At this point in the tutorial, your folder structure should look like this: - -```tree -. -└── circuit - └── ...same as above -└── vite-project - ├── main.js - ├── package.json - └── index.html -``` - -You'll see other files and folders showing up (like `package-lock.json`, `node_modules`) but you shouldn't have to care about those. - -::: - -## Some NoirJS - -We're starting with the good stuff now. If you've compiled the circuit as described above, you should have a `json` file we want to import at the very top of our `main.js` file: - -```ts -import circuit from '../circuit/target/circuit.json'; -``` - -[Noir is backend-agnostic](../index.mdx#whats-new-about-noir). We write Noir, but we also need a proving backend. That's why we need to import and instantiate the two dependencies we installed above: `BarretenbergBackend` and `Noir`. Let's import them right below: - -```js -import { BarretenbergBackend } from '@noir-lang/backend_barretenberg'; -import { Noir } from '@noir-lang/noir_js'; -``` - -And instantiate them inside our try-catch block: - -```ts -// try { -const backend = new BarretenbergBackend(circuit); -const noir = new Noir(circuit, backend); -// } -``` - -:::note - -For the remainder of the tutorial, everything will be happening inside the `try` block - -::: - -## Our app - -Now for the app itself. We're capturing whatever is in the input when people press the submit button. Just add this: - -```js -const x = parseInt(document.getElementById('guessInput').value); -const input = { x, y: 2 }; -``` - -Now we're ready to prove stuff! Let's feed some inputs to our circuit and calculate the proof: - -```js -await setup(); // let's squeeze our wasm inits here - -display('logs', 'Generating proof... ⌛'); -const proof = await noir.generateFinalProof(input); -display('logs', 'Generating proof... ✅'); -display('results', proof.proof); -``` - -You're probably eager to see stuff happening, so go and run your app now! - -From your terminal, run `npm run dev`. If it doesn't open a browser for you, just visit `localhost:5173`. You should now see the worst UI ever, with an ugly input. - -![Getting Started 0](@site/static/img/noir_getting_started_1.png) - -Now, our circuit says `fn main(x: Field, y: pub Field)`. This means only the `y` value is public, and it's hardcoded above: `input = { x, y: 2 }`. In other words, you won't need to send your secret`x` to the verifier! - -By inputting any number other than 2 in the input box and clicking "submit", you should get a valid proof. Otherwise the proof won't even generate correctly. By the way, if you're human, you shouldn't be able to understand anything on the "proof" box. That's OK. We like you, human ❤️. - -## Verifying - -Time to celebrate, yes! But we shouldn't trust machines so blindly. Let's add these lines to see our proof being verified: - -```js -display('logs', 'Verifying proof... ⌛'); -const verification = await noir.verifyFinalProof(proof); -if (verification) display('logs', 'Verifying proof... ✅'); -``` - -You have successfully generated a client-side Noir web app! - -![coded app without math knowledge](@site/static/img/memes/flextape.jpeg) - -## Further Reading - -You can see how noirjs is used in a full stack Next.js hardhat application in the [noir-starter repo here](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat). The example shows how to calculate a proof in the browser and verify it with a deployed Solidity verifier contract from noirjs. - -You should also check out the more advanced examples in the [noir-examples repo](https://github.com/noir-lang/noir-examples), where you'll find reference usage for some cool apps. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/explainers/explainer-oracle.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/explainers/explainer-oracle.md deleted file mode 100644 index b84ca5dd986..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/explainers/explainer-oracle.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: Oracles -description: This guide provides an in-depth understanding of how Oracles work in Noir programming. Learn how to use outside calculations in your programs, constrain oracles, and understand their uses and limitations. -keywords: - - Noir Programming - - Oracles - - JSON-RPC - - Foreign Call Handlers - - Constrained Functions - - Blockchain Programming -sidebar_position: 1 ---- - -If you've seen "The Matrix" you may recall "The Oracle" as Gloria Foster smoking cigarettes and baking cookies. While she appears to "know things", she is actually providing a calculation of a pre-determined future. Noir Oracles are similar, in a way. They don't calculate the future (yet), but they allow you to use outside calculations in your programs. - -![matrix oracle prediction](@site/static/img/memes/matrix_oracle.jpeg) - -A Noir program is usually self-contained. You can pass certain inputs to it, and it will generate a deterministic output for those inputs. But what if you wanted to defer some calculation to an outside process or source? - -Oracles are functions that provide this feature. - -## Use cases - -An example usage for Oracles is proving something on-chain. For example, proving that the ETH-USDC quote was below a certain target at a certain block time. Or even making more complex proofs like proving the ownership of an NFT as an anonymous login method. - -Another interesting use case is to defer expensive calculations to be made outside of the Noir program, and then constraining the result; similar to the use of [unconstrained functions](../noir/concepts//unconstrained.md). - -In short, anything that can be constrained in a Noir program but needs to be fetched from an external source is a great candidate to be used in oracles. - -## Constraining oracles - -Just like in The Matrix, Oracles are powerful. But with great power, comes great responsibility. Just because you're using them in a Noir program doesn't mean they're true. Noir has no superpowers. If you want to prove that Portugal won the Euro Cup 2016, you're still relying on potentially untrusted information. - -To give a concrete example, Alice wants to login to the [NounsDAO](https://nouns.wtf/) forum with her username "noir_nouner" by proving she owns a noun without revealing her ethereum address. Her Noir program could have a oracle call like this: - -```rust -#[oracle(getNoun)] -unconstrained fn get_noun(address: Field) -> Field -``` - -This oracle could naively resolve with the number of Nouns she possesses. However, it is useless as a trusted source, as the oracle could resolve to anything Alice wants. In order to make this oracle call actually useful, Alice would need to constrain the response from the oracle, by proving her address and the noun count belongs to the state tree of the contract. - -In short, **Oracles don't prove anything. Your Noir program does.** - -:::danger - -If you don't constrain the return of your oracle, you could be clearly opening an attack vector on your Noir program. Make double-triple sure that the return of an oracle call is constrained! - -::: - -## How to use Oracles - -On CLI, Nargo resolves oracles by making JSON RPC calls, which means it would require an RPC node to be running. - -In JavaScript, NoirJS accepts and resolves arbitrary call handlers (that is, not limited to JSON) as long as they matches the expected types the developer defines. Refer to [Foreign Call Handler](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) to learn more about NoirJS's call handling. - -If you want to build using oracles, follow through to the [oracle guide](../how_to/how-to-oracles.md) for a simple example on how to do that. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/explainers/explainer-recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/explainers/explainer-recursion.md deleted file mode 100644 index 18846176ca7..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/explainers/explainer-recursion.md +++ /dev/null @@ -1,176 +0,0 @@ ---- -title: Recursive proofs -description: Explore the concept of recursive proofs in Zero-Knowledge programming. Understand how recursion works in Noir, a language for writing smart contracts on the EVM blockchain. Learn through practical examples like Alice and Bob's guessing game, Charlie's recursive merkle tree, and Daniel's reusable components. Discover how to use recursive proofs to optimize computational resources and improve efficiency. - -keywords: - [ - "Recursive Proofs", - "Zero-Knowledge Programming", - "Noir", - "EVM Blockchain", - "Smart Contracts", - "Recursion in Noir", - "Alice and Bob Guessing Game", - "Recursive Merkle Tree", - "Reusable Components", - "Optimizing Computational Resources", - "Improving Efficiency", - "Verification Key", - "Aggregation", - "Recursive zkSNARK schemes", - "PLONK", - "Proving and Verification Keys" - ] -sidebar_position: 1 -pagination_next: how_to/how-to-recursion ---- - -In programming, we tend to think of recursion as something calling itself. A classic example would be the calculation of the factorial of a number: - -```js -function factorial(n) { - if (n === 0 || n === 1) { - return 1; - } else { - return n * factorial(n - 1); - } -} -``` - -In this case, while `n` is not `1`, this function will keep calling itself until it hits the base case, bubbling up the result on the call stack: - -```md - Is `n` 1? <--------- - /\ / - / \ n = n -1 - / \ / - Yes No -------- -``` - -In Zero-Knowledge, recursion has some similarities. - -It is not a Noir function calling itself, but a proof being used as an input to another circuit. In short, you verify one proof *inside* another proof, returning the proof that both proofs are valid. - -This means that, given enough computational resources, you can prove the correctness of any arbitrary number of proofs in a single proof. This could be useful to design state channels (for which a common example would be [Bitcoin's Lightning Network](https://en.wikipedia.org/wiki/Lightning_Network)), to save on gas costs by settling one proof on-chain, or simply to make business logic less dependent on a consensus mechanism. - -## Examples - -Let us look at some of these examples - -### Alice and Bob - Guessing game - -Alice and Bob are friends, and they like guessing games. They want to play a guessing game online, but for that, they need a trusted third-party that knows both of their secrets and finishes the game once someone wins. - -So, they use zero-knowledge proofs. Alice tries to guess Bob's number, and Bob will generate a ZK proof stating whether she succeeded or failed. - -This ZK proof can go on a smart contract, revealing the winner and even giving prizes. However, this means every turn needs to be verified on-chain. This incurs some cost and waiting time that may simply make the game too expensive or time-consuming to be worth it. - -As a solution, Alice proposes the following: "what if Bob generates his proof, and instead of sending it on-chain, I verify it *within* my own proof before playing my own turn?". - -She can then generate a proof that she verified his proof, and so on. - -```md - Did you fail? <-------------------------- - / \ / - / \ n = n -1 - / \ / - Yes No / - | | / - | | / - | You win / - | / - | / -Generate proof of that / - + / - my own guess ---------------- -``` - -### Charlie - Recursive merkle tree - -Charlie is a concerned citizen, and wants to be sure his vote in an election is accounted for. He votes with a ZK proof, but he has no way of knowing that his ZK proof was included in the total vote count! - -If the vote collector puts all of the votes into a [Merkle tree](https://en.wikipedia.org/wiki/Merkle_tree), everyone can prove the verification of two proofs within one proof, as such: - -```md - abcd - __________|______________ - | | - ab cd - _____|_____ ______|______ - | | | | - alice bob charlie daniel -``` - -Doing this recursively allows us to arrive on a final proof `abcd` which if true, verifies the correctness of all the votes. - -### Daniel - Reusable components - -Daniel has a big circuit and a big headache. A part of his circuit is a setup phase that finishes with some assertions that need to be made. But that section alone takes most of the proving time, and is largely independent of the rest of the circuit. - -He might find it more efficient to generate a proof for that setup phase separately, and verify that proof recursively in the actual business logic section of his circuit. This will allow for parallelization of both proofs, which results in a considerable speedup. - -## What params do I need - -As you can see in the [recursion reference](noir/standard_library/recursion.md), a simple recursive proof requires: - -- The proof to verify -- The Verification Key of the circuit that generated the proof -- A hash of this verification key, as it's needed for some backends -- The public inputs for the proof - -:::info - -Recursive zkSNARK schemes do not necessarily "verify a proof" in the sense that you expect a true or false to be spit out by the verifier. Rather an aggregation object is built over the public inputs. - -So, taking the example of Alice and Bob and their guessing game: - -- Alice makes her guess. Her proof is *not* recursive: it doesn't verify any proof within it! It's just a standard `assert(x != y)` circuit -- Bob verifies Alice's proof and makes his own guess. In this circuit, he doesn't exactly *prove* the verification of Alice's proof. Instead, he *aggregates* his proof to Alice's proof. The actual verification is done when the full proof is verified, for example when using `nargo verify` or through the verifier smart contract. - -We can imagine recursive proofs a [relay race](https://en.wikipedia.org/wiki/Relay_race). The first runner doesn't have to receive the baton from anyone else, as he/she already starts with it. But when his/her turn is over, the next runner needs to receive it, run a bit more, and pass it along. Even though every runner could theoretically verify the baton mid-run (why not? 🏃🔍), only at the end of the race does the referee verify that the whole race is valid. - -::: - -## Some architecture - -As with everything in computer science, there's no one-size-fits all. But there are some patterns that could help understanding and implementing them. To give three examples: - -### Adding some logic to a proof verification - -This would be an approach for something like our guessing game, where proofs are sent back and forth and are verified by each opponent. This circuit would be divided in two sections: - -- A `recursive verification` section, which would be just the call to `std::verify_proof`, and that would be skipped on the first move (since there's no proof to verify) -- A `guessing` section, which is basically the logic part where the actual guessing happens - -In such a situation, and assuming Alice is first, she would skip the first part and try to guess Bob's number. Bob would then verify her proof on the first section of his run, and try to guess Alice's number on the second part, and so on. - -### Aggregating proofs - -In some one-way interaction situations, recursion would allow for aggregation of simple proofs that don't need to be immediately verified on-chain or elsewhere. - -To give a practical example, a barman wouldn't need to verify a "proof-of-age" on-chain every time he serves alcohol to a customer. Instead, the architecture would comprise two circuits: - -- A `main`, non-recursive circuit with some logic -- A `recursive` circuit meant to verify two proofs in one proof - -The customer's proofs would be intermediate, and made on their phones, and the barman could just verify them locally. He would then aggregate them into a final proof sent on-chain (or elsewhere) at the end of the day. - -### Recursively verifying different circuits - -Nothing prevents you from verifying different circuits in a recursive proof, for example: - -- A `circuit1` circuit -- A `circuit2` circuit -- A `recursive` circuit - -In this example, a regulator could verify that taxes were paid for a specific purchase by aggregating both a `payer` circuit (proving that a purchase was made and taxes were paid), and a `receipt` circuit (proving that the payment was received) - -## How fast is it - -At the time of writing, verifying recursive proofs is surprisingly fast. This is because most of the time is spent on generating the verification key that will be used to generate the next proof. So you are able to cache the verification key and reuse it later. - -Currently, Noir JS packages don't expose the functionality of loading proving and verification keys, but that feature exists in the underlying `bb.js` package. - -## How can I try it - -Learn more about using recursion in Nargo and NoirJS in the [how-to guide](../how_to/how-to-recursion.md) and see a full example in [noir-examples](https://github.com/noir-lang/noir-examples). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/_category_.json deleted file mode 100644 index 5d694210bbf..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 0, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/hello_noir/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/hello_noir/_category_.json deleted file mode 100644 index 23b560f610b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/hello_noir/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 1, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/hello_noir/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/hello_noir/index.md deleted file mode 100644 index 743c4d8d634..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/hello_noir/index.md +++ /dev/null @@ -1,142 +0,0 @@ ---- -title: Creating a Project -description: - Learn how to create and verify your first Noir program using Nargo, a programming language for - zero-knowledge proofs. -keywords: - [ - Nargo, - Noir, - zero-knowledge proofs, - programming language, - create Noir program, - verify Noir program, - step-by-step guide, - ] -sidebar_position: 1 - ---- - -Now that we have installed Nargo, it is time to make our first hello world program! - -## Create a Project Directory - -Noir code can live anywhere on your computer. Let us create a _projects_ folder in the home -directory to house our Noir programs. - -For Linux, macOS, and Windows PowerShell, create the directory and change directory into it by -running: - -```sh -mkdir ~/projects -cd ~/projects -``` - -## Create Our First Nargo Project - -Now that we are in the projects directory, create a new Nargo project by running: - -```sh -nargo new hello_world -``` - -> **Note:** `hello_world` can be any arbitrary project name, we are simply using `hello_world` for -> demonstration. -> -> In production, the common practice is to name the project folder as `circuits` for better -> identifiability when sitting alongside other folders in the codebase (e.g. `contracts`, `scripts`, -> `test`). - -A `hello_world` folder would be created. Similar to Rust, the folder houses _src/main.nr_ and -_Nargo.toml_ which contain the source code and environmental options of your Noir program -respectively. - -### Intro to Noir Syntax - -Let us take a closer look at _main.nr_. The default _main.nr_ generated should look like this: - -```rust -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` - -The first line of the program specifies the program's inputs: - -```rust -x : Field, y : pub Field -``` - -Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the -keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](../../noir/concepts/data_types/index.md) section. - -The next line of the program specifies its body: - -```rust -assert(x != y); -``` - -The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. - -For more Noir syntax, check the [Language Concepts](../../noir/concepts/comments.md) chapter. - -## Build In/Output Files - -Change directory into _hello_world_ and build in/output files for your Noir program by running: - -```sh -cd hello_world -nargo check -``` - -Two additional files would be generated in your project directory: - -_Prover.toml_ houses input values, and _Verifier.toml_ houses public values. - -## Prove Our Noir Program - -Now that the project is set up, we can create a proof of correct execution of our Noir program. - -Fill in input values for execution in the _Prover.toml_ file. For example: - -```toml -x = "1" -y = "2" -``` - -Prove the valid execution of your Noir program: - -```sh -nargo prove -``` - -A new folder _proofs_ would then be generated in your project directory, containing the proof file -`.proof`, where the project name is defined in Nargo.toml. - -The _Verifier.toml_ file would also be updated with the public values computed from program -execution (in this case the value of `y`): - -```toml -y = "0x0000000000000000000000000000000000000000000000000000000000000002" -``` - -> **Note:** Values in _Verifier.toml_ are computed as 32-byte hex values. - -## Verify Our Noir Program - -Once a proof is generated, we can verify correct execution of our Noir program by verifying the -proof file. - -Verify your proof by running: - -```sh -nargo verify -``` - -The verification will complete in silence if it is successful. If it fails, it will log the -corresponding error instead. - -Congratulations, you have now created and verified a proof for your very first Noir program! - -In the [next section](./project_breakdown.md), we will go into more detail on each step performed. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/hello_noir/project_breakdown.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/hello_noir/project_breakdown.md deleted file mode 100644 index 6160a102c6c..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/hello_noir/project_breakdown.md +++ /dev/null @@ -1,199 +0,0 @@ ---- -title: Project Breakdown -description: - Learn about the anatomy of a Nargo project, including the purpose of the Prover and Verifier TOML - files, and how to prove and verify your program. -keywords: - [Nargo, Nargo project, Prover.toml, Verifier.toml, proof verification, private asset transfer] -sidebar_position: 2 ---- - -This section breaks down our hello world program from the previous section. We elaborate on the project -structure and what the `prove` and `verify` commands did. - -## Anatomy of a Nargo Project - -Upon creating a new project with `nargo new` and building the in/output files with `nargo check` -commands, you would get a minimal Nargo project of the following structure: - - - src - - Prover.toml - - Verifier.toml - - Nargo.toml - -The source directory _src_ holds the source code for your Noir program. By default only a _main.nr_ -file will be generated within it. - -### Prover.toml - -_Prover.toml_ is used for specifying the input values for executing and proving the program. You can specify `toml` files with different names by using the `--prover-name` or `-p` flags, see the [Prover](#provertoml) section below. Optionally you may specify expected output values for prove-time checking as well. - -### Verifier.toml - -_Verifier.toml_ contains public in/output values computed when executing the Noir program. - -### Nargo.toml - -_Nargo.toml_ contains the environmental options of your project. It contains a "package" section and a "dependencies" section. - -Example Nargo.toml: - -```toml -[package] -name = "noir_starter" -type = "bin" -authors = ["Alice"] -compiler_version = "0.9.0" -description = "Getting started with Noir" -entry = "circuit/main.nr" -license = "MIT" - -[dependencies] -ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} -``` - -Nargo.toml for a [workspace](../../noir/modules_packages_crates/workspaces.md) will look a bit different. For example: - -```toml -[workspace] -members = ["crates/a", "crates/b"] -default-member = "crates/a" -``` - -#### Package section - -The package section defines a number of fields including: - -- `name` (**required**) - the name of the package -- `type` (**required**) - can be "bin", "lib", or "contract" to specify whether its a binary, library or Aztec contract -- `authors` (optional) - authors of the project -- `compiler_version` - specifies the version of the compiler to use. This is enforced by the compiler and follow's [Rust's versioning](https://doc.rust-lang.org/cargo/reference/manifest.html#the-version-field), so a `compiler_version = 0.18.0` will enforce Nargo version 0.18.0, `compiler_version = ^0.18.0` will enforce anything above 0.18.0 but below 0.19.0, etc. For more information, see how [Rust handles these operators](https://docs.rs/semver/latest/semver/enum.Op.html) -- `description` (optional) -- `entry` (optional) - a relative filepath to use as the entry point into your package (overrides the default of `src/lib.nr` or `src/main.nr`) -- `backend` (optional) -- `license` (optional) - -#### Dependencies section - -This is where you will specify any dependencies for your project. See the [Dependencies page](../../noir/modules_packages_crates/dependencies.md) for more info. - -`./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or -verifier contract respectively. - -### main.nr - -The _main.nr_ file contains a `main` method, this method is the entry point into your Noir program. - -In our sample program, _main.nr_ looks like this: - -```rust -fn main(x : Field, y : Field) { - assert(x != y); -} -``` - -The parameters `x` and `y` can be seen as the API for the program and must be supplied by the -prover. Since neither `x` nor `y` is marked as public, the verifier does not supply any inputs, when -verifying the proof. - -The prover supplies the values for `x` and `y` in the _Prover.toml_ file. - -As for the program body, `assert` ensures that the condition to be satisfied (e.g. `x != y`) is -constrained by the proof of the execution of said program (i.e. if the condition was not met, the -verifier would reject the proof as an invalid proof). - -### Prover.toml - -The _Prover.toml_ file is a file which the prover uses to supply his witness values(both private and -public). - -In our hello world program the _Prover.toml_ file looks like this: - -```toml -x = "1" -y = "2" -``` - -When the command `nargo prove` is executed, two processes happen: - -1. Noir creates a proof that `x`, which holds the value of `1`, and `y`, which holds the value of `2`, - is not equal. This inequality constraint is due to the line `assert(x != y)`. - -2. Noir creates and stores the proof of this statement in the _proofs_ directory in a file called your-project.proof. So if your project is named "private_voting" (defined in the project Nargo.toml), the proof will be saved at `./proofs/private_voting.proof`. Opening this file will display the proof in hex format. - -#### Arrays of Structs - -The following code shows how to pass an array of structs to a Noir program to generate a proof. - -```rust -// main.nr -struct Foo { - bar: Field, - baz: Field, -} - -fn main(foos: [Foo; 3]) -> pub Field { - foos[2].bar + foos[2].baz -} -``` - -Prover.toml: - -```toml -[[foos]] # foos[0] -bar = 0 -baz = 0 - -[[foos]] # foos[1] -bar = 0 -baz = 0 - -[[foos]] # foos[2] -bar = 1 -baz = 2 -``` - -#### Custom toml files - -You can specify a `toml` file with a different name to use for proving by using the `--prover-name` or `-p` flags. - -This command looks for proof inputs in the default **Prover.toml** and generates the proof and saves it at `./proofs/.proof`: - -```bash -nargo prove -``` - -This command looks for proof inputs in the custom **OtherProver.toml** and generates proof and saves it at `./proofs/.proof`: - -```bash -nargo prove -p OtherProver -``` - -## Verifying a Proof - -When the command `nargo verify` is executed, two processes happen: - -1. Noir checks in the _proofs_ directory for a proof file with the project name (eg. test_project.proof) - -2. If that file is found, the proof's validity is checked - -> **Note:** The validity of the proof is linked to the current Noir program; if the program is -> changed and the verifier verifies the proof, it will fail because the proof is not valid for the -> _modified_ Noir program. - -In production, the prover and the verifier are usually two separate entities. A prover would -retrieve the necessary inputs, execute the Noir program, generate a proof and pass it to the -verifier. The verifier would then retrieve the public inputs, usually from external sources, and -verify the validity of the proof against it. - -Take a private asset transfer as an example: - -A person using a browser as the prover would retrieve private inputs locally (e.g. the user's private key) and -public inputs (e.g. the user's encrypted balance on-chain), compute the transfer, generate a proof -and submit it to the verifier smart contract. - -The verifier contract would then draw the user's encrypted balance directly from the blockchain and -verify the proof submitted against it. If the verification passes, additional functions in the -verifier contract could trigger (e.g. approve the asset transfer). - -Now that you understand the concepts, you'll probably want some editor feedback while you are writing more complex code. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/installation/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/installation/_category_.json deleted file mode 100644 index 0c02fb5d4d7..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/installation/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "position": 0, - "label": "Install Nargo", - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/installation/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/installation/index.md deleted file mode 100644 index 4ef86aa5914..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/installation/index.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Nargo Installation -description: - nargo is a command line tool for interacting with Noir programs. This page is a quick guide on how to install Nargo through the most common and easy method, noirup -keywords: [ - Nargo - Noir - Rust - Cargo - Noirup - Installation - Terminal Commands - Version Check - Nightlies - Specific Versions - Branches - Noirup Repository -] -pagination_next: getting_started/hello_noir/index ---- - -`nargo` is the one-stop-shop for almost everything related with Noir. The name comes from our love for Rust and its package manager `cargo`. - -With `nargo`, you can start new projects, compile, execute, prove, verify, test, generate solidity contracts, and do pretty much all that is available in Noir. - -Similarly to `rustup`, we also maintain an easy installation method that covers most machines: `noirup`. - -## Installing Noirup - -Open a terminal on your machine, and write: - -```bash -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -Close the terminal, open another one, and run - -```bash -noirup -``` - -Done. That's it. You should have the latest version working. You can check with `nargo --version`. - -You can also install nightlies, specific versions -or branches. Check out the [noirup repository](https://github.com/noir-lang/noirup) for more -information. - -Now we're ready to start working on [our first Noir program!](../hello_noir/index.md) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/installation/other_install_methods.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/installation/other_install_methods.md deleted file mode 100644 index 076f26dfd94..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/installation/other_install_methods.md +++ /dev/null @@ -1,254 +0,0 @@ ---- -title: Alternative Install Methods -description: There are different ways to install Nargo, the one-stop shop and command-line tool for developing Noir programs. This guide explains other methods that don't rely on noirup, such as compiling from source, installing from binaries, and using WSL for windows -keywords: [ - Installation - Nargo - Noirup - Binaries - Compiling from Source - WSL for Windows - macOS - Linux - Nix - Direnv - Shell & editor experience - Building and testing - Uninstalling Nargo - Noir vs code extension, - ] -sidebar_position: 1 ---- - -## Encouraged Installation Method: Noirup - -Noirup is the endorsed method for installing Nargo, streamlining the process of fetching binaries or compiling from source. It supports a range of options to cater to your specific needs, from nightly builds and specific versions to compiling from various sources. - -### Installing Noirup - -First, ensure you have `noirup` installed: - -```sh -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -### Fetching Binaries - -With `noirup`, you can easily switch between different Nargo versions, including nightly builds: - -- **Nightly Version**: Install the latest nightly build. - - ```sh - noirup --version nightly - ``` - -- **Specific Version**: Install a specific version of Nargo. - ```sh - noirup --version - ``` - -### Compiling from Source - -`noirup` also enables compiling Nargo from various sources: - -- **From a Specific Branch**: Install from the latest commit on a branch. - - ```sh - noirup --branch - ``` - -- **From a Fork**: Install from the main branch of a fork. - - ```sh - noirup --repo - ``` - -- **From a Specific Branch in a Fork**: Install from a specific branch in a fork. - - ```sh - noirup --repo --branch - ``` - -- **From a Specific Pull Request**: Install from a specific PR. - - ```sh - noirup --pr - ``` - -- **From a Specific Commit**: Install from a specific commit. - - ```sh - noirup -C - ``` - -- **From Local Source**: Compile and install from a local directory. - ```sh - noirup --path ./path/to/local/source - ``` - -## Alternate Installation Methods (No Longer Recommended) - -While the following methods are available, they are no longer recommended. We advise using noirup for a more efficient and flexible installation experience. - -However, there are other methods for installing Nargo: - -- [Binaries](#option-1-installing-from-binaries) -- [Compiling from Source](#option-2-compile-from-source) -- [WSL for Windows](#option-3-wsl-for-windows) - -### Option 1: Installing from Binaries - -See [GitHub Releases](https://github.com/noir-lang/noir/releases) for the latest and previous -platform specific binaries. - -#### Step 1 - -Paste and run the following in the terminal to extract and install the binary: - -> **macOS / Linux:** If you are prompted with `Permission denied` when running commands, prepend -> `sudo` and re-run it. - -##### macOS (Apple Silicon) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.24.0/nargo-aarch64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### macOS (Intel) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.24.0/nargo-x86_64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### Linux (Bash) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.24.0/nargo-x86_64-unknown-linux-gnu.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -C $HOME/.nargo/bin/ && \ -echo -e '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.bashrc && \ -source ~/.bashrc -``` - -#### Step 2 - -Check if the installation was successful by running `nargo --version`. You should get a version number. - -> **macOS:** If you are prompted with an OS alert, right-click and open the _nargo_ executable from -> Finder. Close the new terminal popped up and `nargo` should now be accessible. - -### Option 2: Compile from Source - -Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. It helps mitigating issues commonly associated with dependency management, such as conflicts between required package versions for different projects (often referred to as "dependency hell"). - -Combined with direnv, which automatically sets or clears environment variables based on the directory, it further simplifies the development process by seamlessly integrating with the developer's shell, facilitating an efficient and reliable workflow for managing and deploying Noir projects with multiple dependencies. - -#### Setting up your environment - -For the best experience, please follow these instructions to setup your environment: - -1. Install Nix following [their guide](https://nixos.org/download.html) for your operating system. -2. Create the file `~/.config/nix/nix.conf` with the contents: - -```ini -experimental-features = nix-command -extra-experimental-features = flakes -``` - -3. Install direnv into your Nix profile by running: - -```sh -nix profile install nixpkgs#direnv -``` - -4. Add direnv to your shell following [their guide](https://direnv.net/docs/hook.html). - 1. For bash or zshell, add `eval "$(direnv hook bash)"` or `eval "$(direnv hook zsh)"` to your ~/.bashrc or ~/.zshrc file, respectively. -5. Restart your shell. - -#### Shell & editor experience - -Now that your environment is set up, you can get to work on the project. - -1. Clone the repository, such as: - -```sh -git clone git@github.com:noir-lang/noir -``` - -> Replacing `noir` with whichever repository you want to work on. - -2. Navigate to the directory: - -```sh -cd noir -``` - -> Replacing `noir` with whichever repository you cloned. - -3. You should see a **direnv error** because projects aren't allowed by default. Make sure you've reviewed and trust our `.envrc` file, then you need to run: - -```sh -direnv allow -``` - -4. Now, wait awhile for all the native dependencies to be built. This will take some time and direnv will warn you that it is taking a long time, but we just need to let it run. - -5. Once you are presented with your prompt again, you can start your editor within the project directory (we recommend [VSCode](https://code.visualstudio.com/)): - -```sh -code . -``` - -6. (Recommended) When launching VSCode for the first time, you should be prompted to install our recommended plugins. We highly recommend installing these for the best development experience. - -#### Building and testing - -Assuming you are using `direnv` to populate your environment, building and testing the project can be done -with the typical `cargo build`, `cargo test`, and `cargo clippy` commands. You'll notice that the `cargo` version matches the version we specify in `rust-toolchain.toml`, which is 1.71.1 at the time of this writing. - -If you want to build the entire project in an isolated sandbox, you can use Nix commands: - -1. `nix build .` (or `nix build . -L` for verbose output) to build the project in a Nix sandbox. -2. `nix flake check` (or `nix flake check -L` for verbose output) to run clippy and tests in a Nix sandbox. - -#### Without `direnv` - -If you have hesitations with using direnv, you can launch a subshell with `nix develop` and then launch your editor from within the subshell. However, if VSCode was already launched in the project directory, the environment won't be updated. - -Advanced: If you aren't using direnv nor launching your editor within the subshell, you can try to install Barretenberg and other global dependencies the package needs. This is an advanced workflow and likely won't receive support! - -### Option 3: WSL (for Windows) - -The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed natively. However, it is available by using Windows Subsystem for Linux (WSL). - -Step 1: Follow the instructions [here](https://learn.microsoft.com/en-us/windows/wsl/install) to install and run WSL. - -step 2: Follow the [Noirup instructions](#encouraged-installation-method-noirup). - -## Uninstalling Nargo - -### Noirup - -If you installed Nargo with `noirup` or through directly downloading binaries, you can uninstall Nargo by removing the files in `~/.nargo`, `~/nargo`, and `~/noir_cache`. This ensures that all installed binaries, configurations, and cache related to Nargo are fully removed from your system. - -```bash -rm -r ~/.nargo -rm -r ~/nargo -rm -r ~/noir_cache -``` - -### Nix - -If you installed Nargo with Nix or compiled it from source, you can remove the binary located at `~/.nix-profile/bin/nargo`. - -```bash -rm ~/.nix-profile/bin/nargo -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/tooling/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/tooling/_category_.json deleted file mode 100644 index 55804c03a71..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/tooling/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "position": 2, - "label": "Tooling", - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/tooling/index.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/tooling/index.mdx deleted file mode 100644 index ec9ccea4115..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/tooling/index.mdx +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: Tooling -Description: This section provides information about the various tools and utilities available for Noir development. It covers IDE tools, Codespaces, and community projects. -Keywords: [Noir, Development, Playground, IDE Tools, Language Service Provider, VS Code Extension, Codespaces, noir-starter, Community Projects, Awesome Noir Repository, Developer Tooling] ---- - -Noir is meant to be easy to develop with. For that reason, a number of utilities have been put together to ease the development process as much as feasible in the zero-knowledge world. - -## IDE tools - -When you install Nargo, you're also installing a Language Service Provider (LSP), which can be used by IDEs to provide syntax highlighting, codelens, warnings, and more. - -The easiest way to use these tools is by installing the [Noir VS Code extension](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). - -## Codespaces - -Some Noir repos have leveraged Codespaces in order to ease the development process. You can visit the [noir-starter](https://github.com/noir-lang/noir-starter) for an example. - - - -## GitHub Actions - -You can use `noirup` with GitHub Actions for CI/CD and automated testing. It is as simple as -installing `noirup` and running tests in your GitHub Action `yml` file. - -See the -[config file in the Noir repo](https://github.com/TomAFrench/noir-hashes/blob/master/.github/workflows/noir.yml) for an example usage. - -## Community projects - -As an open-source project, Noir has received many contributions over time. Some of them are related with developer tooling, and you can see some of them in [Awesome Noir repository](https://github.com/noir-lang/awesome-noir#dev-tools) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/tooling/language_server.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/tooling/language_server.md deleted file mode 100644 index 81e0356ef8a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/tooling/language_server.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Language Server -description: Learn about the Noir Language Server, how to install the components, and configuration that may be required. -keywords: [Nargo, Language Server, LSP, VSCode, Visual Studio Code] -sidebar_position: 0 ---- - -This section helps you install and configure the Noir Language Server. - -The Language Server Protocol (LSP) has two components, the [Server](#language-server) and the [Client](#language-client). Below we describe each in the context of Noir. - -## Language Server - -The Server component is provided by the Nargo command line tool that you installed at the beginning of this guide. -As long as Nargo is installed and you've used it to run other commands in this guide, it should be good to go! - -If you'd like to verify that the `nargo lsp` command is available, you can run `nargo --help` and look for `lsp` in the list of commands. If you see it, you're using a version of Noir with LSP support. - -## Language Client - -The Client component is usually an editor plugin that launches the Server. It communicates LSP messages between the editor and the Server. For example, when you save a file, the Client will alert the Server, so it can try to compile the project and report any errors. - -Currently, Noir provides a Language Client for Visual Studio Code via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). - -> **Note:** Noir's Language Server Protocol support currently assumes users' VSCode workspace root to be the same as users' Noir project root (i.e. where Nargo.toml lies). -> -> If LSP features seem to be missing / malfunctioning, make sure you are opening your Noir project directly (instead of as a sub-folder) in your VSCode instance. - -When your language server is running correctly and the VSCode plugin is installed, you should see handy codelens buttons for compilation, measuring circuit size, execution, and tests: - -![Compile and Execute](@site/static/img/codelens_compile_execute.png) -![Run test](@site/static/img/codelens_run_test.png) - -You should also see your tests in the `testing` panel: - -![Testing panel](@site/static/img/codelens_testing_panel.png) - -### Configuration - -- **Noir: Enable LSP** - If checked, the extension will launch the Language Server via `nargo lsp` and communicate with it. -- **Noir: Nargo Flags** - Additional flags may be specified if you require them to be added when the extension calls `nargo lsp`. -- **Noir: Nargo Path** - An absolute path to a Nargo binary with the `lsp` command. This may be useful if Nargo is not within the `PATH` of your editor. -- **Noir > Trace: Server** - Setting this to `"messages"` or `"verbose"` will log LSP messages between the Client and Server. Useful for debugging. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/tooling/testing.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/tooling/testing.md deleted file mode 100644 index d3e0c522473..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/tooling/testing.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -title: Testing in Noir -description: Learn how to use Nargo to test your Noir program in a quick and easy way -keywords: [Nargo, testing, Noir, compile, test] -sidebar_position: 1 ---- - -You can test your Noir programs using Noir circuits. - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. - -For example if you have a program like: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test] -fn test_add() { - assert(add(2,2) == 4); - assert(add(0,1) == 1); - assert(add(1,0) == 1); -} -``` - -Running `nargo test` will test that the `test_add` function can be executed while satisfying all -the constraints which allows you to test that add returns the expected values. Test functions can't -have any arguments currently. - -### Test fail - -You can write tests that are expected to fail by using the decorator `#[test(should_fail)]`. For example: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test(should_fail)] -fn test_add() { - assert(add(2,2) == 5); -} -``` - -You can be more specific and make it fail with a specific reason by using `should_fail_with = "`: - -```rust -fn main(african_swallow_avg_speed : Field) { - assert(african_swallow_avg_speed == 65, "What is the airspeed velocity of an unladen swallow"); -} - -#[test] -fn test_king_arthur() { - main(65); -} - -#[test(should_fail_with = "What is the airspeed velocity of an unladen swallow")] -fn test_bridgekeeper() { - main(32); -} - -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/how_to/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/how_to/_category_.json deleted file mode 100644 index 23b560f610b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/how_to/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 1, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/how_to/how-to-oracles.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/how_to/how-to-oracles.md deleted file mode 100644 index ab225b9421f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/how_to/how-to-oracles.md +++ /dev/null @@ -1,280 +0,0 @@ ---- -title: How to use Oracles -description: Learn how to use oracles in your Noir program with examples in both Nargo and NoirJS. This guide also covers writing a JSON RPC server and providing custom foreign call handlers for NoirJS. -keywords: - - Noir Programming - - Oracles - - Nargo - - NoirJS - - JSON RPC Server - - Foreign Call Handlers -sidebar_position: 1 ---- - -This guide shows you how to use oracles in your Noir program. For the sake of clarity, it assumes that: - -- You have read the [explainer on Oracles](../explainers/explainer-oracle.md) and are comfortable with the concept. -- You have a Noir program to add oracles to. You can create one using the [vite-hardhat starter](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat) as a boilerplate. -- You understand the concept of a JSON-RPC server. Visit the [JSON-RPC website](https://www.jsonrpc.org/) if you need a refresher. -- You are comfortable with server-side JavaScript (e.g. Node.js, managing packages, etc.). - -For reference, you can find the snippets used in this tutorial on the [Aztec DevRel Repository](https://github.com/AztecProtocol/dev-rel/tree/main/code-snippets/how-to-oracles). - -## Rundown - -This guide has 3 major steps: - -1. How to modify our Noir program to make use of oracle calls as unconstrained functions -2. How to write a JSON RPC Server to resolve these oracle calls with Nargo -3. How to use them in Nargo and how to provide a custom resolver in NoirJS - -## Step 1 - Modify your Noir program - -An oracle is defined in a Noir program by defining two methods: - -- An unconstrained method - This tells the compiler that it is executing an [unconstrained functions](../noir/concepts//unconstrained.md). -- A decorated oracle method - This tells the compiler that this method is an RPC call. - -An example of an oracle that returns a `Field` would be: - -```rust -#[oracle(getSqrt)] -unconstrained fn sqrt(number: Field) -> Field { } - -unconstrained fn get_sqrt(number: Field) -> Field { - sqrt(number) -} -``` - -In this example, we're wrapping our oracle function in a unconstrained method, and decorating it with `oracle(getSqrt)`. We can then call the unconstrained function as we would call any other function: - -```rust -fn main(input: Field) { - let sqrt = get_sqrt(input); -} -``` - -In the next section, we will make this `getSqrt` (defined on the `sqrt` decorator) be a method of the RPC server Noir will use. - -:::danger - -As explained in the [Oracle Explainer](../explainers/explainer-oracle.md), this `main` function is unsafe unless you constrain its return value. For example: - -```rust -fn main(input: Field) { - let sqrt = get_sqrt(input); - assert(sqrt.pow_32(2) as u64 == input as u64); // <---- constrain the return of an oracle! -} -``` - -::: - -:::info - -Currently, oracles only work with single params or array params. For example: - -```rust -#[oracle(getSqrt)] -unconstrained fn sqrt([Field; 2]) -> [Field; 2] { } -``` - -::: - -## Step 2 - Write an RPC server - -Brillig will call *one* RPC server. Most likely you will have to write your own, and you can do it in whatever language you prefer. In this guide, we will do it in Javascript. - -Let's use the above example of an oracle that consumes an array with two `Field` and returns their square roots: - -```rust -#[oracle(getSqrt)] -unconstrained fn sqrt(input: [Field; 2]) -> [Field; 2] { } - -unconstrained fn get_sqrt(input: [Field; 2]) -> [Field; 2] { - sqrt(input) -} - -fn main(input: [Field; 2]) { - let sqrt = get_sqrt(input); - assert(sqrt[0].pow_32(2) as u64 == input[0] as u64); - assert(sqrt[1].pow_32(2) as u64 == input[1] as u64); -} -``` - -:::info - -Why square root? - -In general, computing square roots is computationally more expensive than multiplications, which takes a toll when speaking about ZK applications. In this case, instead of calculating the square root in Noir, we are using our oracle to offload that computation to be made in plain. In our circuit we can simply multiply the two values. - -::: - -Now, we should write the correspondent RPC server, starting with the [default JSON-RPC 2.0 boilerplate](https://www.npmjs.com/package/json-rpc-2.0#example): - -```js -import { JSONRPCServer } from "json-rpc-2.0"; -import express from "express"; -import bodyParser from "body-parser"; - -const app = express(); -app.use(bodyParser.json()); - -const server = new JSONRPCServer(); -app.post("/", (req, res) => { - const jsonRPCRequest = req.body; - server.receive(jsonRPCRequest).then((jsonRPCResponse) => { - if (jsonRPCResponse) { - res.json(jsonRPCResponse); - } else { - res.sendStatus(204); - } - }); -}); - -app.listen(5555); -``` - -Now, we will add our `getSqrt` method, as expected by the `#[oracle(getSqrt)]` decorator in our Noir code. It maps through the params array and returns their square roots: - -```js -server.addMethod("getSqrt", async (params) => { - const values = params[0].Array.map(({ inner }) => { - return { inner: `${Math.sqrt(parseInt(inner, 16))}` }; - }); - return { values: [{ Array: values }] }; -}); -``` - -:::tip - -Brillig expects an object with an array of values. Each value is an object declaring to be `Single` or `Array` and returning a `inner` property *as a string*. For example: - -```json -{ "values": [{ "Array": [{ "inner": "1" }, { "inner": "2"}]}]} -{ "values": [{ "Single": { "inner": "1" }}]} -{ "values": [{ "Single": { "inner": "1" }}, { "Array": [{ "inner": "1", { "inner": "2" }}]}]} -``` - -If you're using Typescript, the following types may be helpful in understanding the expected return value and making sure they're easy to follow: - -```js -interface Value { - inner: string, -} - -interface SingleForeignCallParam { - Single: Value, -} - -interface ArrayForeignCallParam { - Array: Value[], -} - -type ForeignCallParam = SingleForeignCallParam | ArrayForeignCallParam; - -interface ForeignCallResult { - values: ForeignCallParam[], -} -``` - -::: - -## Step 3 - Usage with Nargo - -Using the [`nargo` CLI tool](../getting_started/installation/index.md), you can use oracles in the `nargo test`, `nargo execute` and `nargo prove` commands by passing a value to `--oracle-resolver`. For example: - -```bash -nargo test --oracle-resolver http://localhost:5555 -``` - -This tells `nargo` to use your RPC Server URL whenever it finds an oracle decorator. - -## Step 4 - Usage with NoirJS - -In a JS environment, an RPC server is not strictly necessary, as you may want to resolve your oracles without needing any JSON call at all. NoirJS simply expects that you pass a callback function when you generate proofs, and that callback function can be anything. - -For example, if your Noir program expects the host machine to provide CPU pseudo-randomness, you could simply pass it as the `foreignCallHandler`. You don't strictly need to create an RPC server to serve pseudo-randomness, as you may as well get it directly in your app: - -```js -const foreignCallHandler = (name, inputs) => crypto.randomBytes(16) // etc - -await noir.generateProof(inputs, foreignCallHandler) -``` - -As one can see, in NoirJS, the [`foreignCallHandler`](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) function simply means "a callback function that returns a value of type [`ForeignCallOutput`](../reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md). It doesn't have to be an RPC call like in the case for Nargo. - -:::tip - -Does this mean you don't have to write an RPC server like in [Step #2](#step-2---write-an-rpc-server)? - -You don't technically have to, but then how would you run `nargo test` or `nargo prove`? To use both `Nargo` and `NoirJS` in your development flow, you will have to write a JSON RPC server. - -::: - -In this case, let's make `foreignCallHandler` call the JSON RPC Server we created in [Step #2](#step-2---write-an-rpc-server), by making it a JSON RPC Client. - -For example, using the same `getSqrt` program in [Step #1](#step-1---modify-your-noir-program) (comments in the code): - -```js -import { JSONRPCClient } from "json-rpc-2.0"; - -// declaring the JSONRPCClient -const client = new JSONRPCClient((jsonRPCRequest) => { -// hitting the same JSON RPC Server we coded above - return fetch("http://localhost:5555", { - method: "POST", - headers: { - "content-type": "application/json", - }, - body: JSON.stringify(jsonRPCRequest), - }).then((response) => { - if (response.status === 200) { - return response - .json() - .then((jsonRPCResponse) => client.receive(jsonRPCResponse)); - } else if (jsonRPCRequest.id !== undefined) { - return Promise.reject(new Error(response.statusText)); - } - }); -}); - -// declaring a function that takes the name of the foreign call (getSqrt) and the inputs -const foreignCallHandler = async (name, input) => { - // notice that the "inputs" parameter contains *all* the inputs - // in this case we to make the RPC request with the first parameter "numbers", which would be input[0] - const oracleReturn = await client.request(name, [ - { Array: input[0].map((i) => ({ inner: i.toString("hex") })) }, - ]); - return [oracleReturn.values[0].Array.map((x) => x.inner)]; -}; - -// the rest of your NoirJS code -const input = { input: [4, 16] }; -const { witness } = await noir.execute(numbers, foreignCallHandler); -``` - -:::tip - -If you're in a NoirJS environment running your RPC server together with a frontend app, you'll probably hit a familiar problem in full-stack development: requests being blocked by [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) policy. For development only, you can simply install and use the [`cors` npm package](https://www.npmjs.com/package/cors) to get around the problem: - -```bash -yarn add cors -``` - -and use it as a middleware: - -```js -import cors from "cors"; - -const app = express(); -app.use(cors()) -``` - -::: - -## Conclusion - -Hopefully by the end of this guide, you should be able to: - -- Write your own logic around Oracles and how to write a JSON RPC server to make them work with your Nargo commands. -- Provide custom foreign call handlers for NoirJS. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/how_to/how-to-recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/how_to/how-to-recursion.md deleted file mode 100644 index 4c45bb87ae2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/how_to/how-to-recursion.md +++ /dev/null @@ -1,179 +0,0 @@ ---- -title: How to use recursion on NoirJS -description: Learn how to implement recursion with NoirJS, a powerful tool for creating smart contracts on the EVM blockchain. This guide assumes familiarity with NoirJS, solidity verifiers, and the Barretenberg proving backend. Discover how to generate both final and intermediate proofs using `noir_js` and `backend_barretenberg`. -keywords: - [ - "NoirJS", - "EVM blockchain", - "smart contracts", - "recursion", - "solidity verifiers", - "Barretenberg backend", - "noir_js", - "backend_barretenberg", - "intermediate proofs", - "final proofs", - "nargo compile", - "json import", - "recursive circuit", - "recursive app" - ] -sidebar_position: 1 ---- - -This guide shows you how to use recursive proofs in your NoirJS app. For the sake of clarity, it is assumed that: - -- You already have a NoirJS app. If you don't, please visit the [NoirJS tutorial](../tutorials/noirjs_app.md) and the [reference](../reference/NoirJS/noir_js/index.md). -- You are familiar with what are recursive proofs and you have read the [recursion explainer](../explainers/explainer-recursion.md) -- You already built a recursive circuit following [the reference](../noir/standard_library/recursion.md), and understand how it works. - -It is also assumed that you're not using `noir_wasm` for compilation, and instead you've used [`nargo compile`](../reference/nargo_commands.md) to generate the `json` you're now importing into your project. However, the guide should work just the same if you're using `noir_wasm`. - -:::info - -As you've read in the [explainer](../explainers/explainer-recursion.md), a recursive proof is an intermediate proof. This means that it doesn't necessarily generate the final step that makes it verifiable in a smart contract. However, it is easy to verify within another circuit. - -While "standard" usage of NoirJS packages abstracts final proofs, it currently lacks the necessary interface to abstract away intermediate proofs. This means that these proofs need to be created by using the backend directly. - -In short: - -- `noir_js` generates *only* final proofs -- `backend_barretenberg` generates both types of proofs - -::: - -In a standard recursive app, you're also dealing with at least two circuits. For the purpose of this guide, we will assume the following: - -- `main`: a circuit of type `assert(x != y)`, where `main` is marked with a `#[recursive]` attribute. This attribute states that the backend should generate proofs that are friendly for verification within another circuit. -- `recursive`: a circuit that verifies `main` - -For a full example on how recursive proofs work, please refer to the [noir-examples](https://github.com/noir-lang/noir-examples) repository. We will *not* be using it as a reference for this guide. - -## Step 1: Setup - -In a common NoirJS app, you need to instantiate a backend with something like `const backend = new Backend(circuit)`. Then you feed it to the `noir_js` interface. - -For recursion, this doesn't happen, and the only need for `noir_js` is only to `execute` a circuit and get its witness and return value. Everything else is not interfaced, so it needs to happen on the `backend` object. - -It is also recommended that you instantiate the backend with as many threads as possible, to allow for maximum concurrency: - -```js -const backend = new Backend(circuit, { threads: 8 }) -``` - -:::tip -You can use the [`os.cpus()`](https://nodejs.org/api/os.html#oscpus) object in `nodejs` or [`navigator.hardwareConcurrency`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/hardwareConcurrency) on the browser to make the most out of those glorious cpu cores -::: - -## Step 2: Generating the witness and the proof for `main` - -After instantiating the backend, you should also instantiate `noir_js`. We will use it to execute the circuit and get the witness. - -```js -const noir = new Noir(circuit, backend) -const { witness } = noir.execute(input) -``` - -With this witness, you are now able to generate the intermediate proof for the main circuit: - -```js -const { proof, publicInputs } = await backend.generateProof(witness) -``` - -:::warning - -Always keep in mind what is actually happening on your development process, otherwise you'll quickly become confused about what circuit we are actually running and why! - -In this case, you can imagine that Alice (running the `main` circuit) is proving something to Bob (running the `recursive` circuit), and Bob is verifying her proof within his proof. - -With this in mind, it becomes clear that our intermediate proof is the one *meant to be verified within another circuit*, so it must be Alice's. Actually, the only final proof in this theoretical scenario would be the last one, sent on-chain. - -::: - -## Step 3 - Verification and proof artifacts - -Optionally, you are able to verify the intermediate proof: - -```js -const verified = await backend.verifyProof({ proof, publicInputs }) -``` - -This can be useful to make sure our intermediate proof was correctly generated. But the real goal is to do it within another circuit. For that, we need to generate recursive proof artifacts that will be passed to the circuit that is verifying the proof we just generated. Instead of passing the proof and verification key as a byte array, we pass them as fields which makes it cheaper to verify in a circuit: - -```js -const { proofAsFields, vkAsFields, vkHash } = await backend.generateRecursiveProofArtifacts( { publicInputs, proof }, publicInputsCount) -``` - -This call takes the public inputs and the proof, but also the public inputs count. While this is easily retrievable by simply counting the `publicInputs` length, the backend interface doesn't currently abstract it away. - -:::info - -The `proofAsFields` has a constant size `[Field; 93]` and verification keys in Barretenberg are always `[Field; 114]`. - -::: - -:::warning - -One common mistake is to forget *who* makes this call. - -In a situation where Alice is generating the `main` proof, if she generates the proof artifacts and sends them to Bob, which gladly takes them as true, this would mean Alice could prove anything! - -Instead, Bob needs to make sure *he* extracts the proof artifacts, using his own instance of the `main` circuit backend. This way, Alice has to provide a valid proof for the correct `main` circuit. - -::: - -## Step 4 - Recursive proof generation - -With the artifacts, generating a recursive proof is no different from a normal proof. You simply use the `backend` (with the recursive circuit) to generate it: - -```js -const recursiveInputs = { - verification_key: vkAsFields, // array of length 114 - proof: proofAsFields, // array of length 93 + size of public inputs - publicInputs: [mainInput.y], // using the example above, where `y` is the only public input - key_hash: vkHash, -} - -const { witness, returnValue } = noir.execute(recursiveInputs) // we're executing the recursive circuit now! -const { proof, publicInputs } = backend.generateProof(witness) -const verified = backend.verifyProof({ proof, publicInputs }) -``` - -You can obviously chain this proof into another proof. In fact, if you're using recursive proofs, you're probably interested of using them this way! - -:::tip - -Managing circuits and "who does what" can be confusing. To make sure your naming is consistent, you can keep them in an object. For example: - -```js -const circuits = { - main: mainJSON, - recursive: recursiveJSON -} -const backends = { - main: new BarretenbergBackend(circuits.main), - recursive: new BarretenbergBackend(circuits.recursive) -} -const noir_programs = { - main: new Noir(circuits.main, backends.main), - recursive: new Noir(circuits.recursive, backends.recursive) -} -``` - -This allows you to neatly call exactly the method you want without conflicting names: - -```js -// Alice runs this 👇 -const { witness: mainWitness } = await noir_programs.main.execute(input) -const proof = await backends.main.generateProof(mainWitness) - -// Bob runs this 👇 -const verified = await backends.main.verifyProof(proof) -const { proofAsFields, vkAsFields, vkHash } = await backends.main.generateRecursiveProofArtifacts( - proof, - numPublicInputs, -); -const recursiveProof = await noir_programs.recursive.generateProof(recursiveInputs) -``` - -::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/how_to/how-to-solidity-verifier.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/how_to/how-to-solidity-verifier.md deleted file mode 100644 index e3c7c1065da..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/how_to/how-to-solidity-verifier.md +++ /dev/null @@ -1,231 +0,0 @@ ---- -title: Generate a Solidity Verifier -description: - Learn how to run the verifier as a smart contract on the blockchain. Compile a Solidity verifier - contract for your Noir program and deploy it on any EVM blockchain acting as a verifier smart - contract. Read more to find out -keywords: - [ - solidity verifier, - smart contract, - blockchain, - compiler, - plonk_vk.sol, - EVM blockchain, - verifying Noir programs, - proving backend, - Barretenberg, - ] -sidebar_position: 0 -pagination_next: tutorials/noirjs_app ---- - -Noir has the ability to generate a verifier contract in Solidity, which can be deployed in many EVM-compatible blockchains such as Ethereum. - -This allows for a powerful feature set, as one can make use of the conciseness and the privacy provided by Noir in an immutable ledger. Applications can range from simple P2P guessing games, to complex private DeFi interactions. - -This guide shows you how to generate a Solidity Verifier and deploy it on the [Remix IDE](https://remix.ethereum.org/). It is assumed that: - -- You are comfortable with the Solidity programming language and understand how contracts are deployed on the Ethereum network -- You have Noir installed and you have a Noir program. If you don't, [get started](../getting_started/installation/index.md) with Nargo and the example Hello Noir circuit -- You are comfortable navigating RemixIDE. If you aren't or you need a refresher, you can find some video tutorials [here](https://www.youtube.com/channel/UCjTUPyFEr2xDGN6Cg8nKDaA) that could help you. - -## Rundown - -Generating a Solidity Verifier contract is actually a one-command process. However, compiling it and deploying it can have some caveats. Here's the rundown of this guide: - -1. How to generate a solidity smart contract -2. How to compile the smart contract in the RemixIDE -3. How to deploy it to a testnet - -## Step 1 - Generate a contract - -This is by far the most straight-forward step. Just run: - -```sh -nargo codegen-verifier -``` - -A new `contract` folder would then be generated in your project directory, containing the Solidity -file `plonk_vk.sol`. It can be deployed to any EVM blockchain acting as a verifier smart contract. - -:::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. - -Barretenberg, the default proving backend for Nargo, supports generation of verifier contracts, for the time being these are only in Solidity. -::: - -## Step 2 - Compiling - -We will mostly skip the details of RemixIDE, as the UI can change from version to version. For now, we can just open -Remix and create a blank workspace. - -![Create Workspace](@site/static/img/how-tos/solidity_verifier_1.png) - -We will create a new file to contain the contract Nargo generated, and copy-paste its content. - -:::warning - -You'll likely see a warning advising you to not trust pasted code. While it is an important warning, it is irrelevant in the context of this guide and can be ignored. We will not be deploying anywhere near a mainnet. - -::: - -To compile our the verifier, we can navigate to the compilation tab: - -![Compilation Tab](@site/static/img/how-tos/solidity_verifier_2.png) - -Remix should automatically match a suitable compiler version. However, hitting the "Compile" button will most likely generate a "Stack too deep" error: - -![Stack too deep](@site/static/img/how-tos/solidity_verifier_3.png) - -This is due to the verify function needing to put many variables on the stack, but enabling the optimizer resolves the issue. To do this, let's open the "Advanced Configurations" tab and enable optimization. The default 200 runs will suffice. - -:::info - -This time we will see a warning about an unused function parameter. This is expected, as the `verify` function doesn't use the `_proof` parameter inside a solidity block, it is loaded from calldata and used in assembly. - -::: - -![Compilation success](@site/static/img/how-tos/solidity_verifier_4.png) - -## Step 3 - Deploying - -At this point we should have a compiled contract read to deploy. If we navigate to the deploy section in Remix, we will see many different environments we can deploy to. The steps to deploy on each environment would be out-of-scope for this guide, so we will just use the default Remix VM. - -Looking closely, we will notice that our "Solidity Verifier" is actually three contracts working together: - -- An `UltraVerificationKey` library which simply stores the verification key for our circuit. -- An abstract contract `BaseUltraVerifier` containing most of the verifying logic. -- A main `UltraVerifier` contract that inherits from the Base and uses the Key contract. - -Remix will take care of the dependencies for us so we can simply deploy the UltraVerifier contract by selecting it and hitting "deploy": - -![Deploying UltraVerifier](@site/static/img/how-tos/solidity_verifier_5.png) - -A contract will show up in the "Deployed Contracts" section, where we can retrieve the Verification Key Hash. This is particularly useful for double-checking the deployer contract is the correct one. - -:::note - -Why "UltraVerifier"? - -To be precise, the Noir compiler (`nargo`) doesn't generate the verifier contract directly. It compiles the Noir code into an intermediate language (ACIR), which is then executed by the backend. So it is the backend that returns the verifier smart contract, not Noir. - -In this case, the Barretenberg Backend uses the UltraPlonk proving system, hence the "UltraVerifier" name. - -::: - -## Step 4 - Verifying - -To verify a proof using the Solidity verifier contract, we call the `verify` function in this extended contract: - -```solidity -function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) -``` - -When using the default example in the [Hello Noir](../getting_started/hello_noir/index.md) guide, the easiest way to confirm that the verifier contract is doing its job is by calling the `verify` function via remix with the required parameters. For `_proof`, run `nargo prove` and use the string in `proof/.proof` (adding the hex `0x` prefix). We can also copy the public input from `Verifier.toml`, as it will be properly formatted as 32-byte strings: - -``` -0x...... , [0x0000.....02] -``` - -A programmatic example of how the `verify` function is called can be seen in the example zk voting application [here](https://github.com/noir-lang/noir-examples/blob/33e598c257e2402ea3a6b68dd4c5ad492bce1b0a/foundry-voting/src/zkVote.sol#L35): - -```solidity -function castVote(bytes calldata proof, uint proposalId, uint vote, bytes32 nullifierHash) public returns (bool) { - // ... - bytes32[] memory publicInputs = new bytes32[](4); - publicInputs[0] = merkleRoot; - publicInputs[1] = bytes32(proposalId); - publicInputs[2] = bytes32(vote); - publicInputs[3] = nullifierHash; - require(verifier.verify(proof, publicInputs), "Invalid proof"); -``` - -:::info[Return Values] - -A circuit doesn't have the concept of a return value. Return values are just syntactic sugar in -Noir. - -Under the hood, the return value is passed as an input to the circuit and is checked at the end of -the circuit program. - -For example, if you have Noir program like this: - -```rust -fn main( - // Public inputs - pubkey_x: pub Field, - pubkey_y: pub Field, - // Private inputs - priv_key: Field, -) -> pub Field -``` - -the `verify` function will expect the public inputs array (second function parameter) to be of length 3, the two inputs and the return value. Like before, these values are populated in Verifier.toml after running `nargo prove`. - -Passing only two inputs will result in an error such as `PUBLIC_INPUT_COUNT_INVALID(3, 2)`. - -In this case, the inputs parameter to `verify` would be an array ordered as `[pubkey_x, pubkey_y, return]`. - -::: - -:::tip[Structs] - -You can pass structs to the verifier contract. They will be flattened so that the array of inputs is 1-dimensional array. - -For example, consider the following program: - -```rust -struct Type1 { - val1: Field, - val2: Field, -} - -struct Nested { - t1: Type1, - is_true: bool, -} - -fn main(x: pub Field, nested: pub Nested, y: pub Field) { - //... -} -``` - -The order of these inputs would be flattened to: `[x, nested.t1.val1, nested.t1.val2, nested.is_true, y]` - -::: - -The other function you can call is our entrypoint `verify` function, as defined above. - -:::tip - -It's worth noticing that the `verify` function is actually a `view` function. A `view` function does not alter the blockchain state, so it doesn't need to be distributed (i.e. it will run only on the executing node), and therefore doesn't cost any gas. - -This can be particularly useful in some situations. If Alice generated a proof and wants Bob to verify its correctness, Bob doesn't need to run Nargo, NoirJS, or any Noir specific infrastructure. He can simply make a call to the blockchain with the proof and verify it is correct without paying any gas. - -It would be incorrect to say that a Noir proof verification costs any gas at all. However, most of the time the result of `verify` is used to modify state (for example, to update a balance, a game state, etc). In that case the whole network needs to execute it, which does incur gas costs (calldata and execution, but not storage). - -::: - -## A Note on EVM chains - -ZK-SNARK verification depends on some precompiled cryptographic primitives such as Elliptic Curve Pairings (if you like complex math, you can read about EC Pairings [here](https://medium.com/@VitalikButerin/exploring-elliptic-curve-pairings-c73c1864e627)). Not all EVM chains support EC Pairings, notably some of the ZK-EVMs. This means that you won't be able to use the verifier contract in all of them. - -For example, chains like `zkSync ERA` and `Polygon zkEVM` do not currently support these precompiles, so proof verification via Solidity verifier contracts won't work. Here's a quick list of EVM chains that have been tested and are known to work: - -- Optimism -- Arbitrum -- Polygon PoS -- Scroll -- Celo - -If you test any other chains, please open a PR on this page to update the list. See [this doc](https://github.com/noir-lang/noir-starter/tree/main/with-foundry#testing-on-chain) for more info about testing verifier contracts on different EVM chains. - -## What's next - -Now that you know how to call a Noir Solidity Verifier on a smart contract using Remix, you should be comfortable with using it with some programmatic frameworks, such as [hardhat](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat) and [foundry](https://github.com/noir-lang/noir-starter/tree/main/with-foundry). - -You can find other tools, examples, boilerplates and libraries in the [awesome-noir](https://github.com/noir-lang/awesome-noir) repository. - -You should also be ready to write and deploy your first NoirJS app and start generating proofs on websites, phones, and NodeJS environments! Head on to the [NoirJS tutorial](../tutorials/noirjs_app.md) to learn how to do that. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/how_to/merkle-proof.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/how_to/merkle-proof.mdx deleted file mode 100644 index 34074659ac1..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/how_to/merkle-proof.mdx +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Prove Merkle Tree Membership -description: - Learn how to use merkle membership proof in Noir to prove that a given leaf is a member of a - merkle tree with a specified root, at a given index. -keywords: - [merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree] ---- - -Let's walk through an example of a merkle membership proof in Noir that proves that a given leaf is -in a merkle tree. - -```rust -use dep::std; - -fn main(message : [Field; 62], index : Field, hashpath : [Field; 40], root : Field) { - let leaf = std::hash::hash_to_field(message); - let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); - assert(merkle_root == root); -} - -``` - -The message is hashed using `hash_to_field`. The specific hash function that is being used is chosen -by the backend. The only requirement is that this hash function can heuristically be used as a -random oracle. If only collision resistance is needed, then one can call `std::hash::pedersen_hash` -instead. - -```rust -let leaf = std::hash::hash_to_field(message); -``` - -The leaf is then passed to a compute_merkle_root function with the root, index and hashpath. The returned root can then be asserted to be the same as the provided root. - -```rust -let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); -assert (merkle_root == root); -``` - -> **Note:** It is possible to re-implement the merkle tree implementation without standard library. -> However, for most usecases, it is enough. In general, the standard library will always opt to be -> as conservative as possible, while striking a balance with efficiency. - -An example, the merkle membership proof, only requires a hash function that has collision -resistance, hence a hash function like Pedersen is allowed, which in most cases is more efficient -than the even more conservative sha256. - -[View an example on the starter repo](https://github.com/noir-lang/noir-examples/blob/3ea09545cabfa464124ec2f3ea8e60c608abe6df/stealthdrop/circuits/src/main.nr#L20) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/how_to/using-devcontainers.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/how_to/using-devcontainers.mdx deleted file mode 100644 index 727ec6ca667..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/how_to/using-devcontainers.mdx +++ /dev/null @@ -1,110 +0,0 @@ ---- -title: Developer Containers and Codespaces -description: "Learn how to set up a devcontainer in your GitHub repository for a seamless coding experience with Codespaces. Follow our easy 8-step guide to create your own Noir environment without installing Nargo locally." -keywords: ["Devcontainer", "Codespaces", "GitHub", "Noir Environment", "Docker Image", "Development Environment", "Remote Coding", "GitHub Codespaces", "Noir Programming", "Nargo", "VSCode Extensions", "Noirup"] -sidebar_position: 1 ---- - -Adding a developer container configuration file to your Noir project is one of the easiest way to unlock coding in browser. - -## What's a devcontainer after all? - -A [Developer Container](https://containers.dev/) (devcontainer for short) is a Docker image that comes preloaded with tools, extensions, and other tools you need to quickly get started or continue a project, without having to install Nargo locally. Think of it as a development environment in a box. - -There are many advantages to this: - -- It's platform and architecture agnostic -- You don't need to have an IDE installed, or Nargo, or use a terminal at all -- It's safer for using on a public machine or public network - -One of the best ways of using devcontainers is... not using your machine at all, for maximum control, performance, and ease of use. -Enter Codespaces. - -## Codespaces - -If a devcontainer is just a Docker image, then what stops you from provisioning a `p3dn.24xlarge` AWS EC2 instance with 92 vCPUs and 768 GiB RAM and using it to prove your 10-gate SNARK proof? - -Nothing! Except perhaps the 30-40$ per hour it will cost you. - -The problem is that provisioning takes time, and I bet you don't want to see the AWS console every time you want to code something real quick. - -Fortunately, there's an easy and free way to get a decent remote machine ready and loaded in less than 2 minutes: Codespaces. [Codespaces is a Github feature](https://github.com/features/codespaces) that allows you to code in a remote machine by using devcontainers, and it's pretty cool: - -- You can start coding Noir in less than a minute -- It uses the resources of a remote machine, so you can code on your grandma's phone if needed be -- It makes it easy to share work with your frens -- It's fully reusable, you can stop and restart whenever you need to - -:::info - -Don't take out your wallet just yet. Free GitHub accounts get about [15-60 hours of coding](https://github.com/features/codespaces) for free per month, depending on the size of your provisioned machine. - -::: - -## Tell me it's _actually_ easy - -It is! - -Github comes with a default codespace and you can use it to code your own devcontainer. That's exactly what we will be doing in this guide. - - - -8 simple steps: - -#### 1. Create a new repository on GitHub. - -#### 2. Click "Start coding with Codespaces". This will use the default image. - -#### 3. Create a folder called `.devcontainer` in the root of your repository. - -#### 4. Create a Dockerfile in that folder, and paste the following code: - -```docker -FROM --platform=linux/amd64 node:lts-bookworm-slim -SHELL ["/bin/bash", "-c"] -RUN apt update && apt install -y curl bash git tar gzip libc++-dev -RUN curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -ENV PATH="/root/.nargo/bin:$PATH" -RUN noirup -ENTRYPOINT ["nargo"] -``` -#### 5. Create a file called `devcontainer.json` in the same folder, and paste the following code: - -```json -{ - "name": "Noir on Codespaces", - "build": { - "context": ".", - "dockerfile": "Dockerfile" - }, - "customizations": { - "vscode": { - "extensions": ["noir-lang.vscode-noir"] - } - } -} -``` -#### 6. Commit and push your changes - -This will pull the new image and build it, so it could take a minute or so - -#### 8. Done! -Just wait for the build to finish, and there's your easy Noir environment. - - -Refer to [noir-starter](https://github.com/noir-lang/noir-starter/) as an example of how devcontainers can be used together with codespaces. - - - -## How do I use it? - -Using the codespace is obviously much easier than setting it up. -Just navigate to your repository and click "Code" -> "Open with Codespaces". It should take a few seconds to load, and you're ready to go. - -:::info - -If you really like the experience, you can add a badge to your readme, links to existing codespaces, and more. -Check out the [official docs](https://docs.github.com/en/codespaces/setting-up-your-project-for-codespaces/setting-up-your-repository/facilitating-quick-creation-and-resumption-of-codespaces) for more info. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/index.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/index.mdx deleted file mode 100644 index 75086ddcdde..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/index.mdx +++ /dev/null @@ -1,67 +0,0 @@ ---- -title: Noir Lang -hide_title: true -description: - Learn about the public alpha release of Noir, a domain specific language heavily influenced by Rust that compiles to - an intermediate language which can be compiled to an arithmetic circuit or a rank-1 constraint system. -keywords: - [Noir, - Domain Specific Language, - Rust, - Intermediate Language, - Arithmetic Circuit, - Rank-1 Constraint System, - Ethereum Developers, - Protocol Developers, - Blockchain Developers, - Proving System, - Smart Contract Language] -sidebar_position: 0 ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -Noir Logo - -Noir is a Domain-Specific Language for SNARK proving systems developed by [Aztec Labs](https://aztec.network/). It allows you to generate complex Zero-Knowledge Programs (ZKP) by using simple and flexible syntax, requiring no previous knowledge on the underlying mathematics or cryptography. - -ZK programs are programs that can generate short proofs of a certain statement without revealing some details about it. You can read more about ZKPs [here](https://dev.to/spalladino/a-beginners-intro-to-coding-zero-knowledge-proofs-c56). - -## What's new about Noir? - -Noir works differently from most ZK languages by taking a two-pronged path. First, it compiles the program to an adaptable intermediate language known as ACIR. From there, depending on a given project's needs, ACIR can be further compiled into an arithmetic circuit for integration with the proving backend. - -:::info - -Noir is backend agnostic, which means it makes no assumptions on which proving backend powers the ZK proof. Being the language that powers [Aztec Contracts](https://docs.aztec.network/developers/contracts/main), it defaults to Aztec's Barretenberg proving backend. - -However, the ACIR output can be transformed to be compatible with other PLONK-based backends, or into a [rank-1 constraint system](https://www.rareskills.io/post/rank-1-constraint-system) suitable for backends such as Arkwork's Marlin. - -::: - -## Who is Noir for? - -Noir can be used both in complex cloud-based backends and in user's smartphones, requiring no knowledge on the underlying math or cryptography. From authorization systems that keep a password in the user's device, to complex on-chain verification of recursive proofs, Noir is designed to abstract away complexity without any significant overhead. Here are some examples of situations where Noir can be used: - - - - Noir Logo - - Aztec Contracts leverage Noir to allow for the storage and execution of private information. Writing an Aztec Contract is as easy as writing Noir, and Aztec developers can easily interact with the network storage and execution through the [Aztec.nr](https://docs.aztec.network/developers/contracts/main) library. - - - Soliditry Verifier Example - Noir can auto-generate Solidity verifier contracts that verify Noir proofs. This allows for non-interactive verification of proofs containing private information in an immutable system. This feature powers a multitude of use-case scenarios, from P2P chess tournaments, to [Aztec Layer-2 Blockchain](https://docs.aztec.network/) - - - Aztec Labs developed NoirJS, an easy interface to generate and verify Noir proofs in a Javascript environment. This allows for Noir to be used in webpages, mobile apps, games, and any other environment supporting JS execution in a standalone manner. - - - - -## Libraries - -Noir is meant to be easy to extend by simply importing Noir libraries just like in Rust. -The [awesome-noir repo](https://github.com/noir-lang/awesome-noir#libraries) is a collection of libraries developed by the Noir community. -Writing a new library is easy and makes code be composable and easy to reuse. See the section on [dependencies](noir/modules_packages_crates/dependencies.md) for more information. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/migration_notes.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/migration_notes.md deleted file mode 100644 index 9f27230a1a0..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/migration_notes.md +++ /dev/null @@ -1,91 +0,0 @@ ---- -title: Migration notes -description: Read about migration notes from previous versions, which could solve problems while updating -keywords: [Noir, notes, migration, updating, upgrading] ---- - -Noir is in full-speed development. Things break fast, wild, and often. This page attempts to leave some notes on errors you might encounter when upgrading and how to resolve them until proper patches are built. - -## ≥0.19 - -### Enforcing `compiler_version` - -From this version on, the compiler will check for the `compiler_version` field in `Nargo.toml`, and will error if it doesn't match the current Nargo version in use. - -To update, please make sure this field in `Nargo.toml` matches the output of `nargo --version`. - -## ≥0.14 - -The index of the [for loops](noir/concepts/control_flow.md#loops) is now of type `u64` instead of `Field`. An example refactor would be: - -```rust -for i in 0..10 { - let i = i as Field; -} -``` - -## ≥v0.11.0 and Nargo backend - -From this version onwards, Nargo starts managing backends through the `nargo backend` command. Upgrading to the versions per usual steps might lead to: - -### `backend encountered an error` - -This is likely due to the existing locally installed version of proving backend (e.g. barretenberg) is incompatible with the version of Nargo in use. - -To fix the issue: - -1. Uninstall the existing backend - -```bash -nargo backend uninstall acvm-backend-barretenberg -``` - -You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. - -2. Reinstall a compatible version of the proving backend. - -If you are using the default barretenberg backend, simply run: - -``` -nargo prove -``` - -with your Noir program. - -This will trigger the download and installation of the latest version of barretenberg compatible with your Nargo in use. - -### `backend encountered an error: illegal instruction` - -On certain Intel-based systems, an `illegal instruction` error may arise due to incompatibility of barretenberg with certain CPU instructions. - -To fix the issue: - -1. Uninstall the existing backend - -```bash -nargo backend uninstall acvm-backend-barretenberg -``` - -You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. - -2. Reinstall a compatible version of the proving backend. - -If you are using the default barretenberg backend, simply run: - -``` -nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/barretenberg-js-binary/raw/master/run-bb.tar.gz -``` - -This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. - -The gzipped file is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. - -Then run: - -``` -DESIRED_BINARY_VERSION=0.8.1 nargo info -``` - -This overrides the bb native binary with a bb.js node application instead, which should be compatible with most if not all hardware. This does come with the drawback of being generally slower than native binary. - -0.8.1 indicates bb.js version 0.8.1, so if you change that it will update to a different version or the default version in the script if none was supplied. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/_category_.json deleted file mode 100644 index 7da08f8a8c5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Concepts", - "position": 0, - "collapsible": true, - "collapsed": true -} \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/comments.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/comments.md deleted file mode 100644 index b51a85f5c94..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/comments.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Comments -description: - Learn how to write comments in Noir programming language. A comment is a line of code that is - ignored by the compiler, but it can be read by programmers. Single-line and multi-line comments - are supported in Noir. -keywords: [Noir programming language, comments, single-line comments, multi-line comments] -sidebar_position: 10 ---- - -A comment is a line in your codebase which the compiler ignores, however it can be read by -programmers. - -Here is a single line comment: - -```rust -// This is a comment and is ignored -``` - -`//` is used to tell the compiler to ignore the rest of the line. - -Noir also supports multi-line block comments. Start a block comment with `/*` and end the block with `*/`. - -Noir does not natively support doc comments. You may be able to use [Rust doc comments](https://doc.rust-lang.org/reference/comments.html) in your code to leverage some Rust documentation build tools with Noir code. - -```rust -/* - This is a block comment describing a complex function. -*/ -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/control_flow.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/control_flow.md deleted file mode 100644 index 4ce65236db3..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/control_flow.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Control Flow -description: - Learn how to use loops and if expressions in the Noir programming language. Discover the syntax - and examples for for loops and if-else statements. -keywords: [Noir programming language, loops, for loop, if-else statements, Rust syntax] -sidebar_position: 2 ---- - -## Loops - -Noir has one kind of loop: the `for` loop. `for` loops allow you to repeat a block of code multiple -times. - -The following block of code between the braces is run 10 times. - -```rust -for i in 0..10 { - // do something -}; -``` - -The index for loops is of type `u64`. - -## If Expressions - -Noir supports `if-else` statements. The syntax is most similar to Rust's where it is not required -for the statement's conditional to be surrounded by parentheses. - -```rust -let a = 0; -let mut x: u32 = 0; - -if a == 0 { - if a != 0 { - x = 6; - } else { - x = 2; - } -} else { - x = 5; - assert(x == 5); -} -assert(x == 2); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_bus.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_bus.md deleted file mode 100644 index e54fc861257..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_bus.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: Data Bus -sidebar_position: 13 ---- -**Disclaimer** this feature is experimental, do not use it! - -The data bus is an optimization that the backend can use to make recursion more efficient. -In order to use it, you must define some inputs of the program entry points (usually the `main()` -function) with the `call_data` modifier, and the return values with the `return_data` modifier. -These modifiers are incompatible with `pub` and `mut` modifiers. - -## Example - -```rust -fn main(mut x: u32, y: call_data u32, z: call_data [u32;4] ) -> return_data u32 { - let a = z[x]; - a+y -} -``` - -As a result, both call_data and return_data will be treated as private inputs and encapsulated into a read-only array each, for the backend to process. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/_category_.json deleted file mode 100644 index 5d694210bbf..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 0, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/arrays.md deleted file mode 100644 index 9a4c485feb1..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/arrays.md +++ /dev/null @@ -1,253 +0,0 @@ ---- -title: Arrays -description: - Dive into the Array data type in Noir. Grasp its methods, practical examples, and best practices for efficiently using Arrays in your Noir code. -keywords: - [ - noir, - array type, - methods, - examples, - indexing, - ] -sidebar_position: 4 ---- - -An array is one way of grouping together values into one compound type. Array types can be inferred -or explicitly specified via the syntax `[; ]`: - -```rust -fn main(x : Field, y : Field) { - let my_arr = [x, y]; - let your_arr: [Field; 2] = [x, y]; -} -``` - -Here, both `my_arr` and `your_arr` are instantiated as an array containing two `Field` elements. - -Array elements can be accessed using indexing: - -```rust -fn main() { - let a = [1, 2, 3, 4, 5]; - - let first = a[0]; - let second = a[1]; -} -``` - -All elements in an array must be of the same type (i.e. homogeneous). That is, an array cannot group -a `Field` value and a `u8` value together for example. - -You can write mutable arrays, like: - -```rust -fn main() { - let mut arr = [1, 2, 3, 4, 5]; - assert(arr[0] == 1); - - arr[0] = 42; - assert(arr[0] == 42); -} -``` - -You can instantiate a new array of a fixed size with the same value repeated for each element. The following example instantiates an array of length 32 where each element is of type Field and has the value 0. - -```rust -let array: [Field; 32] = [0; 32]; -``` - -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: - -```rust -let array: [Field; 32] = [0; 32]; -let sl = array.as_slice() -``` - -You can define multidimensional arrays: - -```rust -let array : [[Field; 2]; 2]; -let element = array[0][0]; -``` - -However, multidimensional slices are not supported. For example, the following code will error at compile time: - -```rust -let slice : [[Field]] = []; -``` - -## Types - -You can create arrays of primitive types or structs. There is not yet support for nested arrays -(arrays of arrays) or arrays of structs that contain arrays. - -## Methods - -For convenience, the STD provides some ready-to-use, common methods for arrays. -Each of these functions are located within the generic impl `impl [T; N] {`. -So anywhere `self` appears, it refers to the variable `self: [T; N]`. - -### len - -Returns the length of an array - -```rust -fn len(self) -> Field -``` - -example - -```rust -fn main() { - let array = [42, 42]; - assert(array.len() == 2); -} -``` - -### sort - -Returns a new sorted array. The original array remains untouched. Notice that this function will -only work for arrays of fields or integers, not for any arbitrary type. This is because the sorting -logic it uses internally is optimized specifically for these values. If you need a sort function to -sort any type, you should use the function `sort_via` described below. - -```rust -fn sort(self) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32]; - let sorted = arr.sort(); - assert(sorted == [32, 42]); -} -``` - -### sort_via - -Sorts the array with a custom comparison function - -```rust -fn sort_via(self, ordering: fn(T, T) -> bool) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32] - let sorted_ascending = arr.sort_via(|a, b| a <= b); - assert(sorted_ascending == [32, 42]); // verifies - - let sorted_descending = arr.sort_via(|a, b| a >= b); - assert(sorted_descending == [32, 42]); // does not verify -} -``` - -### map - -Applies a function to each element of the array, returning a new array containing the mapped elements. - -```rust -fn map(self, f: fn(T) -> U) -> [U; N] -``` - -example - -```rust -let a = [1, 2, 3]; -let b = a.map(|a| a * 2); // b is now [2, 4, 6] -``` - -### fold - -Applies a function to each element of the array, returning the final accumulated value. The first -parameter is the initial value. - -```rust -fn fold(self, mut accumulator: U, f: fn(U, T) -> U) -> U -``` - -This is a left fold, so the given function will be applied to the accumulator and first element of -the array, then the second, and so on. For a given call the expected result would be equivalent to: - -```rust -let a1 = [1]; -let a2 = [1, 2]; -let a3 = [1, 2, 3]; - -let f = |a, b| a - b; -a1.fold(10, f) //=> f(10, 1) -a2.fold(10, f) //=> f(f(10, 1), 2) -a3.fold(10, f) //=> f(f(f(10, 1), 2), 3) -``` - -example: - -```rust - -fn main() { - let arr = [2, 2, 2, 2, 2]; - let folded = arr.fold(0, |a, b| a + b); - assert(folded == 10); -} - -``` - -### reduce - -Same as fold, but uses the first element as starting element. - -```rust -fn reduce(self, f: fn(T, T) -> T) -> T -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let reduced = arr.reduce(|a, b| a + b); - assert(reduced == 10); -} -``` - -### all - -Returns true if all the elements satisfy the given predicate - -```rust -fn all(self, predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let all = arr.all(|a| a == 2); - assert(all); -} -``` - -### any - -Returns true if any of the elements satisfy the given predicate - -```rust -fn any(self, predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 5]; - let any = arr.any(|a| a == 5); - assert(any); -} - -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/booleans.md deleted file mode 100644 index 7211716f63e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/booleans.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Booleans -description: - Delve into the Boolean data type in Noir. Understand its methods, practical examples, and best practices for using Booleans in your Noir programs. -keywords: - [ - noir, - boolean type, - methods, - examples, - logical operations, - ] -sidebar_position: 2 ---- - - -The `bool` type in Noir has two possible values: `true` and `false`: - -```rust -fn main() { - let t = true; - let f: bool = false; -} -``` - -> **Note:** When returning a boolean value, it will show up as a value of 1 for `true` and 0 for -> `false` in _Verifier.toml_. - -The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and -[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/fields.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/fields.md deleted file mode 100644 index 99b4aa63549..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/fields.md +++ /dev/null @@ -1,192 +0,0 @@ ---- -title: Fields -description: - Dive deep into the Field data type in Noir. Understand its methods, practical examples, and best practices to effectively use Fields in your Noir programs. -keywords: - [ - noir, - field type, - methods, - examples, - best practices, - ] -sidebar_position: 0 ---- - -The field type corresponds to the native field type of the proving backend. - -The size of a Noir field depends on the elliptic curve's finite field for the proving backend -adopted. For example, a field would be a 254-bit integer when paired with the default backend that -spans the Grumpkin curve. - -Fields support integer arithmetic and are often used as the default numeric type in Noir: - -```rust -fn main(x : Field, y : Field) { - let z = x + y; -} -``` - -`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new -private value `z` constrained to be equal to `x + y`. - -If proving efficiency is of priority, fields should be used as a default for solving problems. -Smaller integer types (e.g. `u64`) incur extra range constraints. - -## Methods - -After declaring a Field, you can use these common methods on it: - -### to_le_bits - -Transforms the field into an array of bits, Little Endian. - -```rust -fn to_le_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_le_bits(32); -} -``` - -### to_be_bits - -Transforms the field into an array of bits, Big Endian. - -```rust -fn to_be_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_be_bits(32); -} -``` - -### to_le_bytes - -Transforms into an array of bytes, Little Endian - -```rust -fn to_le_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_le_bytes(4); -} -``` - -### to_be_bytes - -Transforms into an array of bytes, Big Endian - -```rust -fn to_be_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_be_bytes(4); -} -``` - -### to_le_radix - -Decomposes into a vector over the specified base, Little Endian - -```rust -fn to_le_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_le_radix(256, 4); -} -``` - -### to_be_radix - -Decomposes into a vector over the specified base, Big Endian - -```rust -fn to_be_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_be_radix(256, 4); -} -``` - -### pow_32 - -Returns the value to the power of the specified exponent - -```rust -fn pow_32(self, exponent: Field) -> Field -``` - -example: - -```rust -fn main() { - let field = 2 - let pow = field.pow_32(4); - assert(pow == 16); -} -``` - -### assert_max_bit_size - -Adds a constraint to specify that the field can be represented with `bit_size` number of bits - -```rust -fn assert_max_bit_size(self, bit_size: u32) -``` - -example: - -```rust -fn main() { - let field = 2 - field.assert_max_bit_size(32); -} -``` - -### sgn0 - -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. - -```rust -fn sgn0(self) -> u1 -``` - - -### lt - -Returns true if the field is less than the other field - -```rust -pub fn lt(self, another: Field) -> bool -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/function_types.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/function_types.md deleted file mode 100644 index f6121af17e2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/function_types.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Function types -sidebar_position: 10 ---- - -Noir supports higher-order functions. The syntax for a function type is as follows: - -```rust -fn(arg1_type, arg2_type, ...) -> return_type -``` - -Example: - -```rust -fn assert_returns_100(f: fn() -> Field) { // f takes no args and returns a Field - assert(f() == 100); -} - -fn main() { - assert_returns_100(|| 100); // ok - assert_returns_100(|| 150); // fails -} -``` - -A function type also has an optional capture environment - this is necessary to support closures. -See [Lambdas](../lambdas.md) for more details. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/index.md deleted file mode 100644 index f09bca0ee04..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/index.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: Data Types -description: - Get a clear understanding of the two categories of Noir data types - primitive types and compound - types. Learn about their characteristics, differences, and how to use them in your Noir - programming. -keywords: - [ - noir, - data types, - primitive types, - compound types, - private types, - public types, - ] ---- - -Every value in Noir has a type, which determines which operations are valid for it. - -All values in Noir are fundamentally composed of `Field` elements. For a more approachable -developing experience, abstractions are added on top to introduce different data types in Noir. - -Noir has two category of data types: primitive types (e.g. `Field`, integers, `bool`) and compound -types that group primitive types (e.g. arrays, tuples, structs). Each value can either be private or -public. - -## Private & Public Types - -A **private value** is known only to the Prover, while a **public value** is known by both the -Prover and Verifier. Mark values as `private` when the value should only be known to the prover. All -primitive types (including individual fields of compound types) in Noir are private by default, and -can be marked public when certain values are intended to be revealed to the Verifier. - -> **Note:** For public values defined in Noir programs paired with smart contract verifiers, once -> the proofs are verified on-chain the values can be considered known to everyone that has access to -> that blockchain. - -Public data types are treated no differently to private types apart from the fact that their values -will be revealed in proofs generated. Simply changing the value of a public type will not change the -circuit (where the same goes for changing values of private types as well). - -_Private values_ are also referred to as _witnesses_ sometimes. - -> **Note:** The terms private and public when applied to a type (e.g. `pub Field`) have a different -> meaning than when applied to a function (e.g. `pub fn foo() {}`). -> -> The former is a visibility modifier for the Prover to interpret if a value should be made known to -> the Verifier, while the latter is a visibility modifier for the compiler to interpret if a -> function should be made accessible to external Noir programs like in other languages. - -### pub Modifier - -All data types in Noir are private by default. Types are explicitly declared as public using the -`pub` modifier: - -```rust -fn main(x : Field, y : pub Field) -> pub Field { - x + y -} -``` - -In this example, `x` is **private** while `y` and `x + y` (the return value) are **public**. Note -that visibility is handled **per variable**, so it is perfectly valid to have one input that is -private and another that is public. - -> **Note:** Public types can only be declared through parameters on `main`. - -## Type Aliases - -A type alias is a new name for an existing type. Type aliases are declared with the keyword `type`: - -```rust -type Id = u8; - -fn main() { - let id: Id = 1; - let zero: u8 = 0; - assert(zero + 1 == id); -} -``` - -Type aliases can also be used with [generics](../generics.md): - -```rust -type Id = Size; - -fn main() { - let id: Id = 1; - let zero: u32 = 0; - assert(zero + 1 == id); -} -``` - -### BigInt - -You can achieve BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/integers.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/integers.md deleted file mode 100644 index 30135d76e4a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/integers.md +++ /dev/null @@ -1,162 +0,0 @@ ---- -title: Integers -description: Explore the Integer data type in Noir. Learn about its methods, see real-world examples, and grasp how to efficiently use Integers in your Noir code. -keywords: [noir, integer types, methods, examples, arithmetic] -sidebar_position: 1 ---- - -An integer type is a range constrained field type. The Noir frontend supports arbitrarily-sized, both unsigned and signed integer types. - -:::info - -When an integer is defined in Noir without a specific type, it will default to `Field`. - -The one exception is for loop indices which default to `u64` since comparisons on `Field`s are not possible. - -::: - -## Unsigned Integers - -An unsigned integer type is specified first with the letter `u` (indicating its unsigned nature) followed by its bit size (e.g. `8`): - -```rust -fn main() { - let x: u8 = 1; - let y: u8 = 1; - let z = x + y; - assert (z == 2); -} -``` - -The bit size determines the maximum value the integer type can store. For example, a `u8` variable can store a value in the range of 0 to 255 (i.e. $\\2^{8}-1\\$). - -## Signed Integers - -A signed integer type is specified first with the letter `i` (which stands for integer) followed by its bit size (e.g. `8`): - -```rust -fn main() { - let x: i8 = -1; - let y: i8 = -1; - let z = x + y; - assert (z == -2); -} -``` - -The bit size determines the maximum and minimum range of value the integer type can store. For example, an `i8` variable can store a value in the range of -128 to 127 (i.e. $\\-2^{7}\\$ to $\\2^{7}-1\\$). - -:::tip - -If you are using the default proving backend with Noir, both even (e.g. _u2_, _i2_) and odd (e.g. _u3_, _i3_) arbitrarily-sized integer types up to 127 bits (i.e. _u127_ and _i127_) are supported. - -::: - - -## 128 bits Unsigned Integers - -The built-in structure `U128` allows you to use 128-bit unsigned integers almost like a native integer type. However, there are some differences to keep in mind: -- You cannot cast between a native integer and `U128` -- There is a higher performance cost when using `U128`, compared to a native type. - -Conversion between unsigned integer types and U128 are done through the use of `from_integer` and `to_integer` functions. - -```rust -fn main() { - let x = U128::from_integer(23); - let y = U128::from_hex("0x7"); - let z = x + y; - assert(z.to_integer() == 30); -} -``` - -`U128` is implemented with two 64 bits limbs, representing the low and high bits, which explains the performance cost. You should expect `U128` to be twice more costly for addition and four times more costly for multiplication. -You can construct a U128 from its limbs: -```rust -fn main(x: u64, y: u64) { - let x = U128::from_u64s_be(x,y); - assert(z.hi == x as Field); - assert(z.lo == y as Field); -} -``` - -Note that the limbs are stored as Field elements in order to avoid unnecessary conversions. -Apart from this, most operations will work as usual: - -```rust -fn main(x: U128, y: U128) { - // multiplication - let c = x * y; - // addition and subtraction - let c = c - x + y; - // division - let c = x / y; - // bit operation; - let c = x & y | y; - // bit shift - let c = x << y; - // comparisons; - let c = x < y; - let c = x == y; -} -``` - -## Overflows - -Computations that exceed the type boundaries will result in overflow errors. This happens with both signed and unsigned integers. For example, attempting to prove: - -```rust -fn main(x: u8, y: u8) { - let z = x + y; -} -``` - -With: - -```toml -x = "255" -y = "1" -``` - -Would result in: - -``` -$ nargo prove -error: Assertion failed: 'attempt to add with overflow' -┌─ ~/src/main.nr:9:13 -│ -│ let z = x + y; -│ ----- -│ -= Call stack: - ... -``` - -A similar error would happen with signed integers: - -```rust -fn main() { - let x: i8 = -118; - let y: i8 = -11; - let z = x + y; -} -``` - -### Wrapping methods - -Although integer overflow is expected to error, some use-cases rely on wrapping. For these use-cases, the standard library provides `wrapping` variants of certain common operations: - -```rust -fn wrapping_add(x: T, y: T) -> T; -fn wrapping_sub(x: T, y: T) -> T; -fn wrapping_mul(x: T, y: T) -> T; -``` - -Example of how it is used: - -```rust -use dep::std; - -fn main(x: u8, y: u8) -> pub u8 { - std::wrapping_add(x, y) -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/references.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/references.md deleted file mode 100644 index a5293d11cfb..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/references.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: References -sidebar_position: 9 ---- - -Noir supports first-class references. References are a bit like pointers: they point to a specific address that can be followed to access the data stored at that address. You can use Rust-like syntax to use pointers in Noir: the `&` operator references the variable, the `*` operator dereferences it. - -Example: - -```rust -fn main() { - let mut x = 2; - - // you can reference x as &mut and pass it to multiplyBy2 - multiplyBy2(&mut x); -} - -// you can access &mut here -fn multiplyBy2(x: &mut Field) { - // and dereference it with * - *x = *x * 2; -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/slices.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/slices.mdx deleted file mode 100644 index 4a6ee816aa2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/slices.mdx +++ /dev/null @@ -1,147 +0,0 @@ ---- -title: Slices -description: Explore the Slice data type in Noir. Understand its methods, see real-world examples, and learn how to effectively use Slices in your Noir programs. -keywords: [noir, slice type, methods, examples, subarrays] -sidebar_position: 5 ---- - -import Experimental from '@site/src/components/Notes/_experimental.mdx'; - - - -A slice is a dynamically-sized view into a sequence of elements. They can be resized at runtime, but because they don't own the data, they cannot be returned from a circuit. You can treat slices as arrays without a constrained size. - -```rust -use dep::std::slice; - -fn main() -> pub Field { - let mut slice: [Field] = [0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -View the corresponding test file [here][test-file]. - -[test-file]: https://github.com/noir-lang/noir/blob/f387ec1475129732f72ba294877efdf6857135ac/crates/nargo_cli/tests/test_data_ssa_refactor/slices/src/main.nr - -## Methods - -For convenience, the STD provides some ready-to-use, common methods for slices: - -### push_back - -Pushes a new element to the end of the slice, returning a new slice with a length one greater than the original unmodified slice. - -```rust -fn push_back(_self: [T], _elem: T) -> [T] -``` - -example: - -```rust -fn main() -> pub Field { - let mut slice: [Field] = [0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -View the corresponding test file [here][test-file]. - -### push_front - -Returns a new array with the specified element inserted at index 0. The existing elements indexes are incremented by 1. - -```rust -fn push_front(_self: Self, _elem: T) -> Self -``` - -Example: - -```rust -let mut new_slice: [Field] = []; -new_slice = new_slice.push_front(20); -assert(new_slice[0] == 20); // returns true -``` - -View the corresponding test file [here][test-file]. - -### pop_front - -Returns a tuple of two items, the first element of the array and the rest of the array. - -```rust -fn pop_front(_self: Self) -> (T, Self) -``` - -Example: - -```rust -let (first_elem, rest_of_slice) = slice.pop_front(); -``` - -View the corresponding test file [here][test-file]. - -### pop_back - -Returns a tuple of two items, the beginning of the array with the last element omitted and the last element. - -```rust -fn pop_back(_self: Self) -> (Self, T) -``` - -Example: - -```rust -let (popped_slice, last_elem) = slice.pop_back(); -``` - -View the corresponding test file [here][test-file]. - -### append - -Loops over a slice and adds it to the end of another. - -```rust -fn append(mut self, other: Self) -> Self -``` - -Example: - -```rust -let append = [1, 2].append([3, 4, 5]); -``` - -### insert - -Inserts an element at a specified index and shifts all following elements by 1. - -```rust -fn insert(_self: Self, _index: Field, _elem: T) -> Self -``` - -Example: - -```rust -new_slice = rest_of_slice.insert(2, 100); -assert(new_slice[2] == 100); -``` - -View the corresponding test file [here][test-file]. - -### remove - -Remove an element at a specified index, shifting all elements after it to the left, returning the altered slice and the removed element. - -```rust -fn remove(_self: Self, _index: Field) -> (Self, T) -``` - -Example: - -```rust -let (remove_slice, removed_elem) = slice.remove(3); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/strings.md deleted file mode 100644 index 8ab5825a4c4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/strings.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: Strings -description: - Discover the String data type in Noir. Learn about its methods, see real-world examples, and understand how to effectively manipulate and use Strings in Noir. -keywords: - [ - noir, - string type, - methods, - examples, - concatenation, - ] -sidebar_position: 3 ---- - - -The string type is a fixed length value defined with `str`. - -You can use strings in `assert()` functions or print them with -`println()`. See more about [Logging](../../standard_library/logging.md). - -```rust -use dep::std; - -fn main(message : pub str<11>, hex_as_string : str<4>) { - println(message); - assert(message == "hello world"); - assert(hex_as_string == "0x41"); -} -``` - -You can convert a `str` to a byte array by calling `as_bytes()` -or a vector by calling `as_bytes_vec()`. - -```rust -fn main() { - let message = "hello world"; - let message_bytes = message.as_bytes(); - let mut message_vec = message.as_bytes_vec(); - assert(message_bytes.len() == 11); - assert(message_bytes[0] == 104); - assert(message_bytes[0] == message_vec.get(0)); -} -``` - -## Escape characters - -You can use escape characters for your strings: - -| Escape Sequence | Description | -|-----------------|-----------------| -| `\r` | Carriage Return | -| `\n` | Newline | -| `\t` | Tab | -| `\0` | Null Character | -| `\"` | Double Quote | -| `\\` | Backslash | - -Example: - -```rust -let s = "Hello \"world" // prints "Hello "world" -let s = "hey \tyou"; // prints "hey you" -``` - -## Raw strings - -A raw string begins with the letter `r` and is optionally delimited by a number of hashes `#`. - -Escape characters are *not* processed within raw strings. All contents are interpreted literally. - -Example: - -```rust -let s = r"Hello world"; -let s = r#"Simon says "hello world""#; - -// Any number of hashes may be used (>= 1) as long as the string also terminates with the same number of hashes -let s = r#####"One "#, Two "##, Three "###, Four "####, Five will end the string."#####; -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/structs.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/structs.md deleted file mode 100644 index dbf68c99813..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/structs.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -title: Structs -description: - Explore the Struct data type in Noir. Learn about its methods, see real-world examples, and grasp how to effectively define and use Structs in your Noir programs. -keywords: - [ - noir, - struct type, - methods, - examples, - data structures, - ] -sidebar_position: 8 ---- - -A struct also allows for grouping multiple values of different types. Unlike tuples, we can also -name each field. - -> **Note:** The usage of _field_ here refers to each element of the struct and is unrelated to the -> field type of Noir. - -Defining a struct requires giving it a name and listing each field within as `: ` pairs: - -```rust -struct Animal { - hands: Field, - legs: Field, - eyes: u8, -} -``` - -An instance of a struct can then be created with actual values in `: ` pairs in any -order. Struct fields are accessible using their given names: - -```rust -fn main() { - let legs = 4; - - let dog = Animal { - eyes: 2, - hands: 0, - legs, - }; - - let zero = dog.hands; -} -``` - -Structs can also be destructured in a pattern, binding each field to a new variable: - -```rust -fn main() { - let Animal { hands, legs: feet, eyes } = get_octopus(); - - let ten = hands + feet + eyes as u8; -} - -fn get_octopus() -> Animal { - let octopus = Animal { - hands: 0, - legs: 8, - eyes: 2, - }; - - octopus -} -``` - -The new variables can be bound with names different from the original struct field names, as -showcased in the `legs --> feet` binding in the example above. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/tuples.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/tuples.md deleted file mode 100644 index 2ec5c9c4113..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/tuples.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Tuples -description: - Dive into the Tuple data type in Noir. Understand its methods, practical examples, and best practices for efficiently using Tuples in your Noir code. -keywords: - [ - noir, - tuple type, - methods, - examples, - multi-value containers, - ] -sidebar_position: 7 ---- - -A tuple collects multiple values like an array, but with the added ability to collect values of -different types: - -```rust -fn main() { - let tup: (u8, u64, Field) = (255, 500, 1000); -} -``` - -One way to access tuple elements is via destructuring using pattern matching: - -```rust -fn main() { - let tup = (1, 2); - - let (one, two) = tup; - - let three = one + two; -} -``` - -Another way to access tuple elements is via direct member access, using a period (`.`) followed by -the index of the element we want to access. Index `0` corresponds to the first tuple element, `1` to -the second and so on: - -```rust -fn main() { - let tup = (5, 6, 7, 8); - - let five = tup.0; - let eight = tup.3; -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/vectors.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/vectors.mdx deleted file mode 100644 index aed13183719..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/vectors.mdx +++ /dev/null @@ -1,171 +0,0 @@ ---- -title: Vectors -description: Delve into the Vector data type in Noir. Learn about its methods, practical examples, and best practices for using Vectors in your Noir code. -keywords: [noir, vector type, methods, examples, dynamic arrays] -sidebar_position: 6 ---- - -import Experimental from '@site/src/components/Notes/_experimental.mdx'; - - - -A vector is a collection type similar to Rust's Vector type. It's convenient way to use slices as mutable arrays. - -Example: - -```rust -let mut vector: Vec = Vec::new(); -for i in 0..5 { - vector.push(i); -} -assert(vector.len() == 5); -``` - -## Methods - -### new - -Creates a new, empty vector. - -```rust -pub fn new() -> Self { - Self { slice: [] } -} -``` - -Example: - -```rust -let empty_vector: Vec = Vec::new(); -assert(empty_vector.len() == 0); -``` - -### from_slice - -Creates a vector containing each element from a given slice. Mutations to the resulting vector will not affect the original slice. - -```rust -pub fn from_slice(slice: [T]) -> Self { - Self { slice } -} -``` - -Example: - -```rust -let arr: [Field] = [1, 2, 3]; -let vector_from_slice = Vec::from_slice(arr); -assert(vector_from_slice.len() == 3); -``` - -### get - -Retrieves an element from the vector at a given index. Panics if the index points beyond the vector's end. - -```rust -pub fn get(self, index: Field) -> T { - self.slice[index] -} -``` - -Example: - -```rust -let vector: Vec = Vec::from_slice([10, 20, 30]); -assert(vector.get(1) == 20); -``` - -### push - -Adds a new element to the vector's end, returning a new vector with a length one greater than the original unmodified vector. - -```rust -pub fn push(&mut self, elem: T) { - self.slice = self.slice.push_back(elem); -} -``` - -Example: - -```rust -let mut vector: Vec = Vec::new(); -vector.push(10); -assert(vector.len() == 1); -``` - -### pop - -Removes an element from the vector's end, returning a new vector with a length one less than the original vector, along with the removed element. Panics if the vector's length is zero. - -```rust -pub fn pop(&mut self) -> T { - let (popped_slice, last_elem) = self.slice.pop_back(); - self.slice = popped_slice; - last_elem -} -``` - -Example: - -```rust -let mut vector = Vec::from_slice([10, 20]); -let popped_elem = vector.pop(); -assert(popped_elem == 20); -assert(vector.len() == 1); -``` - -### insert - -Inserts an element at a specified index, shifting subsequent elements to the right. - -```rust -pub fn insert(&mut self, index: Field, elem: T) { - self.slice = self.slice.insert(index, elem); -} -``` - -Example: - -```rust -let mut vector = Vec::from_slice([10, 30]); -vector.insert(1, 20); -assert(vector.get(1) == 20); -``` - -### remove - -Removes an element at a specified index, shifting subsequent elements to the left, and returns the removed element. - -```rust -pub fn remove(&mut self, index: Field) -> T { - let (new_slice, elem) = self.slice.remove(index); - self.slice = new_slice; - elem -} -``` - -Example: - -```rust -let mut vector = Vec::from_slice([10, 20, 30]); -let removed_elem = vector.remove(1); -assert(removed_elem == 20); -assert(vector.len() == 2); -``` - -### len - -Returns the number of elements in the vector. - -```rust -pub fn len(self) -> Field { - self.slice.len() -} -``` - -Example: - -```rust -let empty_vector: Vec = Vec::new(); -assert(empty_vector.len() == 0); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/distinct.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/distinct.md deleted file mode 100644 index 6c993b8b5e0..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/distinct.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: Distinct Witnesses -sidebar_position: 11 ---- - -The `distinct` keyword prevents repetitions of witness indices in the program's ABI. This ensures -that the witnesses being returned as public inputs are all unique. - -The `distinct` keyword is only used for return values on program entry points (usually the `main()` -function). - -When using `distinct` and `pub` simultaneously, `distinct` comes first. See the example below. - -You can read more about the problem this solves -[here](https://github.com/noir-lang/noir/issues/1183). - -## Example - -Without the `distinct` keyword, the following program - -```rust -fn main(x : pub Field, y : pub Field) -> pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - "return_witnesses": [3, 2, 4, 4] - } -} -``` - -Whereas (with the `distinct` keyword) - -```rust -fn main(x : pub Field, y : pub Field) -> distinct pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - //... - "return_witnesses": [3, 4, 5, 6] - } -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/functions.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/functions.md deleted file mode 100644 index 48aba9cd058..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/functions.md +++ /dev/null @@ -1,226 +0,0 @@ ---- -title: Functions -description: - Learn how to declare functions and methods in Noir, a programming language with Rust semantics. - This guide covers parameter declaration, return types, call expressions, and more. -keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] -sidebar_position: 1 ---- - -Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. - -To declare a function the `fn` keyword is used. - -```rust -fn foo() {} -``` - -By default, functions are visible only within the package they are defined. To make them visible outside of that package (for example, as part of a [library](../modules_packages_crates/crates_and_packages.md#libraries)), you should mark them as `pub`: - -```rust -pub fn foo() {} -``` - -You can also restrict the visibility of the function to only the crate it was defined in, by specifying `pub(crate)`: - -```rust -pub(crate) fn foo() {} //foo can only be called within its crate -``` - -All parameters in a function must have a type and all types are known at compile time. The parameter -is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. - -```rust -fn foo(x : Field, y : Field){} -``` - -The return type of a function can be stated by using the `->` arrow notation. The function below -states that the foo function must return a `Field`. If the function returns no value, then the arrow -is omitted. - -```rust -fn foo(x : Field, y : Field) -> Field { - x + y -} -``` - -Note that a `return` keyword is unneeded in this case - the last expression in a function's body is -returned. - -## Main function - -If you're writing a binary, the `main` function is the starting point of your program. You can pass all types of expressions to it, as long as they have a fixed size at compile time: - -```rust -fn main(x : Field) // this is fine: passing a Field -fn main(x : [Field; 2]) // this is also fine: passing a Field with known size at compile-time -fn main(x : (Field, bool)) // 👌: passing a (Field, bool) tuple means size 2 -fn main(x : str<5>) // this is fine, as long as you pass a string of size 5 - -fn main(x : Vec) // can't compile, has variable size -fn main(x : [Field]) // can't compile, has variable size -fn main(....// i think you got it by now -``` - -Keep in mind [tests](../../getting_started/tooling/testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: - -```rust -fn main(x : [Field]) { - assert(x[0] == 1); -} - -#[test] -fn test_one() { - main([1, 2]); -} -``` - -```bash -$ nargo test -[testing] Running 1 test functions -[testing] Testing test_one... ok -[testing] All tests passed - -$ nargo check -The application panicked (crashed). -Message: Cannot have variable sized arrays as a parameter to main -``` - -## Call Expressions - -Calling a function in Noir is executed by using the function name and passing in the necessary -arguments. - -Below we show how to call the `foo` function from the `main` function using a call expression: - -```rust -fn main(x : Field, y : Field) { - let z = foo(x); -} - -fn foo(x : Field) -> Field { - x + x -} -``` - -## Methods - -You can define methods in Noir on any struct type in scope. - -```rust -struct MyStruct { - foo: Field, - bar: Field, -} - -impl MyStruct { - fn new(foo: Field) -> MyStruct { - MyStruct { - foo, - bar: 2, - } - } - - fn sum(self) -> Field { - self.foo + self.bar - } -} - -fn main() { - let s = MyStruct::new(40); - assert(s.sum() == 42); -} -``` - -Methods are just syntactic sugar for functions, so if we wanted to we could also call `sum` as -follows: - -```rust -assert(MyStruct::sum(s) == 42); -``` - -It is also possible to specialize which method is chosen depending on the [generic](./generics.md) type that is used. In this example, the `foo` function returns different values depending on its type: - -```rust -struct Foo {} - -impl Foo { - fn foo(self) -> Field { 1 } -} - -impl Foo { - fn foo(self) -> Field { 2 } -} - -fn main() { - let f1: Foo = Foo{}; - let f2: Foo = Foo{}; - assert(f1.foo() + f2.foo() == 3); -} -``` - -Also note that impls with the same method name defined in them cannot overlap. For example, if we already have `foo` defined for `Foo` and `Foo` like we do above, we cannot also define `foo` in an `impl Foo` since it would be ambiguous which version of `foo` to choose. - -```rust -// Including this impl in the same project as the above snippet would -// cause an overlapping impls error -impl Foo { - fn foo(self) -> Field { 3 } -} -``` - -## Lambdas - -Lambdas are anonymous functions. They follow the syntax of Rust - `|arg1, arg2, ..., argN| return_expression`. - -```rust -let add_50 = |val| val + 50; -assert(add_50(100) == 150); -``` - -See [Lambdas](./lambdas.md) for more details. - -## Attributes - -Attributes are metadata that can be applied to a function, using the following syntax: `#[attribute(value)]`. - -Supported attributes include: - -- **builtin**: the function is implemented by the compiler, for efficiency purposes. -- **deprecated**: mark the function as _deprecated_. Calling the function will generate a warning: `warning: use of deprecated function` -- **field**: Used to enable conditional compilation of code depending on the field size. See below for more details -- **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./unconstrained.md) and [NoirJS](../../reference/NoirJS/noir_js/index.md) for more details. -- **test**: mark the function as unit tests. See [Tests](../../getting_started/tooling/testing.md) for more details - -### Field Attribute - -The field attribute defines which field the function is compatible for. The function is conditionally compiled, under the condition that the field attribute matches the Noir native field. -The field can be defined implicitly, by using the name of the elliptic curve usually associated to it - for instance bn254, bls12_381 - or explicitly by using the field (prime) order, in decimal or hexadecimal form. -As a result, it is possible to define multiple versions of a function with each version specialized for a different field attribute. This can be useful when a function requires different parameters depending on the underlying elliptic curve. - -Example: we define the function `foo()` three times below. Once for the default Noir bn254 curve, once for the field $\mathbb F_{23}$, which will normally never be used by Noir, and once again for the bls12_381 curve. - -```rust -#[field(bn254)] -fn foo() -> u32 { - 1 -} - -#[field(23)] -fn foo() -> u32 { - 2 -} - -// This commented code would not compile as foo would be defined twice because it is the same field as bn254 -// #[field(21888242871839275222246405745257275088548364400416034343698204186575808495617)] -// fn foo() -> u32 { -// 2 -// } - -#[field(bls12_381)] -fn foo() -> u32 { - 3 -} -``` - -If the field name is not known to Noir, it will discard the function. Field names are case insensitive. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/generics.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/generics.md deleted file mode 100644 index 0c1c27a2221..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/generics.md +++ /dev/null @@ -1,106 +0,0 @@ ---- -title: Generics -description: Learn how to use Generics in Noir -keywords: [Noir, Rust, generics, functions, structs] -sidebar_position: 7 ---- - -Generics allow you to use the same functions with multiple different concrete data types. You can -read more about the concept of generics in the Rust documentation -[here](https://doc.rust-lang.org/book/ch10-01-syntax.html). - -Here is a trivial example showing the identity function that supports any type. In Rust, it is -common to refer to the most general type as `T`. We follow the same convention in Noir. - -```rust -fn id(x: T) -> T { - x -} -``` - -## In Structs - -Generics are useful for specifying types in structs. For example, we can specify that a field in a -struct will be of a certain generic type. In this case `value` is of type `T`. - -```rust -struct RepeatedValue { - value: T, - count: Field, -} - -impl RepeatedValue { - fn print(self) { - for _i in 0 .. self.count { - println(self.value); - } - } -} - -fn main() { - let repeated = RepeatedValue { value: "Hello!", count: 2 }; - repeated.print(); -} -``` - -The `print` function will print `Hello!` an arbitrary number of times, twice in this case. - -If we want to be generic over array lengths (which are type-level integers), we can use numeric -generics. Using these looks just like using regular generics, but these generics can resolve to -integers at compile-time, rather than resolving to types. Here's an example of a struct that is -generic over the size of the array it contains internally: - -```rust -struct BigInt { - limbs: [u32; N], -} - -impl BigInt { - // `N` is in scope of all methods in the impl - fn first(first: BigInt, second: BigInt) -> Self { - assert(first.limbs != second.limbs); - first - - fn second(first: BigInt, second: Self) -> Self { - assert(first.limbs != second.limbs); - second - } -} -``` - -## Calling functions on generic parameters - -Since a generic type `T` can represent any type, how can we call functions on the underlying type? -In other words, how can we go from "any type `T`" to "any type `T` that has certain methods available?" - -This is what [traits](../concepts/traits.md) are for in Noir. Here's an example of a function generic over -any type `T` that implements the `Eq` trait for equality: - -```rust -fn first_element_is_equal(array1: [T; N], array2: [T; N]) -> bool - where T: Eq -{ - if (array1.len() == 0) | (array2.len() == 0) { - true - } else { - array1[0] == array2[0] - } -} - -fn main() { - assert(first_element_is_equal([1, 2, 3], [1, 5, 6])); - - // We can use first_element_is_equal for arrays of any type - // as long as we have an Eq impl for the types we pass in - let array = [MyStruct::new(), MyStruct::new()]; - assert(array_eq(array, array, MyStruct::eq)); -} - -impl Eq for MyStruct { - fn eq(self, other: MyStruct) -> bool { - self.foo == other.foo - } -} -``` - -You can find more details on traits and trait implementations on the [traits page](../concepts/traits.md). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/lambdas.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/lambdas.md deleted file mode 100644 index be3c7e0b5ca..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/lambdas.md +++ /dev/null @@ -1,81 +0,0 @@ ---- -title: Lambdas -description: Learn how to use anonymous functions in Noir programming language. -keywords: [Noir programming language, lambda, closure, function, anonymous function] -sidebar_position: 9 ---- - -## Introduction - -Lambdas are anonymous functions. The syntax is `|arg1, arg2, ..., argN| return_expression`. - -```rust -let add_50 = |val| val + 50; -assert(add_50(100) == 150); -``` - -A block can be used as the body of a lambda, allowing you to declare local variables inside it: - -```rust -let cool = || { - let x = 100; - let y = 100; - x + y -} - -assert(cool() == 200); -``` - -## Closures - -Inside the body of a lambda, you can use variables defined in the enclosing function. Such lambdas are called **closures**. In this example `x` is defined inside `main` and is accessed from within the lambda: - -```rust -fn main() { - let x = 100; - let closure = || x + 150; - assert(closure() == 250); -} -``` - -## Passing closures to higher-order functions - -It may catch you by surprise that the following code fails to compile: - -```rust -fn foo(f: fn () -> Field) -> Field { - f() -} - -fn main() { - let (x, y) = (50, 50); - assert(foo(|| x + y) == 100); // error :( -} -``` - -The reason is that the closure's capture environment affects its type - we have a closure that captures two Fields and `foo` -expects a regular function as an argument - those are incompatible. -:::note - -Variables contained within the `||` are the closure's parameters, and the expression that follows it is the closure's body. The capture environment is comprised of any variables used in the closure's body that are not parameters. - -E.g. in |x| x + y, y would be a captured variable, but x would not be, since it is a parameter of the closure. - -::: -The syntax for the type of a closure is `fn[env](args) -> ret_type`, where `env` is the capture environment of the closure - -in this example that's `(Field, Field)`. - -The best solution in our case is to make `foo` generic over the environment type of its parameter, so that it can be called -with closures with any environment, as well as with regular functions: - -```rust -fn foo(f: fn[Env]() -> Field) -> Field { - f() -} - -fn main() { - let (x, y) = (50, 50); - assert(foo(|| x + y) == 100); // compiles fine - assert(foo(|| 60) == 60); // compiles fine -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/ops.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/ops.md deleted file mode 100644 index 60425cb8994..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/ops.md +++ /dev/null @@ -1,98 +0,0 @@ ---- -title: Logical Operations -description: - Learn about the supported arithmetic and logical operations in the Noir programming language. - Discover how to perform operations on private input types, integers, and booleans. -keywords: - [ - Noir programming language, - supported operations, - arithmetic operations, - logical operations, - predicate operators, - bitwise operations, - short-circuiting, - backend, - ] -sidebar_position: 3 ---- - -# Operations - -## Table of Supported Operations - -| Operation | Description | Requirements | -| :-------- | :------------------------------------------------------------: | -------------------------------------: | -| + | Adds two private input types together | Types must be private input | -| - | Subtracts two private input types together | Types must be private input | -| \* | Multiplies two private input types together | Types must be private input | -| / | Divides two private input types together | Types must be private input | -| ^ | XOR two private input types together | Types must be integer | -| & | AND two private input types together | Types must be integer | -| \| | OR two private input types together | Types must be integer | -| \<\< | Left shift an integer by another integer amount | Types must be integer | -| >> | Right shift an integer by another integer amount | Types must be integer | -| ! | Bitwise not of a value | Type must be integer or boolean | -| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | -| > | returns a bool if one value is more than the other | Upper bound must have a known bit size | -| >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | -| == | returns a bool if one value is equal to the other | Both types must not be constants | -| != | returns a bool if one value is not equal to the other | Both types must not be constants | - -### Predicate Operators - -`<,<=, !=, == , >, >=` are known as predicate/comparison operations because they compare two values. -This differs from the operations such as `+` where the operands are used in _computation_. - -### Bitwise Operations Example - -```rust -fn main(x : Field) { - let y = x as u32; - let z = y & y; -} -``` - -`z` is implicitly constrained to be the result of `y & y`. The `&` operand is used to denote bitwise -`&`. - -> `x & x` would not compile as `x` is a `Field` and not an integer type. - -### Logical Operators - -Noir has no support for the logical operators `||` and `&&`. This is because encoding the -short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can -use the bitwise operators `|` and `&` which operate identically for booleans, just without the -short-circuiting. - -```rust -let my_val = 5; - -let mut flag = 1; -if (my_val > 6) | (my_val == 0) { - flag = 0; -} -assert(flag == 1); - -if (my_val != 10) & (my_val < 50) { - flag = 0; -} -assert(flag == 0); -``` - -### Shorthand operators - -Noir shorthand operators for most of the above operators, namely `+=, -=, *=, /=, %=, &=, |=, ^=, <<=`, and `>>=`. These allow for more concise syntax. For example: - -```rust -let mut i = 0; -i = i + 1; -``` - -could be written as: - -```rust -let mut i = 0; -i += 1; -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/oracles.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/oracles.md deleted file mode 100644 index 2e6a6818d48..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/oracles.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: Oracles -description: Dive into how Noir supports Oracles via RPC calls, and learn how to declare an Oracle in Noir with our comprehensive guide. -keywords: - - Noir - - Oracles - - RPC Calls - - Unconstrained Functions - - Programming - - Blockchain -sidebar_position: 6 ---- - -Noir has support for Oracles via RPC calls. This means Noir will make an RPC call and use the return value for proof generation. - -Since Oracles are not resolved by Noir, they are [`unconstrained` functions](./unconstrained.md) - -You can declare an Oracle through the `#[oracle()]` flag. Example: - -```rust -#[oracle(get_number_sequence)] -unconstrained fn get_number_sequence(_size: Field) -> [Field] {} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/shadowing.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/shadowing.md deleted file mode 100644 index 5ce6130d201..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/shadowing.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Shadowing -sidebar_position: 12 ---- - -Noir allows for inheriting variables' values and re-declaring them with the same name similar to Rust, known as shadowing. - -For example, the following function is valid in Noir: - -```rust -fn main() { - let x = 5; - - { - let x = x * 2; - assert (x == 10); - } - - assert (x == 5); -} -``` - -In this example, a variable x is first defined with the value 5. - -The local scope that follows shadows the original x, i.e. creates a local mutable x based on the value of the original x. It is given a value of 2 times the original x. - -When we return to the main scope, x once again refers to just the original x, which stays at the value of 5. - -## Temporal mutability - -One way that shadowing is useful, in addition to ergonomics across scopes, is for temporarily mutating variables. - -```rust -fn main() { - let age = 30; - // age = age + 5; // Would error as `age` is immutable by default. - - let mut age = age + 5; // Temporarily mutates `age` with a new value. - - let age = age; // Locks `age`'s mutability again. - - assert (age == 35); -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/traits.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/traits.md deleted file mode 100644 index ef1445a5907..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/traits.md +++ /dev/null @@ -1,389 +0,0 @@ ---- -title: Traits -description: - Traits in Noir can be used to abstract out a common interface for functions across - several data types. -keywords: [noir programming language, traits, interfaces, generic, protocol] -sidebar_position: 14 ---- - -## Overview - -Traits in Noir are a useful abstraction similar to interfaces or protocols in other languages. Each trait defines -the interface of several methods contained within the trait. Types can then implement this trait by providing -implementations for these methods. For example in the program: - -```rust -struct Rectangle { - width: Field, - height: Field, -} - -impl Rectangle { - fn area(self) -> Field { - self.width * self.height - } -} - -fn log_area(r: Rectangle) { - println(r.area()); -} -``` - -We have a function `log_area` to log the area of a `Rectangle`. Now how should we change the program if we want this -function to work on `Triangle`s as well?: - -```rust -struct Triangle { - width: Field, - height: Field, -} - -impl Triangle { - fn area(self) -> Field { - self.width * self.height / 2 - } -} -``` - -Making `log_area` generic over all types `T` would be invalid since not all types have an `area` method. Instead, we can -introduce a new `Area` trait and make `log_area` generic over all types `T` that implement `Area`: - -```rust -trait Area { - fn area(self) -> Field; -} - -fn log_area(shape: T) where T: Area { - println(shape.area()); -} -``` - -We also need to explicitly implement `Area` for `Rectangle` and `Triangle`. We can do that by changing their existing -impls slightly. Note that the parameter types and return type of each of our `area` methods must match those defined -by the `Area` trait. - -```rust -impl Area for Rectangle { - fn area(self) -> Field { - self.width * self.height - } -} - -impl Area for Triangle { - fn area(self) -> Field { - self.width * self.height / 2 - } -} -``` - -Now we have a working program that is generic over any type of Shape that is used! Others can even use this program -as a library with their own types - such as `Circle` - as long as they also implement `Area` for these types. - -## Where Clauses - -As seen in `log_area` above, when we want to create a function or method that is generic over any type that implements -a trait, we can add a where clause to the generic function. - -```rust -fn log_area(shape: T) where T: Area { - println(shape.area()); -} -``` - -It is also possible to apply multiple trait constraints on the same variable at once by combining traits with the `+` -operator. Similarly, we can have multiple trait constraints by separating each with a comma: - -```rust -fn foo(elements: [T], thing: U) where - T: Default + Add + Eq, - U: Bar, -{ - let mut sum = T::default(); - - for element in elements { - sum += element; - } - - if sum == T::default() { - thing.bar(); - } -} -``` - -## Generic Implementations - -You can add generics to a trait implementation by adding the generic list after the `impl` keyword: - -```rust -trait Second { - fn second(self) -> Field; -} - -impl Second for (T, Field) { - fn second(self) -> Field { - self.1 - } -} -``` - -You can also implement a trait for every type this way: - -```rust -trait Debug { - fn debug(self); -} - -impl Debug for T { - fn debug(self) { - println(self); - } -} - -fn main() { - 1.debug(); -} -``` - -### Generic Trait Implementations With Where Clauses - -Where clauses can also be placed on trait implementations themselves to restrict generics in a similar way. -For example, while `impl Foo for T` implements the trait `Foo` for every type, `impl Foo for T where T: Bar` -will implement `Foo` only for types that also implement `Bar`. This is often used for implementing generic types. -For example, here is the implementation for array equality: - -```rust -impl Eq for [T; N] where T: Eq { - // Test if two arrays have the same elements. - // Because both arrays must have length N, we know their lengths already match. - fn eq(self, other: Self) -> bool { - let mut result = true; - - for i in 0 .. self.len() { - // The T: Eq constraint is needed to call == on the array elements here - result &= self[i] == other[i]; - } - - result - } -} -``` - -## Generic Traits - -Traits themselves can also be generic by placing the generic arguments after the trait name. These generics are in -scope of every item within the trait. - -```rust -trait Into { - // Convert `self` to type `T` - fn into(self) -> T; -} -``` - -When implementing generic traits the generic arguments of the trait must be specified. This is also true anytime -when referencing a generic trait (e.g. in a `where` clause). - -```rust -struct MyStruct { - array: [Field; 2], -} - -impl Into<[Field; 2]> for MyStruct { - fn into(self) -> [Field; 2] { - self.array - } -} - -fn as_array(x: T) -> [Field; 2] - where T: Into<[Field; 2]> -{ - x.into() -} - -fn main() { - let array = [1, 2]; - let my_struct = MyStruct { array }; - - assert_eq(as_array(my_struct), array); -} -``` - -## Trait Methods With No `self` - -A trait can contain any number of methods, each of which have access to the `Self` type which represents each type -that eventually implements the trait. Similarly, the `self` variable is available as well but is not required to be used. -For example, we can define a trait to create a default value for a type. This trait will need to return the `Self` type -but doesn't need to take any parameters: - -```rust -trait Default { - fn default() -> Self; -} -``` - -Implementing this trait can be done similarly to any other trait: - -```rust -impl Default for Field { - fn default() -> Field { - 0 - } -} - -struct MyType {} - -impl Default for MyType { - fn default() -> Field { - MyType {} - } -} -``` - -However, since there is no `self` parameter, we cannot call it via the method call syntax `object.method()`. -Instead, we'll need to refer to the function directly. This can be done either by referring to the -specific impl `MyType::default()` or referring to the trait itself `Default::default()`. In the later -case, type inference determines the impl that is selected. - -```rust -let my_struct = MyStruct::default(); - -let x: Field = Default::default(); -let result = x + Default::default(); -``` - -:::warning - -```rust -let _ = Default::default(); -``` - -If type inference cannot select which impl to use because of an ambiguous `Self` type, an impl will be -arbitrarily selected. This occurs most often when the result of a trait function call with no parameters -is unused. To avoid this, when calling a trait function with no `self` or `Self` parameters or return type, -always refer to it via the implementation type's namespace - e.g. `MyType::default()`. -This is set to change to an error in future Noir versions. - -::: - -## Default Method Implementations - -A trait can also have default implementations of its methods by giving a body to the desired functions. -Note that this body must be valid for all types that may implement the trait. As a result, the only -valid operations on `self` will be operations valid for any type or other operations on the trait itself. - -```rust -trait Numeric { - fn add(self, other: Self) -> Self; - - // Default implementation of double is (self + self) - fn double(self) -> Self { - self.add(self) - } -} -``` - -When implementing a trait with default functions, a type may choose to implement only the required functions: - -```rust -impl Numeric for Field { - fn add(self, other: Field) -> Field { - self + other - } -} -``` - -Or it may implement the optional methods as well: - -```rust -impl Numeric for u32 { - fn add(self, other: u32) -> u32 { - self + other - } - - fn double(self) -> u32 { - self * 2 - } -} -``` - -## Impl Specialization - -When implementing traits for a generic type it is possible to implement the trait for only a certain combination -of generics. This can be either as an optimization or because those specific generics are required to implement the trait. - -```rust -trait Sub { - fn sub(self, other: Self) -> Self; -} - -struct NonZero { - value: T, -} - -impl Sub for NonZero { - fn sub(self, other: Self) -> Self { - let value = self.value - other.value; - assert(value != 0); - NonZero { value } - } -} -``` - -## Overlapping Implementations - -Overlapping implementations are disallowed by Noir to ensure Noir's decision on which impl to select is never ambiguous. -This means if a trait `Foo` is already implemented -by a type `Bar` for all `T`, then we cannot also have a separate impl for `Bar` (or any other -type argument). Similarly, if there is an impl for all `T` such as `impl Debug for T`, we cannot create -any more impls to `Debug` for other types since it would be ambiguous which impl to choose for any given -method call. - -```rust -trait Trait {} - -// Previous impl defined here -impl Trait for (A, B) {} - -// error: Impl for type `(Field, Field)` overlaps with existing impl -impl Trait for (Field, Field) {} -``` - -## Trait Coherence - -Another restriction on trait implementations is coherence. This restriction ensures other crates cannot create -impls that may overlap with other impls, even if several unrelated crates are used as dependencies in the same -program. - -The coherence restriction is: to implement a trait, either the trait itself or the object type must be declared -in the crate the impl is in. - -In practice this often comes up when using types provided by libraries. If a library provides a type `Foo` that does -not implement a trait in the standard library such as `Default`, you may not `impl Default for Foo` in your own crate. -While restrictive, this prevents later issues or silent changes in the program if the `Foo` library later added its -own impl for `Default`. If you are a user of the `Foo` library in this scenario and need a trait not implemented by the -library your choices are to either submit a patch to the library or use the newtype pattern. - -### The Newtype Pattern - -The newtype pattern gets around the coherence restriction by creating a new wrapper type around the library type -that we cannot create `impl`s for. Since the new wrapper type is defined in our current crate, we can create -impls for any trait we need on it. - -```rust -struct Wrapper { - foo: dep::some_library::Foo, -} - -impl Default for Wrapper { - fn default() -> Wrapper { - Wrapper { - foo: dep::some_library::Foo::new(), - } - } -} -``` - -Since we have an impl for our own type, the behavior of this code will not change even if `some_library` is updated -to provide its own `impl Default for Foo`. The downside of this pattern is that it requires extra wrapping and -unwrapping of values when converting to and from the `Wrapper` and `Foo` types. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/unconstrained.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/unconstrained.md deleted file mode 100644 index 89d12c1c971..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/unconstrained.md +++ /dev/null @@ -1,95 +0,0 @@ ---- -title: Unconstrained Functions -description: "Learn about what unconstrained functions in Noir are, how to use them and when you'd want to." - -keywords: [Noir programming language, unconstrained, open] -sidebar_position: 5 ---- - -Unconstrained functions are functions which do not constrain any of the included computation and allow for non-deterministic computation. - -## Why? - -Zero-knowledge (ZK) domain-specific languages (DSL) enable developers to generate ZK proofs from their programs by compiling code down to the constraints of an NP complete language (such as R1CS or PLONKish languages). However, the hard bounds of a constraint system can be very limiting to the functionality of a ZK DSL. - -Enabling a circuit language to perform unconstrained execution is a powerful tool. Said another way, unconstrained execution lets developers generate witnesses from code that does not generate any constraints. Being able to execute logic outside of a circuit is critical for both circuit performance and constructing proofs on information that is external to a circuit. - -Fetching information from somewhere external to a circuit can also be used to enable developers to improve circuit efficiency. - -A ZK DSL does not just prove computation, but proves that some computation was handled correctly. Thus, it is necessary that when we switch from performing some operation directly inside of a circuit to inside of an unconstrained environment that the appropriate constraints are still laid down elsewhere in the circuit. - -## Example - -An in depth example might help drive the point home. This example comes from the excellent [post](https://discord.com/channels/1113924620781883405/1124022445054111926/1128747641853972590) by Tom in the Noir Discord. - -Let's look at how we can optimize a function to turn a `u72` into an array of `u8`s. - -```rust -fn main(num: u72) -> pub [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8)) as u72 & 0xff) as u8; - } - - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 91 -Backend circuit size: 3619 -``` - -A lot of the operations in this function are optimized away by the compiler (all the bit-shifts turn into divisions by constants). However we can save a bunch of gates by casting to u8 a bit earlier. This automatically truncates the bit-shifted value to fit in a u8 which allows us to remove the AND against 0xff. This saves us ~480 gates in total. - -```rust -fn main(num: u72) -> pub [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8)) as u8; - } - - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 75 -Backend circuit size: 3143 -``` - -Those are some nice savings already but we can do better. This code is all constrained so we're proving every step of calculating out using num, but we don't actually care about how we calculate this, just that it's correct. This is where brillig comes in. - -It turns out that truncating a u72 into a u8 is hard to do inside a snark, each time we do as u8 we lay down 4 ACIR opcodes which get converted into multiple gates. It's actually much easier to calculate num from out than the other way around. All we need to do is multiply each element of out by a constant and add them all together, both relatively easy operations inside a snark. - -We can then run u72_to_u8 as unconstrained brillig code in order to calculate out, then use that result in our constrained function and assert that if we were to do the reverse calculation we'd get back num. This looks a little like the below: - -```rust -fn main(num: u72) -> pub [u8; 8] { - let out = u72_to_u8(num); - - let mut reconstructed_num: u72 = 0; - for i in 0..8 { - reconstructed_num += (out[i] as u72 << (56 - (8 * i))); - } - assert(num == reconstructed_num); - out -} - -unconstrained fn u72_to_u8(num: u72) -> [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8))) as u8; - } - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 78 -Backend circuit size: 2902 -``` - -This ends up taking off another ~250 gates from our circuit! We've ended up with more ACIR opcodes than before but they're easier for the backend to prove (resulting in fewer gates). - -Generally we want to use brillig whenever there's something that's easy to verify but hard to compute within the circuit. For example, if you wanted to calculate a square root of a number it'll be a much better idea to calculate this in brillig and then assert that if you square the result you get back your number. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/_category_.json deleted file mode 100644 index 1debcfe7675..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Modules, Packages and Crates", - "position": 2, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/crates_and_packages.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/crates_and_packages.md deleted file mode 100644 index 95ee9f52ab2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/crates_and_packages.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Crates and Packages -description: Learn how to use Crates and Packages in your Noir project -keywords: [Nargo, dependencies, package management, crates, package] -sidebar_position: 0 ---- - -## Crates - -A crate is the smallest amount of code that the Noir compiler considers at a time. -Crates can contain modules, and the modules may be defined in other files that get compiled with the crate, as we’ll see in the coming sections. - -### Crate Types - -A Noir crate can come in several forms: binaries, libraries or contracts. - -#### Binaries - -_Binary crates_ are programs which you can compile to an ACIR circuit which you can then create proofs against. Each must have a function called `main` that defines the ACIR circuit which is to be proved. - -#### Libraries - -_Library crates_ don't have a `main` function and they don't compile down to ACIR. Instead they define functionality intended to be shared with multiple projects, and eventually included in a binary crate. - -#### Contracts - -Contract crates are similar to binary crates in that they compile to ACIR which you can create proofs against. They are different in that they do not have a single `main` function, but are a collection of functions to be deployed to the [Aztec network](https://aztec.network). You can learn more about the technical details of Aztec in the [monorepo](https://github.com/AztecProtocol/aztec-packages) or contract [examples](https://github.com/AztecProtocol/aztec-packages/tree/master/noir-projects/noir-contracts/contracts). - -### Crate Root - -Every crate has a root, which is the source file that the compiler starts, this is also known as the root module. The Noir compiler does not enforce any conditions on the name of the file which is the crate root, however if you are compiling via Nargo the crate root must be called `lib.nr` or `main.nr` for library or binary crates respectively. - -## Packages - -A Nargo _package_ is a collection of one of more crates that provides a set of functionality. A package must include a Nargo.toml file. - -A package _must_ contain either a library or a binary crate, but not both. - -### Differences from Cargo Packages - -One notable difference between Rust's Cargo and Noir's Nargo is that while Cargo allows a package to contain an unlimited number of binary crates and a single library crate, Nargo currently only allows a package to contain a single crate. - -In future this restriction may be lifted to allow a Nargo package to contain both a binary and library crate or multiple binary crates. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/dependencies.md deleted file mode 100644 index d9d21ef0485..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/dependencies.md +++ /dev/null @@ -1,124 +0,0 @@ ---- -title: Dependencies -description: - Learn how to specify and manage dependencies in Nargo, allowing you to upload packages to GitHub - and use them easily in your project. -keywords: [Nargo, dependencies, GitHub, package management, versioning] -sidebar_position: 1 ---- - -Nargo allows you to upload packages to GitHub and use them as dependencies. - -## Specifying a dependency - -Specifying a dependency requires a tag to a specific commit and the git url to the url containing -the package. - -Currently, there are no requirements on the tag contents. If requirements are added, it would follow -semver 2.0 guidelines. - -> Note: Without a `tag` , there would be no versioning and dependencies would change each time you -> compile your project. - -For example, to add the [ecrecover-noir library](https://github.com/colinnielsen/ecrecover-noir) to your project, add it to `Nargo.toml`: - -```toml -# Nargo.toml - -[dependencies] -ecrecover = {tag = "v0.8.0", git = "https://github.com/colinnielsen/ecrecover-noir"} -``` - -If the module is in a subdirectory, you can define a subdirectory in your git repository, for example: - -```toml -# Nargo.toml - -[dependencies] -easy_private_token_contract = {tag ="v0.1.0-alpha62", git = "https://github.com/AztecProtocol/aztec-packages", directory = "yarn-project/noir-contracts/contracts/easy_private_token_contract"} -``` - -## Specifying a local dependency - -You can also specify dependencies that are local to your machine. - -For example, this file structure has a library and binary crate - -```tree -├── binary_crate -│   ├── Nargo.toml -│   └── src -│   └── main.nr -└── lib_a - ├── Nargo.toml - └── src - └── lib.nr -``` - -Inside of the binary crate, you can specify: - -```toml -# Nargo.toml - -[dependencies] -lib_a = { path = "../lib_a" } -``` - -## Importing dependencies - -You can import a dependency to a Noir file using the following syntax. For example, to import the -ecrecover-noir library and local lib_a referenced above: - -```rust -use dep::ecrecover; -use dep::lib_a; -``` - -You can also import only the specific parts of dependency that you want to use, like so: - -```rust -use dep::std::hash::sha256; -use dep::std::scalar_mul::fixed_base_embedded_curve; -``` - -Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you -can import multiple items in the same line by enclosing them in curly braces: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; -``` - -We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. - -Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. - -## Dependencies of Dependencies - -Note that when you import a dependency, you also get access to all of the dependencies of that package. - -For example, the [phy_vector](https://github.com/resurgencelabs/phy_vector) library imports an [fraction](https://github.com/resurgencelabs/fraction) library. If you're importing the phy_vector library, then you can access the functions in fractions library like so: - -```rust -use dep::phy_vector; - -fn main(x : Field, y : pub Field) { - //... - let f = phy_vector::fraction::toFraction(true, 2, 1); - //... -} -``` - -## Available Libraries - -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). - -Some libraries that are available today include: - -- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library -- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) -- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers -- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address -- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees -- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir -- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/modules.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/modules.md deleted file mode 100644 index ae822a1cff4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/modules.md +++ /dev/null @@ -1,105 +0,0 @@ ---- -title: Modules -description: - Learn how to organize your files using modules in Noir, following the same convention as Rust's - module system. Examples included. -keywords: [Noir, Rust, modules, organizing files, sub-modules] -sidebar_position: 2 ---- - -Noir's module system follows the same convention as the _newer_ version of Rust's module system. - -## Purpose of Modules - -Modules are used to organize files. Without modules all of your code would need to live in a single -file. In Noir, the compiler does not automatically scan all of your files to detect modules. This -must be done explicitly by the developer. - -## Examples - -### Importing a module in the crate root - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::hello_world(); -} -``` - -Filename : `src/foo.nr` - -```rust -fn from_foo() {} -``` - -In the above snippet, the crate root is the `src/main.nr` file. The compiler sees the module -declaration `mod foo` which prompts it to look for a foo.nr file. - -Visually this module hierarchy looks like the following : - -``` -crate - ├── main - │ - └── foo - └── from_foo - -``` - -### Importing a module throughout the tree - -All modules are accessible from the `crate::` namespace. - -``` -crate - ├── bar - ├── foo - └── main - -``` - -In the above snippet, if `bar` would like to use functions in `foo`, it can do so by `use crate::foo::function_name`. - -### Sub-modules - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::from_foo(); -} -``` - -Filename : `src/foo.nr` - -```rust -mod bar; -fn from_foo() {} -``` - -Filename : `src/foo/bar.nr` - -```rust -fn from_bar() {} -``` - -In the above snippet, we have added an extra module to the module tree; `bar`. `bar` is a submodule -of `foo` hence we declare bar in `foo.nr` with `mod bar`. Since `foo` is not the crate root, the -compiler looks for the file associated with the `bar` module in `src/foo/bar.nr` - -Visually the module hierarchy looks as follows: - -``` -crate - ├── main - │ - └── foo - ├── from_foo - └── bar - └── from_bar -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/workspaces.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/workspaces.md deleted file mode 100644 index 513497f12bf..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/workspaces.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Workspaces -sidebar_position: 3 ---- - -Workspaces are a feature of nargo that allow you to manage multiple related Noir packages in a single repository. A workspace is essentially a group of related projects that share common build output directories and configurations. - -Each Noir project (with it's own Nargo.toml file) can be thought of as a package. Each package is expected to contain exactly one "named circuit", being the "name" defined in Nargo.toml with the program logic defined in `./src/main.nr`. - -For a project with the following structure: - -```tree -├── crates -│ ├── a -│ │ ├── Nargo.toml -│ │ └── Prover.toml -│ │ └── src -│ │ └── main.nr -│ └── b -│ ├── Nargo.toml -│ └── Prover.toml -│ └── src -│ └── main.nr -│ -└── Nargo.toml -``` - -You can define a workspace in Nargo.toml like so: - -```toml -[workspace] -members = ["crates/a", "crates/b"] -default-member = "crates/a" -``` - -`members` indicates which packages are included in the workspace. As such, all member packages of a workspace will be processed when the `--workspace` flag is used with various commands or if a `default-member` is not specified. - -`default-member` indicates which package various commands process by default. - -Libraries can be defined in a workspace. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. - -Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/_category_.json deleted file mode 100644 index af04c0933fd..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Standard Library", - "position": 1, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/black_box_fns.md deleted file mode 100644 index e8b62f21d4e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/black_box_fns.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Black Box Functions -description: Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. -keywords: [noir, black box functions] ---- - -Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. This makes certain zk-snark unfriendly computations cheaper than if they were implemented in Noir. - -The ACVM spec defines a set of blackbox functions which backends will be expected to implement. This allows backends to use optimized implementations of these constraints if they have them, however they may also fallback to less efficient naive implementations if not. - -## Function list - -Here is a list of the current black box functions: - -- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) -- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) -- [Blake3](./cryptographic_primitives/hashes.mdx#blake3) -- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash) -- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx) -- AND -- XOR -- RANGE -- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion.md) - -Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. - -You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/noir/blob/master/acvm-repo/acir/src/circuit/black_box_functions.rs). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/bn254.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/bn254.md deleted file mode 100644 index 3294f005dbb..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/bn254.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: Bn254 Field Library ---- - -Noir provides a module in standard library with some optimized functions for bn254 Fr in `std::field::bn254`. - -## decompose - -```rust -fn decompose(x: Field) -> (Field, Field) {} -``` - -Decomposes a single field into two fields, low and high. The low field contains the lower 16 bytes of the input field and the high field contains the upper 16 bytes of the input field. Both field results are range checked to 128 bits. - - -## assert_gt - -```rust -fn assert_gt(a: Field, b: Field) {} -``` - -Asserts that a > b. This will generate less constraints than using `assert(gt(a, b))`. - -## assert_lt - -```rust -fn assert_lt(a: Field, b: Field) {} -``` - -Asserts that a < b. This will generate less constraints than using `assert(lt(a, b))`. - -## gt - -```rust -fn gt(a: Field, b: Field) -> bool {} -``` - -Returns true if a > b. - -## lt - -```rust -fn lt(a: Field, b: Field) -> bool {} -``` - -Returns true if a < b. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/cryptographic_primitives/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/cryptographic_primitives/_category_.json deleted file mode 100644 index 5d694210bbf..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/cryptographic_primitives/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 0, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/cryptographic_primitives/ec_primitives.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/cryptographic_primitives/ec_primitives.md deleted file mode 100644 index 48d2408e1e4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/cryptographic_primitives/ec_primitives.md +++ /dev/null @@ -1,102 +0,0 @@ ---- -title: Elliptic Curve Primitives -keywords: [cryptographic primitives, Noir project] -sidebar_position: 4 ---- - -Data structures and methods on them that allow you to carry out computations involving elliptic -curves over the (mathematical) field corresponding to `Field`. For the field currently at our -disposal, applications would involve a curve embedded in BN254, e.g. the -[Baby Jubjub curve](https://eips.ethereum.org/EIPS/eip-2494). - -## Data structures - -### Elliptic curve configurations - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Curve`), i.e. the specific elliptic -curve you want to use, which would be specified using any one of the methods -`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::new` which take the coefficients in the -defining equation together with a generator point as parameters. You can find more detail in the -comments in -[`noir_stdlib/src/ec.nr`](https://github.com/noir-lang/noir/blob/v0.24.0/noir_stdlib/src/ec.nr), but -the gist of it is that the elliptic curves of interest are usually expressed in one of the standard -forms implemented here (Twisted Edwards, Montgomery and Short Weierstraß), and in addition to that, -you could choose to use `affine` coordinates (Cartesian coordinates - the usual (x,y) - possibly -together with a point at infinity) or `curvegroup` coordinates (some form of projective coordinates -requiring more coordinates but allowing for more efficient implementations of elliptic curve -operations). Conversions between all of these forms are provided, and under the hood these -conversions are done whenever an operation is more efficient in a different representation (or a -mixed coordinate representation is employed). - -### Points - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Point`), i.e. points lying on the -elliptic curve. For a curve configuration `c` and a point `p`, it may be checked that `p` -does indeed lie on `c` by calling `c.contains(p1)`. - -## Methods - -(given a choice of curve representation, e.g. use `std::ec::tecurve::affine::Curve` and use -`std::ec::tecurve::affine::Point`) - -- The **zero element** is given by `Point::zero()`, and we can verify whether a point `p: Point` is - zero by calling `p.is_zero()`. -- **Equality**: Points `p1: Point` and `p2: Point` may be checked for equality by calling - `p1.eq(p2)`. -- **Addition**: For `c: Curve` and points `p1: Point` and `p2: Point` on the curve, adding these two - points is accomplished by calling `c.add(p1,p2)`. -- **Negation**: For a point `p: Point`, `p.negate()` is its negation. -- **Subtraction**: For `c` and `p1`, `p2` as above, subtracting `p2` from `p1` is accomplished by - calling `c.subtract(p1,p2)`. -- **Scalar multiplication**: For `c` as above, `p: Point` a point on the curve and `n: Field`, - scalar multiplication is given by `c.mul(n,p)`. If instead `n :: [u1; N]`, i.e. `n` is a bit - array, the `bit_mul` method may be used instead: `c.bit_mul(n,p)` -- **Multi-scalar multiplication**: For `c` as above and arrays `n: [Field; N]` and `p: [Point; N]`, - multi-scalar multiplication is given by `c.msm(n,p)`. -- **Coordinate representation conversions**: The `into_group` method converts a point or curve - configuration in the affine representation to one in the CurveGroup representation, and - `into_affine` goes in the other direction. -- **Curve representation conversions**: `tecurve` and `montcurve` curves and points are equivalent - and may be converted between one another by calling `into_montcurve` or `into_tecurve` on their - configurations or points. `swcurve` is more general and a curve c of one of the other two types - may be converted to this representation by calling `c.into_swcurve()`, whereas a point `p` lying - on the curve given by `c` may be mapped to its corresponding `swcurve` point by calling - `c.map_into_swcurve(p)`. -- **Map-to-curve methods**: The Elligator 2 method of mapping a field element `n: Field` into a - `tecurve` or `montcurve` with configuration `c` may be called as `c.elligator2_map(n)`. For all of - the curve configurations, the SWU map-to-curve method may be called as `c.swu_map(z,n)`, where - `z: Field` depends on `Field` and `c` and must be chosen by the user (the conditions it needs to - satisfy are specified in the comments - [here](https://github.com/noir-lang/noir/blob/v0.24.0/noir_stdlib/src/ec.nr). - -## Examples - -The -[ec_baby_jubjub test](https://github.com/noir-lang/noir/blob/master/test_programs/compile_success_empty/ec_baby_jubjub/src/main.nr) -illustrates all of the above primitives on various forms of the Baby Jubjub curve. A couple of more -interesting examples in Noir would be: - -Public-key cryptography: Given an elliptic curve and a 'base point' on it, determine the public key -from the private key. This is a matter of using scalar multiplication. In the case of Baby Jubjub, -for example, this code would do: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; - -fn bjj_pub_key(priv_key: Field) -> Point -{ - - let bjj = Curve::new(168700, 168696, G::new(995203441582195749578291179787384436505546430278305826713579947235728471134,5472060717959818805561601436314318772137091100104008585924551046643952123905)); - - let base_pt = Point::new(5299619240641551281634865583518297030282874472190772894086521144482721001553, 16950150798460657717958625567821834550301663161624707787222815936182638968203); - - bjj.mul(priv_key,base_pt) -} -``` - -This would come in handy in a Merkle proof. - -- EdDSA signature verification: This is a matter of combining these primitives with a suitable hash - function. See - [feat(stdlib): EdDSA sig verification noir#1136](https://github.com/noir-lang/noir/pull/1136) for - the case of Baby Jubjub and the Poseidon hash function. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx deleted file mode 100644 index 4bf09cef178..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx +++ /dev/null @@ -1,60 +0,0 @@ ---- -title: ECDSA Signature Verification -description: Learn about the cryptographic primitives regarding ECDSA over the secp256k1 and secp256r1 curves -keywords: [cryptographic primitives, Noir project, ecdsa, secp256k1, secp256r1, signatures] -sidebar_position: 3 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -Noir supports ECDSA signatures verification over the secp256k1 and secp256r1 curves. - -## ecdsa_secp256k1::verify_signature - -Verifier for ECDSA Secp256k1 signatures - -```rust title="ecdsa_secp256k1" showLineNumbers -pub fn verify_signature( - public_key_x: [u8; 32], - public_key_y: [u8; 32], - signature: [u8; 64], - message_hash: [u8; N] -) -> bool -``` -> Source code: noir_stdlib/src/ecdsa_secp256k1.nr#L2-L9 - - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - -## ecdsa_secp256r1::verify_signature - -Verifier for ECDSA Secp256r1 signatures - -```rust title="ecdsa_secp256r1" showLineNumbers -pub fn verify_signature( - public_key_x: [u8; 32], - public_key_y: [u8; 32], - signature: [u8; 64], - message_hash: [u8; N] -) -> bool -``` -> Source code: noir_stdlib/src/ecdsa_secp256r1.nr#L2-L9 - - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/cryptographic_primitives/eddsa.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/cryptographic_primitives/eddsa.mdx deleted file mode 100644 index a9c10da6c06..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/cryptographic_primitives/eddsa.mdx +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: EdDSA Verification -description: Learn about the cryptographic primitives regarding EdDSA -keywords: [cryptographic primitives, Noir project, eddsa, signatures] -sidebar_position: 5 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## eddsa::eddsa_poseidon_verify - -Verifier for EdDSA signatures - -```rust -fn eddsa_poseidon_verify(public_key_x : Field, public_key_y : Field, signature_s: Field, signature_r8_x: Field, signature_r8_y: Field, message: Field) -> bool -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/cryptographic_primitives/hashes.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/cryptographic_primitives/hashes.mdx deleted file mode 100644 index 730b6d4117f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/cryptographic_primitives/hashes.mdx +++ /dev/null @@ -1,234 +0,0 @@ ---- -title: Hash methods -description: - Learn about the cryptographic primitives ready to use for any Noir project, including sha256, - blake2s, pedersen, mimc_bn254 and mimc -keywords: - [cryptographic primitives, Noir project, sha256, blake2s, pedersen, mimc_bn254, mimc, hash] -sidebar_position: 0 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## sha256 - -Given an array of bytes, returns the resulting sha256 hash. - -```rust title="sha256" showLineNumbers -pub fn sha256(input: [u8; N]) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L5-L7 - - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::sha256(x); -} -``` - - - -## blake2s - -Given an array of bytes, returns an array with the Blake2 hash - -```rust title="blake2s" showLineNumbers -pub fn blake2s(input: [u8; N]) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L11-L13 - - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::blake2s(x); -} -``` - - - -## blake3 - -Given an array of bytes, returns an array with the Blake3 hash - -```rust title="blake3" showLineNumbers -pub fn blake3(input: [u8; N]) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L17-L19 - - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::blake3(x); -} -``` - - - -## pedersen_hash - -Given an array of Fields, returns the Pedersen hash. - -```rust title="pedersen_hash" showLineNumbers -pub fn pedersen_hash(input: [Field; N]) -> Field -``` -> Source code: noir_stdlib/src/hash.nr#L42-L44 - - -example: - -```rust title="pedersen-hash" showLineNumbers -use dep::std; - -fn main(x: Field, y: Field, expected_hash: Field) { - let hash = std::hash::pedersen_hash([x, y]); - assert_eq(hash, expected_hash); -} -``` -> Source code: test_programs/execution_success/pedersen_hash/src/main.nr#L1-L8 - - - - - -## pedersen_commitment - -Given an array of Fields, returns the Pedersen commitment. - -```rust title="pedersen_commitment" showLineNumbers -struct PedersenPoint { - x : Field, - y : Field, -} - -pub fn pedersen_commitment(input: [Field; N]) -> PedersenPoint -``` -> Source code: noir_stdlib/src/hash.nr#L22-L29 - - -example: - -```rust title="pedersen-commitment" showLineNumbers -use dep::std; - -fn main(x: Field, y: Field, expected_commitment: std::hash::PedersenPoint) { - let commitment = std::hash::pedersen_commitment([x, y]); - assert_eq(commitment.x, expected_commitment.x); - assert_eq(commitment.y, expected_commitment.y); -} -``` -> Source code: test_programs/execution_success/pedersen_commitment/src/main.nr#L1-L9 - - - - -## keccak256 - -Given an array of bytes (`u8`), returns the resulting keccak hash as an array of 32 bytes -(`[u8; 32]`). Specify a message_size to hash only the first `message_size` bytes -of the input. - -```rust title="keccak256" showLineNumbers -pub fn keccak256(input: [u8; N], message_size: u32) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L67-L69 - - -example: - -```rust title="keccak256" showLineNumbers -use dep::std; - -fn main(x: Field, result: [u8; 32]) { - // We use the `as` keyword here to denote the fact that we want to take just the first byte from the x Field - // The padding is taken care of by the program - let digest = std::hash::keccak256([x as u8], 1); - assert(digest == result); - - //#1399: variable message size - let message_size = 4; - let hash_a = std::hash::keccak256([1, 2, 3, 4], message_size); - let hash_b = std::hash::keccak256([1, 2, 3, 4, 0, 0, 0, 0], message_size); - - assert(hash_a == hash_b); - - let message_size_big = 8; - let hash_c = std::hash::keccak256([1, 2, 3, 4, 0, 0, 0, 0], message_size_big); - - assert(hash_a != hash_c); -} -``` -> Source code: test_programs/execution_success/keccak256/src/main.nr#L1-L22 - - - - -## poseidon - -Given an array of Fields, returns a new Field with the Poseidon Hash. Mind that you need to specify -how many inputs are there to your Poseidon function. - -```rust -// example for hash_1, hash_2 accepts an array of length 2, etc -fn hash_1(input: [Field; 1]) -> Field -``` - -example: - -```rust title="poseidon" showLineNumbers -use dep::std::hash::poseidon; - -fn main(x1: [Field; 2], y1: pub Field, x2: [Field; 4], y2: pub Field) { - let hash1 = poseidon::bn254::hash_2(x1); - assert(hash1 == y1); - - let hash2 = poseidon::bn254::hash_4(x2); - assert(hash2 == y2); -} -``` -> Source code: test_programs/execution_success/poseidon_bn254_hash/src/main.nr#L1-L11 - - -## mimc_bn254 and mimc - -`mimc_bn254` is `mimc`, but with hardcoded parameters for the BN254 curve. You can use it by -providing an array of Fields, and it returns a Field with the hash. You can use the `mimc` method if -you're willing to input your own constants: - -```rust -fn mimc(x: Field, k: Field, constants: [Field; N], exp : Field) -> Field -``` - -otherwise, use the `mimc_bn254` method: - -```rust -fn mimc_bn254(array: [Field; N]) -> Field -``` - -example: - -```rust - -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::mimc::mimc_bn254(x); -} -``` - -## hash_to_field - -```rust -fn hash_to_field(_input : [Field; N]) -> Field {} -``` - -Calculates the `blake2s` hash of the inputs and returns the hash modulo the field modulus to return -a value which can be represented as a `Field`. - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/cryptographic_primitives/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/cryptographic_primitives/index.md deleted file mode 100644 index 650f30165d5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/cryptographic_primitives/index.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Cryptographic Primitives -description: - Learn about the cryptographic primitives ready to use for any Noir project -keywords: - [ - cryptographic primitives, - Noir project, - ] ---- - -The Noir team is progressively adding new cryptographic primitives to the standard library. Reach out for news or if you would be interested in adding more of these calculations in Noir. - -Some methods are available thanks to the Aztec backend, not being performed using Noir. When using other backends, these methods may or may not be supplied. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/cryptographic_primitives/scalar.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/cryptographic_primitives/scalar.mdx deleted file mode 100644 index df411ca5443..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/cryptographic_primitives/scalar.mdx +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Scalar multiplication -description: See how you can perform scalar multiplications over a fixed base in Noir -keywords: [cryptographic primitives, Noir project, scalar multiplication] -sidebar_position: 1 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## scalar_mul::fixed_base_embedded_curve - -Performs scalar multiplication over the embedded curve whose coordinates are defined by the -configured noir field. For the BN254 scalar field, this is BabyJubJub or Grumpkin. - -```rust title="fixed_base_embedded_curve" showLineNumbers -pub fn fixed_base_embedded_curve( - low: Field, - high: Field -) -> [Field; 2] -``` -> Source code: noir_stdlib/src/scalar_mul.nr#L27-L32 - - -example - -```rust -fn main(x : Field) { - let scal = std::scalar_mul::fixed_base_embedded_curve(x); - println(scal); -} -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/cryptographic_primitives/schnorr.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/cryptographic_primitives/schnorr.mdx deleted file mode 100644 index ae12e6c12dc..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/cryptographic_primitives/schnorr.mdx +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Schnorr Signatures -description: Learn how you can verify Schnorr signatures using Noir -keywords: [cryptographic primitives, Noir project, schnorr, signatures] -sidebar_position: 2 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## schnorr::verify_signature - -Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin). - -```rust title="schnorr_verify" showLineNumbers -pub fn verify_signature( - public_key_x: Field, - public_key_y: Field, - signature: [u8; 64], - message: [u8; N] -) -> bool -``` -> Source code: noir_stdlib/src/schnorr.nr#L2-L9 - - -where `_signature` can be generated like so using the npm package -[@noir-lang/barretenberg](https://www.npmjs.com/package/@noir-lang/barretenberg) - -```js -const { BarretenbergWasm } = require('@noir-lang/barretenberg/dest/wasm'); -const { Schnorr } = require('@noir-lang/barretenberg/dest/crypto/schnorr'); - -... - -const barretenberg = await BarretenbergWasm.new(); -const schnorr = new Schnorr(barretenberg); -const pubKey = schnorr.computePublicKey(privateKey); -const message = ... -const signature = Array.from( - schnorr.constructSignature(hash, privateKey).toBuffer() -); - -... -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/logging.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/logging.md deleted file mode 100644 index db75ef9f86f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/logging.md +++ /dev/null @@ -1,78 +0,0 @@ ---- -title: Logging -description: - Learn how to use the println statement for debugging in Noir with this tutorial. Understand the - basics of logging in Noir and how to implement it in your code. -keywords: - [ - noir logging, - println statement, - print statement, - debugging in noir, - noir std library, - logging tutorial, - basic logging in noir, - noir logging implementation, - noir debugging techniques, - rust, - ] ---- - -The standard library provides two familiar statements you can use: `println` and `print`. Despite being a limited implementation of rust's `println!` and `print!` macros, these constructs can be useful for debugging. - -You can print the output of both statements in your Noir code by using the `nargo execute` command or the `--show-output` flag when using `nargo test` (provided there are print statements in your tests). - -It is recommended to use `nargo execute` if you want to debug failing constraints with `println` or `print` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). Neither `println`, nor `print` are callable for failed constraints caught at compile time. - -Both `print` and `println` are generic functions which can work on integers, fields, strings, and even structs or expressions. Note however, that slices are currently unsupported. For example: - -```rust -struct Person { - age: Field, - height: Field, -} - -fn main(age: Field, height: Field) { - let person = Person { - age: age, - height: height, - }; - println(person); - println(age + height); - println("Hello world!"); -} -``` - -You can print different types in the same statement (including strings) with a type called `fmtstr`. It can be specified in the same way as a normal string, just prepended with an "f" character: - -```rust - let fmt_str = f"i: {i}, j: {j}"; - println(fmt_str); - - let s = myStruct { y: x, x: y }; - println(s); - - println(f"i: {i}, s: {s}"); - - println(x); - println([x, y]); - - let foo = fooStruct { my_struct: s, foo: 15 }; - println(f"s: {s}, foo: {foo}"); - - println(15); // prints 0x0f, implicit Field - println(-1 as u8); // prints 255 - println(-1 as i8); // prints -1 -``` - -Examples shown above are interchangeable between the two `print` statements: - -```rust -let person = Person { age : age, height : height }; - -println(person); -print(person); - -println("Hello world!"); // Prints with a newline at the end of the input -print("Hello world!"); // Prints the input and keeps cursor on the same line -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/merkle_trees.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/merkle_trees.md deleted file mode 100644 index fa488677884..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/merkle_trees.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: Merkle Trees -description: Learn about Merkle Trees in Noir with this tutorial. Explore the basics of computing a merkle root using a proof, with examples. -keywords: - [ - Merkle trees in Noir, - Noir programming language, - check membership, - computing root from leaf, - Noir Merkle tree implementation, - Merkle tree tutorial, - Merkle tree code examples, - Noir libraries, - pedersen hash., - ] ---- - -## compute_merkle_root - -Returns the root of the tree from the provided leaf and its hash path, using a [Pedersen hash](./cryptographic_primitives/hashes.mdx#pedersen_hash). - -```rust -fn compute_merkle_root(leaf : Field, index : Field, hash_path: [Field]) -> Field -``` - -example: - -```rust -/** - // these values are for this example only - index = "0" - priv_key = "0x000000000000000000000000000000000000000000000000000000616c696365" - secret = "0x1929ea3ab8d9106a899386883d9428f8256cfedb3c4f6b66bf4aa4d28a79988f" - note_hash_path = [ - "0x1e61bdae0f027b1b2159e1f9d3f8d00fa668a952dddd822fda80dc745d6f65cc", - "0x0e4223f3925f98934393c74975142bd73079ab0621f4ee133cee050a3c194f1a", - "0x2fd7bb412155bf8693a3bd2a3e7581a679c95c68a052f835dddca85fa1569a40" - ] - */ -fn main(index: Field, priv_key: Field, secret: Field, note_hash_path: [Field; 3]) { - - let pubkey = std::scalar_mul::fixed_base_embedded_curve(priv_key); - let pubkey_x = pubkey[0]; - let pubkey_y = pubkey[1]; - let note_commitment = std::hash::pedersen([pubkey_x, pubkey_y, secret]); - - let root = std::merkle::compute_merkle_root(note_commitment[0], index, note_hash_path); - println(root); -} -``` - -To check merkle tree membership: - -1. Include a merkle root as a program input. -2. Compute the merkle root of a given leaf, index and hash path. -3. Assert the merkle roots are equal. - -For more info about merkle trees, see the Wikipedia [page](https://en.wikipedia.org/wiki/Merkle_tree). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/recursion.md deleted file mode 100644 index ed2ed01fceb..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/recursion.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -title: Recursive Proofs -description: Learn about how to write recursive proofs in Noir. -keywords: [recursion, recursive proofs, verification_key, verify_proof] ---- - -Noir supports recursively verifying proofs, meaning you verify the proof of a Noir program in another Noir program. This enables creating proofs of arbitrary size by doing step-wise verification of smaller components of a large proof. - -Read [the explainer on recursion](../../explainers/explainer-recursion.md) to know more about this function and the [guide on how to use it.](../../how_to/how-to-recursion.md) - -## The `#[recursive]` Attribute - -In Noir, the `#[recursive]` attribute is used to indicate that a circuit is designed for recursive proof generation. When applied, it informs the compiler and the tooling that the circuit should be compiled in a way that makes its proofs suitable for recursive verification. This attribute eliminates the need for manual flagging of recursion at the tooling level, streamlining the proof generation process for recursive circuits. - -### Example usage with `#[recursive]` - -```rust -#[recursive] -fn main(x: Field, y: pub Field) { - assert(x == y, "x and y are not equal"); -} - -// This marks the circuit as recursion-friendly and indicates that proofs generated from this circuit -// are intended for recursive verification. -``` - -By incorporating this attribute directly in the circuit's definition, tooling like Nargo and NoirJS can automatically execute recursive-specific duties for Noir programs (e.g. recursive-friendly proof artifact generation) without additional flags or configurations. - -## Verifying Recursive Proofs - -```rust -#[foreign(verify_proof)] -fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : Field, _key_hash : Field) {} -``` - -:::info - -This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. - -::: - -## Example usage - -```rust -use dep::std; - -fn main( - verification_key : [Field; 114], - proof : [Field; 93], - public_inputs : [Field; 1], - key_hash : Field, - proof_b : [Field; 93], -) { - std::verify_proof( - verification_key.as_slice(), - proof.as_slice(), - public_inputs.as_slice(), - key_hash - ); - - std::verify_proof( - verification_key.as_slice(), - proof_b.as_slice(), - public_inputs.as_slice(), - key_hash - ); -} -``` - -You can see a full example of recursive proofs in [this example recursion demo repo](https://github.com/noir-lang/noir-examples/tree/master/recursion). - -## Parameters - -### `verification_key` - -The verification key for the zk program that is being verified. - -### `proof` - -The proof for the zk program that is being verified. - -### `public_inputs` - -These represent the public inputs of the proof we are verifying. - -### `key_hash` - -A key hash is used to check the validity of the verification key. The circuit implementing this opcode can use this hash to ensure that the key provided to the circuit matches the key produced by the circuit creator. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/traits.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/traits.md deleted file mode 100644 index ba9fa2ee841..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/traits.md +++ /dev/null @@ -1,399 +0,0 @@ ---- -title: Traits -description: Noir's stdlib provides a few commonly used traits. -keywords: [traits, trait, interface, protocol, default, add, eq] ---- - -## `std::default` - -### `std::default::Default` - -```rust title="default-trait" showLineNumbers -trait Default { - fn default() -> Self; -} -``` -> Source code: noir_stdlib/src/default.nr#L1-L5 - - -Constructs a default value of a type. - -Implementations: -```rust -impl Default for Field { .. } - -impl Default for i8 { .. } -impl Default for i16 { .. } -impl Default for i32 { .. } -impl Default for i64 { .. } - -impl Default for u8 { .. } -impl Default for u16 { .. } -impl Default for u32 { .. } -impl Default for u64 { .. } - -impl Default for () { .. } -impl Default for bool { .. } - -impl Default for [T; N] - where T: Default { .. } - -impl Default for (A, B) - where A: Default, B: Default { .. } - -impl Default for (A, B, C) - where A: Default, B: Default, C: Default { .. } - -impl Default for (A, B, C, D) - where A: Default, B: Default, C: Default, D: Default { .. } - -impl Default for (A, B, C, D, E) - where A: Default, B: Default, C: Default, D: Default, E: Default { .. } -``` - -For primitive integer types, the return value of `default` is `0`. Container -types such as arrays are filled with default values of their element type. - - -## `std::convert` - -### `std::convert::From` - -```rust title="from-trait" showLineNumbers -trait From { - fn from(input: T) -> Self; -} -``` -> Source code: noir_stdlib/src/convert.nr#L1-L5 - - -The `From` trait defines how to convert from a given type `T` to the type on which the trait is implemented. - -The Noir standard library provides a number of implementations of `From` between primitive types. -```rust title="from-impls" showLineNumbers -// Unsigned integers - -impl From for u32 { fn from(value: u8) -> u32 { value as u32 } } - -impl From for u64 { fn from(value: u8) -> u64 { value as u64 } } -impl From for u64 { fn from(value: u32) -> u64 { value as u64 } } - -impl From for Field { fn from(value: u8) -> Field { value as Field } } -impl From for Field { fn from(value: u32) -> Field { value as Field } } -impl From for Field { fn from(value: u64) -> Field { value as Field } } - -// Signed integers - -impl From for i32 { fn from(value: i8) -> i32 { value as i32 } } - -impl From for i64 { fn from(value: i8) -> i64 { value as i64 } } -impl From for i64 { fn from(value: i32) -> i64 { value as i64 } } - -// Booleans -impl From for u8 { fn from(value: bool) -> u8 { value as u8 } } -impl From for u32 { fn from(value: bool) -> u32 { value as u32 } } -impl From for u64 { fn from(value: bool) -> u64 { value as u64 } } -impl From for i8 { fn from(value: bool) -> i8 { value as i8 } } -impl From for i32 { fn from(value: bool) -> i32 { value as i32 } } -impl From for i64 { fn from(value: bool) -> i64 { value as i64 } } -impl From for Field { fn from(value: bool) -> Field { value as Field } } -``` -> Source code: noir_stdlib/src/convert.nr#L25-L52 - - -#### When to implement `From` - -As a general rule of thumb, `From` may be implemented in the [situations where it would be suitable in Rust](https://doc.rust-lang.org/std/convert/trait.From.html#when-to-implement-from): - -- The conversion is *infallible*: Noir does not provide an equivalent to Rust's `TryFrom`, if the conversion can fail then provide a named method instead. -- The conversion is *lossless*: semantically, it should not lose or discard information. For example, `u32: From` can losslessly convert any `u16` into a valid `u32` such that the original `u16` can be recovered. On the other hand, `u16: From` should not be implemented as `2**16` is a `u32` which cannot be losslessly converted into a `u16`. -- The conversion is *value-preserving*: the conceptual kind and meaning of the resulting value is the same, even though the Noir type and technical representation might be different. While it's possible to infallibly and losslessly convert a `u8` into a `str<2>` hex representation, `4u8` and `"04"` are too different for `str<2>: From` to be implemented. -- The conversion is *obvious*: it's the only reasonable conversion between the two types. If there's ambiguity on how to convert between them such that the same input could potentially map to two different values then a named method should be used. For instance rather than implementing `U128: From<[u8; 16]>`, the methods `U128::from_le_bytes` and `U128::from_be_bytes` are used as otherwise the endianness of the array would be ambiguous, resulting in two potential values of `U128` from the same byte array. - -One additional recommendation specific to Noir is: -- The conversion is *efficient*: it's relatively cheap to convert between the two types. Due to being a ZK DSL, it's more important to avoid unnecessary computation compared to Rust. If the implementation of `From` would encourage users to perform unnecessary conversion, resulting in additional proving time, then it may be preferable to expose functionality such that this conversion may be avoided. - -### `std::convert::Into` - -The `Into` trait is defined as the reciprocal of `From`. It should be easy to convince yourself that if we can convert to type `A` from type `B`, then it's possible to convert type `B` into type `A`. - -For this reason, implementing `From` on a type will automatically generate a matching `Into` implementation. One should always prefer implementing `From` over `Into` as implementing `Into` will not generate a matching `From` implementation. - -```rust title="into-trait" showLineNumbers -trait Into { - fn into(input: Self) -> T; -} - -impl Into for U where T: From { - fn into(input: U) -> T { - T::from(input) - } -} -``` -> Source code: noir_stdlib/src/convert.nr#L13-L23 - - -`Into` is most useful when passing function arguments where the types don't quite match up with what the function expects. In this case, the compiler has enough type information to perform the necessary conversion by just appending `.into()` onto the arguments in question. - - -## `std::cmp` - -### `std::cmp::Eq` - -```rust title="eq-trait" showLineNumbers -trait Eq { - fn eq(self, other: Self) -> bool; -} -``` -> Source code: noir_stdlib/src/cmp.nr#L1-L5 - - -Returns `true` if `self` is equal to `other`. Implementing this trait on a type -allows the type to be used with `==` and `!=`. - -Implementations: -```rust -impl Eq for Field { .. } - -impl Eq for i8 { .. } -impl Eq for i16 { .. } -impl Eq for i32 { .. } -impl Eq for i64 { .. } - -impl Eq for u8 { .. } -impl Eq for u16 { .. } -impl Eq for u32 { .. } -impl Eq for u64 { .. } - -impl Eq for () { .. } -impl Eq for bool { .. } - -impl Eq for [T; N] - where T: Eq { .. } - -impl Eq for (A, B) - where A: Eq, B: Eq { .. } - -impl Eq for (A, B, C) - where A: Eq, B: Eq, C: Eq { .. } - -impl Eq for (A, B, C, D) - where A: Eq, B: Eq, C: Eq, D: Eq { .. } - -impl Eq for (A, B, C, D, E) - where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq { .. } -``` - -### `std::cmp::Ord` - -```rust title="ord-trait" showLineNumbers -trait Ord { - fn cmp(self, other: Self) -> Ordering; -} -``` -> Source code: noir_stdlib/src/cmp.nr#L92-L96 - - -`a.cmp(b)` compares two values returning `Ordering::less()` if `a < b`, -`Ordering::equal()` if `a == b`, or `Ordering::greater()` if `a > b`. -Implementing this trait on a type allows `<`, `<=`, `>`, and `>=` to be -used on values of the type. - -Implementations: - -```rust -impl Ord for u8 { .. } -impl Ord for u16 { .. } -impl Ord for u32 { .. } -impl Ord for u64 { .. } - -impl Ord for i8 { .. } -impl Ord for i16 { .. } -impl Ord for i32 { .. } - -impl Ord for i64 { .. } - -impl Ord for () { .. } -impl Ord for bool { .. } - -impl Ord for [T; N] - where T: Ord { .. } - -impl Ord for (A, B) - where A: Ord, B: Ord { .. } - -impl Ord for (A, B, C) - where A: Ord, B: Ord, C: Ord { .. } - -impl Ord for (A, B, C, D) - where A: Ord, B: Ord, C: Ord, D: Ord { .. } - -impl Ord for (A, B, C, D, E) - where A: Ord, B: Ord, C: Ord, D: Ord, E: Ord { .. } -``` - -## `std::ops` - -### `std::ops::Add`, `std::ops::Sub`, `std::ops::Mul`, and `std::ops::Div` - -These traits abstract over addition, subtraction, multiplication, and division respectively. -Implementing these traits for a given type will also allow that type to be used with the corresponding operator -for that trait (`+` for Add, etc) in addition to the normal method names. - -```rust title="add-trait" showLineNumbers -trait Add { - fn add(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L1-L5 - -```rust title="sub-trait" showLineNumbers -trait Sub { - fn sub(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L17-L21 - -```rust title="mul-trait" showLineNumbers -trait Mul { - fn mul(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L33-L37 - -```rust title="div-trait" showLineNumbers -trait Div { - fn div(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L49-L53 - - -The implementations block below is given for the `Add` trait, but the same types that implement -`Add` also implement `Sub`, `Mul`, and `Div`. - -Implementations: -```rust -impl Add for Field { .. } - -impl Add for i8 { .. } -impl Add for i16 { .. } -impl Add for i32 { .. } -impl Add for i64 { .. } - -impl Add for u8 { .. } -impl Add for u16 { .. } -impl Add for u32 { .. } -impl Add for u64 { .. } -``` - -### `std::ops::Rem` - -```rust title="rem-trait" showLineNumbers -trait Rem{ - fn rem(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L65-L69 - - -`Rem::rem(a, b)` is the remainder function returning the result of what is -left after dividing `a` and `b`. Implementing `Rem` allows the `%` operator -to be used with the implementation type. - -Unlike other numeric traits, `Rem` is not implemented for `Field`. - -Implementations: -```rust -impl Rem for u8 { fn rem(self, other: u8) -> u8 { self % other } } -impl Rem for u16 { fn rem(self, other: u16) -> u16 { self % other } } -impl Rem for u32 { fn rem(self, other: u32) -> u32 { self % other } } -impl Rem for u64 { fn rem(self, other: u64) -> u64 { self % other } } - -impl Rem for i8 { fn rem(self, other: i8) -> i8 { self % other } } -impl Rem for i16 { fn rem(self, other: i16) -> i16 { self % other } } -impl Rem for i32 { fn rem(self, other: i32) -> i32 { self % other } } -impl Rem for i64 { fn rem(self, other: i64) -> i64 { self % other } } -``` - -### `std::ops::{ BitOr, BitAnd, BitXor }` - -```rust title="bitor-trait" showLineNumbers -trait BitOr { - fn bitor(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L79-L83 - -```rust title="bitand-trait" showLineNumbers -trait BitAnd { - fn bitand(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L95-L99 - -```rust title="bitxor-trait" showLineNumbers -trait BitXor { - fn bitxor(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L111-L115 - - -Traits for the bitwise operations `|`, `&`, and `^`. - -Implementing `BitOr`, `BitAnd` or `BitXor` for a type allows the `|`, `&`, or `^` operator respectively -to be used with the type. - -The implementations block below is given for the `BitOr` trait, but the same types that implement -`BitOr` also implement `BitAnd` and `BitXor`. - -Implementations: -```rust -impl BitOr for bool { fn bitor(self, other: bool) -> bool { self | other } } - -impl BitOr for u8 { fn bitor(self, other: u8) -> u8 { self | other } } -impl BitOr for u16 { fn bitor(self, other: u16) -> u16 { self | other } } -impl BitOr for u32 { fn bitor(self, other: u32) -> u32 { self | other } } -impl BitOr for u64 { fn bitor(self, other: u64) -> u64 { self | other } } - -impl BitOr for i8 { fn bitor(self, other: i8) -> i8 { self | other } } -impl BitOr for i16 { fn bitor(self, other: i16) -> i16 { self | other } } -impl BitOr for i32 { fn bitor(self, other: i32) -> i32 { self | other } } -impl BitOr for i64 { fn bitor(self, other: i64) -> i64 { self | other } } -``` - -### `std::ops::{ Shl, Shr }` - -```rust title="shl-trait" showLineNumbers -trait Shl { - fn shl(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L127-L131 - -```rust title="shr-trait" showLineNumbers -trait Shr { - fn shr(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L142-L146 - - -Traits for a bit shift left and bit shift right. - -Implementing `Shl` for a type allows the left shift operator (`<<`) to be used with the implementation type. -Similarly, implementing `Shr` allows the right shift operator (`>>`) to be used with the type. - -Note that bit shifting is not currently implemented for signed types. - -The implementations block below is given for the `Shl` trait, but the same types that implement -`Shl` also implement `Shr`. - -Implementations: -```rust -impl Shl for u8 { fn shl(self, other: u8) -> u8 { self << other } } -impl Shl for u16 { fn shl(self, other: u16) -> u16 { self << other } } -impl Shl for u32 { fn shl(self, other: u32) -> u32 { self << other } } -impl Shl for u64 { fn shl(self, other: u64) -> u64 { self << other } } -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/zeroed.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/zeroed.md deleted file mode 100644 index 97dab02dac2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/zeroed.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: Zeroed Function -description: - The zeroed function returns a zeroed value of any type. -keywords: - [ - zeroed - ] ---- - -Implements `fn zeroed() -> T` to return a zeroed value of any type. This function is generally unsafe to use as the zeroed bit pattern is not guaranteed to be valid for all types. It can however, be useful in cases when the value is guaranteed not to be used such as in a BoundedVec library implementing a growable vector, up to a certain length, backed by an array. The array can be initialized with zeroed values which are guaranteed to be inaccessible until the vector is pushed to. Similarly, enumerations in noir can be implemented using this method by providing zeroed values for the unused variants. - -You can access the function at `std::unsafe::zeroed`. - -This function currently supports the following types: - -- Field -- Bool -- Uint -- Array -- String -- Tuple -- Function - -Using it on other types could result in unexpected behavior. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/reference/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/reference/_category_.json deleted file mode 100644 index 5b6a20a609a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/reference/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 4, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/reference/nargo_commands.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/reference/nargo_commands.md deleted file mode 100644 index 8a309ef4e7e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/reference/nargo_commands.md +++ /dev/null @@ -1,380 +0,0 @@ ---- -title: Nargo -description: - Noir CLI Commands for Noir Prover and Verifier to create, execute, prove and verify programs, - generate Solidity verifier smart contract and compile into JSON file containing ACIR - representation and ABI of circuit. -keywords: - [ - Nargo, - Noir CLI, - Noir Prover, - Noir Verifier, - generate Solidity verifier, - compile JSON file, - ACIR representation, - ABI of circuit, - TypeScript, - ] -sidebar_position: 0 ---- - -# Command-Line Help for `nargo` - -This document contains the help content for the `nargo` command-line program. - -**Command Overview:** - -* [`nargo`↴](#nargo) -* [`nargo backend`↴](#nargo-backend) -* [`nargo backend current`↴](#nargo-backend-current) -* [`nargo backend ls`↴](#nargo-backend-ls) -* [`nargo backend use`↴](#nargo-backend-use) -* [`nargo backend install`↴](#nargo-backend-install) -* [`nargo backend uninstall`↴](#nargo-backend-uninstall) -* [`nargo check`↴](#nargo-check) -* [`nargo fmt`↴](#nargo-fmt) -* [`nargo codegen-verifier`↴](#nargo-codegen-verifier) -* [`nargo compile`↴](#nargo-compile) -* [`nargo new`↴](#nargo-new) -* [`nargo init`↴](#nargo-init) -* [`nargo execute`↴](#nargo-execute) -* [`nargo prove`↴](#nargo-prove) -* [`nargo verify`↴](#nargo-verify) -* [`nargo test`↴](#nargo-test) -* [`nargo info`↴](#nargo-info) -* [`nargo lsp`↴](#nargo-lsp) - -## `nargo` - -Noir's package manager - -**Usage:** `nargo ` - -###### **Subcommands:** - -* `backend` — Install and select custom backends used to generate and verify proofs -* `check` — Checks the constraint system for errors -* `fmt` — Format the Noir files in a workspace -* `codegen-verifier` — Generates a Solidity verifier smart contract for the program -* `compile` — Compile the program and its secret execution trace into ACIR format -* `new` — Create a Noir project in a new directory -* `init` — Create a Noir project in the current directory -* `execute` — Executes a circuit to calculate its return value -* `prove` — Create proof for this program. The proof is returned as a hex encoded string -* `verify` — Given a proof and a program, verify whether the proof is valid -* `test` — Run the tests for this program -* `info` — Provides detailed information on a circuit -* `lsp` — Starts the Noir LSP server - -###### **Options:** - - - - -## `nargo backend` - -Install and select custom backends used to generate and verify proofs - -**Usage:** `nargo backend ` - -###### **Subcommands:** - -* `current` — Prints the name of the currently active backend -* `ls` — Prints the list of currently installed backends -* `use` — Select the backend to use -* `install` — Install a new backend from a URL -* `uninstall` — Uninstalls a backend - - - -## `nargo backend current` - -Prints the name of the currently active backend - -**Usage:** `nargo backend current` - - - -## `nargo backend ls` - -Prints the list of currently installed backends - -**Usage:** `nargo backend ls` - - - -## `nargo backend use` - -Select the backend to use - -**Usage:** `nargo backend use ` - -###### **Arguments:** - -* `` - - - -## `nargo backend install` - -Install a new backend from a URL - -**Usage:** `nargo backend install ` - -###### **Arguments:** - -* `` — The name of the backend to install -* `` — The URL from which to download the backend - - - -## `nargo backend uninstall` - -Uninstalls a backend - -**Usage:** `nargo backend uninstall ` - -###### **Arguments:** - -* `` — The name of the backend to uninstall - - - -## `nargo check` - -Checks the constraint system for errors - -**Usage:** `nargo check [OPTIONS]` - -###### **Options:** - -* `--package ` — The name of the package to check -* `--workspace` — Check all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings - - - -## `nargo fmt` - -Format the Noir files in a workspace - -**Usage:** `nargo fmt [OPTIONS]` - -###### **Options:** - -* `--check` — Run noirfmt in check mode - - - -## `nargo codegen-verifier` - -Generates a Solidity verifier smart contract for the program - -**Usage:** `nargo codegen-verifier [OPTIONS]` - -###### **Options:** - -* `--package ` — The name of the package to codegen -* `--workspace` — Codegen all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings - - - -## `nargo compile` - -Compile the program and its secret execution trace into ACIR format - -**Usage:** `nargo compile [OPTIONS]` - -###### **Options:** - -* `--package ` — The name of the package to compile -* `--workspace` — Compile all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings - - - -## `nargo new` - -Create a Noir project in a new directory - -**Usage:** `nargo new [OPTIONS] ` - -###### **Arguments:** - -* `` — The path to save the new project - -###### **Options:** - -* `--name ` — Name of the package [default: package directory name] -* `--lib` — Use a library template -* `--bin` — Use a binary template [default] -* `--contract` — Use a contract template - - - -## `nargo init` - -Create a Noir project in the current directory - -**Usage:** `nargo init [OPTIONS]` - -###### **Options:** - -* `--name ` — Name of the package [default: current directory name] -* `--lib` — Use a library template -* `--bin` — Use a binary template [default] -* `--contract` — Use a contract template - - - -## `nargo execute` - -Executes a circuit to calculate its return value - -**Usage:** `nargo execute [OPTIONS] [WITNESS_NAME]` - -###### **Arguments:** - -* `` — Write the execution witness to named file - -###### **Options:** - -* `-p`, `--prover-name ` — The name of the toml file which contains the inputs for the prover - - Default value: `Prover` -* `--package ` — The name of the package to execute -* `--workspace` — Execute all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings -* `--oracle-resolver ` — JSON RPC url to solve oracle calls - - - -## `nargo prove` - -Create proof for this program. The proof is returned as a hex encoded string - -**Usage:** `nargo prove [OPTIONS]` - -###### **Options:** - -* `-p`, `--prover-name ` — The name of the toml file which contains the inputs for the prover - - Default value: `Prover` -* `-v`, `--verifier-name ` — The name of the toml file which contains the inputs for the verifier - - Default value: `Verifier` -* `--verify` — Verify proof after proving -* `--package ` — The name of the package to prove -* `--workspace` — Prove all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings -* `--oracle-resolver ` — JSON RPC url to solve oracle calls - - - -## `nargo verify` - -Given a proof and a program, verify whether the proof is valid - -**Usage:** `nargo verify [OPTIONS]` - -###### **Options:** - -* `-v`, `--verifier-name ` — The name of the toml file which contains the inputs for the verifier - - Default value: `Verifier` -* `--package ` — The name of the package verify -* `--workspace` — Verify all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings - - - -## `nargo test` - -Run the tests for this program - -**Usage:** `nargo test [OPTIONS] [TEST_NAME]` - -###### **Arguments:** - -* `` — If given, only tests with names containing this string will be run - -###### **Options:** - -* `--show-output` — Display output of `println` statements -* `--exact` — Only run tests that match exactly -* `--package ` — The name of the package to test -* `--workspace` — Test all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings -* `--oracle-resolver ` — JSON RPC url to solve oracle calls - - - -## `nargo info` - -Provides detailed information on a circuit - -Current information provided: 1. The number of ACIR opcodes 2. Counts the final number gates in the circuit used by a backend - -**Usage:** `nargo info [OPTIONS]` - -###### **Options:** - -* `--package ` — The name of the package to detail -* `--workspace` — Detail all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings - - - -## `nargo lsp` - -Starts the Noir LSP server - -Starts an LSP server which allows IDEs such as VS Code to display diagnostics in Noir source. - -VS Code Noir Language Support: https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir - -**Usage:** `nargo lsp` - - - -
- - - This document was generated automatically by - clap-markdown. - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/tutorials/noirjs_app.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/tutorials/noirjs_app.md deleted file mode 100644 index 0d75e2e8045..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/tutorials/noirjs_app.md +++ /dev/null @@ -1,279 +0,0 @@ ---- -title: Building a web app with NoirJS -description: Learn how to setup a new app that uses Noir to generate and verify zero-knowledge SNARK proofs in a typescript or javascript environment. -keywords: [how to, guide, javascript, typescript, noir, barretenberg, zero-knowledge, proofs, app] -sidebar_position: 0 -pagination_next: noir/concepts/data_types/index ---- - -NoirJS is a set of packages meant to work both in a browser and a server environment. In this tutorial, we will build a simple web app using them. From here, you should get an idea on how to proceed with your own Noir projects! - -You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). - -## Setup - -:::note - -Feel free to use whatever versions, just keep in mind that Nargo and the NoirJS packages are meant to be in sync. For example, Nargo 0.19.x matches `noir_js@0.19.x`, etc. - -In this guide, we will be pinned to 0.19.4. - -::: - -Before we start, we want to make sure we have Node and Nargo installed. - -We start by opening a terminal and executing `node --version`. If we don't get an output like `v20.10.0`, that means node is not installed. Let's do that by following the handy [nvm guide](https://github.com/nvm-sh/nvm?tab=readme-ov-file#install--update-script). - -As for `Nargo`, we can follow the [Nargo guide](../getting_started/installation/index.md) to install it. If you're lazy, just paste this on a terminal and run `noirup`: - -```sh -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -Easy enough. Onwards! - -## Our project - -ZK is a powerful technology. An app that doesn't reveal one of the inputs to *anyone* is almost unbelievable, yet Noir makes it as easy as a single line of code. - -In fact, it's so simple that it comes nicely packaged in `nargo`. Let's do that! - -### Nargo - -Run: - -```nargo new circuit``` - -And... That's about it. Your program is ready to be compiled and run. - -To compile, let's `cd` into the `circuit` folder to enter our project, and call: - -```nargo compile``` - -This compiles our circuit into `json` format and add it to a new `target` folder. - -:::info - -At this point in the tutorial, your folder structure should look like this: - -```tree -. -└── circuit <---- our working directory - ├── Nargo.toml - ├── src - │ └── main.nr - └── target - └── circuit.json -``` - -::: - -### Node and Vite - -If you want to explore Nargo, feel free to go on a side-quest now and follow the steps in the -[getting started](../getting_started/hello_noir/index.md) guide. However, we want our app to run on the browser, so we need Vite. - -Vite is a powerful tool to generate static websites. While it provides all kinds of features, let's just go barebones with some good old vanilla JS. - -To do this this, go back to the previous folder (`cd ..`) and create a new vite project by running `npm create vite` and choosing "Vanilla" and "Javascript". - -You should see `vite-project` appear in your root folder. This seems like a good time to `cd` into it and install our NoirJS packages: - -```bash -npm i @noir-lang/backend_barretenberg@0.19.4 @noir-lang/noir_js@0.19.4 -``` - -:::info - -At this point in the tutorial, your folder structure should look like this: - -```tree -. -└── circuit - └── ...etc... -└── vite-project <---- our working directory - └── ...etc... -``` - -::: - -#### Some cleanup - -`npx create vite` is amazing but it creates a bunch of files we don't really need for our simple example. Actually, let's just delete everything except for `index.html`, `main.js` and `package.json`. I feel lighter already. - -![my heart is ready for you, noir.js](@site/static/img/memes/titanic.jpeg) - -## HTML - -Our app won't run like this, of course. We need some working HTML, at least. Let's open our broken-hearted `index.html` and replace everything with this code snippet: - -```html - - - - - - -

Noir app

-
- - -
-
-

Logs

-

Proof

-
- - -``` - -It *could* be a beautiful UI... Depending on which universe you live in. - -## Some good old vanilla Javascript - -Our love for Noir needs undivided attention, so let's just open `main.js` and delete everything (this is where the romantic scenery becomes a bit creepy). - -Start by pasting in this boilerplate code: - -```js -const setup = async () => { - await Promise.all([ - import("@noir-lang/noirc_abi").then(module => - module.default(new URL("@noir-lang/noirc_abi/web/noirc_abi_wasm_bg.wasm", import.meta.url).toString()) - ), - import("@noir-lang/acvm_js").then(module => - module.default(new URL("@noir-lang/acvm_js/web/acvm_js_bg.wasm", import.meta.url).toString()) - ) - ]); -} - -function display(container, msg) { - const c = document.getElementById(container); - const p = document.createElement('p'); - p.textContent = msg; - c.appendChild(p); -} - -document.getElementById('submitGuess').addEventListener('click', async () => { - try { - // here's where love happens - } catch(err) { - display("logs", "Oh 💔 Wrong guess") - } -}); - -``` - -The display function doesn't do much. We're simply manipulating our website to see stuff happening. For example, if the proof fails, it will simply log a broken heart 😢 - -As for the `setup` function, it's just a sad reminder that dealing with `wasm` on the browser is not as easy as it should. Just copy, paste, and forget. - -:::info - -At this point in the tutorial, your folder structure should look like this: - -```tree -. -└── circuit - └── ...same as above -└── vite-project - ├── main.js - ├── package.json - └── index.html -``` - -You'll see other files and folders showing up (like `package-lock.json`, `node_modules`) but you shouldn't have to care about those. - -::: - -## Some NoirJS - -We're starting with the good stuff now. If you've compiled the circuit as described above, you should have a `json` file we want to import at the very top of our `main.js` file: - -```ts -import circuit from '../circuit/target/circuit.json'; -``` - -[Noir is backend-agnostic](../index.mdx#whats-new-about-noir). We write Noir, but we also need a proving backend. That's why we need to import and instantiate the two dependencies we installed above: `BarretenbergBackend` and `Noir`. Let's import them right below: - -```js -import { BarretenbergBackend } from '@noir-lang/backend_barretenberg'; -import { Noir } from '@noir-lang/noir_js'; -``` - -And instantiate them inside our try-catch block: - -```ts -// try { -const backend = new BarretenbergBackend(circuit); -const noir = new Noir(circuit, backend); -// } -``` - -:::note - -For the remainder of the tutorial, everything will be happening inside the `try` block - -::: - -## Our app - -Now for the app itself. We're capturing whatever is in the input when people press the submit button. Just add this: - -```js -const x = parseInt(document.getElementById('guessInput').value); -const input = { x, y: 2 }; -``` - -Now we're ready to prove stuff! Let's feed some inputs to our circuit and calculate the proof: - -```js -await setup(); // let's squeeze our wasm inits here - -display('logs', 'Generating proof... ⌛'); -const proof = await noir.generateProof(input); -display('logs', 'Generating proof... ✅'); -display('results', proof.proof); -``` - -You're probably eager to see stuff happening, so go and run your app now! - -From your terminal, run `npm run dev`. If it doesn't open a browser for you, just visit `localhost:5173`. You should now see the worst UI ever, with an ugly input. - -![Getting Started 0](@site/static/img/noir_getting_started_1.png) - -Now, our circuit says `fn main(x: Field, y: pub Field)`. This means only the `y` value is public, and it's hardcoded above: `input = { x, y: 2 }`. In other words, you won't need to send your secret`x` to the verifier! - -By inputting any number other than 2 in the input box and clicking "submit", you should get a valid proof. Otherwise the proof won't even generate correctly. By the way, if you're human, you shouldn't be able to understand anything on the "proof" box. That's OK. We like you, human ❤️. - -## Verifying - -Time to celebrate, yes! But we shouldn't trust machines so blindly. Let's add these lines to see our proof being verified: - -```js -display('logs', 'Verifying proof... ⌛'); -const verification = await noir.verifyProof(proof); -if (verification) display('logs', 'Verifying proof... ✅'); -``` - -You have successfully generated a client-side Noir web app! - -![coded app without math knowledge](@site/static/img/memes/flextape.jpeg) - -## Further Reading - -You can see how noirjs is used in a full stack Next.js hardhat application in the [noir-starter repo here](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat). The example shows how to calculate a proof in the browser and verify it with a deployed Solidity verifier contract from noirjs. - -You should also check out the more advanced examples in the [noir-examples repo](https://github.com/noir-lang/noir-examples), where you'll find reference usage for some cool apps. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/explainers/explainer-oracle.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/explainers/explainer-oracle.md deleted file mode 100644 index b84ca5dd986..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/explainers/explainer-oracle.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: Oracles -description: This guide provides an in-depth understanding of how Oracles work in Noir programming. Learn how to use outside calculations in your programs, constrain oracles, and understand their uses and limitations. -keywords: - - Noir Programming - - Oracles - - JSON-RPC - - Foreign Call Handlers - - Constrained Functions - - Blockchain Programming -sidebar_position: 1 ---- - -If you've seen "The Matrix" you may recall "The Oracle" as Gloria Foster smoking cigarettes and baking cookies. While she appears to "know things", she is actually providing a calculation of a pre-determined future. Noir Oracles are similar, in a way. They don't calculate the future (yet), but they allow you to use outside calculations in your programs. - -![matrix oracle prediction](@site/static/img/memes/matrix_oracle.jpeg) - -A Noir program is usually self-contained. You can pass certain inputs to it, and it will generate a deterministic output for those inputs. But what if you wanted to defer some calculation to an outside process or source? - -Oracles are functions that provide this feature. - -## Use cases - -An example usage for Oracles is proving something on-chain. For example, proving that the ETH-USDC quote was below a certain target at a certain block time. Or even making more complex proofs like proving the ownership of an NFT as an anonymous login method. - -Another interesting use case is to defer expensive calculations to be made outside of the Noir program, and then constraining the result; similar to the use of [unconstrained functions](../noir/concepts//unconstrained.md). - -In short, anything that can be constrained in a Noir program but needs to be fetched from an external source is a great candidate to be used in oracles. - -## Constraining oracles - -Just like in The Matrix, Oracles are powerful. But with great power, comes great responsibility. Just because you're using them in a Noir program doesn't mean they're true. Noir has no superpowers. If you want to prove that Portugal won the Euro Cup 2016, you're still relying on potentially untrusted information. - -To give a concrete example, Alice wants to login to the [NounsDAO](https://nouns.wtf/) forum with her username "noir_nouner" by proving she owns a noun without revealing her ethereum address. Her Noir program could have a oracle call like this: - -```rust -#[oracle(getNoun)] -unconstrained fn get_noun(address: Field) -> Field -``` - -This oracle could naively resolve with the number of Nouns she possesses. However, it is useless as a trusted source, as the oracle could resolve to anything Alice wants. In order to make this oracle call actually useful, Alice would need to constrain the response from the oracle, by proving her address and the noun count belongs to the state tree of the contract. - -In short, **Oracles don't prove anything. Your Noir program does.** - -:::danger - -If you don't constrain the return of your oracle, you could be clearly opening an attack vector on your Noir program. Make double-triple sure that the return of an oracle call is constrained! - -::: - -## How to use Oracles - -On CLI, Nargo resolves oracles by making JSON RPC calls, which means it would require an RPC node to be running. - -In JavaScript, NoirJS accepts and resolves arbitrary call handlers (that is, not limited to JSON) as long as they matches the expected types the developer defines. Refer to [Foreign Call Handler](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) to learn more about NoirJS's call handling. - -If you want to build using oracles, follow through to the [oracle guide](../how_to/how-to-oracles.md) for a simple example on how to do that. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/explainers/explainer-recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/explainers/explainer-recursion.md deleted file mode 100644 index 18846176ca7..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/explainers/explainer-recursion.md +++ /dev/null @@ -1,176 +0,0 @@ ---- -title: Recursive proofs -description: Explore the concept of recursive proofs in Zero-Knowledge programming. Understand how recursion works in Noir, a language for writing smart contracts on the EVM blockchain. Learn through practical examples like Alice and Bob's guessing game, Charlie's recursive merkle tree, and Daniel's reusable components. Discover how to use recursive proofs to optimize computational resources and improve efficiency. - -keywords: - [ - "Recursive Proofs", - "Zero-Knowledge Programming", - "Noir", - "EVM Blockchain", - "Smart Contracts", - "Recursion in Noir", - "Alice and Bob Guessing Game", - "Recursive Merkle Tree", - "Reusable Components", - "Optimizing Computational Resources", - "Improving Efficiency", - "Verification Key", - "Aggregation", - "Recursive zkSNARK schemes", - "PLONK", - "Proving and Verification Keys" - ] -sidebar_position: 1 -pagination_next: how_to/how-to-recursion ---- - -In programming, we tend to think of recursion as something calling itself. A classic example would be the calculation of the factorial of a number: - -```js -function factorial(n) { - if (n === 0 || n === 1) { - return 1; - } else { - return n * factorial(n - 1); - } -} -``` - -In this case, while `n` is not `1`, this function will keep calling itself until it hits the base case, bubbling up the result on the call stack: - -```md - Is `n` 1? <--------- - /\ / - / \ n = n -1 - / \ / - Yes No -------- -``` - -In Zero-Knowledge, recursion has some similarities. - -It is not a Noir function calling itself, but a proof being used as an input to another circuit. In short, you verify one proof *inside* another proof, returning the proof that both proofs are valid. - -This means that, given enough computational resources, you can prove the correctness of any arbitrary number of proofs in a single proof. This could be useful to design state channels (for which a common example would be [Bitcoin's Lightning Network](https://en.wikipedia.org/wiki/Lightning_Network)), to save on gas costs by settling one proof on-chain, or simply to make business logic less dependent on a consensus mechanism. - -## Examples - -Let us look at some of these examples - -### Alice and Bob - Guessing game - -Alice and Bob are friends, and they like guessing games. They want to play a guessing game online, but for that, they need a trusted third-party that knows both of their secrets and finishes the game once someone wins. - -So, they use zero-knowledge proofs. Alice tries to guess Bob's number, and Bob will generate a ZK proof stating whether she succeeded or failed. - -This ZK proof can go on a smart contract, revealing the winner and even giving prizes. However, this means every turn needs to be verified on-chain. This incurs some cost and waiting time that may simply make the game too expensive or time-consuming to be worth it. - -As a solution, Alice proposes the following: "what if Bob generates his proof, and instead of sending it on-chain, I verify it *within* my own proof before playing my own turn?". - -She can then generate a proof that she verified his proof, and so on. - -```md - Did you fail? <-------------------------- - / \ / - / \ n = n -1 - / \ / - Yes No / - | | / - | | / - | You win / - | / - | / -Generate proof of that / - + / - my own guess ---------------- -``` - -### Charlie - Recursive merkle tree - -Charlie is a concerned citizen, and wants to be sure his vote in an election is accounted for. He votes with a ZK proof, but he has no way of knowing that his ZK proof was included in the total vote count! - -If the vote collector puts all of the votes into a [Merkle tree](https://en.wikipedia.org/wiki/Merkle_tree), everyone can prove the verification of two proofs within one proof, as such: - -```md - abcd - __________|______________ - | | - ab cd - _____|_____ ______|______ - | | | | - alice bob charlie daniel -``` - -Doing this recursively allows us to arrive on a final proof `abcd` which if true, verifies the correctness of all the votes. - -### Daniel - Reusable components - -Daniel has a big circuit and a big headache. A part of his circuit is a setup phase that finishes with some assertions that need to be made. But that section alone takes most of the proving time, and is largely independent of the rest of the circuit. - -He might find it more efficient to generate a proof for that setup phase separately, and verify that proof recursively in the actual business logic section of his circuit. This will allow for parallelization of both proofs, which results in a considerable speedup. - -## What params do I need - -As you can see in the [recursion reference](noir/standard_library/recursion.md), a simple recursive proof requires: - -- The proof to verify -- The Verification Key of the circuit that generated the proof -- A hash of this verification key, as it's needed for some backends -- The public inputs for the proof - -:::info - -Recursive zkSNARK schemes do not necessarily "verify a proof" in the sense that you expect a true or false to be spit out by the verifier. Rather an aggregation object is built over the public inputs. - -So, taking the example of Alice and Bob and their guessing game: - -- Alice makes her guess. Her proof is *not* recursive: it doesn't verify any proof within it! It's just a standard `assert(x != y)` circuit -- Bob verifies Alice's proof and makes his own guess. In this circuit, he doesn't exactly *prove* the verification of Alice's proof. Instead, he *aggregates* his proof to Alice's proof. The actual verification is done when the full proof is verified, for example when using `nargo verify` or through the verifier smart contract. - -We can imagine recursive proofs a [relay race](https://en.wikipedia.org/wiki/Relay_race). The first runner doesn't have to receive the baton from anyone else, as he/she already starts with it. But when his/her turn is over, the next runner needs to receive it, run a bit more, and pass it along. Even though every runner could theoretically verify the baton mid-run (why not? 🏃🔍), only at the end of the race does the referee verify that the whole race is valid. - -::: - -## Some architecture - -As with everything in computer science, there's no one-size-fits all. But there are some patterns that could help understanding and implementing them. To give three examples: - -### Adding some logic to a proof verification - -This would be an approach for something like our guessing game, where proofs are sent back and forth and are verified by each opponent. This circuit would be divided in two sections: - -- A `recursive verification` section, which would be just the call to `std::verify_proof`, and that would be skipped on the first move (since there's no proof to verify) -- A `guessing` section, which is basically the logic part where the actual guessing happens - -In such a situation, and assuming Alice is first, she would skip the first part and try to guess Bob's number. Bob would then verify her proof on the first section of his run, and try to guess Alice's number on the second part, and so on. - -### Aggregating proofs - -In some one-way interaction situations, recursion would allow for aggregation of simple proofs that don't need to be immediately verified on-chain or elsewhere. - -To give a practical example, a barman wouldn't need to verify a "proof-of-age" on-chain every time he serves alcohol to a customer. Instead, the architecture would comprise two circuits: - -- A `main`, non-recursive circuit with some logic -- A `recursive` circuit meant to verify two proofs in one proof - -The customer's proofs would be intermediate, and made on their phones, and the barman could just verify them locally. He would then aggregate them into a final proof sent on-chain (or elsewhere) at the end of the day. - -### Recursively verifying different circuits - -Nothing prevents you from verifying different circuits in a recursive proof, for example: - -- A `circuit1` circuit -- A `circuit2` circuit -- A `recursive` circuit - -In this example, a regulator could verify that taxes were paid for a specific purchase by aggregating both a `payer` circuit (proving that a purchase was made and taxes were paid), and a `receipt` circuit (proving that the payment was received) - -## How fast is it - -At the time of writing, verifying recursive proofs is surprisingly fast. This is because most of the time is spent on generating the verification key that will be used to generate the next proof. So you are able to cache the verification key and reuse it later. - -Currently, Noir JS packages don't expose the functionality of loading proving and verification keys, but that feature exists in the underlying `bb.js` package. - -## How can I try it - -Learn more about using recursion in Nargo and NoirJS in the [how-to guide](../how_to/how-to-recursion.md) and see a full example in [noir-examples](https://github.com/noir-lang/noir-examples). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/_category_.json deleted file mode 100644 index 5d694210bbf..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 0, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/hello_noir/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/hello_noir/_category_.json deleted file mode 100644 index 23b560f610b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/hello_noir/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 1, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/hello_noir/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/hello_noir/index.md deleted file mode 100644 index 743c4d8d634..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/hello_noir/index.md +++ /dev/null @@ -1,142 +0,0 @@ ---- -title: Creating a Project -description: - Learn how to create and verify your first Noir program using Nargo, a programming language for - zero-knowledge proofs. -keywords: - [ - Nargo, - Noir, - zero-knowledge proofs, - programming language, - create Noir program, - verify Noir program, - step-by-step guide, - ] -sidebar_position: 1 - ---- - -Now that we have installed Nargo, it is time to make our first hello world program! - -## Create a Project Directory - -Noir code can live anywhere on your computer. Let us create a _projects_ folder in the home -directory to house our Noir programs. - -For Linux, macOS, and Windows PowerShell, create the directory and change directory into it by -running: - -```sh -mkdir ~/projects -cd ~/projects -``` - -## Create Our First Nargo Project - -Now that we are in the projects directory, create a new Nargo project by running: - -```sh -nargo new hello_world -``` - -> **Note:** `hello_world` can be any arbitrary project name, we are simply using `hello_world` for -> demonstration. -> -> In production, the common practice is to name the project folder as `circuits` for better -> identifiability when sitting alongside other folders in the codebase (e.g. `contracts`, `scripts`, -> `test`). - -A `hello_world` folder would be created. Similar to Rust, the folder houses _src/main.nr_ and -_Nargo.toml_ which contain the source code and environmental options of your Noir program -respectively. - -### Intro to Noir Syntax - -Let us take a closer look at _main.nr_. The default _main.nr_ generated should look like this: - -```rust -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` - -The first line of the program specifies the program's inputs: - -```rust -x : Field, y : pub Field -``` - -Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the -keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](../../noir/concepts/data_types/index.md) section. - -The next line of the program specifies its body: - -```rust -assert(x != y); -``` - -The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. - -For more Noir syntax, check the [Language Concepts](../../noir/concepts/comments.md) chapter. - -## Build In/Output Files - -Change directory into _hello_world_ and build in/output files for your Noir program by running: - -```sh -cd hello_world -nargo check -``` - -Two additional files would be generated in your project directory: - -_Prover.toml_ houses input values, and _Verifier.toml_ houses public values. - -## Prove Our Noir Program - -Now that the project is set up, we can create a proof of correct execution of our Noir program. - -Fill in input values for execution in the _Prover.toml_ file. For example: - -```toml -x = "1" -y = "2" -``` - -Prove the valid execution of your Noir program: - -```sh -nargo prove -``` - -A new folder _proofs_ would then be generated in your project directory, containing the proof file -`.proof`, where the project name is defined in Nargo.toml. - -The _Verifier.toml_ file would also be updated with the public values computed from program -execution (in this case the value of `y`): - -```toml -y = "0x0000000000000000000000000000000000000000000000000000000000000002" -``` - -> **Note:** Values in _Verifier.toml_ are computed as 32-byte hex values. - -## Verify Our Noir Program - -Once a proof is generated, we can verify correct execution of our Noir program by verifying the -proof file. - -Verify your proof by running: - -```sh -nargo verify -``` - -The verification will complete in silence if it is successful. If it fails, it will log the -corresponding error instead. - -Congratulations, you have now created and verified a proof for your very first Noir program! - -In the [next section](./project_breakdown.md), we will go into more detail on each step performed. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/hello_noir/project_breakdown.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/hello_noir/project_breakdown.md deleted file mode 100644 index 6160a102c6c..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/hello_noir/project_breakdown.md +++ /dev/null @@ -1,199 +0,0 @@ ---- -title: Project Breakdown -description: - Learn about the anatomy of a Nargo project, including the purpose of the Prover and Verifier TOML - files, and how to prove and verify your program. -keywords: - [Nargo, Nargo project, Prover.toml, Verifier.toml, proof verification, private asset transfer] -sidebar_position: 2 ---- - -This section breaks down our hello world program from the previous section. We elaborate on the project -structure and what the `prove` and `verify` commands did. - -## Anatomy of a Nargo Project - -Upon creating a new project with `nargo new` and building the in/output files with `nargo check` -commands, you would get a minimal Nargo project of the following structure: - - - src - - Prover.toml - - Verifier.toml - - Nargo.toml - -The source directory _src_ holds the source code for your Noir program. By default only a _main.nr_ -file will be generated within it. - -### Prover.toml - -_Prover.toml_ is used for specifying the input values for executing and proving the program. You can specify `toml` files with different names by using the `--prover-name` or `-p` flags, see the [Prover](#provertoml) section below. Optionally you may specify expected output values for prove-time checking as well. - -### Verifier.toml - -_Verifier.toml_ contains public in/output values computed when executing the Noir program. - -### Nargo.toml - -_Nargo.toml_ contains the environmental options of your project. It contains a "package" section and a "dependencies" section. - -Example Nargo.toml: - -```toml -[package] -name = "noir_starter" -type = "bin" -authors = ["Alice"] -compiler_version = "0.9.0" -description = "Getting started with Noir" -entry = "circuit/main.nr" -license = "MIT" - -[dependencies] -ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} -``` - -Nargo.toml for a [workspace](../../noir/modules_packages_crates/workspaces.md) will look a bit different. For example: - -```toml -[workspace] -members = ["crates/a", "crates/b"] -default-member = "crates/a" -``` - -#### Package section - -The package section defines a number of fields including: - -- `name` (**required**) - the name of the package -- `type` (**required**) - can be "bin", "lib", or "contract" to specify whether its a binary, library or Aztec contract -- `authors` (optional) - authors of the project -- `compiler_version` - specifies the version of the compiler to use. This is enforced by the compiler and follow's [Rust's versioning](https://doc.rust-lang.org/cargo/reference/manifest.html#the-version-field), so a `compiler_version = 0.18.0` will enforce Nargo version 0.18.0, `compiler_version = ^0.18.0` will enforce anything above 0.18.0 but below 0.19.0, etc. For more information, see how [Rust handles these operators](https://docs.rs/semver/latest/semver/enum.Op.html) -- `description` (optional) -- `entry` (optional) - a relative filepath to use as the entry point into your package (overrides the default of `src/lib.nr` or `src/main.nr`) -- `backend` (optional) -- `license` (optional) - -#### Dependencies section - -This is where you will specify any dependencies for your project. See the [Dependencies page](../../noir/modules_packages_crates/dependencies.md) for more info. - -`./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or -verifier contract respectively. - -### main.nr - -The _main.nr_ file contains a `main` method, this method is the entry point into your Noir program. - -In our sample program, _main.nr_ looks like this: - -```rust -fn main(x : Field, y : Field) { - assert(x != y); -} -``` - -The parameters `x` and `y` can be seen as the API for the program and must be supplied by the -prover. Since neither `x` nor `y` is marked as public, the verifier does not supply any inputs, when -verifying the proof. - -The prover supplies the values for `x` and `y` in the _Prover.toml_ file. - -As for the program body, `assert` ensures that the condition to be satisfied (e.g. `x != y`) is -constrained by the proof of the execution of said program (i.e. if the condition was not met, the -verifier would reject the proof as an invalid proof). - -### Prover.toml - -The _Prover.toml_ file is a file which the prover uses to supply his witness values(both private and -public). - -In our hello world program the _Prover.toml_ file looks like this: - -```toml -x = "1" -y = "2" -``` - -When the command `nargo prove` is executed, two processes happen: - -1. Noir creates a proof that `x`, which holds the value of `1`, and `y`, which holds the value of `2`, - is not equal. This inequality constraint is due to the line `assert(x != y)`. - -2. Noir creates and stores the proof of this statement in the _proofs_ directory in a file called your-project.proof. So if your project is named "private_voting" (defined in the project Nargo.toml), the proof will be saved at `./proofs/private_voting.proof`. Opening this file will display the proof in hex format. - -#### Arrays of Structs - -The following code shows how to pass an array of structs to a Noir program to generate a proof. - -```rust -// main.nr -struct Foo { - bar: Field, - baz: Field, -} - -fn main(foos: [Foo; 3]) -> pub Field { - foos[2].bar + foos[2].baz -} -``` - -Prover.toml: - -```toml -[[foos]] # foos[0] -bar = 0 -baz = 0 - -[[foos]] # foos[1] -bar = 0 -baz = 0 - -[[foos]] # foos[2] -bar = 1 -baz = 2 -``` - -#### Custom toml files - -You can specify a `toml` file with a different name to use for proving by using the `--prover-name` or `-p` flags. - -This command looks for proof inputs in the default **Prover.toml** and generates the proof and saves it at `./proofs/.proof`: - -```bash -nargo prove -``` - -This command looks for proof inputs in the custom **OtherProver.toml** and generates proof and saves it at `./proofs/.proof`: - -```bash -nargo prove -p OtherProver -``` - -## Verifying a Proof - -When the command `nargo verify` is executed, two processes happen: - -1. Noir checks in the _proofs_ directory for a proof file with the project name (eg. test_project.proof) - -2. If that file is found, the proof's validity is checked - -> **Note:** The validity of the proof is linked to the current Noir program; if the program is -> changed and the verifier verifies the proof, it will fail because the proof is not valid for the -> _modified_ Noir program. - -In production, the prover and the verifier are usually two separate entities. A prover would -retrieve the necessary inputs, execute the Noir program, generate a proof and pass it to the -verifier. The verifier would then retrieve the public inputs, usually from external sources, and -verify the validity of the proof against it. - -Take a private asset transfer as an example: - -A person using a browser as the prover would retrieve private inputs locally (e.g. the user's private key) and -public inputs (e.g. the user's encrypted balance on-chain), compute the transfer, generate a proof -and submit it to the verifier smart contract. - -The verifier contract would then draw the user's encrypted balance directly from the blockchain and -verify the proof submitted against it. If the verification passes, additional functions in the -verifier contract could trigger (e.g. approve the asset transfer). - -Now that you understand the concepts, you'll probably want some editor feedback while you are writing more complex code. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/installation/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/installation/_category_.json deleted file mode 100644 index 0c02fb5d4d7..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/installation/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "position": 0, - "label": "Install Nargo", - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/installation/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/installation/index.md deleted file mode 100644 index 4ef86aa5914..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/installation/index.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Nargo Installation -description: - nargo is a command line tool for interacting with Noir programs. This page is a quick guide on how to install Nargo through the most common and easy method, noirup -keywords: [ - Nargo - Noir - Rust - Cargo - Noirup - Installation - Terminal Commands - Version Check - Nightlies - Specific Versions - Branches - Noirup Repository -] -pagination_next: getting_started/hello_noir/index ---- - -`nargo` is the one-stop-shop for almost everything related with Noir. The name comes from our love for Rust and its package manager `cargo`. - -With `nargo`, you can start new projects, compile, execute, prove, verify, test, generate solidity contracts, and do pretty much all that is available in Noir. - -Similarly to `rustup`, we also maintain an easy installation method that covers most machines: `noirup`. - -## Installing Noirup - -Open a terminal on your machine, and write: - -```bash -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -Close the terminal, open another one, and run - -```bash -noirup -``` - -Done. That's it. You should have the latest version working. You can check with `nargo --version`. - -You can also install nightlies, specific versions -or branches. Check out the [noirup repository](https://github.com/noir-lang/noirup) for more -information. - -Now we're ready to start working on [our first Noir program!](../hello_noir/index.md) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/installation/other_install_methods.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/installation/other_install_methods.md deleted file mode 100644 index a35e34aaf9c..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/installation/other_install_methods.md +++ /dev/null @@ -1,254 +0,0 @@ ---- -title: Alternative Install Methods -description: There are different ways to install Nargo, the one-stop shop and command-line tool for developing Noir programs. This guide explains other methods that don't rely on noirup, such as compiling from source, installing from binaries, and using WSL for windows -keywords: [ - Installation - Nargo - Noirup - Binaries - Compiling from Source - WSL for Windows - macOS - Linux - Nix - Direnv - Shell & editor experience - Building and testing - Uninstalling Nargo - Noir vs code extension, - ] -sidebar_position: 1 ---- - -## Encouraged Installation Method: Noirup - -Noirup is the endorsed method for installing Nargo, streamlining the process of fetching binaries or compiling from source. It supports a range of options to cater to your specific needs, from nightly builds and specific versions to compiling from various sources. - -### Installing Noirup - -First, ensure you have `noirup` installed: - -```sh -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -### Fetching Binaries - -With `noirup`, you can easily switch between different Nargo versions, including nightly builds: - -- **Nightly Version**: Install the latest nightly build. - - ```sh - noirup --version nightly - ``` - -- **Specific Version**: Install a specific version of Nargo. - ```sh - noirup --version - ``` - -### Compiling from Source - -`noirup` also enables compiling Nargo from various sources: - -- **From a Specific Branch**: Install from the latest commit on a branch. - - ```sh - noirup --branch - ``` - -- **From a Fork**: Install from the main branch of a fork. - - ```sh - noirup --repo - ``` - -- **From a Specific Branch in a Fork**: Install from a specific branch in a fork. - - ```sh - noirup --repo --branch - ``` - -- **From a Specific Pull Request**: Install from a specific PR. - - ```sh - noirup --pr - ``` - -- **From a Specific Commit**: Install from a specific commit. - - ```sh - noirup -C - ``` - -- **From Local Source**: Compile and install from a local directory. - ```sh - noirup --path ./path/to/local/source - ``` - -## Alternate Installation Methods (No Longer Recommended) - -While the following methods are available, they are no longer recommended. We advise using noirup for a more efficient and flexible installation experience. - -However, there are other methods for installing Nargo: - -- [Binaries](#option-1-installing-from-binaries) -- [Compiling from Source](#option-2-compile-from-source) -- [WSL for Windows](#option-3-wsl-for-windows) - -### Option 1: Installing from Binaries - -See [GitHub Releases](https://github.com/noir-lang/noir/releases) for the latest and previous -platform specific binaries. - -#### Step 1 - -Paste and run the following in the terminal to extract and install the binary: - -> **macOS / Linux:** If you are prompted with `Permission denied` when running commands, prepend -> `sudo` and re-run it. - -##### macOS (Apple Silicon) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.24.0/nargo-aarch64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### macOS (Intel) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.24.0/nargo-x86_64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### Linux (Bash) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.24.0/nargo-x86_64-unknown-linux-gnu.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -C $HOME/.nargo/bin/ && \ -echo -e '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.bashrc && \ -source ~/.bashrc -``` - -#### Step 2 - -Check if the installation was successful by running `nargo --version`. You should get a version number. - -> **macOS:** If you are prompted with an OS alert, right-click and open the _nargo_ executable from -> Finder. Close the new terminal popped up and `nargo` should now be accessible. - -### Option 2: Compile from Source - -Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. It helps mitigating issues commonly associated with dependency management, such as conflicts between required package versions for different projects (often referred to as "dependency hell"). - -Combined with direnv, which automatically sets or clears environment variables based on the directory, it further simplifies the development process by seamlessly integrating with the developer's shell, facilitating an efficient and reliable workflow for managing and deploying Noir projects with multiple dependencies. - -#### Setting up your environment - -For the best experience, please follow these instructions to setup your environment: - -1. Install Nix following [their guide](https://nixos.org/download.html) for your operating system. -2. Create the file `~/.config/nix/nix.conf` with the contents: - -```ini -experimental-features = nix-command -extra-experimental-features = flakes -``` - -3. Install direnv into your Nix profile by running: - -```sh -nix profile install nixpkgs#direnv -``` - -4. Add direnv to your shell following [their guide](https://direnv.net/docs/hook.html). - 1. For bash or zshell, add `eval "$(direnv hook bash)"` or `eval "$(direnv hook zsh)"` to your ~/.bashrc or ~/.zshrc file, respectively. -5. Restart your shell. - -#### Shell & editor experience - -Now that your environment is set up, you can get to work on the project. - -1. Clone the repository, such as: - -```sh -git clone git@github.com:noir-lang/noir -``` - -> Replacing `noir` with whichever repository you want to work on. - -2. Navigate to the directory: - -```sh -cd noir -``` - -> Replacing `noir` with whichever repository you cloned. - -3. You should see a **direnv error** because projects aren't allowed by default. Make sure you've reviewed and trust our `.envrc` file, then you need to run: - -```sh -direnv allow -``` - -4. Now, wait awhile for all the native dependencies to be built. This will take some time and direnv will warn you that it is taking a long time, but we just need to let it run. - -5. Once you are presented with your prompt again, you can start your editor within the project directory (we recommend [VSCode](https://code.visualstudio.com/)): - -```sh -code . -``` - -6. (Recommended) When launching VSCode for the first time, you should be prompted to install our recommended plugins. We highly recommend installing these for the best development experience. - -#### Building and testing - -Assuming you are using `direnv` to populate your environment, building and testing the project can be done -with the typical `cargo build`, `cargo test`, and `cargo clippy` commands. You'll notice that the `cargo` version matches the version we specify in `rust-toolchain.toml`, which is 1.73.0 at the time of this writing. - -If you want to build the entire project in an isolated sandbox, you can use Nix commands: - -1. `nix build .` (or `nix build . -L` for verbose output) to build the project in a Nix sandbox. -2. `nix flake check` (or `nix flake check -L` for verbose output) to run clippy and tests in a Nix sandbox. - -#### Without `direnv` - -If you have hesitations with using direnv, you can launch a subshell with `nix develop` and then launch your editor from within the subshell. However, if VSCode was already launched in the project directory, the environment won't be updated. - -Advanced: If you aren't using direnv nor launching your editor within the subshell, you can try to install Barretenberg and other global dependencies the package needs. This is an advanced workflow and likely won't receive support! - -### Option 3: WSL (for Windows) - -The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed natively. However, it is available by using Windows Subsystem for Linux (WSL). - -Step 1: Follow the instructions [here](https://learn.microsoft.com/en-us/windows/wsl/install) to install and run WSL. - -step 2: Follow the [Noirup instructions](#encouraged-installation-method-noirup). - -## Uninstalling Nargo - -### Noirup - -If you installed Nargo with `noirup` or through directly downloading binaries, you can uninstall Nargo by removing the files in `~/.nargo`, `~/nargo`, and `~/noir_cache`. This ensures that all installed binaries, configurations, and cache related to Nargo are fully removed from your system. - -```bash -rm -r ~/.nargo -rm -r ~/nargo -rm -r ~/noir_cache -``` - -### Nix - -If you installed Nargo with Nix or compiled it from source, you can remove the binary located at `~/.nix-profile/bin/nargo`. - -```bash -rm ~/.nix-profile/bin/nargo -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/tooling/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/tooling/_category_.json deleted file mode 100644 index 55804c03a71..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/tooling/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "position": 2, - "label": "Tooling", - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/tooling/index.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/tooling/index.mdx deleted file mode 100644 index ec9ccea4115..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/tooling/index.mdx +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: Tooling -Description: This section provides information about the various tools and utilities available for Noir development. It covers IDE tools, Codespaces, and community projects. -Keywords: [Noir, Development, Playground, IDE Tools, Language Service Provider, VS Code Extension, Codespaces, noir-starter, Community Projects, Awesome Noir Repository, Developer Tooling] ---- - -Noir is meant to be easy to develop with. For that reason, a number of utilities have been put together to ease the development process as much as feasible in the zero-knowledge world. - -## IDE tools - -When you install Nargo, you're also installing a Language Service Provider (LSP), which can be used by IDEs to provide syntax highlighting, codelens, warnings, and more. - -The easiest way to use these tools is by installing the [Noir VS Code extension](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). - -## Codespaces - -Some Noir repos have leveraged Codespaces in order to ease the development process. You can visit the [noir-starter](https://github.com/noir-lang/noir-starter) for an example. - - - -## GitHub Actions - -You can use `noirup` with GitHub Actions for CI/CD and automated testing. It is as simple as -installing `noirup` and running tests in your GitHub Action `yml` file. - -See the -[config file in the Noir repo](https://github.com/TomAFrench/noir-hashes/blob/master/.github/workflows/noir.yml) for an example usage. - -## Community projects - -As an open-source project, Noir has received many contributions over time. Some of them are related with developer tooling, and you can see some of them in [Awesome Noir repository](https://github.com/noir-lang/awesome-noir#dev-tools) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/tooling/language_server.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/tooling/language_server.md deleted file mode 100644 index 81e0356ef8a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/tooling/language_server.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Language Server -description: Learn about the Noir Language Server, how to install the components, and configuration that may be required. -keywords: [Nargo, Language Server, LSP, VSCode, Visual Studio Code] -sidebar_position: 0 ---- - -This section helps you install and configure the Noir Language Server. - -The Language Server Protocol (LSP) has two components, the [Server](#language-server) and the [Client](#language-client). Below we describe each in the context of Noir. - -## Language Server - -The Server component is provided by the Nargo command line tool that you installed at the beginning of this guide. -As long as Nargo is installed and you've used it to run other commands in this guide, it should be good to go! - -If you'd like to verify that the `nargo lsp` command is available, you can run `nargo --help` and look for `lsp` in the list of commands. If you see it, you're using a version of Noir with LSP support. - -## Language Client - -The Client component is usually an editor plugin that launches the Server. It communicates LSP messages between the editor and the Server. For example, when you save a file, the Client will alert the Server, so it can try to compile the project and report any errors. - -Currently, Noir provides a Language Client for Visual Studio Code via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). - -> **Note:** Noir's Language Server Protocol support currently assumes users' VSCode workspace root to be the same as users' Noir project root (i.e. where Nargo.toml lies). -> -> If LSP features seem to be missing / malfunctioning, make sure you are opening your Noir project directly (instead of as a sub-folder) in your VSCode instance. - -When your language server is running correctly and the VSCode plugin is installed, you should see handy codelens buttons for compilation, measuring circuit size, execution, and tests: - -![Compile and Execute](@site/static/img/codelens_compile_execute.png) -![Run test](@site/static/img/codelens_run_test.png) - -You should also see your tests in the `testing` panel: - -![Testing panel](@site/static/img/codelens_testing_panel.png) - -### Configuration - -- **Noir: Enable LSP** - If checked, the extension will launch the Language Server via `nargo lsp` and communicate with it. -- **Noir: Nargo Flags** - Additional flags may be specified if you require them to be added when the extension calls `nargo lsp`. -- **Noir: Nargo Path** - An absolute path to a Nargo binary with the `lsp` command. This may be useful if Nargo is not within the `PATH` of your editor. -- **Noir > Trace: Server** - Setting this to `"messages"` or `"verbose"` will log LSP messages between the Client and Server. Useful for debugging. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/tooling/testing.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/tooling/testing.md deleted file mode 100644 index d3e0c522473..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/tooling/testing.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -title: Testing in Noir -description: Learn how to use Nargo to test your Noir program in a quick and easy way -keywords: [Nargo, testing, Noir, compile, test] -sidebar_position: 1 ---- - -You can test your Noir programs using Noir circuits. - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. - -For example if you have a program like: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test] -fn test_add() { - assert(add(2,2) == 4); - assert(add(0,1) == 1); - assert(add(1,0) == 1); -} -``` - -Running `nargo test` will test that the `test_add` function can be executed while satisfying all -the constraints which allows you to test that add returns the expected values. Test functions can't -have any arguments currently. - -### Test fail - -You can write tests that are expected to fail by using the decorator `#[test(should_fail)]`. For example: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test(should_fail)] -fn test_add() { - assert(add(2,2) == 5); -} -``` - -You can be more specific and make it fail with a specific reason by using `should_fail_with = "`: - -```rust -fn main(african_swallow_avg_speed : Field) { - assert(african_swallow_avg_speed == 65, "What is the airspeed velocity of an unladen swallow"); -} - -#[test] -fn test_king_arthur() { - main(65); -} - -#[test(should_fail_with = "What is the airspeed velocity of an unladen swallow")] -fn test_bridgekeeper() { - main(32); -} - -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/_category_.json deleted file mode 100644 index 23b560f610b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 1, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/how-to-oracles.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/how-to-oracles.md deleted file mode 100644 index ab225b9421f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/how-to-oracles.md +++ /dev/null @@ -1,280 +0,0 @@ ---- -title: How to use Oracles -description: Learn how to use oracles in your Noir program with examples in both Nargo and NoirJS. This guide also covers writing a JSON RPC server and providing custom foreign call handlers for NoirJS. -keywords: - - Noir Programming - - Oracles - - Nargo - - NoirJS - - JSON RPC Server - - Foreign Call Handlers -sidebar_position: 1 ---- - -This guide shows you how to use oracles in your Noir program. For the sake of clarity, it assumes that: - -- You have read the [explainer on Oracles](../explainers/explainer-oracle.md) and are comfortable with the concept. -- You have a Noir program to add oracles to. You can create one using the [vite-hardhat starter](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat) as a boilerplate. -- You understand the concept of a JSON-RPC server. Visit the [JSON-RPC website](https://www.jsonrpc.org/) if you need a refresher. -- You are comfortable with server-side JavaScript (e.g. Node.js, managing packages, etc.). - -For reference, you can find the snippets used in this tutorial on the [Aztec DevRel Repository](https://github.com/AztecProtocol/dev-rel/tree/main/code-snippets/how-to-oracles). - -## Rundown - -This guide has 3 major steps: - -1. How to modify our Noir program to make use of oracle calls as unconstrained functions -2. How to write a JSON RPC Server to resolve these oracle calls with Nargo -3. How to use them in Nargo and how to provide a custom resolver in NoirJS - -## Step 1 - Modify your Noir program - -An oracle is defined in a Noir program by defining two methods: - -- An unconstrained method - This tells the compiler that it is executing an [unconstrained functions](../noir/concepts//unconstrained.md). -- A decorated oracle method - This tells the compiler that this method is an RPC call. - -An example of an oracle that returns a `Field` would be: - -```rust -#[oracle(getSqrt)] -unconstrained fn sqrt(number: Field) -> Field { } - -unconstrained fn get_sqrt(number: Field) -> Field { - sqrt(number) -} -``` - -In this example, we're wrapping our oracle function in a unconstrained method, and decorating it with `oracle(getSqrt)`. We can then call the unconstrained function as we would call any other function: - -```rust -fn main(input: Field) { - let sqrt = get_sqrt(input); -} -``` - -In the next section, we will make this `getSqrt` (defined on the `sqrt` decorator) be a method of the RPC server Noir will use. - -:::danger - -As explained in the [Oracle Explainer](../explainers/explainer-oracle.md), this `main` function is unsafe unless you constrain its return value. For example: - -```rust -fn main(input: Field) { - let sqrt = get_sqrt(input); - assert(sqrt.pow_32(2) as u64 == input as u64); // <---- constrain the return of an oracle! -} -``` - -::: - -:::info - -Currently, oracles only work with single params or array params. For example: - -```rust -#[oracle(getSqrt)] -unconstrained fn sqrt([Field; 2]) -> [Field; 2] { } -``` - -::: - -## Step 2 - Write an RPC server - -Brillig will call *one* RPC server. Most likely you will have to write your own, and you can do it in whatever language you prefer. In this guide, we will do it in Javascript. - -Let's use the above example of an oracle that consumes an array with two `Field` and returns their square roots: - -```rust -#[oracle(getSqrt)] -unconstrained fn sqrt(input: [Field; 2]) -> [Field; 2] { } - -unconstrained fn get_sqrt(input: [Field; 2]) -> [Field; 2] { - sqrt(input) -} - -fn main(input: [Field; 2]) { - let sqrt = get_sqrt(input); - assert(sqrt[0].pow_32(2) as u64 == input[0] as u64); - assert(sqrt[1].pow_32(2) as u64 == input[1] as u64); -} -``` - -:::info - -Why square root? - -In general, computing square roots is computationally more expensive than multiplications, which takes a toll when speaking about ZK applications. In this case, instead of calculating the square root in Noir, we are using our oracle to offload that computation to be made in plain. In our circuit we can simply multiply the two values. - -::: - -Now, we should write the correspondent RPC server, starting with the [default JSON-RPC 2.0 boilerplate](https://www.npmjs.com/package/json-rpc-2.0#example): - -```js -import { JSONRPCServer } from "json-rpc-2.0"; -import express from "express"; -import bodyParser from "body-parser"; - -const app = express(); -app.use(bodyParser.json()); - -const server = new JSONRPCServer(); -app.post("/", (req, res) => { - const jsonRPCRequest = req.body; - server.receive(jsonRPCRequest).then((jsonRPCResponse) => { - if (jsonRPCResponse) { - res.json(jsonRPCResponse); - } else { - res.sendStatus(204); - } - }); -}); - -app.listen(5555); -``` - -Now, we will add our `getSqrt` method, as expected by the `#[oracle(getSqrt)]` decorator in our Noir code. It maps through the params array and returns their square roots: - -```js -server.addMethod("getSqrt", async (params) => { - const values = params[0].Array.map(({ inner }) => { - return { inner: `${Math.sqrt(parseInt(inner, 16))}` }; - }); - return { values: [{ Array: values }] }; -}); -``` - -:::tip - -Brillig expects an object with an array of values. Each value is an object declaring to be `Single` or `Array` and returning a `inner` property *as a string*. For example: - -```json -{ "values": [{ "Array": [{ "inner": "1" }, { "inner": "2"}]}]} -{ "values": [{ "Single": { "inner": "1" }}]} -{ "values": [{ "Single": { "inner": "1" }}, { "Array": [{ "inner": "1", { "inner": "2" }}]}]} -``` - -If you're using Typescript, the following types may be helpful in understanding the expected return value and making sure they're easy to follow: - -```js -interface Value { - inner: string, -} - -interface SingleForeignCallParam { - Single: Value, -} - -interface ArrayForeignCallParam { - Array: Value[], -} - -type ForeignCallParam = SingleForeignCallParam | ArrayForeignCallParam; - -interface ForeignCallResult { - values: ForeignCallParam[], -} -``` - -::: - -## Step 3 - Usage with Nargo - -Using the [`nargo` CLI tool](../getting_started/installation/index.md), you can use oracles in the `nargo test`, `nargo execute` and `nargo prove` commands by passing a value to `--oracle-resolver`. For example: - -```bash -nargo test --oracle-resolver http://localhost:5555 -``` - -This tells `nargo` to use your RPC Server URL whenever it finds an oracle decorator. - -## Step 4 - Usage with NoirJS - -In a JS environment, an RPC server is not strictly necessary, as you may want to resolve your oracles without needing any JSON call at all. NoirJS simply expects that you pass a callback function when you generate proofs, and that callback function can be anything. - -For example, if your Noir program expects the host machine to provide CPU pseudo-randomness, you could simply pass it as the `foreignCallHandler`. You don't strictly need to create an RPC server to serve pseudo-randomness, as you may as well get it directly in your app: - -```js -const foreignCallHandler = (name, inputs) => crypto.randomBytes(16) // etc - -await noir.generateProof(inputs, foreignCallHandler) -``` - -As one can see, in NoirJS, the [`foreignCallHandler`](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) function simply means "a callback function that returns a value of type [`ForeignCallOutput`](../reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md). It doesn't have to be an RPC call like in the case for Nargo. - -:::tip - -Does this mean you don't have to write an RPC server like in [Step #2](#step-2---write-an-rpc-server)? - -You don't technically have to, but then how would you run `nargo test` or `nargo prove`? To use both `Nargo` and `NoirJS` in your development flow, you will have to write a JSON RPC server. - -::: - -In this case, let's make `foreignCallHandler` call the JSON RPC Server we created in [Step #2](#step-2---write-an-rpc-server), by making it a JSON RPC Client. - -For example, using the same `getSqrt` program in [Step #1](#step-1---modify-your-noir-program) (comments in the code): - -```js -import { JSONRPCClient } from "json-rpc-2.0"; - -// declaring the JSONRPCClient -const client = new JSONRPCClient((jsonRPCRequest) => { -// hitting the same JSON RPC Server we coded above - return fetch("http://localhost:5555", { - method: "POST", - headers: { - "content-type": "application/json", - }, - body: JSON.stringify(jsonRPCRequest), - }).then((response) => { - if (response.status === 200) { - return response - .json() - .then((jsonRPCResponse) => client.receive(jsonRPCResponse)); - } else if (jsonRPCRequest.id !== undefined) { - return Promise.reject(new Error(response.statusText)); - } - }); -}); - -// declaring a function that takes the name of the foreign call (getSqrt) and the inputs -const foreignCallHandler = async (name, input) => { - // notice that the "inputs" parameter contains *all* the inputs - // in this case we to make the RPC request with the first parameter "numbers", which would be input[0] - const oracleReturn = await client.request(name, [ - { Array: input[0].map((i) => ({ inner: i.toString("hex") })) }, - ]); - return [oracleReturn.values[0].Array.map((x) => x.inner)]; -}; - -// the rest of your NoirJS code -const input = { input: [4, 16] }; -const { witness } = await noir.execute(numbers, foreignCallHandler); -``` - -:::tip - -If you're in a NoirJS environment running your RPC server together with a frontend app, you'll probably hit a familiar problem in full-stack development: requests being blocked by [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) policy. For development only, you can simply install and use the [`cors` npm package](https://www.npmjs.com/package/cors) to get around the problem: - -```bash -yarn add cors -``` - -and use it as a middleware: - -```js -import cors from "cors"; - -const app = express(); -app.use(cors()) -``` - -::: - -## Conclusion - -Hopefully by the end of this guide, you should be able to: - -- Write your own logic around Oracles and how to write a JSON RPC server to make them work with your Nargo commands. -- Provide custom foreign call handlers for NoirJS. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/how-to-recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/how-to-recursion.md deleted file mode 100644 index 4c45bb87ae2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/how-to-recursion.md +++ /dev/null @@ -1,179 +0,0 @@ ---- -title: How to use recursion on NoirJS -description: Learn how to implement recursion with NoirJS, a powerful tool for creating smart contracts on the EVM blockchain. This guide assumes familiarity with NoirJS, solidity verifiers, and the Barretenberg proving backend. Discover how to generate both final and intermediate proofs using `noir_js` and `backend_barretenberg`. -keywords: - [ - "NoirJS", - "EVM blockchain", - "smart contracts", - "recursion", - "solidity verifiers", - "Barretenberg backend", - "noir_js", - "backend_barretenberg", - "intermediate proofs", - "final proofs", - "nargo compile", - "json import", - "recursive circuit", - "recursive app" - ] -sidebar_position: 1 ---- - -This guide shows you how to use recursive proofs in your NoirJS app. For the sake of clarity, it is assumed that: - -- You already have a NoirJS app. If you don't, please visit the [NoirJS tutorial](../tutorials/noirjs_app.md) and the [reference](../reference/NoirJS/noir_js/index.md). -- You are familiar with what are recursive proofs and you have read the [recursion explainer](../explainers/explainer-recursion.md) -- You already built a recursive circuit following [the reference](../noir/standard_library/recursion.md), and understand how it works. - -It is also assumed that you're not using `noir_wasm` for compilation, and instead you've used [`nargo compile`](../reference/nargo_commands.md) to generate the `json` you're now importing into your project. However, the guide should work just the same if you're using `noir_wasm`. - -:::info - -As you've read in the [explainer](../explainers/explainer-recursion.md), a recursive proof is an intermediate proof. This means that it doesn't necessarily generate the final step that makes it verifiable in a smart contract. However, it is easy to verify within another circuit. - -While "standard" usage of NoirJS packages abstracts final proofs, it currently lacks the necessary interface to abstract away intermediate proofs. This means that these proofs need to be created by using the backend directly. - -In short: - -- `noir_js` generates *only* final proofs -- `backend_barretenberg` generates both types of proofs - -::: - -In a standard recursive app, you're also dealing with at least two circuits. For the purpose of this guide, we will assume the following: - -- `main`: a circuit of type `assert(x != y)`, where `main` is marked with a `#[recursive]` attribute. This attribute states that the backend should generate proofs that are friendly for verification within another circuit. -- `recursive`: a circuit that verifies `main` - -For a full example on how recursive proofs work, please refer to the [noir-examples](https://github.com/noir-lang/noir-examples) repository. We will *not* be using it as a reference for this guide. - -## Step 1: Setup - -In a common NoirJS app, you need to instantiate a backend with something like `const backend = new Backend(circuit)`. Then you feed it to the `noir_js` interface. - -For recursion, this doesn't happen, and the only need for `noir_js` is only to `execute` a circuit and get its witness and return value. Everything else is not interfaced, so it needs to happen on the `backend` object. - -It is also recommended that you instantiate the backend with as many threads as possible, to allow for maximum concurrency: - -```js -const backend = new Backend(circuit, { threads: 8 }) -``` - -:::tip -You can use the [`os.cpus()`](https://nodejs.org/api/os.html#oscpus) object in `nodejs` or [`navigator.hardwareConcurrency`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/hardwareConcurrency) on the browser to make the most out of those glorious cpu cores -::: - -## Step 2: Generating the witness and the proof for `main` - -After instantiating the backend, you should also instantiate `noir_js`. We will use it to execute the circuit and get the witness. - -```js -const noir = new Noir(circuit, backend) -const { witness } = noir.execute(input) -``` - -With this witness, you are now able to generate the intermediate proof for the main circuit: - -```js -const { proof, publicInputs } = await backend.generateProof(witness) -``` - -:::warning - -Always keep in mind what is actually happening on your development process, otherwise you'll quickly become confused about what circuit we are actually running and why! - -In this case, you can imagine that Alice (running the `main` circuit) is proving something to Bob (running the `recursive` circuit), and Bob is verifying her proof within his proof. - -With this in mind, it becomes clear that our intermediate proof is the one *meant to be verified within another circuit*, so it must be Alice's. Actually, the only final proof in this theoretical scenario would be the last one, sent on-chain. - -::: - -## Step 3 - Verification and proof artifacts - -Optionally, you are able to verify the intermediate proof: - -```js -const verified = await backend.verifyProof({ proof, publicInputs }) -``` - -This can be useful to make sure our intermediate proof was correctly generated. But the real goal is to do it within another circuit. For that, we need to generate recursive proof artifacts that will be passed to the circuit that is verifying the proof we just generated. Instead of passing the proof and verification key as a byte array, we pass them as fields which makes it cheaper to verify in a circuit: - -```js -const { proofAsFields, vkAsFields, vkHash } = await backend.generateRecursiveProofArtifacts( { publicInputs, proof }, publicInputsCount) -``` - -This call takes the public inputs and the proof, but also the public inputs count. While this is easily retrievable by simply counting the `publicInputs` length, the backend interface doesn't currently abstract it away. - -:::info - -The `proofAsFields` has a constant size `[Field; 93]` and verification keys in Barretenberg are always `[Field; 114]`. - -::: - -:::warning - -One common mistake is to forget *who* makes this call. - -In a situation where Alice is generating the `main` proof, if she generates the proof artifacts and sends them to Bob, which gladly takes them as true, this would mean Alice could prove anything! - -Instead, Bob needs to make sure *he* extracts the proof artifacts, using his own instance of the `main` circuit backend. This way, Alice has to provide a valid proof for the correct `main` circuit. - -::: - -## Step 4 - Recursive proof generation - -With the artifacts, generating a recursive proof is no different from a normal proof. You simply use the `backend` (with the recursive circuit) to generate it: - -```js -const recursiveInputs = { - verification_key: vkAsFields, // array of length 114 - proof: proofAsFields, // array of length 93 + size of public inputs - publicInputs: [mainInput.y], // using the example above, where `y` is the only public input - key_hash: vkHash, -} - -const { witness, returnValue } = noir.execute(recursiveInputs) // we're executing the recursive circuit now! -const { proof, publicInputs } = backend.generateProof(witness) -const verified = backend.verifyProof({ proof, publicInputs }) -``` - -You can obviously chain this proof into another proof. In fact, if you're using recursive proofs, you're probably interested of using them this way! - -:::tip - -Managing circuits and "who does what" can be confusing. To make sure your naming is consistent, you can keep them in an object. For example: - -```js -const circuits = { - main: mainJSON, - recursive: recursiveJSON -} -const backends = { - main: new BarretenbergBackend(circuits.main), - recursive: new BarretenbergBackend(circuits.recursive) -} -const noir_programs = { - main: new Noir(circuits.main, backends.main), - recursive: new Noir(circuits.recursive, backends.recursive) -} -``` - -This allows you to neatly call exactly the method you want without conflicting names: - -```js -// Alice runs this 👇 -const { witness: mainWitness } = await noir_programs.main.execute(input) -const proof = await backends.main.generateProof(mainWitness) - -// Bob runs this 👇 -const verified = await backends.main.verifyProof(proof) -const { proofAsFields, vkAsFields, vkHash } = await backends.main.generateRecursiveProofArtifacts( - proof, - numPublicInputs, -); -const recursiveProof = await noir_programs.recursive.generateProof(recursiveInputs) -``` - -::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/how-to-solidity-verifier.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/how-to-solidity-verifier.md deleted file mode 100644 index e3c7c1065da..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/how-to-solidity-verifier.md +++ /dev/null @@ -1,231 +0,0 @@ ---- -title: Generate a Solidity Verifier -description: - Learn how to run the verifier as a smart contract on the blockchain. Compile a Solidity verifier - contract for your Noir program and deploy it on any EVM blockchain acting as a verifier smart - contract. Read more to find out -keywords: - [ - solidity verifier, - smart contract, - blockchain, - compiler, - plonk_vk.sol, - EVM blockchain, - verifying Noir programs, - proving backend, - Barretenberg, - ] -sidebar_position: 0 -pagination_next: tutorials/noirjs_app ---- - -Noir has the ability to generate a verifier contract in Solidity, which can be deployed in many EVM-compatible blockchains such as Ethereum. - -This allows for a powerful feature set, as one can make use of the conciseness and the privacy provided by Noir in an immutable ledger. Applications can range from simple P2P guessing games, to complex private DeFi interactions. - -This guide shows you how to generate a Solidity Verifier and deploy it on the [Remix IDE](https://remix.ethereum.org/). It is assumed that: - -- You are comfortable with the Solidity programming language and understand how contracts are deployed on the Ethereum network -- You have Noir installed and you have a Noir program. If you don't, [get started](../getting_started/installation/index.md) with Nargo and the example Hello Noir circuit -- You are comfortable navigating RemixIDE. If you aren't or you need a refresher, you can find some video tutorials [here](https://www.youtube.com/channel/UCjTUPyFEr2xDGN6Cg8nKDaA) that could help you. - -## Rundown - -Generating a Solidity Verifier contract is actually a one-command process. However, compiling it and deploying it can have some caveats. Here's the rundown of this guide: - -1. How to generate a solidity smart contract -2. How to compile the smart contract in the RemixIDE -3. How to deploy it to a testnet - -## Step 1 - Generate a contract - -This is by far the most straight-forward step. Just run: - -```sh -nargo codegen-verifier -``` - -A new `contract` folder would then be generated in your project directory, containing the Solidity -file `plonk_vk.sol`. It can be deployed to any EVM blockchain acting as a verifier smart contract. - -:::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. - -Barretenberg, the default proving backend for Nargo, supports generation of verifier contracts, for the time being these are only in Solidity. -::: - -## Step 2 - Compiling - -We will mostly skip the details of RemixIDE, as the UI can change from version to version. For now, we can just open -Remix and create a blank workspace. - -![Create Workspace](@site/static/img/how-tos/solidity_verifier_1.png) - -We will create a new file to contain the contract Nargo generated, and copy-paste its content. - -:::warning - -You'll likely see a warning advising you to not trust pasted code. While it is an important warning, it is irrelevant in the context of this guide and can be ignored. We will not be deploying anywhere near a mainnet. - -::: - -To compile our the verifier, we can navigate to the compilation tab: - -![Compilation Tab](@site/static/img/how-tos/solidity_verifier_2.png) - -Remix should automatically match a suitable compiler version. However, hitting the "Compile" button will most likely generate a "Stack too deep" error: - -![Stack too deep](@site/static/img/how-tos/solidity_verifier_3.png) - -This is due to the verify function needing to put many variables on the stack, but enabling the optimizer resolves the issue. To do this, let's open the "Advanced Configurations" tab and enable optimization. The default 200 runs will suffice. - -:::info - -This time we will see a warning about an unused function parameter. This is expected, as the `verify` function doesn't use the `_proof` parameter inside a solidity block, it is loaded from calldata and used in assembly. - -::: - -![Compilation success](@site/static/img/how-tos/solidity_verifier_4.png) - -## Step 3 - Deploying - -At this point we should have a compiled contract read to deploy. If we navigate to the deploy section in Remix, we will see many different environments we can deploy to. The steps to deploy on each environment would be out-of-scope for this guide, so we will just use the default Remix VM. - -Looking closely, we will notice that our "Solidity Verifier" is actually three contracts working together: - -- An `UltraVerificationKey` library which simply stores the verification key for our circuit. -- An abstract contract `BaseUltraVerifier` containing most of the verifying logic. -- A main `UltraVerifier` contract that inherits from the Base and uses the Key contract. - -Remix will take care of the dependencies for us so we can simply deploy the UltraVerifier contract by selecting it and hitting "deploy": - -![Deploying UltraVerifier](@site/static/img/how-tos/solidity_verifier_5.png) - -A contract will show up in the "Deployed Contracts" section, where we can retrieve the Verification Key Hash. This is particularly useful for double-checking the deployer contract is the correct one. - -:::note - -Why "UltraVerifier"? - -To be precise, the Noir compiler (`nargo`) doesn't generate the verifier contract directly. It compiles the Noir code into an intermediate language (ACIR), which is then executed by the backend. So it is the backend that returns the verifier smart contract, not Noir. - -In this case, the Barretenberg Backend uses the UltraPlonk proving system, hence the "UltraVerifier" name. - -::: - -## Step 4 - Verifying - -To verify a proof using the Solidity verifier contract, we call the `verify` function in this extended contract: - -```solidity -function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) -``` - -When using the default example in the [Hello Noir](../getting_started/hello_noir/index.md) guide, the easiest way to confirm that the verifier contract is doing its job is by calling the `verify` function via remix with the required parameters. For `_proof`, run `nargo prove` and use the string in `proof/.proof` (adding the hex `0x` prefix). We can also copy the public input from `Verifier.toml`, as it will be properly formatted as 32-byte strings: - -``` -0x...... , [0x0000.....02] -``` - -A programmatic example of how the `verify` function is called can be seen in the example zk voting application [here](https://github.com/noir-lang/noir-examples/blob/33e598c257e2402ea3a6b68dd4c5ad492bce1b0a/foundry-voting/src/zkVote.sol#L35): - -```solidity -function castVote(bytes calldata proof, uint proposalId, uint vote, bytes32 nullifierHash) public returns (bool) { - // ... - bytes32[] memory publicInputs = new bytes32[](4); - publicInputs[0] = merkleRoot; - publicInputs[1] = bytes32(proposalId); - publicInputs[2] = bytes32(vote); - publicInputs[3] = nullifierHash; - require(verifier.verify(proof, publicInputs), "Invalid proof"); -``` - -:::info[Return Values] - -A circuit doesn't have the concept of a return value. Return values are just syntactic sugar in -Noir. - -Under the hood, the return value is passed as an input to the circuit and is checked at the end of -the circuit program. - -For example, if you have Noir program like this: - -```rust -fn main( - // Public inputs - pubkey_x: pub Field, - pubkey_y: pub Field, - // Private inputs - priv_key: Field, -) -> pub Field -``` - -the `verify` function will expect the public inputs array (second function parameter) to be of length 3, the two inputs and the return value. Like before, these values are populated in Verifier.toml after running `nargo prove`. - -Passing only two inputs will result in an error such as `PUBLIC_INPUT_COUNT_INVALID(3, 2)`. - -In this case, the inputs parameter to `verify` would be an array ordered as `[pubkey_x, pubkey_y, return]`. - -::: - -:::tip[Structs] - -You can pass structs to the verifier contract. They will be flattened so that the array of inputs is 1-dimensional array. - -For example, consider the following program: - -```rust -struct Type1 { - val1: Field, - val2: Field, -} - -struct Nested { - t1: Type1, - is_true: bool, -} - -fn main(x: pub Field, nested: pub Nested, y: pub Field) { - //... -} -``` - -The order of these inputs would be flattened to: `[x, nested.t1.val1, nested.t1.val2, nested.is_true, y]` - -::: - -The other function you can call is our entrypoint `verify` function, as defined above. - -:::tip - -It's worth noticing that the `verify` function is actually a `view` function. A `view` function does not alter the blockchain state, so it doesn't need to be distributed (i.e. it will run only on the executing node), and therefore doesn't cost any gas. - -This can be particularly useful in some situations. If Alice generated a proof and wants Bob to verify its correctness, Bob doesn't need to run Nargo, NoirJS, or any Noir specific infrastructure. He can simply make a call to the blockchain with the proof and verify it is correct without paying any gas. - -It would be incorrect to say that a Noir proof verification costs any gas at all. However, most of the time the result of `verify` is used to modify state (for example, to update a balance, a game state, etc). In that case the whole network needs to execute it, which does incur gas costs (calldata and execution, but not storage). - -::: - -## A Note on EVM chains - -ZK-SNARK verification depends on some precompiled cryptographic primitives such as Elliptic Curve Pairings (if you like complex math, you can read about EC Pairings [here](https://medium.com/@VitalikButerin/exploring-elliptic-curve-pairings-c73c1864e627)). Not all EVM chains support EC Pairings, notably some of the ZK-EVMs. This means that you won't be able to use the verifier contract in all of them. - -For example, chains like `zkSync ERA` and `Polygon zkEVM` do not currently support these precompiles, so proof verification via Solidity verifier contracts won't work. Here's a quick list of EVM chains that have been tested and are known to work: - -- Optimism -- Arbitrum -- Polygon PoS -- Scroll -- Celo - -If you test any other chains, please open a PR on this page to update the list. See [this doc](https://github.com/noir-lang/noir-starter/tree/main/with-foundry#testing-on-chain) for more info about testing verifier contracts on different EVM chains. - -## What's next - -Now that you know how to call a Noir Solidity Verifier on a smart contract using Remix, you should be comfortable with using it with some programmatic frameworks, such as [hardhat](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat) and [foundry](https://github.com/noir-lang/noir-starter/tree/main/with-foundry). - -You can find other tools, examples, boilerplates and libraries in the [awesome-noir](https://github.com/noir-lang/awesome-noir) repository. - -You should also be ready to write and deploy your first NoirJS app and start generating proofs on websites, phones, and NodeJS environments! Head on to the [NoirJS tutorial](../tutorials/noirjs_app.md) to learn how to do that. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/merkle-proof.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/merkle-proof.mdx deleted file mode 100644 index 34074659ac1..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/merkle-proof.mdx +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Prove Merkle Tree Membership -description: - Learn how to use merkle membership proof in Noir to prove that a given leaf is a member of a - merkle tree with a specified root, at a given index. -keywords: - [merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree] ---- - -Let's walk through an example of a merkle membership proof in Noir that proves that a given leaf is -in a merkle tree. - -```rust -use dep::std; - -fn main(message : [Field; 62], index : Field, hashpath : [Field; 40], root : Field) { - let leaf = std::hash::hash_to_field(message); - let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); - assert(merkle_root == root); -} - -``` - -The message is hashed using `hash_to_field`. The specific hash function that is being used is chosen -by the backend. The only requirement is that this hash function can heuristically be used as a -random oracle. If only collision resistance is needed, then one can call `std::hash::pedersen_hash` -instead. - -```rust -let leaf = std::hash::hash_to_field(message); -``` - -The leaf is then passed to a compute_merkle_root function with the root, index and hashpath. The returned root can then be asserted to be the same as the provided root. - -```rust -let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); -assert (merkle_root == root); -``` - -> **Note:** It is possible to re-implement the merkle tree implementation without standard library. -> However, for most usecases, it is enough. In general, the standard library will always opt to be -> as conservative as possible, while striking a balance with efficiency. - -An example, the merkle membership proof, only requires a hash function that has collision -resistance, hence a hash function like Pedersen is allowed, which in most cases is more efficient -than the even more conservative sha256. - -[View an example on the starter repo](https://github.com/noir-lang/noir-examples/blob/3ea09545cabfa464124ec2f3ea8e60c608abe6df/stealthdrop/circuits/src/main.nr#L20) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/using-devcontainers.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/using-devcontainers.mdx deleted file mode 100644 index 727ec6ca667..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/using-devcontainers.mdx +++ /dev/null @@ -1,110 +0,0 @@ ---- -title: Developer Containers and Codespaces -description: "Learn how to set up a devcontainer in your GitHub repository for a seamless coding experience with Codespaces. Follow our easy 8-step guide to create your own Noir environment without installing Nargo locally." -keywords: ["Devcontainer", "Codespaces", "GitHub", "Noir Environment", "Docker Image", "Development Environment", "Remote Coding", "GitHub Codespaces", "Noir Programming", "Nargo", "VSCode Extensions", "Noirup"] -sidebar_position: 1 ---- - -Adding a developer container configuration file to your Noir project is one of the easiest way to unlock coding in browser. - -## What's a devcontainer after all? - -A [Developer Container](https://containers.dev/) (devcontainer for short) is a Docker image that comes preloaded with tools, extensions, and other tools you need to quickly get started or continue a project, without having to install Nargo locally. Think of it as a development environment in a box. - -There are many advantages to this: - -- It's platform and architecture agnostic -- You don't need to have an IDE installed, or Nargo, or use a terminal at all -- It's safer for using on a public machine or public network - -One of the best ways of using devcontainers is... not using your machine at all, for maximum control, performance, and ease of use. -Enter Codespaces. - -## Codespaces - -If a devcontainer is just a Docker image, then what stops you from provisioning a `p3dn.24xlarge` AWS EC2 instance with 92 vCPUs and 768 GiB RAM and using it to prove your 10-gate SNARK proof? - -Nothing! Except perhaps the 30-40$ per hour it will cost you. - -The problem is that provisioning takes time, and I bet you don't want to see the AWS console every time you want to code something real quick. - -Fortunately, there's an easy and free way to get a decent remote machine ready and loaded in less than 2 minutes: Codespaces. [Codespaces is a Github feature](https://github.com/features/codespaces) that allows you to code in a remote machine by using devcontainers, and it's pretty cool: - -- You can start coding Noir in less than a minute -- It uses the resources of a remote machine, so you can code on your grandma's phone if needed be -- It makes it easy to share work with your frens -- It's fully reusable, you can stop and restart whenever you need to - -:::info - -Don't take out your wallet just yet. Free GitHub accounts get about [15-60 hours of coding](https://github.com/features/codespaces) for free per month, depending on the size of your provisioned machine. - -::: - -## Tell me it's _actually_ easy - -It is! - -Github comes with a default codespace and you can use it to code your own devcontainer. That's exactly what we will be doing in this guide. - - - -8 simple steps: - -#### 1. Create a new repository on GitHub. - -#### 2. Click "Start coding with Codespaces". This will use the default image. - -#### 3. Create a folder called `.devcontainer` in the root of your repository. - -#### 4. Create a Dockerfile in that folder, and paste the following code: - -```docker -FROM --platform=linux/amd64 node:lts-bookworm-slim -SHELL ["/bin/bash", "-c"] -RUN apt update && apt install -y curl bash git tar gzip libc++-dev -RUN curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -ENV PATH="/root/.nargo/bin:$PATH" -RUN noirup -ENTRYPOINT ["nargo"] -``` -#### 5. Create a file called `devcontainer.json` in the same folder, and paste the following code: - -```json -{ - "name": "Noir on Codespaces", - "build": { - "context": ".", - "dockerfile": "Dockerfile" - }, - "customizations": { - "vscode": { - "extensions": ["noir-lang.vscode-noir"] - } - } -} -``` -#### 6. Commit and push your changes - -This will pull the new image and build it, so it could take a minute or so - -#### 8. Done! -Just wait for the build to finish, and there's your easy Noir environment. - - -Refer to [noir-starter](https://github.com/noir-lang/noir-starter/) as an example of how devcontainers can be used together with codespaces. - - - -## How do I use it? - -Using the codespace is obviously much easier than setting it up. -Just navigate to your repository and click "Code" -> "Open with Codespaces". It should take a few seconds to load, and you're ready to go. - -:::info - -If you really like the experience, you can add a badge to your readme, links to existing codespaces, and more. -Check out the [official docs](https://docs.github.com/en/codespaces/setting-up-your-project-for-codespaces/setting-up-your-repository/facilitating-quick-creation-and-resumption-of-codespaces) for more info. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/index.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/index.mdx deleted file mode 100644 index 75086ddcdde..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/index.mdx +++ /dev/null @@ -1,67 +0,0 @@ ---- -title: Noir Lang -hide_title: true -description: - Learn about the public alpha release of Noir, a domain specific language heavily influenced by Rust that compiles to - an intermediate language which can be compiled to an arithmetic circuit or a rank-1 constraint system. -keywords: - [Noir, - Domain Specific Language, - Rust, - Intermediate Language, - Arithmetic Circuit, - Rank-1 Constraint System, - Ethereum Developers, - Protocol Developers, - Blockchain Developers, - Proving System, - Smart Contract Language] -sidebar_position: 0 ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -Noir Logo - -Noir is a Domain-Specific Language for SNARK proving systems developed by [Aztec Labs](https://aztec.network/). It allows you to generate complex Zero-Knowledge Programs (ZKP) by using simple and flexible syntax, requiring no previous knowledge on the underlying mathematics or cryptography. - -ZK programs are programs that can generate short proofs of a certain statement without revealing some details about it. You can read more about ZKPs [here](https://dev.to/spalladino/a-beginners-intro-to-coding-zero-knowledge-proofs-c56). - -## What's new about Noir? - -Noir works differently from most ZK languages by taking a two-pronged path. First, it compiles the program to an adaptable intermediate language known as ACIR. From there, depending on a given project's needs, ACIR can be further compiled into an arithmetic circuit for integration with the proving backend. - -:::info - -Noir is backend agnostic, which means it makes no assumptions on which proving backend powers the ZK proof. Being the language that powers [Aztec Contracts](https://docs.aztec.network/developers/contracts/main), it defaults to Aztec's Barretenberg proving backend. - -However, the ACIR output can be transformed to be compatible with other PLONK-based backends, or into a [rank-1 constraint system](https://www.rareskills.io/post/rank-1-constraint-system) suitable for backends such as Arkwork's Marlin. - -::: - -## Who is Noir for? - -Noir can be used both in complex cloud-based backends and in user's smartphones, requiring no knowledge on the underlying math or cryptography. From authorization systems that keep a password in the user's device, to complex on-chain verification of recursive proofs, Noir is designed to abstract away complexity without any significant overhead. Here are some examples of situations where Noir can be used: - - - - Noir Logo - - Aztec Contracts leverage Noir to allow for the storage and execution of private information. Writing an Aztec Contract is as easy as writing Noir, and Aztec developers can easily interact with the network storage and execution through the [Aztec.nr](https://docs.aztec.network/developers/contracts/main) library. - - - Soliditry Verifier Example - Noir can auto-generate Solidity verifier contracts that verify Noir proofs. This allows for non-interactive verification of proofs containing private information in an immutable system. This feature powers a multitude of use-case scenarios, from P2P chess tournaments, to [Aztec Layer-2 Blockchain](https://docs.aztec.network/) - - - Aztec Labs developed NoirJS, an easy interface to generate and verify Noir proofs in a Javascript environment. This allows for Noir to be used in webpages, mobile apps, games, and any other environment supporting JS execution in a standalone manner. - - - - -## Libraries - -Noir is meant to be easy to extend by simply importing Noir libraries just like in Rust. -The [awesome-noir repo](https://github.com/noir-lang/awesome-noir#libraries) is a collection of libraries developed by the Noir community. -Writing a new library is easy and makes code be composable and easy to reuse. See the section on [dependencies](noir/modules_packages_crates/dependencies.md) for more information. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/_category_.json deleted file mode 100644 index 7da08f8a8c5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Concepts", - "position": 0, - "collapsible": true, - "collapsed": true -} \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/assert.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/assert.md deleted file mode 100644 index bcff613a695..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/assert.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Assert Function -description: - Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or - comparison expression that follows to be true, and what happens if the expression is false at - runtime. -keywords: [Noir programming language, assert statement, predicate expression, comparison expression] -sidebar_position: 4 ---- - -Noir includes a special `assert` function which will explicitly constrain the predicate/comparison -expression that follows to be true. If this expression is false at runtime, the program will fail to -be proven. Example: - -```rust -fn main(x : Field, y : Field) { - assert(x == y); -} -``` - -> Assertions only work for predicate operations, such as `==`. If there's any ambiguity on the operation, the program will fail to compile. For example, it is unclear if `assert(x + y)` would check for `x + y == 0` or simply would return `true`. - -You can optionally provide a message to be logged when the assertion fails: - -```rust -assert(x == y, "x and y are not equal"); -``` - -Aside string literals, the optional message can be a format string or any other type supported as input for Noir's [print](../standard_library/logging.md) functions. This feature lets you incorporate runtime variables into your failed assertion logs: - -```rust -assert(x == y, f"Expected x == y, but got {x} == {y}"); -``` - -Using a variable as an assertion message directly: - -```rust -struct myStruct { - myField: Field -} - -let s = myStruct { myField: y }; -assert(s.myField == x, s); -``` - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/comments.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/comments.md deleted file mode 100644 index b51a85f5c94..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/comments.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Comments -description: - Learn how to write comments in Noir programming language. A comment is a line of code that is - ignored by the compiler, but it can be read by programmers. Single-line and multi-line comments - are supported in Noir. -keywords: [Noir programming language, comments, single-line comments, multi-line comments] -sidebar_position: 10 ---- - -A comment is a line in your codebase which the compiler ignores, however it can be read by -programmers. - -Here is a single line comment: - -```rust -// This is a comment and is ignored -``` - -`//` is used to tell the compiler to ignore the rest of the line. - -Noir also supports multi-line block comments. Start a block comment with `/*` and end the block with `*/`. - -Noir does not natively support doc comments. You may be able to use [Rust doc comments](https://doc.rust-lang.org/reference/comments.html) in your code to leverage some Rust documentation build tools with Noir code. - -```rust -/* - This is a block comment describing a complex function. -*/ -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/control_flow.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/control_flow.md deleted file mode 100644 index 4ce65236db3..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/control_flow.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Control Flow -description: - Learn how to use loops and if expressions in the Noir programming language. Discover the syntax - and examples for for loops and if-else statements. -keywords: [Noir programming language, loops, for loop, if-else statements, Rust syntax] -sidebar_position: 2 ---- - -## Loops - -Noir has one kind of loop: the `for` loop. `for` loops allow you to repeat a block of code multiple -times. - -The following block of code between the braces is run 10 times. - -```rust -for i in 0..10 { - // do something -}; -``` - -The index for loops is of type `u64`. - -## If Expressions - -Noir supports `if-else` statements. The syntax is most similar to Rust's where it is not required -for the statement's conditional to be surrounded by parentheses. - -```rust -let a = 0; -let mut x: u32 = 0; - -if a == 0 { - if a != 0 { - x = 6; - } else { - x = 2; - } -} else { - x = 5; - assert(x == 5); -} -assert(x == 2); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_bus.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_bus.md deleted file mode 100644 index e54fc861257..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_bus.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: Data Bus -sidebar_position: 13 ---- -**Disclaimer** this feature is experimental, do not use it! - -The data bus is an optimization that the backend can use to make recursion more efficient. -In order to use it, you must define some inputs of the program entry points (usually the `main()` -function) with the `call_data` modifier, and the return values with the `return_data` modifier. -These modifiers are incompatible with `pub` and `mut` modifiers. - -## Example - -```rust -fn main(mut x: u32, y: call_data u32, z: call_data [u32;4] ) -> return_data u32 { - let a = z[x]; - a+y -} -``` - -As a result, both call_data and return_data will be treated as private inputs and encapsulated into a read-only array each, for the backend to process. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/_category_.json deleted file mode 100644 index 5d694210bbf..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 0, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/arrays.md deleted file mode 100644 index 9a4c485feb1..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/arrays.md +++ /dev/null @@ -1,253 +0,0 @@ ---- -title: Arrays -description: - Dive into the Array data type in Noir. Grasp its methods, practical examples, and best practices for efficiently using Arrays in your Noir code. -keywords: - [ - noir, - array type, - methods, - examples, - indexing, - ] -sidebar_position: 4 ---- - -An array is one way of grouping together values into one compound type. Array types can be inferred -or explicitly specified via the syntax `[; ]`: - -```rust -fn main(x : Field, y : Field) { - let my_arr = [x, y]; - let your_arr: [Field; 2] = [x, y]; -} -``` - -Here, both `my_arr` and `your_arr` are instantiated as an array containing two `Field` elements. - -Array elements can be accessed using indexing: - -```rust -fn main() { - let a = [1, 2, 3, 4, 5]; - - let first = a[0]; - let second = a[1]; -} -``` - -All elements in an array must be of the same type (i.e. homogeneous). That is, an array cannot group -a `Field` value and a `u8` value together for example. - -You can write mutable arrays, like: - -```rust -fn main() { - let mut arr = [1, 2, 3, 4, 5]; - assert(arr[0] == 1); - - arr[0] = 42; - assert(arr[0] == 42); -} -``` - -You can instantiate a new array of a fixed size with the same value repeated for each element. The following example instantiates an array of length 32 where each element is of type Field and has the value 0. - -```rust -let array: [Field; 32] = [0; 32]; -``` - -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: - -```rust -let array: [Field; 32] = [0; 32]; -let sl = array.as_slice() -``` - -You can define multidimensional arrays: - -```rust -let array : [[Field; 2]; 2]; -let element = array[0][0]; -``` - -However, multidimensional slices are not supported. For example, the following code will error at compile time: - -```rust -let slice : [[Field]] = []; -``` - -## Types - -You can create arrays of primitive types or structs. There is not yet support for nested arrays -(arrays of arrays) or arrays of structs that contain arrays. - -## Methods - -For convenience, the STD provides some ready-to-use, common methods for arrays. -Each of these functions are located within the generic impl `impl [T; N] {`. -So anywhere `self` appears, it refers to the variable `self: [T; N]`. - -### len - -Returns the length of an array - -```rust -fn len(self) -> Field -``` - -example - -```rust -fn main() { - let array = [42, 42]; - assert(array.len() == 2); -} -``` - -### sort - -Returns a new sorted array. The original array remains untouched. Notice that this function will -only work for arrays of fields or integers, not for any arbitrary type. This is because the sorting -logic it uses internally is optimized specifically for these values. If you need a sort function to -sort any type, you should use the function `sort_via` described below. - -```rust -fn sort(self) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32]; - let sorted = arr.sort(); - assert(sorted == [32, 42]); -} -``` - -### sort_via - -Sorts the array with a custom comparison function - -```rust -fn sort_via(self, ordering: fn(T, T) -> bool) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32] - let sorted_ascending = arr.sort_via(|a, b| a <= b); - assert(sorted_ascending == [32, 42]); // verifies - - let sorted_descending = arr.sort_via(|a, b| a >= b); - assert(sorted_descending == [32, 42]); // does not verify -} -``` - -### map - -Applies a function to each element of the array, returning a new array containing the mapped elements. - -```rust -fn map(self, f: fn(T) -> U) -> [U; N] -``` - -example - -```rust -let a = [1, 2, 3]; -let b = a.map(|a| a * 2); // b is now [2, 4, 6] -``` - -### fold - -Applies a function to each element of the array, returning the final accumulated value. The first -parameter is the initial value. - -```rust -fn fold(self, mut accumulator: U, f: fn(U, T) -> U) -> U -``` - -This is a left fold, so the given function will be applied to the accumulator and first element of -the array, then the second, and so on. For a given call the expected result would be equivalent to: - -```rust -let a1 = [1]; -let a2 = [1, 2]; -let a3 = [1, 2, 3]; - -let f = |a, b| a - b; -a1.fold(10, f) //=> f(10, 1) -a2.fold(10, f) //=> f(f(10, 1), 2) -a3.fold(10, f) //=> f(f(f(10, 1), 2), 3) -``` - -example: - -```rust - -fn main() { - let arr = [2, 2, 2, 2, 2]; - let folded = arr.fold(0, |a, b| a + b); - assert(folded == 10); -} - -``` - -### reduce - -Same as fold, but uses the first element as starting element. - -```rust -fn reduce(self, f: fn(T, T) -> T) -> T -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let reduced = arr.reduce(|a, b| a + b); - assert(reduced == 10); -} -``` - -### all - -Returns true if all the elements satisfy the given predicate - -```rust -fn all(self, predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let all = arr.all(|a| a == 2); - assert(all); -} -``` - -### any - -Returns true if any of the elements satisfy the given predicate - -```rust -fn any(self, predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 5]; - let any = arr.any(|a| a == 5); - assert(any); -} - -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/booleans.md deleted file mode 100644 index 7211716f63e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/booleans.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Booleans -description: - Delve into the Boolean data type in Noir. Understand its methods, practical examples, and best practices for using Booleans in your Noir programs. -keywords: - [ - noir, - boolean type, - methods, - examples, - logical operations, - ] -sidebar_position: 2 ---- - - -The `bool` type in Noir has two possible values: `true` and `false`: - -```rust -fn main() { - let t = true; - let f: bool = false; -} -``` - -> **Note:** When returning a boolean value, it will show up as a value of 1 for `true` and 0 for -> `false` in _Verifier.toml_. - -The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and -[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/fields.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/fields.md deleted file mode 100644 index 99b4aa63549..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/fields.md +++ /dev/null @@ -1,192 +0,0 @@ ---- -title: Fields -description: - Dive deep into the Field data type in Noir. Understand its methods, practical examples, and best practices to effectively use Fields in your Noir programs. -keywords: - [ - noir, - field type, - methods, - examples, - best practices, - ] -sidebar_position: 0 ---- - -The field type corresponds to the native field type of the proving backend. - -The size of a Noir field depends on the elliptic curve's finite field for the proving backend -adopted. For example, a field would be a 254-bit integer when paired with the default backend that -spans the Grumpkin curve. - -Fields support integer arithmetic and are often used as the default numeric type in Noir: - -```rust -fn main(x : Field, y : Field) { - let z = x + y; -} -``` - -`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new -private value `z` constrained to be equal to `x + y`. - -If proving efficiency is of priority, fields should be used as a default for solving problems. -Smaller integer types (e.g. `u64`) incur extra range constraints. - -## Methods - -After declaring a Field, you can use these common methods on it: - -### to_le_bits - -Transforms the field into an array of bits, Little Endian. - -```rust -fn to_le_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_le_bits(32); -} -``` - -### to_be_bits - -Transforms the field into an array of bits, Big Endian. - -```rust -fn to_be_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_be_bits(32); -} -``` - -### to_le_bytes - -Transforms into an array of bytes, Little Endian - -```rust -fn to_le_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_le_bytes(4); -} -``` - -### to_be_bytes - -Transforms into an array of bytes, Big Endian - -```rust -fn to_be_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_be_bytes(4); -} -``` - -### to_le_radix - -Decomposes into a vector over the specified base, Little Endian - -```rust -fn to_le_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_le_radix(256, 4); -} -``` - -### to_be_radix - -Decomposes into a vector over the specified base, Big Endian - -```rust -fn to_be_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_be_radix(256, 4); -} -``` - -### pow_32 - -Returns the value to the power of the specified exponent - -```rust -fn pow_32(self, exponent: Field) -> Field -``` - -example: - -```rust -fn main() { - let field = 2 - let pow = field.pow_32(4); - assert(pow == 16); -} -``` - -### assert_max_bit_size - -Adds a constraint to specify that the field can be represented with `bit_size` number of bits - -```rust -fn assert_max_bit_size(self, bit_size: u32) -``` - -example: - -```rust -fn main() { - let field = 2 - field.assert_max_bit_size(32); -} -``` - -### sgn0 - -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. - -```rust -fn sgn0(self) -> u1 -``` - - -### lt - -Returns true if the field is less than the other field - -```rust -pub fn lt(self, another: Field) -> bool -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/function_types.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/function_types.md deleted file mode 100644 index f6121af17e2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/function_types.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Function types -sidebar_position: 10 ---- - -Noir supports higher-order functions. The syntax for a function type is as follows: - -```rust -fn(arg1_type, arg2_type, ...) -> return_type -``` - -Example: - -```rust -fn assert_returns_100(f: fn() -> Field) { // f takes no args and returns a Field - assert(f() == 100); -} - -fn main() { - assert_returns_100(|| 100); // ok - assert_returns_100(|| 150); // fails -} -``` - -A function type also has an optional capture environment - this is necessary to support closures. -See [Lambdas](../lambdas.md) for more details. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/index.md deleted file mode 100644 index 357813c147a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/index.md +++ /dev/null @@ -1,110 +0,0 @@ ---- -title: Data Types -description: - Get a clear understanding of the two categories of Noir data types - primitive types and compound - types. Learn about their characteristics, differences, and how to use them in your Noir - programming. -keywords: - [ - noir, - data types, - primitive types, - compound types, - private types, - public types, - ] ---- - -Every value in Noir has a type, which determines which operations are valid for it. - -All values in Noir are fundamentally composed of `Field` elements. For a more approachable -developing experience, abstractions are added on top to introduce different data types in Noir. - -Noir has two category of data types: primitive types (e.g. `Field`, integers, `bool`) and compound -types that group primitive types (e.g. arrays, tuples, structs). Each value can either be private or -public. - -## Private & Public Types - -A **private value** is known only to the Prover, while a **public value** is known by both the -Prover and Verifier. Mark values as `private` when the value should only be known to the prover. All -primitive types (including individual fields of compound types) in Noir are private by default, and -can be marked public when certain values are intended to be revealed to the Verifier. - -> **Note:** For public values defined in Noir programs paired with smart contract verifiers, once -> the proofs are verified on-chain the values can be considered known to everyone that has access to -> that blockchain. - -Public data types are treated no differently to private types apart from the fact that their values -will be revealed in proofs generated. Simply changing the value of a public type will not change the -circuit (where the same goes for changing values of private types as well). - -_Private values_ are also referred to as _witnesses_ sometimes. - -> **Note:** The terms private and public when applied to a type (e.g. `pub Field`) have a different -> meaning than when applied to a function (e.g. `pub fn foo() {}`). -> -> The former is a visibility modifier for the Prover to interpret if a value should be made known to -> the Verifier, while the latter is a visibility modifier for the compiler to interpret if a -> function should be made accessible to external Noir programs like in other languages. - -### pub Modifier - -All data types in Noir are private by default. Types are explicitly declared as public using the -`pub` modifier: - -```rust -fn main(x : Field, y : pub Field) -> pub Field { - x + y -} -``` - -In this example, `x` is **private** while `y` and `x + y` (the return value) are **public**. Note -that visibility is handled **per variable**, so it is perfectly valid to have one input that is -private and another that is public. - -> **Note:** Public types can only be declared through parameters on `main`. - -## Type Aliases - -A type alias is a new name for an existing type. Type aliases are declared with the keyword `type`: - -```rust -type Id = u8; - -fn main() { - let id: Id = 1; - let zero: u8 = 0; - assert(zero + 1 == id); -} -``` - -Type aliases can also be used with [generics](../generics.md): - -```rust -type Id = Size; - -fn main() { - let id: Id = 1; - let zero: u32 = 0; - assert(zero + 1 == id); -} -``` - -Type aliases can even refer to other aliases. An error will be issued if they form a cycle: - -```rust -// Ok! -type A = B; -type B = Field; - -type Bad1 = Bad2; - -// error: Dependency cycle found -type Bad2 = Bad1; -// ^^^^^^^^^^^ 'Bad2' recursively depends on itself: Bad2 -> Bad1 -> Bad2 -``` - -### BigInt - -You can achieve BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/integers.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/integers.md deleted file mode 100644 index 4d58d96fed5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/integers.md +++ /dev/null @@ -1,155 +0,0 @@ ---- -title: Integers -description: Explore the Integer data type in Noir. Learn about its methods, see real-world examples, and grasp how to efficiently use Integers in your Noir code. -keywords: [noir, integer types, methods, examples, arithmetic] -sidebar_position: 1 ---- - -An integer type is a range constrained field type. The Noir frontend supports both unsigned and signed integer types. The allowed sizes are 1, 8, 32 and 64 bits. - -:::info - -When an integer is defined in Noir without a specific type, it will default to `Field`. - -The one exception is for loop indices which default to `u64` since comparisons on `Field`s are not possible. - -::: - -## Unsigned Integers - -An unsigned integer type is specified first with the letter `u` (indicating its unsigned nature) followed by its bit size (e.g. `8`): - -```rust -fn main() { - let x: u8 = 1; - let y: u8 = 1; - let z = x + y; - assert (z == 2); -} -``` - -The bit size determines the maximum value the integer type can store. For example, a `u8` variable can store a value in the range of 0 to 255 (i.e. $\\2^{8}-1\\$). - -## Signed Integers - -A signed integer type is specified first with the letter `i` (which stands for integer) followed by its bit size (e.g. `8`): - -```rust -fn main() { - let x: i8 = -1; - let y: i8 = -1; - let z = x + y; - assert (z == -2); -} -``` - -The bit size determines the maximum and minimum range of value the integer type can store. For example, an `i8` variable can store a value in the range of -128 to 127 (i.e. $\\-2^{7}\\$ to $\\2^{7}-1\\$). - -## 128 bits Unsigned Integers - -The built-in structure `U128` allows you to use 128-bit unsigned integers almost like a native integer type. However, there are some differences to keep in mind: -- You cannot cast between a native integer and `U128` -- There is a higher performance cost when using `U128`, compared to a native type. - -Conversion between unsigned integer types and U128 are done through the use of `from_integer` and `to_integer` functions. - -```rust -fn main() { - let x = U128::from_integer(23); - let y = U128::from_hex("0x7"); - let z = x + y; - assert(z.to_integer() == 30); -} -``` - -`U128` is implemented with two 64 bits limbs, representing the low and high bits, which explains the performance cost. You should expect `U128` to be twice more costly for addition and four times more costly for multiplication. -You can construct a U128 from its limbs: -```rust -fn main(x: u64, y: u64) { - let x = U128::from_u64s_be(x,y); - assert(z.hi == x as Field); - assert(z.lo == y as Field); -} -``` - -Note that the limbs are stored as Field elements in order to avoid unnecessary conversions. -Apart from this, most operations will work as usual: - -```rust -fn main(x: U128, y: U128) { - // multiplication - let c = x * y; - // addition and subtraction - let c = c - x + y; - // division - let c = x / y; - // bit operation; - let c = x & y | y; - // bit shift - let c = x << y; - // comparisons; - let c = x < y; - let c = x == y; -} -``` - -## Overflows - -Computations that exceed the type boundaries will result in overflow errors. This happens with both signed and unsigned integers. For example, attempting to prove: - -```rust -fn main(x: u8, y: u8) { - let z = x + y; -} -``` - -With: - -```toml -x = "255" -y = "1" -``` - -Would result in: - -``` -$ nargo prove -error: Assertion failed: 'attempt to add with overflow' -┌─ ~/src/main.nr:9:13 -│ -│ let z = x + y; -│ ----- -│ -= Call stack: - ... -``` - -A similar error would happen with signed integers: - -```rust -fn main() { - let x: i8 = -118; - let y: i8 = -11; - let z = x + y; -} -``` - -### Wrapping methods - -Although integer overflow is expected to error, some use-cases rely on wrapping. For these use-cases, the standard library provides `wrapping` variants of certain common operations: - -```rust -fn wrapping_add(x: T, y: T) -> T; -fn wrapping_sub(x: T, y: T) -> T; -fn wrapping_mul(x: T, y: T) -> T; -``` - -Example of how it is used: - -```rust -use dep::std; - -fn main(x: u8, y: u8) -> pub u8 { - std::wrapping_add(x, y) -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/references.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/references.md deleted file mode 100644 index a5293d11cfb..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/references.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: References -sidebar_position: 9 ---- - -Noir supports first-class references. References are a bit like pointers: they point to a specific address that can be followed to access the data stored at that address. You can use Rust-like syntax to use pointers in Noir: the `&` operator references the variable, the `*` operator dereferences it. - -Example: - -```rust -fn main() { - let mut x = 2; - - // you can reference x as &mut and pass it to multiplyBy2 - multiplyBy2(&mut x); -} - -// you can access &mut here -fn multiplyBy2(x: &mut Field) { - // and dereference it with * - *x = *x * 2; -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/slices.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/slices.mdx deleted file mode 100644 index 4a6ee816aa2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/slices.mdx +++ /dev/null @@ -1,147 +0,0 @@ ---- -title: Slices -description: Explore the Slice data type in Noir. Understand its methods, see real-world examples, and learn how to effectively use Slices in your Noir programs. -keywords: [noir, slice type, methods, examples, subarrays] -sidebar_position: 5 ---- - -import Experimental from '@site/src/components/Notes/_experimental.mdx'; - - - -A slice is a dynamically-sized view into a sequence of elements. They can be resized at runtime, but because they don't own the data, they cannot be returned from a circuit. You can treat slices as arrays without a constrained size. - -```rust -use dep::std::slice; - -fn main() -> pub Field { - let mut slice: [Field] = [0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -View the corresponding test file [here][test-file]. - -[test-file]: https://github.com/noir-lang/noir/blob/f387ec1475129732f72ba294877efdf6857135ac/crates/nargo_cli/tests/test_data_ssa_refactor/slices/src/main.nr - -## Methods - -For convenience, the STD provides some ready-to-use, common methods for slices: - -### push_back - -Pushes a new element to the end of the slice, returning a new slice with a length one greater than the original unmodified slice. - -```rust -fn push_back(_self: [T], _elem: T) -> [T] -``` - -example: - -```rust -fn main() -> pub Field { - let mut slice: [Field] = [0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -View the corresponding test file [here][test-file]. - -### push_front - -Returns a new array with the specified element inserted at index 0. The existing elements indexes are incremented by 1. - -```rust -fn push_front(_self: Self, _elem: T) -> Self -``` - -Example: - -```rust -let mut new_slice: [Field] = []; -new_slice = new_slice.push_front(20); -assert(new_slice[0] == 20); // returns true -``` - -View the corresponding test file [here][test-file]. - -### pop_front - -Returns a tuple of two items, the first element of the array and the rest of the array. - -```rust -fn pop_front(_self: Self) -> (T, Self) -``` - -Example: - -```rust -let (first_elem, rest_of_slice) = slice.pop_front(); -``` - -View the corresponding test file [here][test-file]. - -### pop_back - -Returns a tuple of two items, the beginning of the array with the last element omitted and the last element. - -```rust -fn pop_back(_self: Self) -> (Self, T) -``` - -Example: - -```rust -let (popped_slice, last_elem) = slice.pop_back(); -``` - -View the corresponding test file [here][test-file]. - -### append - -Loops over a slice and adds it to the end of another. - -```rust -fn append(mut self, other: Self) -> Self -``` - -Example: - -```rust -let append = [1, 2].append([3, 4, 5]); -``` - -### insert - -Inserts an element at a specified index and shifts all following elements by 1. - -```rust -fn insert(_self: Self, _index: Field, _elem: T) -> Self -``` - -Example: - -```rust -new_slice = rest_of_slice.insert(2, 100); -assert(new_slice[2] == 100); -``` - -View the corresponding test file [here][test-file]. - -### remove - -Remove an element at a specified index, shifting all elements after it to the left, returning the altered slice and the removed element. - -```rust -fn remove(_self: Self, _index: Field) -> (Self, T) -``` - -Example: - -```rust -let (remove_slice, removed_elem) = slice.remove(3); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/strings.md deleted file mode 100644 index 8ab5825a4c4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/strings.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: Strings -description: - Discover the String data type in Noir. Learn about its methods, see real-world examples, and understand how to effectively manipulate and use Strings in Noir. -keywords: - [ - noir, - string type, - methods, - examples, - concatenation, - ] -sidebar_position: 3 ---- - - -The string type is a fixed length value defined with `str`. - -You can use strings in `assert()` functions or print them with -`println()`. See more about [Logging](../../standard_library/logging.md). - -```rust -use dep::std; - -fn main(message : pub str<11>, hex_as_string : str<4>) { - println(message); - assert(message == "hello world"); - assert(hex_as_string == "0x41"); -} -``` - -You can convert a `str` to a byte array by calling `as_bytes()` -or a vector by calling `as_bytes_vec()`. - -```rust -fn main() { - let message = "hello world"; - let message_bytes = message.as_bytes(); - let mut message_vec = message.as_bytes_vec(); - assert(message_bytes.len() == 11); - assert(message_bytes[0] == 104); - assert(message_bytes[0] == message_vec.get(0)); -} -``` - -## Escape characters - -You can use escape characters for your strings: - -| Escape Sequence | Description | -|-----------------|-----------------| -| `\r` | Carriage Return | -| `\n` | Newline | -| `\t` | Tab | -| `\0` | Null Character | -| `\"` | Double Quote | -| `\\` | Backslash | - -Example: - -```rust -let s = "Hello \"world" // prints "Hello "world" -let s = "hey \tyou"; // prints "hey you" -``` - -## Raw strings - -A raw string begins with the letter `r` and is optionally delimited by a number of hashes `#`. - -Escape characters are *not* processed within raw strings. All contents are interpreted literally. - -Example: - -```rust -let s = r"Hello world"; -let s = r#"Simon says "hello world""#; - -// Any number of hashes may be used (>= 1) as long as the string also terminates with the same number of hashes -let s = r#####"One "#, Two "##, Three "###, Four "####, Five will end the string."#####; -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/structs.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/structs.md deleted file mode 100644 index dbf68c99813..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/structs.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -title: Structs -description: - Explore the Struct data type in Noir. Learn about its methods, see real-world examples, and grasp how to effectively define and use Structs in your Noir programs. -keywords: - [ - noir, - struct type, - methods, - examples, - data structures, - ] -sidebar_position: 8 ---- - -A struct also allows for grouping multiple values of different types. Unlike tuples, we can also -name each field. - -> **Note:** The usage of _field_ here refers to each element of the struct and is unrelated to the -> field type of Noir. - -Defining a struct requires giving it a name and listing each field within as `: ` pairs: - -```rust -struct Animal { - hands: Field, - legs: Field, - eyes: u8, -} -``` - -An instance of a struct can then be created with actual values in `: ` pairs in any -order. Struct fields are accessible using their given names: - -```rust -fn main() { - let legs = 4; - - let dog = Animal { - eyes: 2, - hands: 0, - legs, - }; - - let zero = dog.hands; -} -``` - -Structs can also be destructured in a pattern, binding each field to a new variable: - -```rust -fn main() { - let Animal { hands, legs: feet, eyes } = get_octopus(); - - let ten = hands + feet + eyes as u8; -} - -fn get_octopus() -> Animal { - let octopus = Animal { - hands: 0, - legs: 8, - eyes: 2, - }; - - octopus -} -``` - -The new variables can be bound with names different from the original struct field names, as -showcased in the `legs --> feet` binding in the example above. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/tuples.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/tuples.md deleted file mode 100644 index 2ec5c9c4113..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/tuples.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Tuples -description: - Dive into the Tuple data type in Noir. Understand its methods, practical examples, and best practices for efficiently using Tuples in your Noir code. -keywords: - [ - noir, - tuple type, - methods, - examples, - multi-value containers, - ] -sidebar_position: 7 ---- - -A tuple collects multiple values like an array, but with the added ability to collect values of -different types: - -```rust -fn main() { - let tup: (u8, u64, Field) = (255, 500, 1000); -} -``` - -One way to access tuple elements is via destructuring using pattern matching: - -```rust -fn main() { - let tup = (1, 2); - - let (one, two) = tup; - - let three = one + two; -} -``` - -Another way to access tuple elements is via direct member access, using a period (`.`) followed by -the index of the element we want to access. Index `0` corresponds to the first tuple element, `1` to -the second and so on: - -```rust -fn main() { - let tup = (5, 6, 7, 8); - - let five = tup.0; - let eight = tup.3; -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/distinct.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/distinct.md deleted file mode 100644 index 6c993b8b5e0..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/distinct.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: Distinct Witnesses -sidebar_position: 11 ---- - -The `distinct` keyword prevents repetitions of witness indices in the program's ABI. This ensures -that the witnesses being returned as public inputs are all unique. - -The `distinct` keyword is only used for return values on program entry points (usually the `main()` -function). - -When using `distinct` and `pub` simultaneously, `distinct` comes first. See the example below. - -You can read more about the problem this solves -[here](https://github.com/noir-lang/noir/issues/1183). - -## Example - -Without the `distinct` keyword, the following program - -```rust -fn main(x : pub Field, y : pub Field) -> pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - "return_witnesses": [3, 2, 4, 4] - } -} -``` - -Whereas (with the `distinct` keyword) - -```rust -fn main(x : pub Field, y : pub Field) -> distinct pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - //... - "return_witnesses": [3, 4, 5, 6] - } -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/functions.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/functions.md deleted file mode 100644 index 48aba9cd058..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/functions.md +++ /dev/null @@ -1,226 +0,0 @@ ---- -title: Functions -description: - Learn how to declare functions and methods in Noir, a programming language with Rust semantics. - This guide covers parameter declaration, return types, call expressions, and more. -keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] -sidebar_position: 1 ---- - -Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. - -To declare a function the `fn` keyword is used. - -```rust -fn foo() {} -``` - -By default, functions are visible only within the package they are defined. To make them visible outside of that package (for example, as part of a [library](../modules_packages_crates/crates_and_packages.md#libraries)), you should mark them as `pub`: - -```rust -pub fn foo() {} -``` - -You can also restrict the visibility of the function to only the crate it was defined in, by specifying `pub(crate)`: - -```rust -pub(crate) fn foo() {} //foo can only be called within its crate -``` - -All parameters in a function must have a type and all types are known at compile time. The parameter -is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. - -```rust -fn foo(x : Field, y : Field){} -``` - -The return type of a function can be stated by using the `->` arrow notation. The function below -states that the foo function must return a `Field`. If the function returns no value, then the arrow -is omitted. - -```rust -fn foo(x : Field, y : Field) -> Field { - x + y -} -``` - -Note that a `return` keyword is unneeded in this case - the last expression in a function's body is -returned. - -## Main function - -If you're writing a binary, the `main` function is the starting point of your program. You can pass all types of expressions to it, as long as they have a fixed size at compile time: - -```rust -fn main(x : Field) // this is fine: passing a Field -fn main(x : [Field; 2]) // this is also fine: passing a Field with known size at compile-time -fn main(x : (Field, bool)) // 👌: passing a (Field, bool) tuple means size 2 -fn main(x : str<5>) // this is fine, as long as you pass a string of size 5 - -fn main(x : Vec) // can't compile, has variable size -fn main(x : [Field]) // can't compile, has variable size -fn main(....// i think you got it by now -``` - -Keep in mind [tests](../../getting_started/tooling/testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: - -```rust -fn main(x : [Field]) { - assert(x[0] == 1); -} - -#[test] -fn test_one() { - main([1, 2]); -} -``` - -```bash -$ nargo test -[testing] Running 1 test functions -[testing] Testing test_one... ok -[testing] All tests passed - -$ nargo check -The application panicked (crashed). -Message: Cannot have variable sized arrays as a parameter to main -``` - -## Call Expressions - -Calling a function in Noir is executed by using the function name and passing in the necessary -arguments. - -Below we show how to call the `foo` function from the `main` function using a call expression: - -```rust -fn main(x : Field, y : Field) { - let z = foo(x); -} - -fn foo(x : Field) -> Field { - x + x -} -``` - -## Methods - -You can define methods in Noir on any struct type in scope. - -```rust -struct MyStruct { - foo: Field, - bar: Field, -} - -impl MyStruct { - fn new(foo: Field) -> MyStruct { - MyStruct { - foo, - bar: 2, - } - } - - fn sum(self) -> Field { - self.foo + self.bar - } -} - -fn main() { - let s = MyStruct::new(40); - assert(s.sum() == 42); -} -``` - -Methods are just syntactic sugar for functions, so if we wanted to we could also call `sum` as -follows: - -```rust -assert(MyStruct::sum(s) == 42); -``` - -It is also possible to specialize which method is chosen depending on the [generic](./generics.md) type that is used. In this example, the `foo` function returns different values depending on its type: - -```rust -struct Foo {} - -impl Foo { - fn foo(self) -> Field { 1 } -} - -impl Foo { - fn foo(self) -> Field { 2 } -} - -fn main() { - let f1: Foo = Foo{}; - let f2: Foo = Foo{}; - assert(f1.foo() + f2.foo() == 3); -} -``` - -Also note that impls with the same method name defined in them cannot overlap. For example, if we already have `foo` defined for `Foo` and `Foo` like we do above, we cannot also define `foo` in an `impl Foo` since it would be ambiguous which version of `foo` to choose. - -```rust -// Including this impl in the same project as the above snippet would -// cause an overlapping impls error -impl Foo { - fn foo(self) -> Field { 3 } -} -``` - -## Lambdas - -Lambdas are anonymous functions. They follow the syntax of Rust - `|arg1, arg2, ..., argN| return_expression`. - -```rust -let add_50 = |val| val + 50; -assert(add_50(100) == 150); -``` - -See [Lambdas](./lambdas.md) for more details. - -## Attributes - -Attributes are metadata that can be applied to a function, using the following syntax: `#[attribute(value)]`. - -Supported attributes include: - -- **builtin**: the function is implemented by the compiler, for efficiency purposes. -- **deprecated**: mark the function as _deprecated_. Calling the function will generate a warning: `warning: use of deprecated function` -- **field**: Used to enable conditional compilation of code depending on the field size. See below for more details -- **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./unconstrained.md) and [NoirJS](../../reference/NoirJS/noir_js/index.md) for more details. -- **test**: mark the function as unit tests. See [Tests](../../getting_started/tooling/testing.md) for more details - -### Field Attribute - -The field attribute defines which field the function is compatible for. The function is conditionally compiled, under the condition that the field attribute matches the Noir native field. -The field can be defined implicitly, by using the name of the elliptic curve usually associated to it - for instance bn254, bls12_381 - or explicitly by using the field (prime) order, in decimal or hexadecimal form. -As a result, it is possible to define multiple versions of a function with each version specialized for a different field attribute. This can be useful when a function requires different parameters depending on the underlying elliptic curve. - -Example: we define the function `foo()` three times below. Once for the default Noir bn254 curve, once for the field $\mathbb F_{23}$, which will normally never be used by Noir, and once again for the bls12_381 curve. - -```rust -#[field(bn254)] -fn foo() -> u32 { - 1 -} - -#[field(23)] -fn foo() -> u32 { - 2 -} - -// This commented code would not compile as foo would be defined twice because it is the same field as bn254 -// #[field(21888242871839275222246405745257275088548364400416034343698204186575808495617)] -// fn foo() -> u32 { -// 2 -// } - -#[field(bls12_381)] -fn foo() -> u32 { - 3 -} -``` - -If the field name is not known to Noir, it will discard the function. Field names are case insensitive. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/generics.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/generics.md deleted file mode 100644 index 0c1c27a2221..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/generics.md +++ /dev/null @@ -1,106 +0,0 @@ ---- -title: Generics -description: Learn how to use Generics in Noir -keywords: [Noir, Rust, generics, functions, structs] -sidebar_position: 7 ---- - -Generics allow you to use the same functions with multiple different concrete data types. You can -read more about the concept of generics in the Rust documentation -[here](https://doc.rust-lang.org/book/ch10-01-syntax.html). - -Here is a trivial example showing the identity function that supports any type. In Rust, it is -common to refer to the most general type as `T`. We follow the same convention in Noir. - -```rust -fn id(x: T) -> T { - x -} -``` - -## In Structs - -Generics are useful for specifying types in structs. For example, we can specify that a field in a -struct will be of a certain generic type. In this case `value` is of type `T`. - -```rust -struct RepeatedValue { - value: T, - count: Field, -} - -impl RepeatedValue { - fn print(self) { - for _i in 0 .. self.count { - println(self.value); - } - } -} - -fn main() { - let repeated = RepeatedValue { value: "Hello!", count: 2 }; - repeated.print(); -} -``` - -The `print` function will print `Hello!` an arbitrary number of times, twice in this case. - -If we want to be generic over array lengths (which are type-level integers), we can use numeric -generics. Using these looks just like using regular generics, but these generics can resolve to -integers at compile-time, rather than resolving to types. Here's an example of a struct that is -generic over the size of the array it contains internally: - -```rust -struct BigInt { - limbs: [u32; N], -} - -impl BigInt { - // `N` is in scope of all methods in the impl - fn first(first: BigInt, second: BigInt) -> Self { - assert(first.limbs != second.limbs); - first - - fn second(first: BigInt, second: Self) -> Self { - assert(first.limbs != second.limbs); - second - } -} -``` - -## Calling functions on generic parameters - -Since a generic type `T` can represent any type, how can we call functions on the underlying type? -In other words, how can we go from "any type `T`" to "any type `T` that has certain methods available?" - -This is what [traits](../concepts/traits.md) are for in Noir. Here's an example of a function generic over -any type `T` that implements the `Eq` trait for equality: - -```rust -fn first_element_is_equal(array1: [T; N], array2: [T; N]) -> bool - where T: Eq -{ - if (array1.len() == 0) | (array2.len() == 0) { - true - } else { - array1[0] == array2[0] - } -} - -fn main() { - assert(first_element_is_equal([1, 2, 3], [1, 5, 6])); - - // We can use first_element_is_equal for arrays of any type - // as long as we have an Eq impl for the types we pass in - let array = [MyStruct::new(), MyStruct::new()]; - assert(array_eq(array, array, MyStruct::eq)); -} - -impl Eq for MyStruct { - fn eq(self, other: MyStruct) -> bool { - self.foo == other.foo - } -} -``` - -You can find more details on traits and trait implementations on the [traits page](../concepts/traits.md). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/globals.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/globals.md deleted file mode 100644 index 063a3d89248..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/globals.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -title: Global Variables -description: - Learn about global variables in Noir. Discover how - to declare, modify, and use them in your programs. -keywords: [noir programming language, globals, global variables, constants] -sidebar_position: 8 ---- - -## Globals - - -Noir supports global variables. The global's type can be inferred by the compiler entirely: - -```rust -global N = 5; // Same as `global N: Field = 5` - -global TUPLE = (3, 2); - -fn main() { - assert(N == 5); - assert(N == TUPLE.0 + TUPLE.1); -} -``` - -:::info - -Globals can be defined as any expression, so long as they don't depend on themselves - otherwise there would be a dependency cycle! For example: - -```rust -global T = foo(T); // dependency error -``` - -::: - - -If they are initialized to a literal integer, globals can be used to specify an array's length: - -```rust -global N: Field = 2; - -fn main(y : [Field; N]) { - assert(y[0] == y[1]) -} -``` - -A global from another module can be imported or referenced externally like any other name: - -```rust -global N = 20; - -fn main() { - assert(my_submodule::N != N); -} - -mod my_submodule { - global N: Field = 10; -} -``` - -When a global is used, Noir replaces the name with its definition on each occurrence. -This means globals defined using function calls will repeat the call each time they're used: - -```rust -global RESULT = foo(); - -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. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/lambdas.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/lambdas.md deleted file mode 100644 index be3c7e0b5ca..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/lambdas.md +++ /dev/null @@ -1,81 +0,0 @@ ---- -title: Lambdas -description: Learn how to use anonymous functions in Noir programming language. -keywords: [Noir programming language, lambda, closure, function, anonymous function] -sidebar_position: 9 ---- - -## Introduction - -Lambdas are anonymous functions. The syntax is `|arg1, arg2, ..., argN| return_expression`. - -```rust -let add_50 = |val| val + 50; -assert(add_50(100) == 150); -``` - -A block can be used as the body of a lambda, allowing you to declare local variables inside it: - -```rust -let cool = || { - let x = 100; - let y = 100; - x + y -} - -assert(cool() == 200); -``` - -## Closures - -Inside the body of a lambda, you can use variables defined in the enclosing function. Such lambdas are called **closures**. In this example `x` is defined inside `main` and is accessed from within the lambda: - -```rust -fn main() { - let x = 100; - let closure = || x + 150; - assert(closure() == 250); -} -``` - -## Passing closures to higher-order functions - -It may catch you by surprise that the following code fails to compile: - -```rust -fn foo(f: fn () -> Field) -> Field { - f() -} - -fn main() { - let (x, y) = (50, 50); - assert(foo(|| x + y) == 100); // error :( -} -``` - -The reason is that the closure's capture environment affects its type - we have a closure that captures two Fields and `foo` -expects a regular function as an argument - those are incompatible. -:::note - -Variables contained within the `||` are the closure's parameters, and the expression that follows it is the closure's body. The capture environment is comprised of any variables used in the closure's body that are not parameters. - -E.g. in |x| x + y, y would be a captured variable, but x would not be, since it is a parameter of the closure. - -::: -The syntax for the type of a closure is `fn[env](args) -> ret_type`, where `env` is the capture environment of the closure - -in this example that's `(Field, Field)`. - -The best solution in our case is to make `foo` generic over the environment type of its parameter, so that it can be called -with closures with any environment, as well as with regular functions: - -```rust -fn foo(f: fn[Env]() -> Field) -> Field { - f() -} - -fn main() { - let (x, y) = (50, 50); - assert(foo(|| x + y) == 100); // compiles fine - assert(foo(|| 60) == 60); // compiles fine -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/mutability.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/mutability.md deleted file mode 100644 index fdeef6a87c5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/mutability.md +++ /dev/null @@ -1,121 +0,0 @@ ---- -title: Mutability -description: - Learn about mutable variables in Noir. Discover how - to declare, modify, and use them in your programs. -keywords: [noir programming language, mutability in noir, mutable variables] -sidebar_position: 8 ---- - -Variables in noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned -to via an assignment expression. - -```rust -let x = 2; -x = 3; // error: x must be mutable to be assigned to - -let mut y = 3; -let y = 4; // OK -``` - -The `mut` modifier can also apply to patterns: - -```rust -let (a, mut b) = (1, 2); -a = 11; // error: a must be mutable to be assigned to -b = 12; // OK - -let mut (c, d) = (3, 4); -c = 13; // OK -d = 14; // OK - -// etc. -let MyStruct { x: mut y } = MyStruct { x: a }; -// y is now in scope -``` - -Note that mutability in noir is local and everything is passed by value, so if a called function -mutates its parameters then the parent function will keep the old value of the parameters. - -```rust -fn main() -> pub Field { - let x = 3; - helper(x); - x // x is still 3 -} - -fn helper(mut x: i32) { - x = 4; -} -``` - -## Non-local mutability - -Non-local mutability can be achieved through the mutable reference type `&mut T`: - -```rust -fn set_to_zero(x: &mut Field) { - *x = 0; -} - -fn main() { - let mut y = 42; - set_to_zero(&mut y); - assert(*y == 0); -} -``` - -When creating a mutable reference, the original variable being referred to (`y` in this -example) must also be mutable. Since mutable references are a reference type, they must -be explicitly dereferenced via `*` to retrieve the underlying value. Note that this yields -a copy of the value, so mutating this copy will not change the original value behind the -reference: - -```rust -fn main() { - let mut x = 1; - let x_ref = &mut x; - - let mut y = *x_ref; - let y_ref = &mut y; - - x = 2; - *x_ref = 3; - - y = 4; - *y_ref = 5; - - assert(x == 3); - assert(*x_ref == 3); - assert(y == 5); - assert(*y_ref == 5); -} -``` - -Note that types in Noir are actually deeply immutable so the copy that occurs when -dereferencing is only a conceptual copy - no additional constraints will occur. - -Mutable references can also be stored within structs. Note that there is also -no lifetime parameter on these unlike rust. This is because the allocated memory -always lasts the entire program - as if it were an array of one element. - -```rust -struct Foo { - x: &mut Field -} - -impl Foo { - fn incr(mut self) { - *self.x += 1; - } -} - -fn main() { - let foo = Foo { x: &mut 0 }; - foo.incr(); - assert(*foo.x == 1); -} -``` - -In general, you should avoid non-local & shared mutability unless it is needed. Sticking -to only local mutability will improve readability and potentially improve compiler optimizations as well. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/ops.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/ops.md deleted file mode 100644 index 60425cb8994..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/ops.md +++ /dev/null @@ -1,98 +0,0 @@ ---- -title: Logical Operations -description: - Learn about the supported arithmetic and logical operations in the Noir programming language. - Discover how to perform operations on private input types, integers, and booleans. -keywords: - [ - Noir programming language, - supported operations, - arithmetic operations, - logical operations, - predicate operators, - bitwise operations, - short-circuiting, - backend, - ] -sidebar_position: 3 ---- - -# Operations - -## Table of Supported Operations - -| Operation | Description | Requirements | -| :-------- | :------------------------------------------------------------: | -------------------------------------: | -| + | Adds two private input types together | Types must be private input | -| - | Subtracts two private input types together | Types must be private input | -| \* | Multiplies two private input types together | Types must be private input | -| / | Divides two private input types together | Types must be private input | -| ^ | XOR two private input types together | Types must be integer | -| & | AND two private input types together | Types must be integer | -| \| | OR two private input types together | Types must be integer | -| \<\< | Left shift an integer by another integer amount | Types must be integer | -| >> | Right shift an integer by another integer amount | Types must be integer | -| ! | Bitwise not of a value | Type must be integer or boolean | -| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | -| > | returns a bool if one value is more than the other | Upper bound must have a known bit size | -| >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | -| == | returns a bool if one value is equal to the other | Both types must not be constants | -| != | returns a bool if one value is not equal to the other | Both types must not be constants | - -### Predicate Operators - -`<,<=, !=, == , >, >=` are known as predicate/comparison operations because they compare two values. -This differs from the operations such as `+` where the operands are used in _computation_. - -### Bitwise Operations Example - -```rust -fn main(x : Field) { - let y = x as u32; - let z = y & y; -} -``` - -`z` is implicitly constrained to be the result of `y & y`. The `&` operand is used to denote bitwise -`&`. - -> `x & x` would not compile as `x` is a `Field` and not an integer type. - -### Logical Operators - -Noir has no support for the logical operators `||` and `&&`. This is because encoding the -short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can -use the bitwise operators `|` and `&` which operate identically for booleans, just without the -short-circuiting. - -```rust -let my_val = 5; - -let mut flag = 1; -if (my_val > 6) | (my_val == 0) { - flag = 0; -} -assert(flag == 1); - -if (my_val != 10) & (my_val < 50) { - flag = 0; -} -assert(flag == 0); -``` - -### Shorthand operators - -Noir shorthand operators for most of the above operators, namely `+=, -=, *=, /=, %=, &=, |=, ^=, <<=`, and `>>=`. These allow for more concise syntax. For example: - -```rust -let mut i = 0; -i = i + 1; -``` - -could be written as: - -```rust -let mut i = 0; -i += 1; -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/oracles.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/oracles.md deleted file mode 100644 index 2e6a6818d48..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/oracles.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: Oracles -description: Dive into how Noir supports Oracles via RPC calls, and learn how to declare an Oracle in Noir with our comprehensive guide. -keywords: - - Noir - - Oracles - - RPC Calls - - Unconstrained Functions - - Programming - - Blockchain -sidebar_position: 6 ---- - -Noir has support for Oracles via RPC calls. This means Noir will make an RPC call and use the return value for proof generation. - -Since Oracles are not resolved by Noir, they are [`unconstrained` functions](./unconstrained.md) - -You can declare an Oracle through the `#[oracle()]` flag. Example: - -```rust -#[oracle(get_number_sequence)] -unconstrained fn get_number_sequence(_size: Field) -> [Field] {} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/shadowing.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/shadowing.md deleted file mode 100644 index 5ce6130d201..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/shadowing.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Shadowing -sidebar_position: 12 ---- - -Noir allows for inheriting variables' values and re-declaring them with the same name similar to Rust, known as shadowing. - -For example, the following function is valid in Noir: - -```rust -fn main() { - let x = 5; - - { - let x = x * 2; - assert (x == 10); - } - - assert (x == 5); -} -``` - -In this example, a variable x is first defined with the value 5. - -The local scope that follows shadows the original x, i.e. creates a local mutable x based on the value of the original x. It is given a value of 2 times the original x. - -When we return to the main scope, x once again refers to just the original x, which stays at the value of 5. - -## Temporal mutability - -One way that shadowing is useful, in addition to ergonomics across scopes, is for temporarily mutating variables. - -```rust -fn main() { - let age = 30; - // age = age + 5; // Would error as `age` is immutable by default. - - let mut age = age + 5; // Temporarily mutates `age` with a new value. - - let age = age; // Locks `age`'s mutability again. - - assert (age == 35); -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/traits.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/traits.md deleted file mode 100644 index ef1445a5907..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/traits.md +++ /dev/null @@ -1,389 +0,0 @@ ---- -title: Traits -description: - Traits in Noir can be used to abstract out a common interface for functions across - several data types. -keywords: [noir programming language, traits, interfaces, generic, protocol] -sidebar_position: 14 ---- - -## Overview - -Traits in Noir are a useful abstraction similar to interfaces or protocols in other languages. Each trait defines -the interface of several methods contained within the trait. Types can then implement this trait by providing -implementations for these methods. For example in the program: - -```rust -struct Rectangle { - width: Field, - height: Field, -} - -impl Rectangle { - fn area(self) -> Field { - self.width * self.height - } -} - -fn log_area(r: Rectangle) { - println(r.area()); -} -``` - -We have a function `log_area` to log the area of a `Rectangle`. Now how should we change the program if we want this -function to work on `Triangle`s as well?: - -```rust -struct Triangle { - width: Field, - height: Field, -} - -impl Triangle { - fn area(self) -> Field { - self.width * self.height / 2 - } -} -``` - -Making `log_area` generic over all types `T` would be invalid since not all types have an `area` method. Instead, we can -introduce a new `Area` trait and make `log_area` generic over all types `T` that implement `Area`: - -```rust -trait Area { - fn area(self) -> Field; -} - -fn log_area(shape: T) where T: Area { - println(shape.area()); -} -``` - -We also need to explicitly implement `Area` for `Rectangle` and `Triangle`. We can do that by changing their existing -impls slightly. Note that the parameter types and return type of each of our `area` methods must match those defined -by the `Area` trait. - -```rust -impl Area for Rectangle { - fn area(self) -> Field { - self.width * self.height - } -} - -impl Area for Triangle { - fn area(self) -> Field { - self.width * self.height / 2 - } -} -``` - -Now we have a working program that is generic over any type of Shape that is used! Others can even use this program -as a library with their own types - such as `Circle` - as long as they also implement `Area` for these types. - -## Where Clauses - -As seen in `log_area` above, when we want to create a function or method that is generic over any type that implements -a trait, we can add a where clause to the generic function. - -```rust -fn log_area(shape: T) where T: Area { - println(shape.area()); -} -``` - -It is also possible to apply multiple trait constraints on the same variable at once by combining traits with the `+` -operator. Similarly, we can have multiple trait constraints by separating each with a comma: - -```rust -fn foo(elements: [T], thing: U) where - T: Default + Add + Eq, - U: Bar, -{ - let mut sum = T::default(); - - for element in elements { - sum += element; - } - - if sum == T::default() { - thing.bar(); - } -} -``` - -## Generic Implementations - -You can add generics to a trait implementation by adding the generic list after the `impl` keyword: - -```rust -trait Second { - fn second(self) -> Field; -} - -impl Second for (T, Field) { - fn second(self) -> Field { - self.1 - } -} -``` - -You can also implement a trait for every type this way: - -```rust -trait Debug { - fn debug(self); -} - -impl Debug for T { - fn debug(self) { - println(self); - } -} - -fn main() { - 1.debug(); -} -``` - -### Generic Trait Implementations With Where Clauses - -Where clauses can also be placed on trait implementations themselves to restrict generics in a similar way. -For example, while `impl Foo for T` implements the trait `Foo` for every type, `impl Foo for T where T: Bar` -will implement `Foo` only for types that also implement `Bar`. This is often used for implementing generic types. -For example, here is the implementation for array equality: - -```rust -impl Eq for [T; N] where T: Eq { - // Test if two arrays have the same elements. - // Because both arrays must have length N, we know their lengths already match. - fn eq(self, other: Self) -> bool { - let mut result = true; - - for i in 0 .. self.len() { - // The T: Eq constraint is needed to call == on the array elements here - result &= self[i] == other[i]; - } - - result - } -} -``` - -## Generic Traits - -Traits themselves can also be generic by placing the generic arguments after the trait name. These generics are in -scope of every item within the trait. - -```rust -trait Into { - // Convert `self` to type `T` - fn into(self) -> T; -} -``` - -When implementing generic traits the generic arguments of the trait must be specified. This is also true anytime -when referencing a generic trait (e.g. in a `where` clause). - -```rust -struct MyStruct { - array: [Field; 2], -} - -impl Into<[Field; 2]> for MyStruct { - fn into(self) -> [Field; 2] { - self.array - } -} - -fn as_array(x: T) -> [Field; 2] - where T: Into<[Field; 2]> -{ - x.into() -} - -fn main() { - let array = [1, 2]; - let my_struct = MyStruct { array }; - - assert_eq(as_array(my_struct), array); -} -``` - -## Trait Methods With No `self` - -A trait can contain any number of methods, each of which have access to the `Self` type which represents each type -that eventually implements the trait. Similarly, the `self` variable is available as well but is not required to be used. -For example, we can define a trait to create a default value for a type. This trait will need to return the `Self` type -but doesn't need to take any parameters: - -```rust -trait Default { - fn default() -> Self; -} -``` - -Implementing this trait can be done similarly to any other trait: - -```rust -impl Default for Field { - fn default() -> Field { - 0 - } -} - -struct MyType {} - -impl Default for MyType { - fn default() -> Field { - MyType {} - } -} -``` - -However, since there is no `self` parameter, we cannot call it via the method call syntax `object.method()`. -Instead, we'll need to refer to the function directly. This can be done either by referring to the -specific impl `MyType::default()` or referring to the trait itself `Default::default()`. In the later -case, type inference determines the impl that is selected. - -```rust -let my_struct = MyStruct::default(); - -let x: Field = Default::default(); -let result = x + Default::default(); -``` - -:::warning - -```rust -let _ = Default::default(); -``` - -If type inference cannot select which impl to use because of an ambiguous `Self` type, an impl will be -arbitrarily selected. This occurs most often when the result of a trait function call with no parameters -is unused. To avoid this, when calling a trait function with no `self` or `Self` parameters or return type, -always refer to it via the implementation type's namespace - e.g. `MyType::default()`. -This is set to change to an error in future Noir versions. - -::: - -## Default Method Implementations - -A trait can also have default implementations of its methods by giving a body to the desired functions. -Note that this body must be valid for all types that may implement the trait. As a result, the only -valid operations on `self` will be operations valid for any type or other operations on the trait itself. - -```rust -trait Numeric { - fn add(self, other: Self) -> Self; - - // Default implementation of double is (self + self) - fn double(self) -> Self { - self.add(self) - } -} -``` - -When implementing a trait with default functions, a type may choose to implement only the required functions: - -```rust -impl Numeric for Field { - fn add(self, other: Field) -> Field { - self + other - } -} -``` - -Or it may implement the optional methods as well: - -```rust -impl Numeric for u32 { - fn add(self, other: u32) -> u32 { - self + other - } - - fn double(self) -> u32 { - self * 2 - } -} -``` - -## Impl Specialization - -When implementing traits for a generic type it is possible to implement the trait for only a certain combination -of generics. This can be either as an optimization or because those specific generics are required to implement the trait. - -```rust -trait Sub { - fn sub(self, other: Self) -> Self; -} - -struct NonZero { - value: T, -} - -impl Sub for NonZero { - fn sub(self, other: Self) -> Self { - let value = self.value - other.value; - assert(value != 0); - NonZero { value } - } -} -``` - -## Overlapping Implementations - -Overlapping implementations are disallowed by Noir to ensure Noir's decision on which impl to select is never ambiguous. -This means if a trait `Foo` is already implemented -by a type `Bar` for all `T`, then we cannot also have a separate impl for `Bar` (or any other -type argument). Similarly, if there is an impl for all `T` such as `impl Debug for T`, we cannot create -any more impls to `Debug` for other types since it would be ambiguous which impl to choose for any given -method call. - -```rust -trait Trait {} - -// Previous impl defined here -impl Trait for (A, B) {} - -// error: Impl for type `(Field, Field)` overlaps with existing impl -impl Trait for (Field, Field) {} -``` - -## Trait Coherence - -Another restriction on trait implementations is coherence. This restriction ensures other crates cannot create -impls that may overlap with other impls, even if several unrelated crates are used as dependencies in the same -program. - -The coherence restriction is: to implement a trait, either the trait itself or the object type must be declared -in the crate the impl is in. - -In practice this often comes up when using types provided by libraries. If a library provides a type `Foo` that does -not implement a trait in the standard library such as `Default`, you may not `impl Default for Foo` in your own crate. -While restrictive, this prevents later issues or silent changes in the program if the `Foo` library later added its -own impl for `Default`. If you are a user of the `Foo` library in this scenario and need a trait not implemented by the -library your choices are to either submit a patch to the library or use the newtype pattern. - -### The Newtype Pattern - -The newtype pattern gets around the coherence restriction by creating a new wrapper type around the library type -that we cannot create `impl`s for. Since the new wrapper type is defined in our current crate, we can create -impls for any trait we need on it. - -```rust -struct Wrapper { - foo: dep::some_library::Foo, -} - -impl Default for Wrapper { - fn default() -> Wrapper { - Wrapper { - foo: dep::some_library::Foo::new(), - } - } -} -``` - -Since we have an impl for our own type, the behavior of this code will not change even if `some_library` is updated -to provide its own `impl Default for Foo`. The downside of this pattern is that it requires extra wrapping and -unwrapping of values when converting to and from the `Wrapper` and `Foo` types. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/unconstrained.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/unconstrained.md deleted file mode 100644 index 89d12c1c971..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/unconstrained.md +++ /dev/null @@ -1,95 +0,0 @@ ---- -title: Unconstrained Functions -description: "Learn about what unconstrained functions in Noir are, how to use them and when you'd want to." - -keywords: [Noir programming language, unconstrained, open] -sidebar_position: 5 ---- - -Unconstrained functions are functions which do not constrain any of the included computation and allow for non-deterministic computation. - -## Why? - -Zero-knowledge (ZK) domain-specific languages (DSL) enable developers to generate ZK proofs from their programs by compiling code down to the constraints of an NP complete language (such as R1CS or PLONKish languages). However, the hard bounds of a constraint system can be very limiting to the functionality of a ZK DSL. - -Enabling a circuit language to perform unconstrained execution is a powerful tool. Said another way, unconstrained execution lets developers generate witnesses from code that does not generate any constraints. Being able to execute logic outside of a circuit is critical for both circuit performance and constructing proofs on information that is external to a circuit. - -Fetching information from somewhere external to a circuit can also be used to enable developers to improve circuit efficiency. - -A ZK DSL does not just prove computation, but proves that some computation was handled correctly. Thus, it is necessary that when we switch from performing some operation directly inside of a circuit to inside of an unconstrained environment that the appropriate constraints are still laid down elsewhere in the circuit. - -## Example - -An in depth example might help drive the point home. This example comes from the excellent [post](https://discord.com/channels/1113924620781883405/1124022445054111926/1128747641853972590) by Tom in the Noir Discord. - -Let's look at how we can optimize a function to turn a `u72` into an array of `u8`s. - -```rust -fn main(num: u72) -> pub [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8)) as u72 & 0xff) as u8; - } - - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 91 -Backend circuit size: 3619 -``` - -A lot of the operations in this function are optimized away by the compiler (all the bit-shifts turn into divisions by constants). However we can save a bunch of gates by casting to u8 a bit earlier. This automatically truncates the bit-shifted value to fit in a u8 which allows us to remove the AND against 0xff. This saves us ~480 gates in total. - -```rust -fn main(num: u72) -> pub [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8)) as u8; - } - - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 75 -Backend circuit size: 3143 -``` - -Those are some nice savings already but we can do better. This code is all constrained so we're proving every step of calculating out using num, but we don't actually care about how we calculate this, just that it's correct. This is where brillig comes in. - -It turns out that truncating a u72 into a u8 is hard to do inside a snark, each time we do as u8 we lay down 4 ACIR opcodes which get converted into multiple gates. It's actually much easier to calculate num from out than the other way around. All we need to do is multiply each element of out by a constant and add them all together, both relatively easy operations inside a snark. - -We can then run u72_to_u8 as unconstrained brillig code in order to calculate out, then use that result in our constrained function and assert that if we were to do the reverse calculation we'd get back num. This looks a little like the below: - -```rust -fn main(num: u72) -> pub [u8; 8] { - let out = u72_to_u8(num); - - let mut reconstructed_num: u72 = 0; - for i in 0..8 { - reconstructed_num += (out[i] as u72 << (56 - (8 * i))); - } - assert(num == reconstructed_num); - out -} - -unconstrained fn u72_to_u8(num: u72) -> [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8))) as u8; - } - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 78 -Backend circuit size: 2902 -``` - -This ends up taking off another ~250 gates from our circuit! We've ended up with more ACIR opcodes than before but they're easier for the backend to prove (resulting in fewer gates). - -Generally we want to use brillig whenever there's something that's easy to verify but hard to compute within the circuit. For example, if you wanted to calculate a square root of a number it'll be a much better idea to calculate this in brillig and then assert that if you square the result you get back your number. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/_category_.json deleted file mode 100644 index 1debcfe7675..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Modules, Packages and Crates", - "position": 2, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/crates_and_packages.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/crates_and_packages.md deleted file mode 100644 index 95ee9f52ab2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/crates_and_packages.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Crates and Packages -description: Learn how to use Crates and Packages in your Noir project -keywords: [Nargo, dependencies, package management, crates, package] -sidebar_position: 0 ---- - -## Crates - -A crate is the smallest amount of code that the Noir compiler considers at a time. -Crates can contain modules, and the modules may be defined in other files that get compiled with the crate, as we’ll see in the coming sections. - -### Crate Types - -A Noir crate can come in several forms: binaries, libraries or contracts. - -#### Binaries - -_Binary crates_ are programs which you can compile to an ACIR circuit which you can then create proofs against. Each must have a function called `main` that defines the ACIR circuit which is to be proved. - -#### Libraries - -_Library crates_ don't have a `main` function and they don't compile down to ACIR. Instead they define functionality intended to be shared with multiple projects, and eventually included in a binary crate. - -#### Contracts - -Contract crates are similar to binary crates in that they compile to ACIR which you can create proofs against. They are different in that they do not have a single `main` function, but are a collection of functions to be deployed to the [Aztec network](https://aztec.network). You can learn more about the technical details of Aztec in the [monorepo](https://github.com/AztecProtocol/aztec-packages) or contract [examples](https://github.com/AztecProtocol/aztec-packages/tree/master/noir-projects/noir-contracts/contracts). - -### Crate Root - -Every crate has a root, which is the source file that the compiler starts, this is also known as the root module. The Noir compiler does not enforce any conditions on the name of the file which is the crate root, however if you are compiling via Nargo the crate root must be called `lib.nr` or `main.nr` for library or binary crates respectively. - -## Packages - -A Nargo _package_ is a collection of one of more crates that provides a set of functionality. A package must include a Nargo.toml file. - -A package _must_ contain either a library or a binary crate, but not both. - -### Differences from Cargo Packages - -One notable difference between Rust's Cargo and Noir's Nargo is that while Cargo allows a package to contain an unlimited number of binary crates and a single library crate, Nargo currently only allows a package to contain a single crate. - -In future this restriction may be lifted to allow a Nargo package to contain both a binary and library crate or multiple binary crates. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/dependencies.md deleted file mode 100644 index 2c028d85853..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/dependencies.md +++ /dev/null @@ -1,124 +0,0 @@ ---- -title: Dependencies -description: - Learn how to specify and manage dependencies in Nargo, allowing you to upload packages to GitHub - and use them easily in your project. -keywords: [Nargo, dependencies, GitHub, package management, versioning] -sidebar_position: 1 ---- - -Nargo allows you to upload packages to GitHub and use them as dependencies. - -## Specifying a dependency - -Specifying a dependency requires a tag to a specific commit and the git url to the url containing -the package. - -Currently, there are no requirements on the tag contents. If requirements are added, it would follow -semver 2.0 guidelines. - -> Note: Without a `tag` , there would be no versioning and dependencies would change each time you -> compile your project. - -For example, to add the [ecrecover-noir library](https://github.com/colinnielsen/ecrecover-noir) to your project, add it to `Nargo.toml`: - -```toml -# Nargo.toml - -[dependencies] -ecrecover = {tag = "v0.8.0", git = "https://github.com/colinnielsen/ecrecover-noir"} -``` - -If the module is in a subdirectory, you can define a subdirectory in your git repository, for example: - -```toml -# Nargo.toml - -[dependencies] -easy_private_token_contract = {tag ="v0.1.0-alpha62", git = "https://github.com/AztecProtocol/aztec-packages", directory = "noir-contracts/contracts/easy_private_token_contract"} -``` - -## Specifying a local dependency - -You can also specify dependencies that are local to your machine. - -For example, this file structure has a library and binary crate - -```tree -├── binary_crate -│   ├── Nargo.toml -│   └── src -│   └── main.nr -└── lib_a - ├── Nargo.toml - └── src - └── lib.nr -``` - -Inside of the binary crate, you can specify: - -```toml -# Nargo.toml - -[dependencies] -lib_a = { path = "../lib_a" } -``` - -## Importing dependencies - -You can import a dependency to a Noir file using the following syntax. For example, to import the -ecrecover-noir library and local lib_a referenced above: - -```rust -use dep::ecrecover; -use dep::lib_a; -``` - -You can also import only the specific parts of dependency that you want to use, like so: - -```rust -use dep::std::hash::sha256; -use dep::std::scalar_mul::fixed_base_embedded_curve; -``` - -Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you -can import multiple items in the same line by enclosing them in curly braces: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; -``` - -We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. - -Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. - -## Dependencies of Dependencies - -Note that when you import a dependency, you also get access to all of the dependencies of that package. - -For example, the [phy_vector](https://github.com/resurgencelabs/phy_vector) library imports an [fraction](https://github.com/resurgencelabs/fraction) library. If you're importing the phy_vector library, then you can access the functions in fractions library like so: - -```rust -use dep::phy_vector; - -fn main(x : Field, y : pub Field) { - //... - let f = phy_vector::fraction::toFraction(true, 2, 1); - //... -} -``` - -## Available Libraries - -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). - -Some libraries that are available today include: - -- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library -- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) -- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers -- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address -- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees -- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir -- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/modules.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/modules.md deleted file mode 100644 index ae822a1cff4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/modules.md +++ /dev/null @@ -1,105 +0,0 @@ ---- -title: Modules -description: - Learn how to organize your files using modules in Noir, following the same convention as Rust's - module system. Examples included. -keywords: [Noir, Rust, modules, organizing files, sub-modules] -sidebar_position: 2 ---- - -Noir's module system follows the same convention as the _newer_ version of Rust's module system. - -## Purpose of Modules - -Modules are used to organize files. Without modules all of your code would need to live in a single -file. In Noir, the compiler does not automatically scan all of your files to detect modules. This -must be done explicitly by the developer. - -## Examples - -### Importing a module in the crate root - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::hello_world(); -} -``` - -Filename : `src/foo.nr` - -```rust -fn from_foo() {} -``` - -In the above snippet, the crate root is the `src/main.nr` file. The compiler sees the module -declaration `mod foo` which prompts it to look for a foo.nr file. - -Visually this module hierarchy looks like the following : - -``` -crate - ├── main - │ - └── foo - └── from_foo - -``` - -### Importing a module throughout the tree - -All modules are accessible from the `crate::` namespace. - -``` -crate - ├── bar - ├── foo - └── main - -``` - -In the above snippet, if `bar` would like to use functions in `foo`, it can do so by `use crate::foo::function_name`. - -### Sub-modules - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::from_foo(); -} -``` - -Filename : `src/foo.nr` - -```rust -mod bar; -fn from_foo() {} -``` - -Filename : `src/foo/bar.nr` - -```rust -fn from_bar() {} -``` - -In the above snippet, we have added an extra module to the module tree; `bar`. `bar` is a submodule -of `foo` hence we declare bar in `foo.nr` with `mod bar`. Since `foo` is not the crate root, the -compiler looks for the file associated with the `bar` module in `src/foo/bar.nr` - -Visually the module hierarchy looks as follows: - -``` -crate - ├── main - │ - └── foo - ├── from_foo - └── bar - └── from_bar -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/workspaces.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/workspaces.md deleted file mode 100644 index 513497f12bf..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/workspaces.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Workspaces -sidebar_position: 3 ---- - -Workspaces are a feature of nargo that allow you to manage multiple related Noir packages in a single repository. A workspace is essentially a group of related projects that share common build output directories and configurations. - -Each Noir project (with it's own Nargo.toml file) can be thought of as a package. Each package is expected to contain exactly one "named circuit", being the "name" defined in Nargo.toml with the program logic defined in `./src/main.nr`. - -For a project with the following structure: - -```tree -├── crates -│ ├── a -│ │ ├── Nargo.toml -│ │ └── Prover.toml -│ │ └── src -│ │ └── main.nr -│ └── b -│ ├── Nargo.toml -│ └── Prover.toml -│ └── src -│ └── main.nr -│ -└── Nargo.toml -``` - -You can define a workspace in Nargo.toml like so: - -```toml -[workspace] -members = ["crates/a", "crates/b"] -default-member = "crates/a" -``` - -`members` indicates which packages are included in the workspace. As such, all member packages of a workspace will be processed when the `--workspace` flag is used with various commands or if a `default-member` is not specified. - -`default-member` indicates which package various commands process by default. - -Libraries can be defined in a workspace. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. - -Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/_category_.json deleted file mode 100644 index af04c0933fd..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Standard Library", - "position": 1, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/black_box_fns.md deleted file mode 100644 index e8b62f21d4e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/black_box_fns.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Black Box Functions -description: Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. -keywords: [noir, black box functions] ---- - -Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. This makes certain zk-snark unfriendly computations cheaper than if they were implemented in Noir. - -The ACVM spec defines a set of blackbox functions which backends will be expected to implement. This allows backends to use optimized implementations of these constraints if they have them, however they may also fallback to less efficient naive implementations if not. - -## Function list - -Here is a list of the current black box functions: - -- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) -- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) -- [Blake3](./cryptographic_primitives/hashes.mdx#blake3) -- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash) -- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx) -- AND -- XOR -- RANGE -- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion.md) - -Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. - -You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/noir/blob/master/acvm-repo/acir/src/circuit/black_box_functions.rs). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/bn254.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/bn254.md deleted file mode 100644 index 3294f005dbb..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/bn254.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: Bn254 Field Library ---- - -Noir provides a module in standard library with some optimized functions for bn254 Fr in `std::field::bn254`. - -## decompose - -```rust -fn decompose(x: Field) -> (Field, Field) {} -``` - -Decomposes a single field into two fields, low and high. The low field contains the lower 16 bytes of the input field and the high field contains the upper 16 bytes of the input field. Both field results are range checked to 128 bits. - - -## assert_gt - -```rust -fn assert_gt(a: Field, b: Field) {} -``` - -Asserts that a > b. This will generate less constraints than using `assert(gt(a, b))`. - -## assert_lt - -```rust -fn assert_lt(a: Field, b: Field) {} -``` - -Asserts that a < b. This will generate less constraints than using `assert(lt(a, b))`. - -## gt - -```rust -fn gt(a: Field, b: Field) -> bool {} -``` - -Returns true if a > b. - -## lt - -```rust -fn lt(a: Field, b: Field) -> bool {} -``` - -Returns true if a < b. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/boundedvec.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/boundedvec.md deleted file mode 100644 index ce4529f6e57..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/boundedvec.md +++ /dev/null @@ -1,326 +0,0 @@ ---- -title: Bounded Vectors -keywords: [noir, vector, bounded vector, slice] -sidebar_position: 1 ---- - -A `BoundedVec` is a growable storage similar to a `Vec` except that it -is bounded with a maximum possible length. Unlike `Vec`, `BoundedVec` is not implemented -via slices and thus is not subject to the same restrictions slices are (notably, nested -slices - and thus nested vectors as well - are disallowed). - -Since a BoundedVec is backed by a normal array under the hood, growing the BoundedVec by -pushing an additional element is also more efficient - the length only needs to be increased -by one. - -For these reasons `BoundedVec` should generally be preferred over `Vec` when there -is a reasonable maximum bound that can be placed on the vector. - -Example: - -```rust -let mut vector: BoundedVec = BoundedVec::new(); -for i in 0..5 { - vector.push(i); -} -assert(vector.len() == 5); -assert(vector.max_len() == 10); -``` - -## Methods - -### new - -```rust -pub fn new() -> Self -``` - -Creates a new, empty vector of length zero. - -Since this container is backed by an array internally, it still needs an initial value -to give each element. To resolve this, each element is zeroed internally. This value -is guaranteed to be inaccessible unless `get_unchecked` is used. - -Example: - -```rust -let empty_vector: BoundedVec = BoundedVec::new(); -assert(empty_vector.len() == 0); -``` - -Note that whenever calling `new` the maximum length of the vector should always be specified -via a type signature: - -```rust title="new_example" showLineNumbers -fn foo() -> BoundedVec { - // Ok! MaxLen is specified with a type annotation - let v1: BoundedVec = BoundedVec::new(); - let v2 = BoundedVec::new(); - - // Ok! MaxLen is known from the type of foo's return value - v2 -} - -fn bad() { - let mut v3 = BoundedVec::new(); - - // Not Ok! We don't know if v3's MaxLen is at least 1, and the compiler often infers 0 by default. - v3.push(5); -} -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L11-L27 - - -This defaulting of `MaxLen` (and numeric generics in general) to zero may change in future noir versions -but for now make sure to use type annotations when using bounded vectors. Otherwise, you will receive a constraint failure at runtime when the vec is pushed to. - -### get - -```rust -pub fn get(mut self: Self, index: u64) -> T { -``` - -Retrieves an element from the vector at the given index, starting from zero. - -If the given index is equal to or greater than the length of the vector, this -will issue a constraint failure. - -Example: - -```rust -fn foo(v: BoundedVec) { - let first = v.get(0); - let last = v.get(v.len() - 1); - assert(first != last); -} -``` - -### get_unchecked - -```rust -pub fn get_unchecked(mut self: Self, index: u64) -> T { -``` - -Retrieves an element from the vector at the given index, starting from zero, without -performing a bounds check. - -Since this function does not perform a bounds check on length before accessing the element, -it is unsafe! Use at your own risk! - -Example: - -```rust title="get_unchecked_example" showLineNumbers -fn sum_of_first_three(v: BoundedVec) -> u32 { - // Always ensure the length is larger than the largest - // index passed to get_unchecked - assert(v.len() > 2); - let first = v.get_unchecked(0); - let second = v.get_unchecked(1); - let third = v.get_unchecked(2); - first + second + third -} -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L54-L64 - - - -### push - -```rust -pub fn push(&mut self, elem: T) { -``` - -Pushes an element to the end of the vector. This increases the length -of the vector by one. - -Panics if the new length of the vector will be greater than the max length. - -Example: - -```rust title="bounded-vec-push-example" showLineNumbers -let mut v: BoundedVec = BoundedVec::new(); - - v.push(1); - v.push(2); - - // Panics with failed assertion "push out of bounds" - v.push(3); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L68-L76 - - -### pop - -```rust -pub fn pop(&mut self) -> T -``` - -Pops the element at the end of the vector. This will decrease the length -of the vector by one. - -Panics if the vector is empty. - -Example: - -```rust title="bounded-vec-pop-example" showLineNumbers -let mut v: BoundedVec = BoundedVec::new(); - v.push(1); - v.push(2); - - let two = v.pop(); - let one = v.pop(); - - assert(two == 2); - assert(one == 1); - // error: cannot pop from an empty vector - // let _ = v.pop(); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L81-L93 - - -### len - -```rust -pub fn len(self) -> u64 { -``` - -Returns the current length of this vector - -Example: - -```rust title="bounded-vec-len-example" showLineNumbers -let mut v: BoundedVec = BoundedVec::new(); - assert(v.len() == 0); - - v.push(100); - assert(v.len() == 1); - - v.push(200); - v.push(300); - v.push(400); - assert(v.len() == 4); - - let _ = v.pop(); - let _ = v.pop(); - assert(v.len() == 2); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L98-L113 - - -### max_len - -```rust -pub fn max_len(_self: BoundedVec) -> u64 { -``` - -Returns the maximum length of this vector. This is always -equal to the `MaxLen` parameter this vector was initialized with. - -Example: - -```rust title="bounded-vec-max-len-example" showLineNumbers -let mut v: BoundedVec = BoundedVec::new(); - - assert(v.max_len() == 5); - v.push(10); - assert(v.max_len() == 5); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L118-L124 - - -### storage - -```rust -pub fn storage(self) -> [T; MaxLen] { -``` - -Returns the internal array within this vector. -Since arrays in Noir are immutable, mutating the returned storage array will not mutate -the storage held internally by this vector. - -Note that uninitialized elements may be zeroed out! - -Example: - -```rust title="bounded-vec-storage-example" showLineNumbers -let mut v: BoundedVec = BoundedVec::new(); - - assert(v.storage() == [0, 0, 0, 0, 0]); - - v.push(57); - assert(v.storage() == [57, 0, 0, 0, 0]); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L129-L136 - - -### extend_from_array - -```rust -pub fn extend_from_array(&mut self, array: [T; Len]) -``` - -Pushes each element from the given array to this vector. - -Panics if pushing each element would cause the length of this vector -to exceed the maximum length. - -Example: - -```rust title="bounded-vec-extend-from-array-example" showLineNumbers -let mut vec: BoundedVec = BoundedVec::new(); - vec.extend_from_array([2, 4]); - - assert(vec.len == 2); - assert(vec.get(0) == 2); - assert(vec.get(1) == 4); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L141-L148 - - -### extend_from_bounded_vec - -```rust -pub fn extend_from_bounded_vec(&mut self, vec: BoundedVec) -``` - -Pushes each element from the other vector to this vector. The length of -the other vector is left unchanged. - -Panics if pushing each element would cause the length of this vector -to exceed the maximum length. - -Example: - -```rust title="bounded-vec-extend-from-bounded-vec-example" showLineNumbers -let mut v1: BoundedVec = BoundedVec::new(); - let mut v2: BoundedVec = BoundedVec::new(); - - v2.extend_from_array([1, 2, 3]); - v1.extend_from_bounded_vec(v2); - - assert(v1.storage() == [1, 2, 3, 0, 0]); - assert(v2.storage() == [1, 2, 3, 0, 0, 0, 0]); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L153-L162 - - -### any - -```rust -pub fn any(self, predicate: fn[Env](T) -> bool) -> bool -``` - -Returns true if the given predicate returns true for any element -in this vector. - -Example: - -```rust title="bounded-vec-any-example" showLineNumbers -let mut v: BoundedVec = BoundedVec::new(); - v.extend_from_array([2, 4, 6]); - - let all_even = !v.any(|elem: u32| elem % 2 != 0); - assert(all_even); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L229-L235 - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/hashmap.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/hashmap.md deleted file mode 100644 index 91604af765d..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/hashmap.md +++ /dev/null @@ -1,569 +0,0 @@ ---- -title: HashMap -keywords: [noir, map, hash, hashmap] -sidebar_position: 1 ---- - -`HashMap` is used to efficiently store and look up key-value pairs. - -`HashMap` is a bounded type which can store anywhere from zero to `MaxLen` total elements. -Note that due to hash collisions, the actual maximum number of elements stored by any particular -hashmap is likely lower than `MaxLen`. This is true even with cryptographic hash functions since -every hash value will be performed modulo `MaxLen`. - -When creating `HashMap`s, the `MaxLen` generic should always be specified if it is not already -known. Otherwise, the compiler may infer a different value for `MaxLen` (such as zero), which -will likely change the result of the program. This behavior is set to become an error in future -versions instead. - -Example: - -```rust -// Create a mapping from Fields to u32s with a maximum length of 12 -// using a pedersen hash -let mut map: HashMap> = HashMap::default(); - -map.insert(1, 2); -map.insert(3, 4); - -let two = map.get(1).unwrap(); -``` - -## Methods - -### default - -```rust title="default" showLineNumbers -impl Default for HashMap -where - B: BuildHasher + Default, - H: Hasher + Default -{ - fn default() -> Self { -``` -> Source code: noir_stdlib/src/collections/map.nr#L462-L469 - - -Creates a fresh, empty HashMap. - -When using this function, always make sure to specify the maximum size of the hash map. - -This is the same `default` from the `Default` implementation given further below. It is -repeated here for convenience since it is the recommended way to create a hashmap. - -Example: - -```rust title="default_example" showLineNumbers -let hashmap: HashMap> = HashMap::default(); - assert(hashmap.is_empty()); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L202-L205 - - -Because `HashMap` has so many generic arguments that are likely to be the same throughout -your program, it may be helpful to create a type alias: - -```rust title="type_alias" showLineNumbers -type MyMap = HashMap>; -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L196-L198 - - -### with_hasher - -```rust title="with_hasher" showLineNumbers -pub fn with_hasher(_build_hasher: B) -> Self - where - B: BuildHasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L82-L86 - - -Creates a hashmap with an existing `BuildHasher`. This can be used to ensure multiple -hashmaps are created with the same hasher instance. - -Example: - -```rust title="with_hasher_example" showLineNumbers -let my_hasher: BuildHasherDefault = Default::default(); - let hashmap: HashMap> = HashMap::with_hasher(my_hasher); - assert(hashmap.is_empty()); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L207-L211 - - -### get - -```rust title="get" showLineNumbers -pub fn get( - self, - key: K - ) -> Option - where - K: Eq + Hash, - B: BuildHasher, - H: Hasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L278-L287 - - -Retrieves a value from the hashmap, returning `Option::none()` if it was not found. - -Example: - -```rust title="get_example" showLineNumbers -fn get_example(map: HashMap>) { - let x = map.get(12); - - if x.is_some() { - assert(x.unwrap() == 42); - } -} -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L299-L307 - - -### insert - -```rust title="insert" showLineNumbers -pub fn insert( - &mut self, - key: K, - value: V - ) - where - K: Eq + Hash, - B: BuildHasher, - H: Hasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L313-L323 - - -Inserts a new key-value pair into the map. If the key was already in the map, its -previous value will be overridden with the newly provided one. - -Example: - -```rust title="insert_example" showLineNumbers -let mut map: HashMap> = HashMap::default(); - map.insert(12, 42); - assert(map.len() == 1); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L213-L217 - - -### remove - -```rust title="remove" showLineNumbers -pub fn remove( - &mut self, - key: K - ) - where - K: Eq + Hash, - B: BuildHasher, - H: Hasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L356-L365 - - -Removes the given key-value pair from the map. If the key was not already present -in the map, this does nothing. - -Example: - -```rust title="remove_example" showLineNumbers -map.remove(12); - assert(map.is_empty()); - - // If a key was not present in the map, remove does nothing - map.remove(12); - assert(map.is_empty()); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L221-L228 - - -### is_empty - -```rust title="is_empty" showLineNumbers -pub fn is_empty(self) -> bool { -``` -> Source code: noir_stdlib/src/collections/map.nr#L115-L117 - - -True if the length of the hash map is empty. - -Example: - -```rust title="is_empty_example" showLineNumbers -assert(map.is_empty()); - - map.insert(1, 2); - assert(!map.is_empty()); - - map.remove(1); - assert(map.is_empty()); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L230-L238 - - -### len - -```rust title="len" showLineNumbers -pub fn len(self) -> u64 { -``` -> Source code: noir_stdlib/src/collections/map.nr#L264-L266 - - -Returns the current length of this hash map. - -Example: - -```rust title="len_example" showLineNumbers -// This is equivalent to checking map.is_empty() - assert(map.len() == 0); - - map.insert(1, 2); - map.insert(3, 4); - map.insert(5, 6); - assert(map.len() == 3); - - // 3 was already present as a key in the hash map, so the length is unchanged - map.insert(3, 7); - assert(map.len() == 3); - - map.remove(1); - assert(map.len() == 2); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L240-L255 - - -### capacity - -```rust title="capacity" showLineNumbers -pub fn capacity(_self: Self) -> u64 { -``` -> Source code: noir_stdlib/src/collections/map.nr#L271-L273 - - -Returns the maximum capacity of this hashmap. This is always equal to the capacity -specified in the hashmap's type. - -Unlike hashmaps in general purpose programming languages, hashmaps in Noir have a -static capacity that does not increase as the map grows larger. Thus, this capacity -is also the maximum possible element count that can be inserted into the hashmap. -Due to hash collisions (modulo the hashmap length), it is likely the actual maximum -element count will be lower than the full capacity. - -Example: - -```rust title="capacity_example" showLineNumbers -let empty_map: HashMap> = HashMap::default(); - assert(empty_map.len() == 0); - assert(empty_map.capacity() == 42); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L257-L261 - - -### clear - -```rust title="clear" showLineNumbers -pub fn clear(&mut self) { -``` -> Source code: noir_stdlib/src/collections/map.nr#L93-L95 - - -Clears the hashmap, removing all key-value pairs from it. - -Example: - -```rust title="clear_example" showLineNumbers -assert(!map.is_empty()); - map.clear(); - assert(map.is_empty()); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L263-L267 - - -### contains_key - -```rust title="contains_key" showLineNumbers -pub fn contains_key( - self, - key: K - ) -> bool - where - K: Hash + Eq, - B: BuildHasher, - H: Hasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L101-L110 - - -True if the hashmap contains the given key. Unlike `get`, this will not also return -the value associated with the key. - -Example: - -```rust title="contains_key_example" showLineNumbers -if map.contains_key(7) { - let value = map.get(7); - assert(value.is_some()); - } else { - println("No value for key 7!"); - } -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L269-L276 - - -### entries - -```rust title="entries" showLineNumbers -pub fn entries(self) -> BoundedVec<(K, V), N> { -``` -> Source code: noir_stdlib/src/collections/map.nr#L123-L125 - - -Returns a vector of each key-value pair present in the hashmap. - -The length of the returned vector is always equal to the length of the hashmap. - -Example: - -```rust title="entries_example" showLineNumbers -let entries = map.entries(); - - // The length of a hashmap may not be compile-time known, so we - // need to loop over its capacity instead - for i in 0..map.capacity() { - if i < entries.len() { - let (key, value) = entries.get(i); - println(f"{key} -> {value}"); - } - } -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L310-L321 - - -### keys - -```rust title="keys" showLineNumbers -pub fn keys(self) -> BoundedVec { -``` -> Source code: noir_stdlib/src/collections/map.nr#L144-L146 - - -Returns a vector of each key present in the hashmap. - -The length of the returned vector is always equal to the length of the hashmap. - -Example: - -```rust title="keys_example" showLineNumbers -let keys = map.keys(); - - for i in 0..keys.max_len() { - if i < keys.len() { - let key = keys.get_unchecked(i); - let value = map.get(key).unwrap_unchecked(); - println(f"{key} -> {value}"); - } - } -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L323-L333 - - -### values - -```rust title="values" showLineNumbers -pub fn values(self) -> BoundedVec { -``` -> Source code: noir_stdlib/src/collections/map.nr#L164-L166 - - -Returns a vector of each value present in the hashmap. - -The length of the returned vector is always equal to the length of the hashmap. - -Example: - -```rust title="values_example" showLineNumbers -let values = map.values(); - - for i in 0..values.max_len() { - if i < values.len() { - let value = values.get_unchecked(i); - println(f"Found value {value}"); - } - } -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L335-L344 - - -### iter_mut - -```rust title="iter_mut" showLineNumbers -pub fn iter_mut( - &mut self, - f: fn(K, V) -> (K, V) - ) - where - K: Eq + Hash, - B: BuildHasher, - H: Hasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L183-L192 - - -Iterates through each key-value pair of the HashMap, setting each key-value pair to the -result returned from the given function. - -Note that since keys can be mutated, the HashMap needs to be rebuilt as it is iterated -through. If this is not desired, use `iter_values_mut` if only values need to be mutated, -or `entries` if neither keys nor values need to be mutated. - -The iteration order is left unspecified. As a result, if two keys are mutated to become -equal, which of the two values that will be present for the key in the resulting map is also unspecified. - -Example: - -```rust title="iter_mut_example" showLineNumbers -// Add 1 to each key in the map, and double the value associated with that key. - map.iter_mut(|k, v| (k + 1, v * 2)); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L348-L351 - - -### iter_keys_mut - -```rust title="iter_keys_mut" showLineNumbers -pub fn iter_keys_mut( - &mut self, - f: fn(K) -> K - ) - where - K: Eq + Hash, - B: BuildHasher, - H: Hasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L208-L217 - - -Iterates through the HashMap, mutating each key to the result returned from -the given function. - -Note that since keys can be mutated, the HashMap needs to be rebuilt as it is iterated -through. If only iteration is desired and the keys are not intended to be mutated, -prefer using `entries` instead. - -The iteration order is left unspecified. As a result, if two keys are mutated to become -equal, which of the two values that will be present for the key in the resulting map is also unspecified. - -Example: - -```rust title="iter_keys_mut_example" showLineNumbers -// Double each key, leaving the value associated with that key untouched - map.iter_keys_mut(|k| k * 2); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L353-L356 - - -### iter_values_mut - -```rust title="iter_values_mut" showLineNumbers -pub fn iter_values_mut(&mut self, f: fn(V) -> V) { -``` -> Source code: noir_stdlib/src/collections/map.nr#L233-L235 - - -Iterates through the HashMap, applying the given function to each value and mutating the -value to equal the result. This function is more efficient than `iter_mut` and `iter_keys_mut` -because the keys are untouched and the underlying hashmap thus does not need to be reordered. - -Example: - -```rust title="iter_values_mut_example" showLineNumbers -// Halve each value - map.iter_values_mut(|v| v / 2); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L358-L361 - - -### retain - -```rust title="retain" showLineNumbers -pub fn retain(&mut self, f: fn(K, V) -> bool) { -``` -> Source code: noir_stdlib/src/collections/map.nr#L247-L249 - - -Retains only the key-value pairs for which the given function returns true. -Any key-value pairs for which the function returns false will be removed from the map. - -Example: - -```rust title="retain_example" showLineNumbers -map.retain(|k, v| (k != 0) & (v != 0)); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L281-L283 - - -## Trait Implementations - -### default - -```rust title="default" showLineNumbers -impl Default for HashMap -where - B: BuildHasher + Default, - H: Hasher + Default -{ - fn default() -> Self { -``` -> Source code: noir_stdlib/src/collections/map.nr#L462-L469 - - -Constructs an empty HashMap. - -Example: - -```rust title="default_example" showLineNumbers -let hashmap: HashMap> = HashMap::default(); - assert(hashmap.is_empty()); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L202-L205 - - -### eq - -```rust title="eq" showLineNumbers -impl Eq for HashMap -where - K: Eq + Hash, - V: Eq, - B: BuildHasher, - H: Hasher -{ - fn eq(self, other: HashMap) -> bool { -``` -> Source code: noir_stdlib/src/collections/map.nr#L426-L435 - - -Checks if two HashMaps are equal. - -Example: - -```rust title="eq_example" showLineNumbers -let mut map1: HashMap> = HashMap::default(); - let mut map2: HashMap> = HashMap::default(); - - map1.insert(1, 2); - map1.insert(3, 4); - - map2.insert(3, 4); - map2.insert(1, 2); - - assert(map1 == map2); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L285-L296 - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/vec.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/vec.mdx deleted file mode 100644 index 1954f05bc76..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/vec.mdx +++ /dev/null @@ -1,151 +0,0 @@ ---- -title: Vectors -description: Delve into the Vec data type in Noir. Learn about its methods, practical examples, and best practices for using Vectors in your Noir code. -keywords: [noir, vector type, methods, examples, dynamic arrays] -sidebar_position: 6 ---- - -import Experimental from '@site/src/components/Notes/_experimental.mdx'; - - - -A vector is a collection type similar to Rust's `Vec` type. In Noir, it is a convenient way to use slices as mutable arrays. - -Example: - -```rust -let mut vector: Vec = Vec::new(); -for i in 0..5 { - vector.push(i); -} -assert(vector.len() == 5); -``` - -## Methods - -### new - -Creates a new, empty vector. - -```rust -pub fn new() -> Self -``` - -Example: - -```rust -let empty_vector: Vec = Vec::new(); -assert(empty_vector.len() == 0); -``` - -### from_slice - -Creates a vector containing each element from a given slice. Mutations to the resulting vector will not affect the original slice. - -```rust -pub fn from_slice(slice: [T]) -> Self -``` - -Example: - -```rust -let arr: [Field] = [1, 2, 3]; -let vector_from_slice = Vec::from_slice(arr); -assert(vector_from_slice.len() == 3); -``` - -### len - -Returns the number of elements in the vector. - -```rust -pub fn len(self) -> Field -``` - -Example: - -```rust -let empty_vector: Vec = Vec::new(); -assert(empty_vector.len() == 0); -``` - -### get - -Retrieves an element from the vector at a given index. Panics if the index points beyond the vector's end. - -```rust -pub fn get(self, index: Field) -> T -``` - -Example: - -```rust -let vector: Vec = Vec::from_slice([10, 20, 30]); -assert(vector.get(1) == 20); -``` - -### push - -Adds a new element to the vector's end, returning a new vector with a length one greater than the original unmodified vector. - -```rust -pub fn push(&mut self, elem: T) -``` - -Example: - -```rust -let mut vector: Vec = Vec::new(); -vector.push(10); -assert(vector.len() == 1); -``` - -### pop - -Removes an element from the vector's end, returning a new vector with a length one less than the original vector, along with the removed element. Panics if the vector's length is zero. - -```rust -pub fn pop(&mut self) -> T -``` - -Example: - -```rust -let mut vector = Vec::from_slice([10, 20]); -let popped_elem = vector.pop(); -assert(popped_elem == 20); -assert(vector.len() == 1); -``` - -### insert - -Inserts an element at a specified index, shifting subsequent elements to the right. - -```rust -pub fn insert(&mut self, index: Field, elem: T) -``` - -Example: - -```rust -let mut vector = Vec::from_slice([10, 30]); -vector.insert(1, 20); -assert(vector.get(1) == 20); -``` - -### remove - -Removes an element at a specified index, shifting subsequent elements to the left, and returns the removed element. - -```rust -pub fn remove(&mut self, index: Field) -> T -``` - -Example: - -```rust -let mut vector = Vec::from_slice([10, 20, 30]); -let removed_elem = vector.remove(1); -assert(removed_elem == 20); -assert(vector.len() == 2); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/_category_.json deleted file mode 100644 index 5d694210bbf..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 0, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/ec_primitives.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/ec_primitives.md deleted file mode 100644 index 694b385e5ae..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/ec_primitives.md +++ /dev/null @@ -1,102 +0,0 @@ ---- -title: Elliptic Curve Primitives -keywords: [cryptographic primitives, Noir project] -sidebar_position: 4 ---- - -Data structures and methods on them that allow you to carry out computations involving elliptic -curves over the (mathematical) field corresponding to `Field`. For the field currently at our -disposal, applications would involve a curve embedded in BN254, e.g. the -[Baby Jubjub curve](https://eips.ethereum.org/EIPS/eip-2494). - -## Data structures - -### Elliptic curve configurations - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Curve`), i.e. the specific elliptic -curve you want to use, which would be specified using any one of the methods -`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::new` which take the coefficients in the -defining equation together with a generator point as parameters. You can find more detail in the -comments in -[`noir_stdlib/src/ec.nr`](https://github.com/noir-lang/noir/blob/v0.25.0/noir_stdlib/src/ec.nr), but -the gist of it is that the elliptic curves of interest are usually expressed in one of the standard -forms implemented here (Twisted Edwards, Montgomery and Short Weierstraß), and in addition to that, -you could choose to use `affine` coordinates (Cartesian coordinates - the usual (x,y) - possibly -together with a point at infinity) or `curvegroup` coordinates (some form of projective coordinates -requiring more coordinates but allowing for more efficient implementations of elliptic curve -operations). Conversions between all of these forms are provided, and under the hood these -conversions are done whenever an operation is more efficient in a different representation (or a -mixed coordinate representation is employed). - -### Points - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Point`), i.e. points lying on the -elliptic curve. For a curve configuration `c` and a point `p`, it may be checked that `p` -does indeed lie on `c` by calling `c.contains(p1)`. - -## Methods - -(given a choice of curve representation, e.g. use `std::ec::tecurve::affine::Curve` and use -`std::ec::tecurve::affine::Point`) - -- The **zero element** is given by `Point::zero()`, and we can verify whether a point `p: Point` is - zero by calling `p.is_zero()`. -- **Equality**: Points `p1: Point` and `p2: Point` may be checked for equality by calling - `p1.eq(p2)`. -- **Addition**: For `c: Curve` and points `p1: Point` and `p2: Point` on the curve, adding these two - points is accomplished by calling `c.add(p1,p2)`. -- **Negation**: For a point `p: Point`, `p.negate()` is its negation. -- **Subtraction**: For `c` and `p1`, `p2` as above, subtracting `p2` from `p1` is accomplished by - calling `c.subtract(p1,p2)`. -- **Scalar multiplication**: For `c` as above, `p: Point` a point on the curve and `n: Field`, - scalar multiplication is given by `c.mul(n,p)`. If instead `n :: [u1; N]`, i.e. `n` is a bit - array, the `bit_mul` method may be used instead: `c.bit_mul(n,p)` -- **Multi-scalar multiplication**: For `c` as above and arrays `n: [Field; N]` and `p: [Point; N]`, - multi-scalar multiplication is given by `c.msm(n,p)`. -- **Coordinate representation conversions**: The `into_group` method converts a point or curve - configuration in the affine representation to one in the CurveGroup representation, and - `into_affine` goes in the other direction. -- **Curve representation conversions**: `tecurve` and `montcurve` curves and points are equivalent - and may be converted between one another by calling `into_montcurve` or `into_tecurve` on their - configurations or points. `swcurve` is more general and a curve c of one of the other two types - may be converted to this representation by calling `c.into_swcurve()`, whereas a point `p` lying - on the curve given by `c` may be mapped to its corresponding `swcurve` point by calling - `c.map_into_swcurve(p)`. -- **Map-to-curve methods**: The Elligator 2 method of mapping a field element `n: Field` into a - `tecurve` or `montcurve` with configuration `c` may be called as `c.elligator2_map(n)`. For all of - the curve configurations, the SWU map-to-curve method may be called as `c.swu_map(z,n)`, where - `z: Field` depends on `Field` and `c` and must be chosen by the user (the conditions it needs to - satisfy are specified in the comments - [here](https://github.com/noir-lang/noir/blob/v0.25.0/noir_stdlib/src/ec.nr). - -## Examples - -The -[ec_baby_jubjub test](https://github.com/noir-lang/noir/blob/master/test_programs/compile_success_empty/ec_baby_jubjub/src/main.nr) -illustrates all of the above primitives on various forms of the Baby Jubjub curve. A couple of more -interesting examples in Noir would be: - -Public-key cryptography: Given an elliptic curve and a 'base point' on it, determine the public key -from the private key. This is a matter of using scalar multiplication. In the case of Baby Jubjub, -for example, this code would do: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; - -fn bjj_pub_key(priv_key: Field) -> Point -{ - - let bjj = Curve::new(168700, 168696, G::new(995203441582195749578291179787384436505546430278305826713579947235728471134,5472060717959818805561601436314318772137091100104008585924551046643952123905)); - - let base_pt = Point::new(5299619240641551281634865583518297030282874472190772894086521144482721001553, 16950150798460657717958625567821834550301663161624707787222815936182638968203); - - bjj.mul(priv_key,base_pt) -} -``` - -This would come in handy in a Merkle proof. - -- EdDSA signature verification: This is a matter of combining these primitives with a suitable hash - function. See - [feat(stdlib): EdDSA sig verification noir#1136](https://github.com/noir-lang/noir/pull/1136) for - the case of Baby Jubjub and the Poseidon hash function. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx deleted file mode 100644 index 4bf09cef178..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx +++ /dev/null @@ -1,60 +0,0 @@ ---- -title: ECDSA Signature Verification -description: Learn about the cryptographic primitives regarding ECDSA over the secp256k1 and secp256r1 curves -keywords: [cryptographic primitives, Noir project, ecdsa, secp256k1, secp256r1, signatures] -sidebar_position: 3 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -Noir supports ECDSA signatures verification over the secp256k1 and secp256r1 curves. - -## ecdsa_secp256k1::verify_signature - -Verifier for ECDSA Secp256k1 signatures - -```rust title="ecdsa_secp256k1" showLineNumbers -pub fn verify_signature( - public_key_x: [u8; 32], - public_key_y: [u8; 32], - signature: [u8; 64], - message_hash: [u8; N] -) -> bool -``` -> Source code: noir_stdlib/src/ecdsa_secp256k1.nr#L2-L9 - - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - -## ecdsa_secp256r1::verify_signature - -Verifier for ECDSA Secp256r1 signatures - -```rust title="ecdsa_secp256r1" showLineNumbers -pub fn verify_signature( - public_key_x: [u8; 32], - public_key_y: [u8; 32], - signature: [u8; 64], - message_hash: [u8; N] -) -> bool -``` -> Source code: noir_stdlib/src/ecdsa_secp256r1.nr#L2-L9 - - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/eddsa.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/eddsa.mdx deleted file mode 100644 index c2c0624dfad..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/eddsa.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: EdDSA Verification -description: Learn about the cryptographic primitives regarding EdDSA -keywords: [cryptographic primitives, Noir project, eddsa, signatures] -sidebar_position: 5 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## eddsa::eddsa_poseidon_verify - -Verifier for EdDSA signatures - -```rust -fn eddsa_poseidon_verify(public_key_x : Field, public_key_y : Field, signature_s: Field, signature_r8_x: Field, signature_r8_y: Field, message: Field) -> bool -``` - -It is also possible to specify the hash algorithm used for the signature by using the `eddsa_verify_with_hasher` function with a parameter implementing the Hasher trait. For instance, if you want to use Poseidon2 instead, you can do the following: -```rust -use dep::std::hash::poseidon2::Poseidon2Hasher; - -let mut hasher = Poseidon2Hasher::default(); -eddsa_verify_with_hasher(pub_key_a.x, pub_key_a.y, s_a, r8_a.x, r8_a.y, msg, &mut hasher); -``` - - - -## eddsa::eddsa_to_pub - -Private to public key conversion. - -Returns `(pub_key_x, pub_key_y)` - -```rust -fn eddsa_to_pub(secret : Field) -> (Field, Field) -``` - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/hashes.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/hashes.mdx deleted file mode 100644 index 119d8ccc70e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/hashes.mdx +++ /dev/null @@ -1,251 +0,0 @@ ---- -title: Hash methods -description: - Learn about the cryptographic primitives ready to use for any Noir project, including sha256, - blake2s, pedersen, mimc_bn254 and mimc -keywords: - [cryptographic primitives, Noir project, sha256, blake2s, pedersen, mimc_bn254, mimc, hash] -sidebar_position: 0 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## sha256 - -Given an array of bytes, returns the resulting sha256 hash. - -```rust title="sha256" showLineNumbers -pub fn sha256(input: [u8; N]) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L9-L11 - - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::sha256(x); -} -``` - - - -## blake2s - -Given an array of bytes, returns an array with the Blake2 hash - -```rust title="blake2s" showLineNumbers -pub fn blake2s(input: [u8; N]) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L15-L17 - - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::blake2s(x); -} -``` - - - -## blake3 - -Given an array of bytes, returns an array with the Blake3 hash - -```rust title="blake3" showLineNumbers -pub fn blake3(input: [u8; N]) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L21-L23 - - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::blake3(x); -} -``` - - - -## pedersen_hash - -Given an array of Fields, returns the Pedersen hash. - -```rust title="pedersen_hash" showLineNumbers -pub fn pedersen_hash(input: [Field; N]) -> Field -``` -> Source code: noir_stdlib/src/hash.nr#L46-L48 - - -example: - -```rust title="pedersen-hash" showLineNumbers -use dep::std; - -fn main(x: Field, y: Field, expected_hash: Field) { - let hash = std::hash::pedersen_hash([x, y]); - assert_eq(hash, expected_hash); -} -``` -> Source code: test_programs/execution_success/pedersen_hash/src/main.nr#L1-L8 - - - - - -## pedersen_commitment - -Given an array of Fields, returns the Pedersen commitment. - -```rust title="pedersen_commitment" showLineNumbers -struct PedersenPoint { - x : Field, - y : Field, -} - -pub fn pedersen_commitment(input: [Field; N]) -> PedersenPoint -``` -> Source code: noir_stdlib/src/hash.nr#L26-L33 - - -example: - -```rust title="pedersen-commitment" showLineNumbers -use dep::std; - -fn main(x: Field, y: Field, expected_commitment: std::hash::PedersenPoint) { - let commitment = std::hash::pedersen_commitment([x, y]); - assert_eq(commitment.x, expected_commitment.x); - assert_eq(commitment.y, expected_commitment.y); -} -``` -> Source code: test_programs/execution_success/pedersen_commitment/src/main.nr#L1-L9 - - - - -## keccak256 - -Given an array of bytes (`u8`), returns the resulting keccak hash as an array of 32 bytes -(`[u8; 32]`). Specify a message_size to hash only the first `message_size` bytes -of the input. - -```rust title="keccak256" showLineNumbers -pub fn keccak256(input: [u8; N], message_size: u32) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L71-L73 - - -example: - -```rust title="keccak256" showLineNumbers -use dep::std; - -fn main(x: Field, result: [u8; 32]) { - // We use the `as` keyword here to denote the fact that we want to take just the first byte from the x Field - // The padding is taken care of by the program - let digest = std::hash::keccak256([x as u8], 1); - assert(digest == result); - - //#1399: variable message size - let message_size = 4; - let hash_a = std::hash::keccak256([1, 2, 3, 4], message_size); - let hash_b = std::hash::keccak256([1, 2, 3, 4, 0, 0, 0, 0], message_size); - - assert(hash_a == hash_b); - - let message_size_big = 8; - let hash_c = std::hash::keccak256([1, 2, 3, 4, 0, 0, 0, 0], message_size_big); - - assert(hash_a != hash_c); -} -``` -> Source code: test_programs/execution_success/keccak256/src/main.nr#L1-L22 - - - - -## poseidon - -Given an array of Fields, returns a new Field with the Poseidon Hash. Mind that you need to specify -how many inputs are there to your Poseidon function. - -```rust -// example for hash_1, hash_2 accepts an array of length 2, etc -fn hash_1(input: [Field; 1]) -> Field -``` - -example: - -```rust title="poseidon" showLineNumbers -use dep::std::hash::poseidon; -use dep::std::hash::poseidon2; - -fn main(x1: [Field; 2], y1: pub Field, x2: [Field; 4], y2: pub Field, x3: [Field; 4], y3: Field) { - let hash1 = poseidon::bn254::hash_2(x1); - assert(hash1 == y1); - - let hash2 = poseidon::bn254::hash_4(x2); - assert(hash2 == y2); - - let hash3 = poseidon2::Poseidon2::hash(x3, x3.len()); - assert(hash3 == y3); -} -``` -> Source code: test_programs/execution_success/poseidon_bn254_hash/src/main.nr#L1-L15 - - -## poseidon 2 - -Given an array of Fields, returns a new Field with the Poseidon2 Hash. Contrary to the Poseidon -function, there is only one hash and you can specify a message_size to hash only the first -`message_size` bytes of the input, - -```rust -// example for hashing the first three elements of the input -Poseidon2::hash(input, 3); -``` - -The above example for Poseidon also includes Poseidon2. - -## mimc_bn254 and mimc - -`mimc_bn254` is `mimc`, but with hardcoded parameters for the BN254 curve. You can use it by -providing an array of Fields, and it returns a Field with the hash. You can use the `mimc` method if -you're willing to input your own constants: - -```rust -fn mimc(x: Field, k: Field, constants: [Field; N], exp : Field) -> Field -``` - -otherwise, use the `mimc_bn254` method: - -```rust -fn mimc_bn254(array: [Field; N]) -> Field -``` - -example: - -```rust - -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::mimc::mimc_bn254(x); -} -``` - -## hash_to_field - -```rust -fn hash_to_field(_input : [Field; N]) -> Field {} -``` - -Calculates the `blake2s` hash of the inputs and returns the hash modulo the field modulus to return -a value which can be represented as a `Field`. - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/index.md deleted file mode 100644 index 650f30165d5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/index.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Cryptographic Primitives -description: - Learn about the cryptographic primitives ready to use for any Noir project -keywords: - [ - cryptographic primitives, - Noir project, - ] ---- - -The Noir team is progressively adding new cryptographic primitives to the standard library. Reach out for news or if you would be interested in adding more of these calculations in Noir. - -Some methods are available thanks to the Aztec backend, not being performed using Noir. When using other backends, these methods may or may not be supplied. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/scalar.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/scalar.mdx deleted file mode 100644 index df411ca5443..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/scalar.mdx +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Scalar multiplication -description: See how you can perform scalar multiplications over a fixed base in Noir -keywords: [cryptographic primitives, Noir project, scalar multiplication] -sidebar_position: 1 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## scalar_mul::fixed_base_embedded_curve - -Performs scalar multiplication over the embedded curve whose coordinates are defined by the -configured noir field. For the BN254 scalar field, this is BabyJubJub or Grumpkin. - -```rust title="fixed_base_embedded_curve" showLineNumbers -pub fn fixed_base_embedded_curve( - low: Field, - high: Field -) -> [Field; 2] -``` -> Source code: noir_stdlib/src/scalar_mul.nr#L27-L32 - - -example - -```rust -fn main(x : Field) { - let scal = std::scalar_mul::fixed_base_embedded_curve(x); - println(scal); -} -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/schnorr.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/schnorr.mdx deleted file mode 100644 index ae12e6c12dc..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/schnorr.mdx +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Schnorr Signatures -description: Learn how you can verify Schnorr signatures using Noir -keywords: [cryptographic primitives, Noir project, schnorr, signatures] -sidebar_position: 2 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## schnorr::verify_signature - -Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin). - -```rust title="schnorr_verify" showLineNumbers -pub fn verify_signature( - public_key_x: Field, - public_key_y: Field, - signature: [u8; 64], - message: [u8; N] -) -> bool -``` -> Source code: noir_stdlib/src/schnorr.nr#L2-L9 - - -where `_signature` can be generated like so using the npm package -[@noir-lang/barretenberg](https://www.npmjs.com/package/@noir-lang/barretenberg) - -```js -const { BarretenbergWasm } = require('@noir-lang/barretenberg/dest/wasm'); -const { Schnorr } = require('@noir-lang/barretenberg/dest/crypto/schnorr'); - -... - -const barretenberg = await BarretenbergWasm.new(); -const schnorr = new Schnorr(barretenberg); -const pubKey = schnorr.computePublicKey(privateKey); -const message = ... -const signature = Array.from( - schnorr.constructSignature(hash, privateKey).toBuffer() -); - -... -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/logging.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/logging.md deleted file mode 100644 index db75ef9f86f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/logging.md +++ /dev/null @@ -1,78 +0,0 @@ ---- -title: Logging -description: - Learn how to use the println statement for debugging in Noir with this tutorial. Understand the - basics of logging in Noir and how to implement it in your code. -keywords: - [ - noir logging, - println statement, - print statement, - debugging in noir, - noir std library, - logging tutorial, - basic logging in noir, - noir logging implementation, - noir debugging techniques, - rust, - ] ---- - -The standard library provides two familiar statements you can use: `println` and `print`. Despite being a limited implementation of rust's `println!` and `print!` macros, these constructs can be useful for debugging. - -You can print the output of both statements in your Noir code by using the `nargo execute` command or the `--show-output` flag when using `nargo test` (provided there are print statements in your tests). - -It is recommended to use `nargo execute` if you want to debug failing constraints with `println` or `print` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). Neither `println`, nor `print` are callable for failed constraints caught at compile time. - -Both `print` and `println` are generic functions which can work on integers, fields, strings, and even structs or expressions. Note however, that slices are currently unsupported. For example: - -```rust -struct Person { - age: Field, - height: Field, -} - -fn main(age: Field, height: Field) { - let person = Person { - age: age, - height: height, - }; - println(person); - println(age + height); - println("Hello world!"); -} -``` - -You can print different types in the same statement (including strings) with a type called `fmtstr`. It can be specified in the same way as a normal string, just prepended with an "f" character: - -```rust - let fmt_str = f"i: {i}, j: {j}"; - println(fmt_str); - - let s = myStruct { y: x, x: y }; - println(s); - - println(f"i: {i}, s: {s}"); - - println(x); - println([x, y]); - - let foo = fooStruct { my_struct: s, foo: 15 }; - println(f"s: {s}, foo: {foo}"); - - println(15); // prints 0x0f, implicit Field - println(-1 as u8); // prints 255 - println(-1 as i8); // prints -1 -``` - -Examples shown above are interchangeable between the two `print` statements: - -```rust -let person = Person { age : age, height : height }; - -println(person); -print(person); - -println("Hello world!"); // Prints with a newline at the end of the input -print("Hello world!"); // Prints the input and keeps cursor on the same line -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/merkle_trees.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/merkle_trees.md deleted file mode 100644 index fa488677884..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/merkle_trees.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: Merkle Trees -description: Learn about Merkle Trees in Noir with this tutorial. Explore the basics of computing a merkle root using a proof, with examples. -keywords: - [ - Merkle trees in Noir, - Noir programming language, - check membership, - computing root from leaf, - Noir Merkle tree implementation, - Merkle tree tutorial, - Merkle tree code examples, - Noir libraries, - pedersen hash., - ] ---- - -## compute_merkle_root - -Returns the root of the tree from the provided leaf and its hash path, using a [Pedersen hash](./cryptographic_primitives/hashes.mdx#pedersen_hash). - -```rust -fn compute_merkle_root(leaf : Field, index : Field, hash_path: [Field]) -> Field -``` - -example: - -```rust -/** - // these values are for this example only - index = "0" - priv_key = "0x000000000000000000000000000000000000000000000000000000616c696365" - secret = "0x1929ea3ab8d9106a899386883d9428f8256cfedb3c4f6b66bf4aa4d28a79988f" - note_hash_path = [ - "0x1e61bdae0f027b1b2159e1f9d3f8d00fa668a952dddd822fda80dc745d6f65cc", - "0x0e4223f3925f98934393c74975142bd73079ab0621f4ee133cee050a3c194f1a", - "0x2fd7bb412155bf8693a3bd2a3e7581a679c95c68a052f835dddca85fa1569a40" - ] - */ -fn main(index: Field, priv_key: Field, secret: Field, note_hash_path: [Field; 3]) { - - let pubkey = std::scalar_mul::fixed_base_embedded_curve(priv_key); - let pubkey_x = pubkey[0]; - let pubkey_y = pubkey[1]; - let note_commitment = std::hash::pedersen([pubkey_x, pubkey_y, secret]); - - let root = std::merkle::compute_merkle_root(note_commitment[0], index, note_hash_path); - println(root); -} -``` - -To check merkle tree membership: - -1. Include a merkle root as a program input. -2. Compute the merkle root of a given leaf, index and hash path. -3. Assert the merkle roots are equal. - -For more info about merkle trees, see the Wikipedia [page](https://en.wikipedia.org/wiki/Merkle_tree). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/options.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/options.md deleted file mode 100644 index a1bd4e1de5f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/options.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -title: Option Type ---- - -The `Option` type is a way to express that a value might be present (`Some(T))` or absent (`None`). It's a safer way to handle potential absence of values, compared to using nulls in many other languages. - -```rust -struct Option { - None, - Some(T), -} -``` - -The `Option` type, already imported into your Noir program, can be used directly: - -```rust -fn main() { - let none = Option::none(); - let some = Option::some(3); -} -``` - -See [this test](https://github.com/noir-lang/noir/blob/5cbfb9c4a06c8865c98ff2b594464b037d821a5c/crates/nargo_cli/tests/test_data/option/src/main.nr) for a more comprehensive set of examples of each of the methods described below. - -## Methods - -### none - -Constructs a none value. - -### some - -Constructs a some wrapper around a given value. - -### is_none - -Returns true if the Option is None. - -### is_some - -Returns true of the Option is Some. - -### unwrap - -Asserts `self.is_some()` and returns the wrapped value. - -### unwrap_unchecked - -Returns the inner value without asserting `self.is_some()`. This method can be useful within an if condition when we already know that `option.is_some()`. If the option is None, there is no guarantee what value will be returned, only that it will be of type T for an `Option`. - -### unwrap_or - -Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value. - -### unwrap_or_else - -Returns the wrapped value if `self.is_some()`. Otherwise, calls the given function to return a default value. - -### expect - -Asserts `self.is_some()` with a provided custom message and returns the contained `Some` value. The custom message is expected to be a format string. - -### map - -If self is `Some(x)`, this returns `Some(f(x))`. Otherwise, this returns `None`. - -### map_or - -If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns the given default value. - -### map_or_else - -If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns `default()`. - -### and - -Returns None if self is None. Otherwise, this returns `other`. - -### and_then - -If self is None, this returns None. Otherwise, this calls the given function with the Some value contained within self, and returns the result of that call. In some languages this function is called `flat_map` or `bind`. - -### or - -If self is Some, return self. Otherwise, return `other`. - -### or_else - -If self is Some, return self. Otherwise, return `default()`. - -### xor - -If only one of the two Options is Some, return that option. Otherwise, if both options are Some or both are None, None is returned. - -### filter - -Returns `Some(x)` if self is `Some(x)` and `predicate(x)` is true. Otherwise, this returns `None`. - -### flatten - -Flattens an `Option>` into a `Option`. This returns `None` if the outer Option is None. Otherwise, this returns the inner Option. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/recursion.md deleted file mode 100644 index ed2ed01fceb..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/recursion.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -title: Recursive Proofs -description: Learn about how to write recursive proofs in Noir. -keywords: [recursion, recursive proofs, verification_key, verify_proof] ---- - -Noir supports recursively verifying proofs, meaning you verify the proof of a Noir program in another Noir program. This enables creating proofs of arbitrary size by doing step-wise verification of smaller components of a large proof. - -Read [the explainer on recursion](../../explainers/explainer-recursion.md) to know more about this function and the [guide on how to use it.](../../how_to/how-to-recursion.md) - -## The `#[recursive]` Attribute - -In Noir, the `#[recursive]` attribute is used to indicate that a circuit is designed for recursive proof generation. When applied, it informs the compiler and the tooling that the circuit should be compiled in a way that makes its proofs suitable for recursive verification. This attribute eliminates the need for manual flagging of recursion at the tooling level, streamlining the proof generation process for recursive circuits. - -### Example usage with `#[recursive]` - -```rust -#[recursive] -fn main(x: Field, y: pub Field) { - assert(x == y, "x and y are not equal"); -} - -// This marks the circuit as recursion-friendly and indicates that proofs generated from this circuit -// are intended for recursive verification. -``` - -By incorporating this attribute directly in the circuit's definition, tooling like Nargo and NoirJS can automatically execute recursive-specific duties for Noir programs (e.g. recursive-friendly proof artifact generation) without additional flags or configurations. - -## Verifying Recursive Proofs - -```rust -#[foreign(verify_proof)] -fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : Field, _key_hash : Field) {} -``` - -:::info - -This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. - -::: - -## Example usage - -```rust -use dep::std; - -fn main( - verification_key : [Field; 114], - proof : [Field; 93], - public_inputs : [Field; 1], - key_hash : Field, - proof_b : [Field; 93], -) { - std::verify_proof( - verification_key.as_slice(), - proof.as_slice(), - public_inputs.as_slice(), - key_hash - ); - - std::verify_proof( - verification_key.as_slice(), - proof_b.as_slice(), - public_inputs.as_slice(), - key_hash - ); -} -``` - -You can see a full example of recursive proofs in [this example recursion demo repo](https://github.com/noir-lang/noir-examples/tree/master/recursion). - -## Parameters - -### `verification_key` - -The verification key for the zk program that is being verified. - -### `proof` - -The proof for the zk program that is being verified. - -### `public_inputs` - -These represent the public inputs of the proof we are verifying. - -### `key_hash` - -A key hash is used to check the validity of the verification key. The circuit implementing this opcode can use this hash to ensure that the key provided to the circuit matches the key produced by the circuit creator. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/traits.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/traits.md deleted file mode 100644 index ba9fa2ee841..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/traits.md +++ /dev/null @@ -1,399 +0,0 @@ ---- -title: Traits -description: Noir's stdlib provides a few commonly used traits. -keywords: [traits, trait, interface, protocol, default, add, eq] ---- - -## `std::default` - -### `std::default::Default` - -```rust title="default-trait" showLineNumbers -trait Default { - fn default() -> Self; -} -``` -> Source code: noir_stdlib/src/default.nr#L1-L5 - - -Constructs a default value of a type. - -Implementations: -```rust -impl Default for Field { .. } - -impl Default for i8 { .. } -impl Default for i16 { .. } -impl Default for i32 { .. } -impl Default for i64 { .. } - -impl Default for u8 { .. } -impl Default for u16 { .. } -impl Default for u32 { .. } -impl Default for u64 { .. } - -impl Default for () { .. } -impl Default for bool { .. } - -impl Default for [T; N] - where T: Default { .. } - -impl Default for (A, B) - where A: Default, B: Default { .. } - -impl Default for (A, B, C) - where A: Default, B: Default, C: Default { .. } - -impl Default for (A, B, C, D) - where A: Default, B: Default, C: Default, D: Default { .. } - -impl Default for (A, B, C, D, E) - where A: Default, B: Default, C: Default, D: Default, E: Default { .. } -``` - -For primitive integer types, the return value of `default` is `0`. Container -types such as arrays are filled with default values of their element type. - - -## `std::convert` - -### `std::convert::From` - -```rust title="from-trait" showLineNumbers -trait From { - fn from(input: T) -> Self; -} -``` -> Source code: noir_stdlib/src/convert.nr#L1-L5 - - -The `From` trait defines how to convert from a given type `T` to the type on which the trait is implemented. - -The Noir standard library provides a number of implementations of `From` between primitive types. -```rust title="from-impls" showLineNumbers -// Unsigned integers - -impl From for u32 { fn from(value: u8) -> u32 { value as u32 } } - -impl From for u64 { fn from(value: u8) -> u64 { value as u64 } } -impl From for u64 { fn from(value: u32) -> u64 { value as u64 } } - -impl From for Field { fn from(value: u8) -> Field { value as Field } } -impl From for Field { fn from(value: u32) -> Field { value as Field } } -impl From for Field { fn from(value: u64) -> Field { value as Field } } - -// Signed integers - -impl From for i32 { fn from(value: i8) -> i32 { value as i32 } } - -impl From for i64 { fn from(value: i8) -> i64 { value as i64 } } -impl From for i64 { fn from(value: i32) -> i64 { value as i64 } } - -// Booleans -impl From for u8 { fn from(value: bool) -> u8 { value as u8 } } -impl From for u32 { fn from(value: bool) -> u32 { value as u32 } } -impl From for u64 { fn from(value: bool) -> u64 { value as u64 } } -impl From for i8 { fn from(value: bool) -> i8 { value as i8 } } -impl From for i32 { fn from(value: bool) -> i32 { value as i32 } } -impl From for i64 { fn from(value: bool) -> i64 { value as i64 } } -impl From for Field { fn from(value: bool) -> Field { value as Field } } -``` -> Source code: noir_stdlib/src/convert.nr#L25-L52 - - -#### When to implement `From` - -As a general rule of thumb, `From` may be implemented in the [situations where it would be suitable in Rust](https://doc.rust-lang.org/std/convert/trait.From.html#when-to-implement-from): - -- The conversion is *infallible*: Noir does not provide an equivalent to Rust's `TryFrom`, if the conversion can fail then provide a named method instead. -- The conversion is *lossless*: semantically, it should not lose or discard information. For example, `u32: From` can losslessly convert any `u16` into a valid `u32` such that the original `u16` can be recovered. On the other hand, `u16: From` should not be implemented as `2**16` is a `u32` which cannot be losslessly converted into a `u16`. -- The conversion is *value-preserving*: the conceptual kind and meaning of the resulting value is the same, even though the Noir type and technical representation might be different. While it's possible to infallibly and losslessly convert a `u8` into a `str<2>` hex representation, `4u8` and `"04"` are too different for `str<2>: From` to be implemented. -- The conversion is *obvious*: it's the only reasonable conversion between the two types. If there's ambiguity on how to convert between them such that the same input could potentially map to two different values then a named method should be used. For instance rather than implementing `U128: From<[u8; 16]>`, the methods `U128::from_le_bytes` and `U128::from_be_bytes` are used as otherwise the endianness of the array would be ambiguous, resulting in two potential values of `U128` from the same byte array. - -One additional recommendation specific to Noir is: -- The conversion is *efficient*: it's relatively cheap to convert between the two types. Due to being a ZK DSL, it's more important to avoid unnecessary computation compared to Rust. If the implementation of `From` would encourage users to perform unnecessary conversion, resulting in additional proving time, then it may be preferable to expose functionality such that this conversion may be avoided. - -### `std::convert::Into` - -The `Into` trait is defined as the reciprocal of `From`. It should be easy to convince yourself that if we can convert to type `A` from type `B`, then it's possible to convert type `B` into type `A`. - -For this reason, implementing `From` on a type will automatically generate a matching `Into` implementation. One should always prefer implementing `From` over `Into` as implementing `Into` will not generate a matching `From` implementation. - -```rust title="into-trait" showLineNumbers -trait Into { - fn into(input: Self) -> T; -} - -impl Into for U where T: From { - fn into(input: U) -> T { - T::from(input) - } -} -``` -> Source code: noir_stdlib/src/convert.nr#L13-L23 - - -`Into` is most useful when passing function arguments where the types don't quite match up with what the function expects. In this case, the compiler has enough type information to perform the necessary conversion by just appending `.into()` onto the arguments in question. - - -## `std::cmp` - -### `std::cmp::Eq` - -```rust title="eq-trait" showLineNumbers -trait Eq { - fn eq(self, other: Self) -> bool; -} -``` -> Source code: noir_stdlib/src/cmp.nr#L1-L5 - - -Returns `true` if `self` is equal to `other`. Implementing this trait on a type -allows the type to be used with `==` and `!=`. - -Implementations: -```rust -impl Eq for Field { .. } - -impl Eq for i8 { .. } -impl Eq for i16 { .. } -impl Eq for i32 { .. } -impl Eq for i64 { .. } - -impl Eq for u8 { .. } -impl Eq for u16 { .. } -impl Eq for u32 { .. } -impl Eq for u64 { .. } - -impl Eq for () { .. } -impl Eq for bool { .. } - -impl Eq for [T; N] - where T: Eq { .. } - -impl Eq for (A, B) - where A: Eq, B: Eq { .. } - -impl Eq for (A, B, C) - where A: Eq, B: Eq, C: Eq { .. } - -impl Eq for (A, B, C, D) - where A: Eq, B: Eq, C: Eq, D: Eq { .. } - -impl Eq for (A, B, C, D, E) - where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq { .. } -``` - -### `std::cmp::Ord` - -```rust title="ord-trait" showLineNumbers -trait Ord { - fn cmp(self, other: Self) -> Ordering; -} -``` -> Source code: noir_stdlib/src/cmp.nr#L92-L96 - - -`a.cmp(b)` compares two values returning `Ordering::less()` if `a < b`, -`Ordering::equal()` if `a == b`, or `Ordering::greater()` if `a > b`. -Implementing this trait on a type allows `<`, `<=`, `>`, and `>=` to be -used on values of the type. - -Implementations: - -```rust -impl Ord for u8 { .. } -impl Ord for u16 { .. } -impl Ord for u32 { .. } -impl Ord for u64 { .. } - -impl Ord for i8 { .. } -impl Ord for i16 { .. } -impl Ord for i32 { .. } - -impl Ord for i64 { .. } - -impl Ord for () { .. } -impl Ord for bool { .. } - -impl Ord for [T; N] - where T: Ord { .. } - -impl Ord for (A, B) - where A: Ord, B: Ord { .. } - -impl Ord for (A, B, C) - where A: Ord, B: Ord, C: Ord { .. } - -impl Ord for (A, B, C, D) - where A: Ord, B: Ord, C: Ord, D: Ord { .. } - -impl Ord for (A, B, C, D, E) - where A: Ord, B: Ord, C: Ord, D: Ord, E: Ord { .. } -``` - -## `std::ops` - -### `std::ops::Add`, `std::ops::Sub`, `std::ops::Mul`, and `std::ops::Div` - -These traits abstract over addition, subtraction, multiplication, and division respectively. -Implementing these traits for a given type will also allow that type to be used with the corresponding operator -for that trait (`+` for Add, etc) in addition to the normal method names. - -```rust title="add-trait" showLineNumbers -trait Add { - fn add(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L1-L5 - -```rust title="sub-trait" showLineNumbers -trait Sub { - fn sub(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L17-L21 - -```rust title="mul-trait" showLineNumbers -trait Mul { - fn mul(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L33-L37 - -```rust title="div-trait" showLineNumbers -trait Div { - fn div(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L49-L53 - - -The implementations block below is given for the `Add` trait, but the same types that implement -`Add` also implement `Sub`, `Mul`, and `Div`. - -Implementations: -```rust -impl Add for Field { .. } - -impl Add for i8 { .. } -impl Add for i16 { .. } -impl Add for i32 { .. } -impl Add for i64 { .. } - -impl Add for u8 { .. } -impl Add for u16 { .. } -impl Add for u32 { .. } -impl Add for u64 { .. } -``` - -### `std::ops::Rem` - -```rust title="rem-trait" showLineNumbers -trait Rem{ - fn rem(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L65-L69 - - -`Rem::rem(a, b)` is the remainder function returning the result of what is -left after dividing `a` and `b`. Implementing `Rem` allows the `%` operator -to be used with the implementation type. - -Unlike other numeric traits, `Rem` is not implemented for `Field`. - -Implementations: -```rust -impl Rem for u8 { fn rem(self, other: u8) -> u8 { self % other } } -impl Rem for u16 { fn rem(self, other: u16) -> u16 { self % other } } -impl Rem for u32 { fn rem(self, other: u32) -> u32 { self % other } } -impl Rem for u64 { fn rem(self, other: u64) -> u64 { self % other } } - -impl Rem for i8 { fn rem(self, other: i8) -> i8 { self % other } } -impl Rem for i16 { fn rem(self, other: i16) -> i16 { self % other } } -impl Rem for i32 { fn rem(self, other: i32) -> i32 { self % other } } -impl Rem for i64 { fn rem(self, other: i64) -> i64 { self % other } } -``` - -### `std::ops::{ BitOr, BitAnd, BitXor }` - -```rust title="bitor-trait" showLineNumbers -trait BitOr { - fn bitor(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L79-L83 - -```rust title="bitand-trait" showLineNumbers -trait BitAnd { - fn bitand(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L95-L99 - -```rust title="bitxor-trait" showLineNumbers -trait BitXor { - fn bitxor(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L111-L115 - - -Traits for the bitwise operations `|`, `&`, and `^`. - -Implementing `BitOr`, `BitAnd` or `BitXor` for a type allows the `|`, `&`, or `^` operator respectively -to be used with the type. - -The implementations block below is given for the `BitOr` trait, but the same types that implement -`BitOr` also implement `BitAnd` and `BitXor`. - -Implementations: -```rust -impl BitOr for bool { fn bitor(self, other: bool) -> bool { self | other } } - -impl BitOr for u8 { fn bitor(self, other: u8) -> u8 { self | other } } -impl BitOr for u16 { fn bitor(self, other: u16) -> u16 { self | other } } -impl BitOr for u32 { fn bitor(self, other: u32) -> u32 { self | other } } -impl BitOr for u64 { fn bitor(self, other: u64) -> u64 { self | other } } - -impl BitOr for i8 { fn bitor(self, other: i8) -> i8 { self | other } } -impl BitOr for i16 { fn bitor(self, other: i16) -> i16 { self | other } } -impl BitOr for i32 { fn bitor(self, other: i32) -> i32 { self | other } } -impl BitOr for i64 { fn bitor(self, other: i64) -> i64 { self | other } } -``` - -### `std::ops::{ Shl, Shr }` - -```rust title="shl-trait" showLineNumbers -trait Shl { - fn shl(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L127-L131 - -```rust title="shr-trait" showLineNumbers -trait Shr { - fn shr(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L142-L146 - - -Traits for a bit shift left and bit shift right. - -Implementing `Shl` for a type allows the left shift operator (`<<`) to be used with the implementation type. -Similarly, implementing `Shr` allows the right shift operator (`>>`) to be used with the type. - -Note that bit shifting is not currently implemented for signed types. - -The implementations block below is given for the `Shl` trait, but the same types that implement -`Shl` also implement `Shr`. - -Implementations: -```rust -impl Shl for u8 { fn shl(self, other: u8) -> u8 { self << other } } -impl Shl for u16 { fn shl(self, other: u16) -> u16 { self << other } } -impl Shl for u32 { fn shl(self, other: u32) -> u32 { self << other } } -impl Shl for u64 { fn shl(self, other: u64) -> u64 { self << other } } -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/zeroed.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/zeroed.md deleted file mode 100644 index 97dab02dac2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/zeroed.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: Zeroed Function -description: - The zeroed function returns a zeroed value of any type. -keywords: - [ - zeroed - ] ---- - -Implements `fn zeroed() -> T` to return a zeroed value of any type. This function is generally unsafe to use as the zeroed bit pattern is not guaranteed to be valid for all types. It can however, be useful in cases when the value is guaranteed not to be used such as in a BoundedVec library implementing a growable vector, up to a certain length, backed by an array. The array can be initialized with zeroed values which are guaranteed to be inaccessible until the vector is pushed to. Similarly, enumerations in noir can be implemented using this method by providing zeroed values for the unused variants. - -You can access the function at `std::unsafe::zeroed`. - -This function currently supports the following types: - -- Field -- Bool -- Uint -- Array -- String -- Tuple -- Function - -Using it on other types could result in unexpected behavior. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/.nojekyll deleted file mode 100644 index e2ac6616add..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md deleted file mode 100644 index d60940df3ea..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md +++ /dev/null @@ -1,127 +0,0 @@ -# BarretenbergBackend - -## Implements - -- [`Backend`](../interfaces/Backend.md) - -## Constructors - -### new BarretenbergBackend(acirCircuit, options) - -```ts -new BarretenbergBackend(acirCircuit, options): BarretenbergBackend -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `acirCircuit` | [`CompiledCircuit`](../type-aliases/CompiledCircuit.md) | -| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | - -#### Returns - -[`BarretenbergBackend`](BarretenbergBackend.md) - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`destroy`](../interfaces/Backend.md#destroy) - -#### Description - -Destroys the backend - -*** - -### generateProof() - -```ts -generateProof(compressedWitness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `compressedWitness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Description - -Generates a proof - -*** - -### generateRecursiveProofArtifacts() - -```ts -generateRecursiveProofArtifacts(proofData, numOfPublicInputs): Promise -``` - -Generates artifacts that will be passed to a circuit that will verify this proof. - -Instead of passing the proof and verification key as a byte array, we pass them -as fields which makes it cheaper to verify in a circuit. - -The proof that is passed here will have been created using a circuit -that has the #[recursive] attribute on its `main` method. - -The number of public inputs denotes how many public inputs are in the inner proof. - -#### Parameters - -| Parameter | Type | Default value | -| :------ | :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | `undefined` | -| `numOfPublicInputs` | `number` | `0` | - -#### Returns - -`Promise`\<`object`\> - -#### Example - -```typescript -const artifacts = await backend.generateRecursiveProofArtifacts(proof, numOfPublicInputs); -``` - -*** - -### verifyProof() - -```ts -verifyProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Verifies a proof - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/index.md deleted file mode 100644 index e32501acb71..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/index.md +++ /dev/null @@ -1,46 +0,0 @@ -# backend_barretenberg - -## Exports - -### Classes - -| Class | Description | -| :------ | :------ | -| [BarretenbergBackend](classes/BarretenbergBackend.md) | - | - -### Interfaces - -| Interface | Description | -| :------ | :------ | -| [Backend](interfaces/Backend.md) | - | - -### Type Aliases - -| Type alias | Description | -| :------ | :------ | -| [BackendOptions](type-aliases/BackendOptions.md) | - | -| [CompiledCircuit](type-aliases/CompiledCircuit.md) | - | -| [ProofData](type-aliases/ProofData.md) | - | - -## Functions - -### publicInputsToWitnessMap() - -```ts -publicInputsToWitnessMap(publicInputs, abi): WitnessMap -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `publicInputs` | `string`[] | -| `abi` | `Abi` | - -#### Returns - -`WitnessMap` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/interfaces/Backend.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/interfaces/Backend.md deleted file mode 100644 index 3eb9645c8d2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/interfaces/Backend.md +++ /dev/null @@ -1,132 +0,0 @@ -# Backend - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Description - -Destroys the backend - -*** - -### generateFinalProof() - -```ts -generateFinalProof(decompressedWitness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `decompressedWitness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Description - -Generates a final proof (not meant to be verified in another circuit) - -*** - -### generateIntermediateProof() - -```ts -generateIntermediateProof(decompressedWitness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `decompressedWitness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Description - -Generates an intermediate proof (meant to be verified in another circuit) - -*** - -### generateIntermediateProofArtifacts() - -```ts -generateIntermediateProofArtifacts(proofData, numOfPublicInputs): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | -| `numOfPublicInputs` | `number` | - -#### Returns - -`Promise`\<`object`\> - -#### Description - -Retrieves the artifacts from a proof in the Field format - -*** - -### verifyFinalProof() - -```ts -verifyFinalProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Verifies a final proof - -*** - -### verifyIntermediateProof() - -```ts -verifyIntermediateProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Verifies an intermediate proof - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit.md deleted file mode 100644 index 34e0dd04205..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit.md +++ /dev/null @@ -1,20 +0,0 @@ -# CompiledCircuit - -```ts -type CompiledCircuit: object; -``` - -## Description - -The representation of a compiled circuit - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `abi` | `Abi` | **Description**

ABI representation of the circuit | -| `bytecode` | `string` | **Description**

The bytecode of the circuit | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/type-aliases/ProofData.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/type-aliases/ProofData.md deleted file mode 100644 index 05cebbc4e94..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/type-aliases/ProofData.md +++ /dev/null @@ -1,20 +0,0 @@ -# ProofData - -```ts -type ProofData: object; -``` - -## Description - -The representation of a proof - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `proof` | `Uint8Array` | **Description**

An byte array representing the proof | -| `publicInputs` | `string`[] | **Description**

Public inputs of a proof | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs deleted file mode 100644 index 2aaa55bccf6..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend","label":"BarretenbergBackend"}]},{"type":"category","label":"Interfaces","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/interfaces/Backend","label":"Backend"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions","label":"BackendOptions"},{"type":"doc","id":"reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit","label":"CompiledCircuit"},{"type":"doc","id":"reference/NoirJS/backend_barretenberg/type-aliases/ProofData","label":"ProofData"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/.nojekyll deleted file mode 100644 index e2ac6616add..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/classes/Noir.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/classes/Noir.md deleted file mode 100644 index 421d274fff8..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/classes/Noir.md +++ /dev/null @@ -1,132 +0,0 @@ -# Noir - -## Constructors - -### new Noir(circuit, backend) - -```ts -new Noir(circuit, backend?): Noir -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `circuit` | [`CompiledCircuit`](../type-aliases/CompiledCircuit.md) | -| `backend`? | `Backend` | - -#### Returns - -[`Noir`](Noir.md) - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Description - -Destroys the underlying backend instance. - -#### Example - -```typescript -await noir.destroy(); -``` - -*** - -### execute() - -```ts -execute(inputs, foreignCallHandler?): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `inputs` | [`InputMap`](../type-aliases/InputMap.md) | -| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | - -#### Returns - -`Promise`\<`object`\> - -#### Description - -Allows to execute a circuit to get its witness and return value. - -#### Example - -```typescript -async execute(inputs) -``` - -*** - -### generateProof() - -```ts -generateProof(inputs, foreignCallHandler?): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `inputs` | [`InputMap`](../type-aliases/InputMap.md) | -| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Description - -Generates a witness and a proof given an object as input. - -#### Example - -```typescript -async generateProof(input) -``` - -*** - -### verifyProof() - -```ts -verifyProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Instantiates the verification key and verifies a proof. - -#### Example - -```typescript -async verifyProof(proof) -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/and.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/and.md deleted file mode 100644 index c783283e396..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/and.md +++ /dev/null @@ -1,22 +0,0 @@ -# and() - -```ts -and(lhs, rhs): string -``` - -Performs a bitwise AND operation between `lhs` and `rhs` - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `lhs` | `string` | | -| `rhs` | `string` | | - -## Returns - -`string` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/blake2s256.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/blake2s256.md deleted file mode 100644 index 7882d0da8d5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/blake2s256.md +++ /dev/null @@ -1,21 +0,0 @@ -# blake2s256() - -```ts -blake2s256(inputs): Uint8Array -``` - -Calculates the Blake2s256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md deleted file mode 100644 index 5e3cd53e9d3..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md +++ /dev/null @@ -1,28 +0,0 @@ -# ecdsa\_secp256k1\_verify() - -```ts -ecdsa_secp256k1_verify( - hashed_msg, - public_key_x_bytes, - public_key_y_bytes, - signature): boolean -``` - -Verifies a ECDSA signature over the secp256k1 curve. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `hashed_msg` | `Uint8Array` | | -| `public_key_x_bytes` | `Uint8Array` | | -| `public_key_y_bytes` | `Uint8Array` | | -| `signature` | `Uint8Array` | | - -## Returns - -`boolean` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md deleted file mode 100644 index 0b20ff68957..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md +++ /dev/null @@ -1,28 +0,0 @@ -# ecdsa\_secp256r1\_verify() - -```ts -ecdsa_secp256r1_verify( - hashed_msg, - public_key_x_bytes, - public_key_y_bytes, - signature): boolean -``` - -Verifies a ECDSA signature over the secp256r1 curve. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `hashed_msg` | `Uint8Array` | | -| `public_key_x_bytes` | `Uint8Array` | | -| `public_key_y_bytes` | `Uint8Array` | | -| `signature` | `Uint8Array` | | - -## Returns - -`boolean` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/keccak256.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/keccak256.md deleted file mode 100644 index d10f155ce86..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/keccak256.md +++ /dev/null @@ -1,21 +0,0 @@ -# keccak256() - -```ts -keccak256(inputs): Uint8Array -``` - -Calculates the Keccak256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/sha256.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/sha256.md deleted file mode 100644 index 6ba4ecac022..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/sha256.md +++ /dev/null @@ -1,21 +0,0 @@ -# sha256() - -```ts -sha256(inputs): Uint8Array -``` - -Calculates the SHA256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/xor.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/xor.md deleted file mode 100644 index 8d762b895d3..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/xor.md +++ /dev/null @@ -1,22 +0,0 @@ -# xor() - -```ts -xor(lhs, rhs): string -``` - -Performs a bitwise XOR operation between `lhs` and `rhs` - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `lhs` | `string` | | -| `rhs` | `string` | | - -## Returns - -`string` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/index.md deleted file mode 100644 index d600e21b299..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/index.md +++ /dev/null @@ -1,37 +0,0 @@ -# noir_js - -## Exports - -### Classes - -| Class | Description | -| :------ | :------ | -| [Noir](classes/Noir.md) | - | - -### Type Aliases - -| Type alias | Description | -| :------ | :------ | -| [CompiledCircuit](type-aliases/CompiledCircuit.md) | - | -| [ForeignCallHandler](type-aliases/ForeignCallHandler.md) | A callback which performs an foreign call and returns the response. | -| [ForeignCallInput](type-aliases/ForeignCallInput.md) | - | -| [ForeignCallOutput](type-aliases/ForeignCallOutput.md) | - | -| [InputMap](type-aliases/InputMap.md) | - | -| [ProofData](type-aliases/ProofData.md) | - | -| [WitnessMap](type-aliases/WitnessMap.md) | - | - -### Functions - -| Function | Description | -| :------ | :------ | -| [and](functions/and.md) | Performs a bitwise AND operation between `lhs` and `rhs` | -| [blake2s256](functions/blake2s256.md) | Calculates the Blake2s256 hash of the input bytes | -| [ecdsa\_secp256k1\_verify](functions/ecdsa_secp256k1_verify.md) | Verifies a ECDSA signature over the secp256k1 curve. | -| [ecdsa\_secp256r1\_verify](functions/ecdsa_secp256r1_verify.md) | Verifies a ECDSA signature over the secp256r1 curve. | -| [keccak256](functions/keccak256.md) | Calculates the Keccak256 hash of the input bytes | -| [sha256](functions/sha256.md) | Calculates the SHA256 hash of the input bytes | -| [xor](functions/xor.md) | Performs a bitwise XOR operation between `lhs` and `rhs` | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/type-aliases/CompiledCircuit.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/type-aliases/CompiledCircuit.md deleted file mode 100644 index 34e0dd04205..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/type-aliases/CompiledCircuit.md +++ /dev/null @@ -1,20 +0,0 @@ -# CompiledCircuit - -```ts -type CompiledCircuit: object; -``` - -## Description - -The representation of a compiled circuit - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `abi` | `Abi` | **Description**

ABI representation of the circuit | -| `bytecode` | `string` | **Description**

The bytecode of the circuit | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md deleted file mode 100644 index 812b8b16481..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md +++ /dev/null @@ -1,24 +0,0 @@ -# ForeignCallHandler - -```ts -type ForeignCallHandler: (name, inputs) => Promise; -``` - -A callback which performs an foreign call and returns the response. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `name` | `string` | The identifier for the type of foreign call being performed. | -| `inputs` | [`ForeignCallInput`](ForeignCallInput.md)[] | An array of hex encoded inputs to the foreign call. | - -## Returns - -`Promise`\<[`ForeignCallOutput`](ForeignCallOutput.md)[]\> - -outputs - An array of hex encoded outputs containing the results of the foreign call. - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md deleted file mode 100644 index dd95809186a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md +++ /dev/null @@ -1,9 +0,0 @@ -# ForeignCallInput - -```ts -type ForeignCallInput: string[]; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md deleted file mode 100644 index b71fb78a946..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md +++ /dev/null @@ -1,9 +0,0 @@ -# ForeignCallOutput - -```ts -type ForeignCallOutput: string | string[]; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/type-aliases/InputMap.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/type-aliases/InputMap.md deleted file mode 100644 index c714e999d93..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/type-aliases/InputMap.md +++ /dev/null @@ -1,13 +0,0 @@ -# InputMap - -```ts -type InputMap: object; -``` - -## Index signature - - \[`key`: `string`\]: `InputValue` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/type-aliases/ProofData.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/type-aliases/ProofData.md deleted file mode 100644 index 05cebbc4e94..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/type-aliases/ProofData.md +++ /dev/null @@ -1,20 +0,0 @@ -# ProofData - -```ts -type ProofData: object; -``` - -## Description - -The representation of a proof - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `proof` | `Uint8Array` | **Description**

An byte array representing the proof | -| `publicInputs` | `string`[] | **Description**

Public inputs of a proof | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md deleted file mode 100644 index 258c46f9d0c..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md +++ /dev/null @@ -1,9 +0,0 @@ -# WitnessMap - -```ts -type WitnessMap: Map; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs deleted file mode 100644 index fe2629ddc9f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/noir_js/classes/Noir","label":"Noir"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/CompiledCircuit","label":"CompiledCircuit"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallHandler","label":"ForeignCallHandler"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallInput","label":"ForeignCallInput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallOutput","label":"ForeignCallOutput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/InputMap","label":"InputMap"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ProofData","label":"ProofData"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/WitnessMap","label":"WitnessMap"}]},{"type":"category","label":"Functions","items":[{"type":"doc","id":"reference/NoirJS/noir_js/functions/and","label":"and"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/blake2s256","label":"blake2s256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify","label":"ecdsa_secp256k1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify","label":"ecdsa_secp256r1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/keccak256","label":"keccak256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/sha256","label":"sha256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/xor","label":"xor"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_wasm/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_wasm/.nojekyll deleted file mode 100644 index e2ac6616add..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_wasm/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_wasm/functions/createFileManager.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_wasm/functions/createFileManager.md deleted file mode 100644 index 7e65c1d69c7..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_wasm/functions/createFileManager.md +++ /dev/null @@ -1,21 +0,0 @@ -# createFileManager() - -```ts -createFileManager(dataDir): FileManager -``` - -Creates a new FileManager instance based on fs in node and memfs in the browser (via webpack alias) - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `dataDir` | `string` | root of the file system | - -## Returns - -`FileManager` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md deleted file mode 100644 index fcea9275341..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md +++ /dev/null @@ -1,21 +0,0 @@ -# inflateDebugSymbols() - -```ts -inflateDebugSymbols(debugSymbols): any -``` - -Decompresses and decodes the debug symbols - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `debugSymbols` | `string` | The base64 encoded debug symbols | - -## Returns - -`any` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/_category_.json deleted file mode 100644 index 5b6a20a609a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 4, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/nargo_commands.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/nargo_commands.md deleted file mode 100644 index 8a309ef4e7e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/nargo_commands.md +++ /dev/null @@ -1,380 +0,0 @@ ---- -title: Nargo -description: - Noir CLI Commands for Noir Prover and Verifier to create, execute, prove and verify programs, - generate Solidity verifier smart contract and compile into JSON file containing ACIR - representation and ABI of circuit. -keywords: - [ - Nargo, - Noir CLI, - Noir Prover, - Noir Verifier, - generate Solidity verifier, - compile JSON file, - ACIR representation, - ABI of circuit, - TypeScript, - ] -sidebar_position: 0 ---- - -# Command-Line Help for `nargo` - -This document contains the help content for the `nargo` command-line program. - -**Command Overview:** - -* [`nargo`↴](#nargo) -* [`nargo backend`↴](#nargo-backend) -* [`nargo backend current`↴](#nargo-backend-current) -* [`nargo backend ls`↴](#nargo-backend-ls) -* [`nargo backend use`↴](#nargo-backend-use) -* [`nargo backend install`↴](#nargo-backend-install) -* [`nargo backend uninstall`↴](#nargo-backend-uninstall) -* [`nargo check`↴](#nargo-check) -* [`nargo fmt`↴](#nargo-fmt) -* [`nargo codegen-verifier`↴](#nargo-codegen-verifier) -* [`nargo compile`↴](#nargo-compile) -* [`nargo new`↴](#nargo-new) -* [`nargo init`↴](#nargo-init) -* [`nargo execute`↴](#nargo-execute) -* [`nargo prove`↴](#nargo-prove) -* [`nargo verify`↴](#nargo-verify) -* [`nargo test`↴](#nargo-test) -* [`nargo info`↴](#nargo-info) -* [`nargo lsp`↴](#nargo-lsp) - -## `nargo` - -Noir's package manager - -**Usage:** `nargo ` - -###### **Subcommands:** - -* `backend` — Install and select custom backends used to generate and verify proofs -* `check` — Checks the constraint system for errors -* `fmt` — Format the Noir files in a workspace -* `codegen-verifier` — Generates a Solidity verifier smart contract for the program -* `compile` — Compile the program and its secret execution trace into ACIR format -* `new` — Create a Noir project in a new directory -* `init` — Create a Noir project in the current directory -* `execute` — Executes a circuit to calculate its return value -* `prove` — Create proof for this program. The proof is returned as a hex encoded string -* `verify` — Given a proof and a program, verify whether the proof is valid -* `test` — Run the tests for this program -* `info` — Provides detailed information on a circuit -* `lsp` — Starts the Noir LSP server - -###### **Options:** - - - - -## `nargo backend` - -Install and select custom backends used to generate and verify proofs - -**Usage:** `nargo backend ` - -###### **Subcommands:** - -* `current` — Prints the name of the currently active backend -* `ls` — Prints the list of currently installed backends -* `use` — Select the backend to use -* `install` — Install a new backend from a URL -* `uninstall` — Uninstalls a backend - - - -## `nargo backend current` - -Prints the name of the currently active backend - -**Usage:** `nargo backend current` - - - -## `nargo backend ls` - -Prints the list of currently installed backends - -**Usage:** `nargo backend ls` - - - -## `nargo backend use` - -Select the backend to use - -**Usage:** `nargo backend use ` - -###### **Arguments:** - -* `` - - - -## `nargo backend install` - -Install a new backend from a URL - -**Usage:** `nargo backend install ` - -###### **Arguments:** - -* `` — The name of the backend to install -* `` — The URL from which to download the backend - - - -## `nargo backend uninstall` - -Uninstalls a backend - -**Usage:** `nargo backend uninstall ` - -###### **Arguments:** - -* `` — The name of the backend to uninstall - - - -## `nargo check` - -Checks the constraint system for errors - -**Usage:** `nargo check [OPTIONS]` - -###### **Options:** - -* `--package ` — The name of the package to check -* `--workspace` — Check all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings - - - -## `nargo fmt` - -Format the Noir files in a workspace - -**Usage:** `nargo fmt [OPTIONS]` - -###### **Options:** - -* `--check` — Run noirfmt in check mode - - - -## `nargo codegen-verifier` - -Generates a Solidity verifier smart contract for the program - -**Usage:** `nargo codegen-verifier [OPTIONS]` - -###### **Options:** - -* `--package ` — The name of the package to codegen -* `--workspace` — Codegen all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings - - - -## `nargo compile` - -Compile the program and its secret execution trace into ACIR format - -**Usage:** `nargo compile [OPTIONS]` - -###### **Options:** - -* `--package ` — The name of the package to compile -* `--workspace` — Compile all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings - - - -## `nargo new` - -Create a Noir project in a new directory - -**Usage:** `nargo new [OPTIONS] ` - -###### **Arguments:** - -* `` — The path to save the new project - -###### **Options:** - -* `--name ` — Name of the package [default: package directory name] -* `--lib` — Use a library template -* `--bin` — Use a binary template [default] -* `--contract` — Use a contract template - - - -## `nargo init` - -Create a Noir project in the current directory - -**Usage:** `nargo init [OPTIONS]` - -###### **Options:** - -* `--name ` — Name of the package [default: current directory name] -* `--lib` — Use a library template -* `--bin` — Use a binary template [default] -* `--contract` — Use a contract template - - - -## `nargo execute` - -Executes a circuit to calculate its return value - -**Usage:** `nargo execute [OPTIONS] [WITNESS_NAME]` - -###### **Arguments:** - -* `` — Write the execution witness to named file - -###### **Options:** - -* `-p`, `--prover-name ` — The name of the toml file which contains the inputs for the prover - - Default value: `Prover` -* `--package ` — The name of the package to execute -* `--workspace` — Execute all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings -* `--oracle-resolver ` — JSON RPC url to solve oracle calls - - - -## `nargo prove` - -Create proof for this program. The proof is returned as a hex encoded string - -**Usage:** `nargo prove [OPTIONS]` - -###### **Options:** - -* `-p`, `--prover-name ` — The name of the toml file which contains the inputs for the prover - - Default value: `Prover` -* `-v`, `--verifier-name ` — The name of the toml file which contains the inputs for the verifier - - Default value: `Verifier` -* `--verify` — Verify proof after proving -* `--package ` — The name of the package to prove -* `--workspace` — Prove all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings -* `--oracle-resolver ` — JSON RPC url to solve oracle calls - - - -## `nargo verify` - -Given a proof and a program, verify whether the proof is valid - -**Usage:** `nargo verify [OPTIONS]` - -###### **Options:** - -* `-v`, `--verifier-name ` — The name of the toml file which contains the inputs for the verifier - - Default value: `Verifier` -* `--package ` — The name of the package verify -* `--workspace` — Verify all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings - - - -## `nargo test` - -Run the tests for this program - -**Usage:** `nargo test [OPTIONS] [TEST_NAME]` - -###### **Arguments:** - -* `` — If given, only tests with names containing this string will be run - -###### **Options:** - -* `--show-output` — Display output of `println` statements -* `--exact` — Only run tests that match exactly -* `--package ` — The name of the package to test -* `--workspace` — Test all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings -* `--oracle-resolver ` — JSON RPC url to solve oracle calls - - - -## `nargo info` - -Provides detailed information on a circuit - -Current information provided: 1. The number of ACIR opcodes 2. Counts the final number gates in the circuit used by a backend - -**Usage:** `nargo info [OPTIONS]` - -###### **Options:** - -* `--package ` — The name of the package to detail -* `--workspace` — Detail all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings - - - -## `nargo lsp` - -Starts the Noir LSP server - -Starts an LSP server which allows IDEs such as VS Code to display diagnostics in Noir source. - -VS Code Noir Language Support: https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir - -**Usage:** `nargo lsp` - - - -
- - - This document was generated automatically by - clap-markdown. - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/tutorials/noirjs_app.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/tutorials/noirjs_app.md deleted file mode 100644 index 0cea72314ce..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/tutorials/noirjs_app.md +++ /dev/null @@ -1,324 +0,0 @@ ---- -title: Building a web app with NoirJS -description: Learn how to setup a new app that uses Noir to generate and verify zero-knowledge SNARK proofs in a typescript or javascript environment. -keywords: [how to, guide, javascript, typescript, noir, barretenberg, zero-knowledge, proofs, app] -sidebar_position: 0 -pagination_next: noir/concepts/data_types/index ---- - -NoirJS is a set of packages meant to work both in a browser and a server environment. In this tutorial, we will build a simple web app using them. From here, you should get an idea on how to proceed with your own Noir projects! - -You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). - -## Setup - -:::note - -Feel free to use whatever versions, just keep in mind that Nargo and the NoirJS packages are meant to be in sync. For example, Nargo 0.25.x matches `noir_js@0.25.x`, etc. - -In this guide, we will be pinned to 0.25.0. - -::: - -Before we start, we want to make sure we have Node and Nargo installed. - -We start by opening a terminal and executing `node --version`. If we don't get an output like `v20.10.0`, that means node is not installed. Let's do that by following the handy [nvm guide](https://github.com/nvm-sh/nvm?tab=readme-ov-file#install--update-script). - -As for `Nargo`, we can follow the [Nargo guide](../getting_started/installation/index.md) to install it. If you're lazy, just paste this on a terminal and run `noirup`: - -```sh -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -Easy enough. Onwards! - -## Our project - -ZK is a powerful technology. An app that doesn't reveal one of the inputs to _anyone_ is almost unbelievable, yet Noir makes it as easy as a single line of code. - -In fact, it's so simple that it comes nicely packaged in `nargo`. Let's do that! - -### Nargo - -Run: - -`nargo new circuit` - -And... That's about it. Your program is ready to be compiled and run. - -To compile, let's `cd` into the `circuit` folder to enter our project, and call: - -`nargo compile` - -This compiles our circuit into `json` format and add it to a new `target` folder. - -:::info - -At this point in the tutorial, your folder structure should look like this: - -```tree -. -└── circuit <---- our working directory - ├── Nargo.toml - ├── src - │ └── main.nr - └── target - └── circuit.json -``` - -::: - -### Node and Vite - -If you want to explore Nargo, feel free to go on a side-quest now and follow the steps in the -[getting started](../getting_started/hello_noir/index.md) guide. However, we want our app to run on the browser, so we need Vite. - -Vite is a powerful tool to generate static websites. While it provides all kinds of features, let's just go barebones with some good old vanilla JS. - -To do this this, go back to the previous folder (`cd ..`) and create a new vite project by running `npm create vite` and choosing "Vanilla" and "Javascript". - -A wild `vite-project` directory should now appear in your root folder! Let's not waste any time and dive right in: - -```bash -cd vite-project -``` - -### Setting Up Vite and Configuring the Project - -Before we proceed with any coding, let's get our environment tailored for Noir. We'll start by laying down the foundations with a `vite.config.js` file. This little piece of configuration is our secret sauce for making sure everything meshes well with the NoirJS libraries and other special setups we might need, like handling WebAssembly modules. Here’s how you get that going: - -#### Creating the vite.config.js - -In your freshly minted `vite-project` folder, create a new file named `vite.config.js` and open it in your code editor. Paste the following to set the stage: - -```javascript -import { defineConfig } from "vite"; -import copy from "rollup-plugin-copy"; - -export default defineConfig({ - esbuild: { - target: "esnext", - }, - optimizeDeps: { - esbuildOptions: { - target: "esnext", - }, - }, - plugins: [ - copy({ - targets: [ - { src: "node_modules/**/*.wasm", dest: "node_modules/.vite/dist" }, - ], - copySync: true, - hook: "buildStart", - }), - ], - server: { - port: 3000, - }, -}); -``` - -#### Install Dependencies - -Now that our stage is set, install the necessary NoirJS packages along with our other dependencies: - -```bash -npm install && npm install @noir-lang/backend_barretenberg@0.25.0 @noir-lang/noir_js@0.25.0 -npm install rollup-plugin-copy --save-dev -``` - -:::info - -At this point in the tutorial, your folder structure should look like this: - -```tree -. -└── circuit - └── ...etc... -└── vite-project <---- our working directory - └── ...etc... -``` - -::: - -#### Some cleanup - -`npx create vite` is amazing but it creates a bunch of files we don't really need for our simple example. Actually, let's just delete everything except for `vite.config.js`, `index.html`, `main.js` and `package.json`. I feel lighter already. - -![my heart is ready for you, noir.js](@site/static/img/memes/titanic.jpeg) - -## HTML - -Our app won't run like this, of course. We need some working HTML, at least. Let's open our broken-hearted `index.html` and replace everything with this code snippet: - -```html - - - - - - -

Noir app

-
- - -
-
-

Logs

-

Proof

-
- - -``` - -It _could_ be a beautiful UI... Depending on which universe you live in. - -## Some good old vanilla Javascript - -Our love for Noir needs undivided attention, so let's just open `main.js` and delete everything (this is where the romantic scenery becomes a bit creepy). - -Start by pasting in this boilerplate code: - -```js -const setup = async () => { - await Promise.all([ - import('@noir-lang/noirc_abi').then((module) => - module.default(new URL('@noir-lang/noirc_abi/web/noirc_abi_wasm_bg.wasm', import.meta.url).toString()), - ), - import('@noir-lang/acvm_js').then((module) => - module.default(new URL('@noir-lang/acvm_js/web/acvm_js_bg.wasm', import.meta.url).toString()), - ), - ]); -}; - -function display(container, msg) { - const c = document.getElementById(container); - const p = document.createElement('p'); - p.textContent = msg; - c.appendChild(p); -} - -document.getElementById('submitGuess').addEventListener('click', async () => { - try { - // here's where love happens - } catch (err) { - display('logs', 'Oh 💔 Wrong guess'); - } -}); -``` - -The display function doesn't do much. We're simply manipulating our website to see stuff happening. For example, if the proof fails, it will simply log a broken heart 😢 - -As for the `setup` function, it's just a sad reminder that dealing with `wasm` on the browser is not as easy as it should. Just copy, paste, and forget. - -:::info - -At this point in the tutorial, your folder structure should look like this: - -```tree -. -└── circuit - └── ...same as above -└── vite-project - └── vite.config.js - ├── main.js - ├── package.json - └── index.html -``` - -You'll see other files and folders showing up (like `package-lock.json`, `node_modules`) but you shouldn't have to care about those. - -::: - -## Some NoirJS - -We're starting with the good stuff now. If you've compiled the circuit as described above, you should have a `json` file we want to import at the very top of our `main.js` file: - -```ts -import circuit from '../circuit/target/circuit.json'; -``` - -[Noir is backend-agnostic](../index.mdx#whats-new-about-noir). We write Noir, but we also need a proving backend. That's why we need to import and instantiate the two dependencies we installed above: `BarretenbergBackend` and `Noir`. Let's import them right below: - -```js -import { BarretenbergBackend } from '@noir-lang/backend_barretenberg'; -import { Noir } from '@noir-lang/noir_js'; -``` - -And instantiate them inside our try-catch block: - -```ts -// try { -const backend = new BarretenbergBackend(circuit); -const noir = new Noir(circuit, backend); -// } -``` - -:::note - -For the remainder of the tutorial, everything will be happening inside the `try` block - -::: - -## Our app - -Now for the app itself. We're capturing whatever is in the input when people press the submit button. Just add this: - -```js -const x = parseInt(document.getElementById('guessInput').value); -const input = { x, y: 2 }; -``` - -Now we're ready to prove stuff! Let's feed some inputs to our circuit and calculate the proof: - -```js -await setup(); // let's squeeze our wasm inits here - -display('logs', 'Generating proof... ⌛'); -const proof = await noir.generateProof(input); -display('logs', 'Generating proof... ✅'); -display('results', proof.proof); -``` - -You're probably eager to see stuff happening, so go and run your app now! - -From your terminal, run `npm run dev`. If it doesn't open a browser for you, just visit `localhost:5173`. You should now see the worst UI ever, with an ugly input. - -![Getting Started 0](@site/static/img/noir_getting_started_1.png) - -Now, our circuit says `fn main(x: Field, y: pub Field)`. This means only the `y` value is public, and it's hardcoded above: `input = { x, y: 2 }`. In other words, you won't need to send your secret`x` to the verifier! - -By inputting any number other than 2 in the input box and clicking "submit", you should get a valid proof. Otherwise the proof won't even generate correctly. By the way, if you're human, you shouldn't be able to understand anything on the "proof" box. That's OK. We like you, human ❤️. - -## Verifying - -Time to celebrate, yes! But we shouldn't trust machines so blindly. Let's add these lines to see our proof being verified: - -```js -display('logs', 'Verifying proof... ⌛'); -const verification = await noir.verifyProof(proof); -if (verification) display('logs', 'Verifying proof... ✅'); -``` - -You have successfully generated a client-side Noir web app! - -![coded app without math knowledge](@site/static/img/memes/flextape.jpeg) - -## Further Reading - -You can see how noirjs is used in a full stack Next.js hardhat application in the [noir-starter repo here](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat). The example shows how to calculate a proof in the browser and verify it with a deployed Solidity verifier contract from noirjs. - -You should also check out the more advanced examples in the [noir-examples repo](https://github.com/noir-lang/noir-examples), where you'll find reference usage for some cool apps. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/explainers/explainer-oracle.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/explainers/explainer-oracle.md deleted file mode 100644 index b84ca5dd986..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/explainers/explainer-oracle.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: Oracles -description: This guide provides an in-depth understanding of how Oracles work in Noir programming. Learn how to use outside calculations in your programs, constrain oracles, and understand their uses and limitations. -keywords: - - Noir Programming - - Oracles - - JSON-RPC - - Foreign Call Handlers - - Constrained Functions - - Blockchain Programming -sidebar_position: 1 ---- - -If you've seen "The Matrix" you may recall "The Oracle" as Gloria Foster smoking cigarettes and baking cookies. While she appears to "know things", she is actually providing a calculation of a pre-determined future. Noir Oracles are similar, in a way. They don't calculate the future (yet), but they allow you to use outside calculations in your programs. - -![matrix oracle prediction](@site/static/img/memes/matrix_oracle.jpeg) - -A Noir program is usually self-contained. You can pass certain inputs to it, and it will generate a deterministic output for those inputs. But what if you wanted to defer some calculation to an outside process or source? - -Oracles are functions that provide this feature. - -## Use cases - -An example usage for Oracles is proving something on-chain. For example, proving that the ETH-USDC quote was below a certain target at a certain block time. Or even making more complex proofs like proving the ownership of an NFT as an anonymous login method. - -Another interesting use case is to defer expensive calculations to be made outside of the Noir program, and then constraining the result; similar to the use of [unconstrained functions](../noir/concepts//unconstrained.md). - -In short, anything that can be constrained in a Noir program but needs to be fetched from an external source is a great candidate to be used in oracles. - -## Constraining oracles - -Just like in The Matrix, Oracles are powerful. But with great power, comes great responsibility. Just because you're using them in a Noir program doesn't mean they're true. Noir has no superpowers. If you want to prove that Portugal won the Euro Cup 2016, you're still relying on potentially untrusted information. - -To give a concrete example, Alice wants to login to the [NounsDAO](https://nouns.wtf/) forum with her username "noir_nouner" by proving she owns a noun without revealing her ethereum address. Her Noir program could have a oracle call like this: - -```rust -#[oracle(getNoun)] -unconstrained fn get_noun(address: Field) -> Field -``` - -This oracle could naively resolve with the number of Nouns she possesses. However, it is useless as a trusted source, as the oracle could resolve to anything Alice wants. In order to make this oracle call actually useful, Alice would need to constrain the response from the oracle, by proving her address and the noun count belongs to the state tree of the contract. - -In short, **Oracles don't prove anything. Your Noir program does.** - -:::danger - -If you don't constrain the return of your oracle, you could be clearly opening an attack vector on your Noir program. Make double-triple sure that the return of an oracle call is constrained! - -::: - -## How to use Oracles - -On CLI, Nargo resolves oracles by making JSON RPC calls, which means it would require an RPC node to be running. - -In JavaScript, NoirJS accepts and resolves arbitrary call handlers (that is, not limited to JSON) as long as they matches the expected types the developer defines. Refer to [Foreign Call Handler](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) to learn more about NoirJS's call handling. - -If you want to build using oracles, follow through to the [oracle guide](../how_to/how-to-oracles.md) for a simple example on how to do that. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/explainers/explainer-recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/explainers/explainer-recursion.md deleted file mode 100644 index 18846176ca7..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/explainers/explainer-recursion.md +++ /dev/null @@ -1,176 +0,0 @@ ---- -title: Recursive proofs -description: Explore the concept of recursive proofs in Zero-Knowledge programming. Understand how recursion works in Noir, a language for writing smart contracts on the EVM blockchain. Learn through practical examples like Alice and Bob's guessing game, Charlie's recursive merkle tree, and Daniel's reusable components. Discover how to use recursive proofs to optimize computational resources and improve efficiency. - -keywords: - [ - "Recursive Proofs", - "Zero-Knowledge Programming", - "Noir", - "EVM Blockchain", - "Smart Contracts", - "Recursion in Noir", - "Alice and Bob Guessing Game", - "Recursive Merkle Tree", - "Reusable Components", - "Optimizing Computational Resources", - "Improving Efficiency", - "Verification Key", - "Aggregation", - "Recursive zkSNARK schemes", - "PLONK", - "Proving and Verification Keys" - ] -sidebar_position: 1 -pagination_next: how_to/how-to-recursion ---- - -In programming, we tend to think of recursion as something calling itself. A classic example would be the calculation of the factorial of a number: - -```js -function factorial(n) { - if (n === 0 || n === 1) { - return 1; - } else { - return n * factorial(n - 1); - } -} -``` - -In this case, while `n` is not `1`, this function will keep calling itself until it hits the base case, bubbling up the result on the call stack: - -```md - Is `n` 1? <--------- - /\ / - / \ n = n -1 - / \ / - Yes No -------- -``` - -In Zero-Knowledge, recursion has some similarities. - -It is not a Noir function calling itself, but a proof being used as an input to another circuit. In short, you verify one proof *inside* another proof, returning the proof that both proofs are valid. - -This means that, given enough computational resources, you can prove the correctness of any arbitrary number of proofs in a single proof. This could be useful to design state channels (for which a common example would be [Bitcoin's Lightning Network](https://en.wikipedia.org/wiki/Lightning_Network)), to save on gas costs by settling one proof on-chain, or simply to make business logic less dependent on a consensus mechanism. - -## Examples - -Let us look at some of these examples - -### Alice and Bob - Guessing game - -Alice and Bob are friends, and they like guessing games. They want to play a guessing game online, but for that, they need a trusted third-party that knows both of their secrets and finishes the game once someone wins. - -So, they use zero-knowledge proofs. Alice tries to guess Bob's number, and Bob will generate a ZK proof stating whether she succeeded or failed. - -This ZK proof can go on a smart contract, revealing the winner and even giving prizes. However, this means every turn needs to be verified on-chain. This incurs some cost and waiting time that may simply make the game too expensive or time-consuming to be worth it. - -As a solution, Alice proposes the following: "what if Bob generates his proof, and instead of sending it on-chain, I verify it *within* my own proof before playing my own turn?". - -She can then generate a proof that she verified his proof, and so on. - -```md - Did you fail? <-------------------------- - / \ / - / \ n = n -1 - / \ / - Yes No / - | | / - | | / - | You win / - | / - | / -Generate proof of that / - + / - my own guess ---------------- -``` - -### Charlie - Recursive merkle tree - -Charlie is a concerned citizen, and wants to be sure his vote in an election is accounted for. He votes with a ZK proof, but he has no way of knowing that his ZK proof was included in the total vote count! - -If the vote collector puts all of the votes into a [Merkle tree](https://en.wikipedia.org/wiki/Merkle_tree), everyone can prove the verification of two proofs within one proof, as such: - -```md - abcd - __________|______________ - | | - ab cd - _____|_____ ______|______ - | | | | - alice bob charlie daniel -``` - -Doing this recursively allows us to arrive on a final proof `abcd` which if true, verifies the correctness of all the votes. - -### Daniel - Reusable components - -Daniel has a big circuit and a big headache. A part of his circuit is a setup phase that finishes with some assertions that need to be made. But that section alone takes most of the proving time, and is largely independent of the rest of the circuit. - -He might find it more efficient to generate a proof for that setup phase separately, and verify that proof recursively in the actual business logic section of his circuit. This will allow for parallelization of both proofs, which results in a considerable speedup. - -## What params do I need - -As you can see in the [recursion reference](noir/standard_library/recursion.md), a simple recursive proof requires: - -- The proof to verify -- The Verification Key of the circuit that generated the proof -- A hash of this verification key, as it's needed for some backends -- The public inputs for the proof - -:::info - -Recursive zkSNARK schemes do not necessarily "verify a proof" in the sense that you expect a true or false to be spit out by the verifier. Rather an aggregation object is built over the public inputs. - -So, taking the example of Alice and Bob and their guessing game: - -- Alice makes her guess. Her proof is *not* recursive: it doesn't verify any proof within it! It's just a standard `assert(x != y)` circuit -- Bob verifies Alice's proof and makes his own guess. In this circuit, he doesn't exactly *prove* the verification of Alice's proof. Instead, he *aggregates* his proof to Alice's proof. The actual verification is done when the full proof is verified, for example when using `nargo verify` or through the verifier smart contract. - -We can imagine recursive proofs a [relay race](https://en.wikipedia.org/wiki/Relay_race). The first runner doesn't have to receive the baton from anyone else, as he/she already starts with it. But when his/her turn is over, the next runner needs to receive it, run a bit more, and pass it along. Even though every runner could theoretically verify the baton mid-run (why not? 🏃🔍), only at the end of the race does the referee verify that the whole race is valid. - -::: - -## Some architecture - -As with everything in computer science, there's no one-size-fits all. But there are some patterns that could help understanding and implementing them. To give three examples: - -### Adding some logic to a proof verification - -This would be an approach for something like our guessing game, where proofs are sent back and forth and are verified by each opponent. This circuit would be divided in two sections: - -- A `recursive verification` section, which would be just the call to `std::verify_proof`, and that would be skipped on the first move (since there's no proof to verify) -- A `guessing` section, which is basically the logic part where the actual guessing happens - -In such a situation, and assuming Alice is first, she would skip the first part and try to guess Bob's number. Bob would then verify her proof on the first section of his run, and try to guess Alice's number on the second part, and so on. - -### Aggregating proofs - -In some one-way interaction situations, recursion would allow for aggregation of simple proofs that don't need to be immediately verified on-chain or elsewhere. - -To give a practical example, a barman wouldn't need to verify a "proof-of-age" on-chain every time he serves alcohol to a customer. Instead, the architecture would comprise two circuits: - -- A `main`, non-recursive circuit with some logic -- A `recursive` circuit meant to verify two proofs in one proof - -The customer's proofs would be intermediate, and made on their phones, and the barman could just verify them locally. He would then aggregate them into a final proof sent on-chain (or elsewhere) at the end of the day. - -### Recursively verifying different circuits - -Nothing prevents you from verifying different circuits in a recursive proof, for example: - -- A `circuit1` circuit -- A `circuit2` circuit -- A `recursive` circuit - -In this example, a regulator could verify that taxes were paid for a specific purchase by aggregating both a `payer` circuit (proving that a purchase was made and taxes were paid), and a `receipt` circuit (proving that the payment was received) - -## How fast is it - -At the time of writing, verifying recursive proofs is surprisingly fast. This is because most of the time is spent on generating the verification key that will be used to generate the next proof. So you are able to cache the verification key and reuse it later. - -Currently, Noir JS packages don't expose the functionality of loading proving and verification keys, but that feature exists in the underlying `bb.js` package. - -## How can I try it - -Learn more about using recursion in Nargo and NoirJS in the [how-to guide](../how_to/how-to-recursion.md) and see a full example in [noir-examples](https://github.com/noir-lang/noir-examples). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/_category_.json deleted file mode 100644 index 5d694210bbf..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 0, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/hello_noir/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/hello_noir/_category_.json deleted file mode 100644 index 23b560f610b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/hello_noir/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 1, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/hello_noir/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/hello_noir/index.md deleted file mode 100644 index 743c4d8d634..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/hello_noir/index.md +++ /dev/null @@ -1,142 +0,0 @@ ---- -title: Creating a Project -description: - Learn how to create and verify your first Noir program using Nargo, a programming language for - zero-knowledge proofs. -keywords: - [ - Nargo, - Noir, - zero-knowledge proofs, - programming language, - create Noir program, - verify Noir program, - step-by-step guide, - ] -sidebar_position: 1 - ---- - -Now that we have installed Nargo, it is time to make our first hello world program! - -## Create a Project Directory - -Noir code can live anywhere on your computer. Let us create a _projects_ folder in the home -directory to house our Noir programs. - -For Linux, macOS, and Windows PowerShell, create the directory and change directory into it by -running: - -```sh -mkdir ~/projects -cd ~/projects -``` - -## Create Our First Nargo Project - -Now that we are in the projects directory, create a new Nargo project by running: - -```sh -nargo new hello_world -``` - -> **Note:** `hello_world` can be any arbitrary project name, we are simply using `hello_world` for -> demonstration. -> -> In production, the common practice is to name the project folder as `circuits` for better -> identifiability when sitting alongside other folders in the codebase (e.g. `contracts`, `scripts`, -> `test`). - -A `hello_world` folder would be created. Similar to Rust, the folder houses _src/main.nr_ and -_Nargo.toml_ which contain the source code and environmental options of your Noir program -respectively. - -### Intro to Noir Syntax - -Let us take a closer look at _main.nr_. The default _main.nr_ generated should look like this: - -```rust -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` - -The first line of the program specifies the program's inputs: - -```rust -x : Field, y : pub Field -``` - -Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the -keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](../../noir/concepts/data_types/index.md) section. - -The next line of the program specifies its body: - -```rust -assert(x != y); -``` - -The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. - -For more Noir syntax, check the [Language Concepts](../../noir/concepts/comments.md) chapter. - -## Build In/Output Files - -Change directory into _hello_world_ and build in/output files for your Noir program by running: - -```sh -cd hello_world -nargo check -``` - -Two additional files would be generated in your project directory: - -_Prover.toml_ houses input values, and _Verifier.toml_ houses public values. - -## Prove Our Noir Program - -Now that the project is set up, we can create a proof of correct execution of our Noir program. - -Fill in input values for execution in the _Prover.toml_ file. For example: - -```toml -x = "1" -y = "2" -``` - -Prove the valid execution of your Noir program: - -```sh -nargo prove -``` - -A new folder _proofs_ would then be generated in your project directory, containing the proof file -`.proof`, where the project name is defined in Nargo.toml. - -The _Verifier.toml_ file would also be updated with the public values computed from program -execution (in this case the value of `y`): - -```toml -y = "0x0000000000000000000000000000000000000000000000000000000000000002" -``` - -> **Note:** Values in _Verifier.toml_ are computed as 32-byte hex values. - -## Verify Our Noir Program - -Once a proof is generated, we can verify correct execution of our Noir program by verifying the -proof file. - -Verify your proof by running: - -```sh -nargo verify -``` - -The verification will complete in silence if it is successful. If it fails, it will log the -corresponding error instead. - -Congratulations, you have now created and verified a proof for your very first Noir program! - -In the [next section](./project_breakdown.md), we will go into more detail on each step performed. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/hello_noir/project_breakdown.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/hello_noir/project_breakdown.md deleted file mode 100644 index 6160a102c6c..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/hello_noir/project_breakdown.md +++ /dev/null @@ -1,199 +0,0 @@ ---- -title: Project Breakdown -description: - Learn about the anatomy of a Nargo project, including the purpose of the Prover and Verifier TOML - files, and how to prove and verify your program. -keywords: - [Nargo, Nargo project, Prover.toml, Verifier.toml, proof verification, private asset transfer] -sidebar_position: 2 ---- - -This section breaks down our hello world program from the previous section. We elaborate on the project -structure and what the `prove` and `verify` commands did. - -## Anatomy of a Nargo Project - -Upon creating a new project with `nargo new` and building the in/output files with `nargo check` -commands, you would get a minimal Nargo project of the following structure: - - - src - - Prover.toml - - Verifier.toml - - Nargo.toml - -The source directory _src_ holds the source code for your Noir program. By default only a _main.nr_ -file will be generated within it. - -### Prover.toml - -_Prover.toml_ is used for specifying the input values for executing and proving the program. You can specify `toml` files with different names by using the `--prover-name` or `-p` flags, see the [Prover](#provertoml) section below. Optionally you may specify expected output values for prove-time checking as well. - -### Verifier.toml - -_Verifier.toml_ contains public in/output values computed when executing the Noir program. - -### Nargo.toml - -_Nargo.toml_ contains the environmental options of your project. It contains a "package" section and a "dependencies" section. - -Example Nargo.toml: - -```toml -[package] -name = "noir_starter" -type = "bin" -authors = ["Alice"] -compiler_version = "0.9.0" -description = "Getting started with Noir" -entry = "circuit/main.nr" -license = "MIT" - -[dependencies] -ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} -``` - -Nargo.toml for a [workspace](../../noir/modules_packages_crates/workspaces.md) will look a bit different. For example: - -```toml -[workspace] -members = ["crates/a", "crates/b"] -default-member = "crates/a" -``` - -#### Package section - -The package section defines a number of fields including: - -- `name` (**required**) - the name of the package -- `type` (**required**) - can be "bin", "lib", or "contract" to specify whether its a binary, library or Aztec contract -- `authors` (optional) - authors of the project -- `compiler_version` - specifies the version of the compiler to use. This is enforced by the compiler and follow's [Rust's versioning](https://doc.rust-lang.org/cargo/reference/manifest.html#the-version-field), so a `compiler_version = 0.18.0` will enforce Nargo version 0.18.0, `compiler_version = ^0.18.0` will enforce anything above 0.18.0 but below 0.19.0, etc. For more information, see how [Rust handles these operators](https://docs.rs/semver/latest/semver/enum.Op.html) -- `description` (optional) -- `entry` (optional) - a relative filepath to use as the entry point into your package (overrides the default of `src/lib.nr` or `src/main.nr`) -- `backend` (optional) -- `license` (optional) - -#### Dependencies section - -This is where you will specify any dependencies for your project. See the [Dependencies page](../../noir/modules_packages_crates/dependencies.md) for more info. - -`./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or -verifier contract respectively. - -### main.nr - -The _main.nr_ file contains a `main` method, this method is the entry point into your Noir program. - -In our sample program, _main.nr_ looks like this: - -```rust -fn main(x : Field, y : Field) { - assert(x != y); -} -``` - -The parameters `x` and `y` can be seen as the API for the program and must be supplied by the -prover. Since neither `x` nor `y` is marked as public, the verifier does not supply any inputs, when -verifying the proof. - -The prover supplies the values for `x` and `y` in the _Prover.toml_ file. - -As for the program body, `assert` ensures that the condition to be satisfied (e.g. `x != y`) is -constrained by the proof of the execution of said program (i.e. if the condition was not met, the -verifier would reject the proof as an invalid proof). - -### Prover.toml - -The _Prover.toml_ file is a file which the prover uses to supply his witness values(both private and -public). - -In our hello world program the _Prover.toml_ file looks like this: - -```toml -x = "1" -y = "2" -``` - -When the command `nargo prove` is executed, two processes happen: - -1. Noir creates a proof that `x`, which holds the value of `1`, and `y`, which holds the value of `2`, - is not equal. This inequality constraint is due to the line `assert(x != y)`. - -2. Noir creates and stores the proof of this statement in the _proofs_ directory in a file called your-project.proof. So if your project is named "private_voting" (defined in the project Nargo.toml), the proof will be saved at `./proofs/private_voting.proof`. Opening this file will display the proof in hex format. - -#### Arrays of Structs - -The following code shows how to pass an array of structs to a Noir program to generate a proof. - -```rust -// main.nr -struct Foo { - bar: Field, - baz: Field, -} - -fn main(foos: [Foo; 3]) -> pub Field { - foos[2].bar + foos[2].baz -} -``` - -Prover.toml: - -```toml -[[foos]] # foos[0] -bar = 0 -baz = 0 - -[[foos]] # foos[1] -bar = 0 -baz = 0 - -[[foos]] # foos[2] -bar = 1 -baz = 2 -``` - -#### Custom toml files - -You can specify a `toml` file with a different name to use for proving by using the `--prover-name` or `-p` flags. - -This command looks for proof inputs in the default **Prover.toml** and generates the proof and saves it at `./proofs/.proof`: - -```bash -nargo prove -``` - -This command looks for proof inputs in the custom **OtherProver.toml** and generates proof and saves it at `./proofs/.proof`: - -```bash -nargo prove -p OtherProver -``` - -## Verifying a Proof - -When the command `nargo verify` is executed, two processes happen: - -1. Noir checks in the _proofs_ directory for a proof file with the project name (eg. test_project.proof) - -2. If that file is found, the proof's validity is checked - -> **Note:** The validity of the proof is linked to the current Noir program; if the program is -> changed and the verifier verifies the proof, it will fail because the proof is not valid for the -> _modified_ Noir program. - -In production, the prover and the verifier are usually two separate entities. A prover would -retrieve the necessary inputs, execute the Noir program, generate a proof and pass it to the -verifier. The verifier would then retrieve the public inputs, usually from external sources, and -verify the validity of the proof against it. - -Take a private asset transfer as an example: - -A person using a browser as the prover would retrieve private inputs locally (e.g. the user's private key) and -public inputs (e.g. the user's encrypted balance on-chain), compute the transfer, generate a proof -and submit it to the verifier smart contract. - -The verifier contract would then draw the user's encrypted balance directly from the blockchain and -verify the proof submitted against it. If the verification passes, additional functions in the -verifier contract could trigger (e.g. approve the asset transfer). - -Now that you understand the concepts, you'll probably want some editor feedback while you are writing more complex code. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/installation/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/installation/_category_.json deleted file mode 100644 index 0c02fb5d4d7..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/installation/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "position": 0, - "label": "Install Nargo", - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/installation/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/installation/index.md deleted file mode 100644 index 4ef86aa5914..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/installation/index.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Nargo Installation -description: - nargo is a command line tool for interacting with Noir programs. This page is a quick guide on how to install Nargo through the most common and easy method, noirup -keywords: [ - Nargo - Noir - Rust - Cargo - Noirup - Installation - Terminal Commands - Version Check - Nightlies - Specific Versions - Branches - Noirup Repository -] -pagination_next: getting_started/hello_noir/index ---- - -`nargo` is the one-stop-shop for almost everything related with Noir. The name comes from our love for Rust and its package manager `cargo`. - -With `nargo`, you can start new projects, compile, execute, prove, verify, test, generate solidity contracts, and do pretty much all that is available in Noir. - -Similarly to `rustup`, we also maintain an easy installation method that covers most machines: `noirup`. - -## Installing Noirup - -Open a terminal on your machine, and write: - -```bash -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -Close the terminal, open another one, and run - -```bash -noirup -``` - -Done. That's it. You should have the latest version working. You can check with `nargo --version`. - -You can also install nightlies, specific versions -or branches. Check out the [noirup repository](https://github.com/noir-lang/noirup) for more -information. - -Now we're ready to start working on [our first Noir program!](../hello_noir/index.md) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/tooling/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/tooling/_category_.json deleted file mode 100644 index 55804c03a71..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/tooling/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "position": 2, - "label": "Tooling", - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/tooling/index.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/tooling/index.mdx deleted file mode 100644 index ec9ccea4115..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/tooling/index.mdx +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: Tooling -Description: This section provides information about the various tools and utilities available for Noir development. It covers IDE tools, Codespaces, and community projects. -Keywords: [Noir, Development, Playground, IDE Tools, Language Service Provider, VS Code Extension, Codespaces, noir-starter, Community Projects, Awesome Noir Repository, Developer Tooling] ---- - -Noir is meant to be easy to develop with. For that reason, a number of utilities have been put together to ease the development process as much as feasible in the zero-knowledge world. - -## IDE tools - -When you install Nargo, you're also installing a Language Service Provider (LSP), which can be used by IDEs to provide syntax highlighting, codelens, warnings, and more. - -The easiest way to use these tools is by installing the [Noir VS Code extension](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). - -## Codespaces - -Some Noir repos have leveraged Codespaces in order to ease the development process. You can visit the [noir-starter](https://github.com/noir-lang/noir-starter) for an example. - - - -## GitHub Actions - -You can use `noirup` with GitHub Actions for CI/CD and automated testing. It is as simple as -installing `noirup` and running tests in your GitHub Action `yml` file. - -See the -[config file in the Noir repo](https://github.com/TomAFrench/noir-hashes/blob/master/.github/workflows/noir.yml) for an example usage. - -## Community projects - -As an open-source project, Noir has received many contributions over time. Some of them are related with developer tooling, and you can see some of them in [Awesome Noir repository](https://github.com/noir-lang/awesome-noir#dev-tools) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/tooling/language_server.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/tooling/language_server.md deleted file mode 100644 index 81e0356ef8a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/tooling/language_server.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Language Server -description: Learn about the Noir Language Server, how to install the components, and configuration that may be required. -keywords: [Nargo, Language Server, LSP, VSCode, Visual Studio Code] -sidebar_position: 0 ---- - -This section helps you install and configure the Noir Language Server. - -The Language Server Protocol (LSP) has two components, the [Server](#language-server) and the [Client](#language-client). Below we describe each in the context of Noir. - -## Language Server - -The Server component is provided by the Nargo command line tool that you installed at the beginning of this guide. -As long as Nargo is installed and you've used it to run other commands in this guide, it should be good to go! - -If you'd like to verify that the `nargo lsp` command is available, you can run `nargo --help` and look for `lsp` in the list of commands. If you see it, you're using a version of Noir with LSP support. - -## Language Client - -The Client component is usually an editor plugin that launches the Server. It communicates LSP messages between the editor and the Server. For example, when you save a file, the Client will alert the Server, so it can try to compile the project and report any errors. - -Currently, Noir provides a Language Client for Visual Studio Code via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). - -> **Note:** Noir's Language Server Protocol support currently assumes users' VSCode workspace root to be the same as users' Noir project root (i.e. where Nargo.toml lies). -> -> If LSP features seem to be missing / malfunctioning, make sure you are opening your Noir project directly (instead of as a sub-folder) in your VSCode instance. - -When your language server is running correctly and the VSCode plugin is installed, you should see handy codelens buttons for compilation, measuring circuit size, execution, and tests: - -![Compile and Execute](@site/static/img/codelens_compile_execute.png) -![Run test](@site/static/img/codelens_run_test.png) - -You should also see your tests in the `testing` panel: - -![Testing panel](@site/static/img/codelens_testing_panel.png) - -### Configuration - -- **Noir: Enable LSP** - If checked, the extension will launch the Language Server via `nargo lsp` and communicate with it. -- **Noir: Nargo Flags** - Additional flags may be specified if you require them to be added when the extension calls `nargo lsp`. -- **Noir: Nargo Path** - An absolute path to a Nargo binary with the `lsp` command. This may be useful if Nargo is not within the `PATH` of your editor. -- **Noir > Trace: Server** - Setting this to `"messages"` or `"verbose"` will log LSP messages between the Client and Server. Useful for debugging. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/tooling/noir_codegen.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/tooling/noir_codegen.md deleted file mode 100644 index d65151da0ab..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/tooling/noir_codegen.md +++ /dev/null @@ -1,113 +0,0 @@ ---- -title: Noir Codegen for TypeScript -description: Learn how to use Noir codegen to generate TypeScript bindings -keywords: [Nargo, Noir, compile, TypeScript] -sidebar_position: 2 ---- - -When using TypeScript, it is extra work to interpret Noir program outputs in a type-safe way. Third party libraries may exist for popular Noir programs, but they are either hard to find or unmaintained. - -Now you can generate TypeScript bindings for your Noir programs in two steps: -1. Exporting Noir functions using `nargo export` -2. Using the TypeScript module `noir_codegen` to generate TypeScript binding - -**Note:** you can only export functions from a Noir *library* (not binary or contract program types). - -## Installation - -### Your TypeScript project - -If you don't already have a TypeScript project you can add the module with `yarn` (or `npm`), then initialize it: - -```bash -yarn add typescript -D -npx tsc --init -``` - -### Add TypeScript module - `noir_codegen` - -The following command will add the module to your project's devDependencies: - -```bash -yarn add @noir-lang/noir_codegen -D -``` - -### Nargo library -Make sure you have Nargo, v0.25.0 or greater, installed. If you don't, follow the [installation guide](../installation/index.md). - -If you're in a new project, make a `circuits` folder and create a new Noir library: - -```bash -mkdir circuits && cd circuits -nargo new --lib myNoirLib -``` - -## Usage - -### Export ABI of specified functions - -First go to the `.nr` files in your Noir library, and add the `#[export]` macro to each function that you want to use in TypeScript. - -```rust -#[export] -fn your_function(... -``` - -From your Noir library (where `Nargo.toml` is), run the following command: - -```bash -nargo export -``` - -You will now have an `export` directory with a .json file per exported function. - -You can also specify the directory of Noir programs using `--program-dir`, for example: - -```bash -nargo export --program-dir=./circuits/myNoirLib -``` - -### Generate TypeScript bindings from exported functions - -To use the `noir-codegen` package we added to the TypeScript project: - -```bash -yarn noir-codegen ./export/your_function.json -``` - -This creates an `exports` directory with an `index.ts` file containing all exported functions. - -**Note:** adding `--out-dir` allows you to specify an output dir for your TypeScript bindings to go. Eg: - -```bash -yarn noir-codegen ./export/*.json --out-dir ./path/to/output/dir -``` - -## Example .nr function to .ts output - -Consider a Noir library with this function: - -```rust -#[export] -fn not_equal(x: Field, y: Field) -> bool { - x != y -} -``` - -After the export and codegen steps, you should have an `index.ts` like: - -```typescript -export type Field = string; - - -export const is_equal_circuit: CompiledCircuit = {"abi":{"parameters":[{"name":"x","type":{"kind":"field"},"visibility":"private"},{"name":"y","type":{"kind":"field"},"visibility":"private"}],"param_witnesses":{"x":[{"start":0,"end":1}],"y":[{"start":1,"end":2}]},"return_type":{"abi_type":{"kind":"boolean"},"visibility":"private"},"return_witnesses":[4]},"bytecode":"H4sIAAAAAAAA/7WUMQ7DIAxFQ0Krrr2JjSGYLVcpKrn/CaqqDQN12WK+hPBgmWd/wEyHbF1SS923uhOs3pfoChI+wKXMAXzIKyNj4PB0TFTYc0w5RUjoqeAeEu1wqK0F54RGkWvW44LPzExnlkbMEs4JNZmN8PxS42uHv82T8a3Jeyn2Ks+VLPcO558HmyLMCDOXAXXtpPt4R/Rt9T36ss6dS9HGPx/eG17nGegKBQAA"}; - -export async function is_equal(x: Field, y: Field, foreignCallHandler?: ForeignCallHandler): Promise { - const program = new Noir(is_equal_circuit); - const args: InputMap = { x, y }; - const { returnValue } = await program.execute(args, foreignCallHandler); - return returnValue as boolean; -} -``` - -Now the `is_equal()` function and relevant types are readily available for use in TypeScript. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/tooling/testing.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/tooling/testing.md deleted file mode 100644 index d3e0c522473..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/tooling/testing.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -title: Testing in Noir -description: Learn how to use Nargo to test your Noir program in a quick and easy way -keywords: [Nargo, testing, Noir, compile, test] -sidebar_position: 1 ---- - -You can test your Noir programs using Noir circuits. - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. - -For example if you have a program like: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test] -fn test_add() { - assert(add(2,2) == 4); - assert(add(0,1) == 1); - assert(add(1,0) == 1); -} -``` - -Running `nargo test` will test that the `test_add` function can be executed while satisfying all -the constraints which allows you to test that add returns the expected values. Test functions can't -have any arguments currently. - -### Test fail - -You can write tests that are expected to fail by using the decorator `#[test(should_fail)]`. For example: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test(should_fail)] -fn test_add() { - assert(add(2,2) == 5); -} -``` - -You can be more specific and make it fail with a specific reason by using `should_fail_with = "`: - -```rust -fn main(african_swallow_avg_speed : Field) { - assert(african_swallow_avg_speed == 65, "What is the airspeed velocity of an unladen swallow"); -} - -#[test] -fn test_king_arthur() { - main(65); -} - -#[test(should_fail_with = "What is the airspeed velocity of an unladen swallow")] -fn test_bridgekeeper() { - main(32); -} - -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/how_to/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/how_to/_category_.json deleted file mode 100644 index 23b560f610b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/how_to/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 1, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/how_to/how-to-oracles.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/how_to/how-to-oracles.md deleted file mode 100644 index 8cf8035a5c4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/how_to/how-to-oracles.md +++ /dev/null @@ -1,276 +0,0 @@ ---- -title: How to use Oracles -description: Learn how to use oracles in your Noir program with examples in both Nargo and NoirJS. This guide also covers writing a JSON RPC server and providing custom foreign call handlers for NoirJS. -keywords: - - Noir Programming - - Oracles - - Nargo - - NoirJS - - JSON RPC Server - - Foreign Call Handlers -sidebar_position: 1 ---- - -This guide shows you how to use oracles in your Noir program. For the sake of clarity, it assumes that: - -- You have read the [explainer on Oracles](../explainers/explainer-oracle.md) and are comfortable with the concept. -- You have a Noir program to add oracles to. You can create one using the [vite-hardhat starter](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat) as a boilerplate. -- You understand the concept of a JSON-RPC server. Visit the [JSON-RPC website](https://www.jsonrpc.org/) if you need a refresher. -- You are comfortable with server-side JavaScript (e.g. Node.js, managing packages, etc.). - -For reference, you can find the snippets used in this tutorial on the [Aztec DevRel Repository](https://github.com/AztecProtocol/dev-rel/tree/main/code-snippets/how-to-oracles). - -## Rundown - -This guide has 3 major steps: - -1. How to modify our Noir program to make use of oracle calls as unconstrained functions -2. How to write a JSON RPC Server to resolve these oracle calls with Nargo -3. How to use them in Nargo and how to provide a custom resolver in NoirJS - -## Step 1 - Modify your Noir program - -An oracle is defined in a Noir program by defining two methods: - -- An unconstrained method - This tells the compiler that it is executing an [unconstrained functions](../noir/concepts//unconstrained.md). -- A decorated oracle method - This tells the compiler that this method is an RPC call. - -An example of an oracle that returns a `Field` would be: - -```rust -#[oracle(getSqrt)] -unconstrained fn sqrt(number: Field) -> Field { } - -unconstrained fn get_sqrt(number: Field) -> Field { - sqrt(number) -} -``` - -In this example, we're wrapping our oracle function in a unconstrained method, and decorating it with `oracle(getSqrt)`. We can then call the unconstrained function as we would call any other function: - -```rust -fn main(input: Field) { - let sqrt = get_sqrt(input); -} -``` - -In the next section, we will make this `getSqrt` (defined on the `sqrt` decorator) be a method of the RPC server Noir will use. - -:::danger - -As explained in the [Oracle Explainer](../explainers/explainer-oracle.md), this `main` function is unsafe unless you constrain its return value. For example: - -```rust -fn main(input: Field) { - let sqrt = get_sqrt(input); - assert(sqrt.pow_32(2) as u64 == input as u64); // <---- constrain the return of an oracle! -} -``` - -::: - -:::info - -Currently, oracles only work with single params or array params. For example: - -```rust -#[oracle(getSqrt)] -unconstrained fn sqrt([Field; 2]) -> [Field; 2] { } -``` - -::: - -## Step 2 - Write an RPC server - -Brillig will call *one* RPC server. Most likely you will have to write your own, and you can do it in whatever language you prefer. In this guide, we will do it in Javascript. - -Let's use the above example of an oracle that consumes an array with two `Field` and returns their square roots: - -```rust -#[oracle(getSqrt)] -unconstrained fn sqrt(input: [Field; 2]) -> [Field; 2] { } - -unconstrained fn get_sqrt(input: [Field; 2]) -> [Field; 2] { - sqrt(input) -} - -fn main(input: [Field; 2]) { - let sqrt = get_sqrt(input); - assert(sqrt[0].pow_32(2) as u64 == input[0] as u64); - assert(sqrt[1].pow_32(2) as u64 == input[1] as u64); -} -``` - -:::info - -Why square root? - -In general, computing square roots is computationally more expensive than multiplications, which takes a toll when speaking about ZK applications. In this case, instead of calculating the square root in Noir, we are using our oracle to offload that computation to be made in plain. In our circuit we can simply multiply the two values. - -::: - -Now, we should write the correspondent RPC server, starting with the [default JSON-RPC 2.0 boilerplate](https://www.npmjs.com/package/json-rpc-2.0#example): - -```js -import { JSONRPCServer } from "json-rpc-2.0"; -import express from "express"; -import bodyParser from "body-parser"; - -const app = express(); -app.use(bodyParser.json()); - -const server = new JSONRPCServer(); -app.post("/", (req, res) => { - const jsonRPCRequest = req.body; - server.receive(jsonRPCRequest).then((jsonRPCResponse) => { - if (jsonRPCResponse) { - res.json(jsonRPCResponse); - } else { - res.sendStatus(204); - } - }); -}); - -app.listen(5555); -``` - -Now, we will add our `getSqrt` method, as expected by the `#[oracle(getSqrt)]` decorator in our Noir code. It maps through the params array and returns their square roots: - -```js -server.addMethod("getSqrt", async (params) => { - const values = params[0].Array.map((field) => { - return `${Math.sqrt(parseInt(field, 16))}`; - }); - return { values: [{ Array: values }] }; -}); -``` - -:::tip - -Brillig expects an object with an array of values. Each value is an object declaring to be `Single` or `Array` and returning a field element *as a string*. For example: - -```json -{ "values": [{ "Array": ["1", "2"] }]} -{ "values": [{ "Single": "1" }]} -{ "values": [{ "Single": "1" }, { "Array": ["1", "2"] }]} -``` - -If you're using Typescript, the following types may be helpful in understanding the expected return value and making sure they're easy to follow: - -```js -interface SingleForeignCallParam { - Single: string, -} - -interface ArrayForeignCallParam { - Array: string[], -} - -type ForeignCallParam = SingleForeignCallParam | ArrayForeignCallParam; - -interface ForeignCallResult { - values: ForeignCallParam[], -} -``` - -::: - -## Step 3 - Usage with Nargo - -Using the [`nargo` CLI tool](../getting_started/installation/index.md), you can use oracles in the `nargo test`, `nargo execute` and `nargo prove` commands by passing a value to `--oracle-resolver`. For example: - -```bash -nargo test --oracle-resolver http://localhost:5555 -``` - -This tells `nargo` to use your RPC Server URL whenever it finds an oracle decorator. - -## Step 4 - Usage with NoirJS - -In a JS environment, an RPC server is not strictly necessary, as you may want to resolve your oracles without needing any JSON call at all. NoirJS simply expects that you pass a callback function when you generate proofs, and that callback function can be anything. - -For example, if your Noir program expects the host machine to provide CPU pseudo-randomness, you could simply pass it as the `foreignCallHandler`. You don't strictly need to create an RPC server to serve pseudo-randomness, as you may as well get it directly in your app: - -```js -const foreignCallHandler = (name, inputs) => crypto.randomBytes(16) // etc - -await noir.generateProof(inputs, foreignCallHandler) -``` - -As one can see, in NoirJS, the [`foreignCallHandler`](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) function simply means "a callback function that returns a value of type [`ForeignCallOutput`](../reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md). It doesn't have to be an RPC call like in the case for Nargo. - -:::tip - -Does this mean you don't have to write an RPC server like in [Step #2](#step-2---write-an-rpc-server)? - -You don't technically have to, but then how would you run `nargo test` or `nargo prove`? To use both `Nargo` and `NoirJS` in your development flow, you will have to write a JSON RPC server. - -::: - -In this case, let's make `foreignCallHandler` call the JSON RPC Server we created in [Step #2](#step-2---write-an-rpc-server), by making it a JSON RPC Client. - -For example, using the same `getSqrt` program in [Step #1](#step-1---modify-your-noir-program) (comments in the code): - -```js -import { JSONRPCClient } from "json-rpc-2.0"; - -// declaring the JSONRPCClient -const client = new JSONRPCClient((jsonRPCRequest) => { -// hitting the same JSON RPC Server we coded above - return fetch("http://localhost:5555", { - method: "POST", - headers: { - "content-type": "application/json", - }, - body: JSON.stringify(jsonRPCRequest), - }).then((response) => { - if (response.status === 200) { - return response - .json() - .then((jsonRPCResponse) => client.receive(jsonRPCResponse)); - } else if (jsonRPCRequest.id !== undefined) { - return Promise.reject(new Error(response.statusText)); - } - }); -}); - -// declaring a function that takes the name of the foreign call (getSqrt) and the inputs -const foreignCallHandler = async (name, input) => { - // notice that the "inputs" parameter contains *all* the inputs - // in this case we to make the RPC request with the first parameter "numbers", which would be input[0] - const oracleReturn = await client.request(name, [ - { Array: input[0].map((i) => i.toString("hex")) }, - ]); - return [oracleReturn.values[0].Array]; -}; - -// the rest of your NoirJS code -const input = { input: [4, 16] }; -const { witness } = await noir.execute(numbers, foreignCallHandler); -``` - -:::tip - -If you're in a NoirJS environment running your RPC server together with a frontend app, you'll probably hit a familiar problem in full-stack development: requests being blocked by [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) policy. For development only, you can simply install and use the [`cors` npm package](https://www.npmjs.com/package/cors) to get around the problem: - -```bash -yarn add cors -``` - -and use it as a middleware: - -```js -import cors from "cors"; - -const app = express(); -app.use(cors()) -``` - -::: - -## Conclusion - -Hopefully by the end of this guide, you should be able to: - -- Write your own logic around Oracles and how to write a JSON RPC server to make them work with your Nargo commands. -- Provide custom foreign call handlers for NoirJS. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/how_to/how-to-recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/how_to/how-to-recursion.md deleted file mode 100644 index 4c45bb87ae2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/how_to/how-to-recursion.md +++ /dev/null @@ -1,179 +0,0 @@ ---- -title: How to use recursion on NoirJS -description: Learn how to implement recursion with NoirJS, a powerful tool for creating smart contracts on the EVM blockchain. This guide assumes familiarity with NoirJS, solidity verifiers, and the Barretenberg proving backend. Discover how to generate both final and intermediate proofs using `noir_js` and `backend_barretenberg`. -keywords: - [ - "NoirJS", - "EVM blockchain", - "smart contracts", - "recursion", - "solidity verifiers", - "Barretenberg backend", - "noir_js", - "backend_barretenberg", - "intermediate proofs", - "final proofs", - "nargo compile", - "json import", - "recursive circuit", - "recursive app" - ] -sidebar_position: 1 ---- - -This guide shows you how to use recursive proofs in your NoirJS app. For the sake of clarity, it is assumed that: - -- You already have a NoirJS app. If you don't, please visit the [NoirJS tutorial](../tutorials/noirjs_app.md) and the [reference](../reference/NoirJS/noir_js/index.md). -- You are familiar with what are recursive proofs and you have read the [recursion explainer](../explainers/explainer-recursion.md) -- You already built a recursive circuit following [the reference](../noir/standard_library/recursion.md), and understand how it works. - -It is also assumed that you're not using `noir_wasm` for compilation, and instead you've used [`nargo compile`](../reference/nargo_commands.md) to generate the `json` you're now importing into your project. However, the guide should work just the same if you're using `noir_wasm`. - -:::info - -As you've read in the [explainer](../explainers/explainer-recursion.md), a recursive proof is an intermediate proof. This means that it doesn't necessarily generate the final step that makes it verifiable in a smart contract. However, it is easy to verify within another circuit. - -While "standard" usage of NoirJS packages abstracts final proofs, it currently lacks the necessary interface to abstract away intermediate proofs. This means that these proofs need to be created by using the backend directly. - -In short: - -- `noir_js` generates *only* final proofs -- `backend_barretenberg` generates both types of proofs - -::: - -In a standard recursive app, you're also dealing with at least two circuits. For the purpose of this guide, we will assume the following: - -- `main`: a circuit of type `assert(x != y)`, where `main` is marked with a `#[recursive]` attribute. This attribute states that the backend should generate proofs that are friendly for verification within another circuit. -- `recursive`: a circuit that verifies `main` - -For a full example on how recursive proofs work, please refer to the [noir-examples](https://github.com/noir-lang/noir-examples) repository. We will *not* be using it as a reference for this guide. - -## Step 1: Setup - -In a common NoirJS app, you need to instantiate a backend with something like `const backend = new Backend(circuit)`. Then you feed it to the `noir_js` interface. - -For recursion, this doesn't happen, and the only need for `noir_js` is only to `execute` a circuit and get its witness and return value. Everything else is not interfaced, so it needs to happen on the `backend` object. - -It is also recommended that you instantiate the backend with as many threads as possible, to allow for maximum concurrency: - -```js -const backend = new Backend(circuit, { threads: 8 }) -``` - -:::tip -You can use the [`os.cpus()`](https://nodejs.org/api/os.html#oscpus) object in `nodejs` or [`navigator.hardwareConcurrency`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/hardwareConcurrency) on the browser to make the most out of those glorious cpu cores -::: - -## Step 2: Generating the witness and the proof for `main` - -After instantiating the backend, you should also instantiate `noir_js`. We will use it to execute the circuit and get the witness. - -```js -const noir = new Noir(circuit, backend) -const { witness } = noir.execute(input) -``` - -With this witness, you are now able to generate the intermediate proof for the main circuit: - -```js -const { proof, publicInputs } = await backend.generateProof(witness) -``` - -:::warning - -Always keep in mind what is actually happening on your development process, otherwise you'll quickly become confused about what circuit we are actually running and why! - -In this case, you can imagine that Alice (running the `main` circuit) is proving something to Bob (running the `recursive` circuit), and Bob is verifying her proof within his proof. - -With this in mind, it becomes clear that our intermediate proof is the one *meant to be verified within another circuit*, so it must be Alice's. Actually, the only final proof in this theoretical scenario would be the last one, sent on-chain. - -::: - -## Step 3 - Verification and proof artifacts - -Optionally, you are able to verify the intermediate proof: - -```js -const verified = await backend.verifyProof({ proof, publicInputs }) -``` - -This can be useful to make sure our intermediate proof was correctly generated. But the real goal is to do it within another circuit. For that, we need to generate recursive proof artifacts that will be passed to the circuit that is verifying the proof we just generated. Instead of passing the proof and verification key as a byte array, we pass them as fields which makes it cheaper to verify in a circuit: - -```js -const { proofAsFields, vkAsFields, vkHash } = await backend.generateRecursiveProofArtifacts( { publicInputs, proof }, publicInputsCount) -``` - -This call takes the public inputs and the proof, but also the public inputs count. While this is easily retrievable by simply counting the `publicInputs` length, the backend interface doesn't currently abstract it away. - -:::info - -The `proofAsFields` has a constant size `[Field; 93]` and verification keys in Barretenberg are always `[Field; 114]`. - -::: - -:::warning - -One common mistake is to forget *who* makes this call. - -In a situation where Alice is generating the `main` proof, if she generates the proof artifacts and sends them to Bob, which gladly takes them as true, this would mean Alice could prove anything! - -Instead, Bob needs to make sure *he* extracts the proof artifacts, using his own instance of the `main` circuit backend. This way, Alice has to provide a valid proof for the correct `main` circuit. - -::: - -## Step 4 - Recursive proof generation - -With the artifacts, generating a recursive proof is no different from a normal proof. You simply use the `backend` (with the recursive circuit) to generate it: - -```js -const recursiveInputs = { - verification_key: vkAsFields, // array of length 114 - proof: proofAsFields, // array of length 93 + size of public inputs - publicInputs: [mainInput.y], // using the example above, where `y` is the only public input - key_hash: vkHash, -} - -const { witness, returnValue } = noir.execute(recursiveInputs) // we're executing the recursive circuit now! -const { proof, publicInputs } = backend.generateProof(witness) -const verified = backend.verifyProof({ proof, publicInputs }) -``` - -You can obviously chain this proof into another proof. In fact, if you're using recursive proofs, you're probably interested of using them this way! - -:::tip - -Managing circuits and "who does what" can be confusing. To make sure your naming is consistent, you can keep them in an object. For example: - -```js -const circuits = { - main: mainJSON, - recursive: recursiveJSON -} -const backends = { - main: new BarretenbergBackend(circuits.main), - recursive: new BarretenbergBackend(circuits.recursive) -} -const noir_programs = { - main: new Noir(circuits.main, backends.main), - recursive: new Noir(circuits.recursive, backends.recursive) -} -``` - -This allows you to neatly call exactly the method you want without conflicting names: - -```js -// Alice runs this 👇 -const { witness: mainWitness } = await noir_programs.main.execute(input) -const proof = await backends.main.generateProof(mainWitness) - -// Bob runs this 👇 -const verified = await backends.main.verifyProof(proof) -const { proofAsFields, vkAsFields, vkHash } = await backends.main.generateRecursiveProofArtifacts( - proof, - numPublicInputs, -); -const recursiveProof = await noir_programs.recursive.generateProof(recursiveInputs) -``` - -::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/how_to/how-to-solidity-verifier.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/how_to/how-to-solidity-verifier.md deleted file mode 100644 index e3c7c1065da..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/how_to/how-to-solidity-verifier.md +++ /dev/null @@ -1,231 +0,0 @@ ---- -title: Generate a Solidity Verifier -description: - Learn how to run the verifier as a smart contract on the blockchain. Compile a Solidity verifier - contract for your Noir program and deploy it on any EVM blockchain acting as a verifier smart - contract. Read more to find out -keywords: - [ - solidity verifier, - smart contract, - blockchain, - compiler, - plonk_vk.sol, - EVM blockchain, - verifying Noir programs, - proving backend, - Barretenberg, - ] -sidebar_position: 0 -pagination_next: tutorials/noirjs_app ---- - -Noir has the ability to generate a verifier contract in Solidity, which can be deployed in many EVM-compatible blockchains such as Ethereum. - -This allows for a powerful feature set, as one can make use of the conciseness and the privacy provided by Noir in an immutable ledger. Applications can range from simple P2P guessing games, to complex private DeFi interactions. - -This guide shows you how to generate a Solidity Verifier and deploy it on the [Remix IDE](https://remix.ethereum.org/). It is assumed that: - -- You are comfortable with the Solidity programming language and understand how contracts are deployed on the Ethereum network -- You have Noir installed and you have a Noir program. If you don't, [get started](../getting_started/installation/index.md) with Nargo and the example Hello Noir circuit -- You are comfortable navigating RemixIDE. If you aren't or you need a refresher, you can find some video tutorials [here](https://www.youtube.com/channel/UCjTUPyFEr2xDGN6Cg8nKDaA) that could help you. - -## Rundown - -Generating a Solidity Verifier contract is actually a one-command process. However, compiling it and deploying it can have some caveats. Here's the rundown of this guide: - -1. How to generate a solidity smart contract -2. How to compile the smart contract in the RemixIDE -3. How to deploy it to a testnet - -## Step 1 - Generate a contract - -This is by far the most straight-forward step. Just run: - -```sh -nargo codegen-verifier -``` - -A new `contract` folder would then be generated in your project directory, containing the Solidity -file `plonk_vk.sol`. It can be deployed to any EVM blockchain acting as a verifier smart contract. - -:::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. - -Barretenberg, the default proving backend for Nargo, supports generation of verifier contracts, for the time being these are only in Solidity. -::: - -## Step 2 - Compiling - -We will mostly skip the details of RemixIDE, as the UI can change from version to version. For now, we can just open -Remix and create a blank workspace. - -![Create Workspace](@site/static/img/how-tos/solidity_verifier_1.png) - -We will create a new file to contain the contract Nargo generated, and copy-paste its content. - -:::warning - -You'll likely see a warning advising you to not trust pasted code. While it is an important warning, it is irrelevant in the context of this guide and can be ignored. We will not be deploying anywhere near a mainnet. - -::: - -To compile our the verifier, we can navigate to the compilation tab: - -![Compilation Tab](@site/static/img/how-tos/solidity_verifier_2.png) - -Remix should automatically match a suitable compiler version. However, hitting the "Compile" button will most likely generate a "Stack too deep" error: - -![Stack too deep](@site/static/img/how-tos/solidity_verifier_3.png) - -This is due to the verify function needing to put many variables on the stack, but enabling the optimizer resolves the issue. To do this, let's open the "Advanced Configurations" tab and enable optimization. The default 200 runs will suffice. - -:::info - -This time we will see a warning about an unused function parameter. This is expected, as the `verify` function doesn't use the `_proof` parameter inside a solidity block, it is loaded from calldata and used in assembly. - -::: - -![Compilation success](@site/static/img/how-tos/solidity_verifier_4.png) - -## Step 3 - Deploying - -At this point we should have a compiled contract read to deploy. If we navigate to the deploy section in Remix, we will see many different environments we can deploy to. The steps to deploy on each environment would be out-of-scope for this guide, so we will just use the default Remix VM. - -Looking closely, we will notice that our "Solidity Verifier" is actually three contracts working together: - -- An `UltraVerificationKey` library which simply stores the verification key for our circuit. -- An abstract contract `BaseUltraVerifier` containing most of the verifying logic. -- A main `UltraVerifier` contract that inherits from the Base and uses the Key contract. - -Remix will take care of the dependencies for us so we can simply deploy the UltraVerifier contract by selecting it and hitting "deploy": - -![Deploying UltraVerifier](@site/static/img/how-tos/solidity_verifier_5.png) - -A contract will show up in the "Deployed Contracts" section, where we can retrieve the Verification Key Hash. This is particularly useful for double-checking the deployer contract is the correct one. - -:::note - -Why "UltraVerifier"? - -To be precise, the Noir compiler (`nargo`) doesn't generate the verifier contract directly. It compiles the Noir code into an intermediate language (ACIR), which is then executed by the backend. So it is the backend that returns the verifier smart contract, not Noir. - -In this case, the Barretenberg Backend uses the UltraPlonk proving system, hence the "UltraVerifier" name. - -::: - -## Step 4 - Verifying - -To verify a proof using the Solidity verifier contract, we call the `verify` function in this extended contract: - -```solidity -function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) -``` - -When using the default example in the [Hello Noir](../getting_started/hello_noir/index.md) guide, the easiest way to confirm that the verifier contract is doing its job is by calling the `verify` function via remix with the required parameters. For `_proof`, run `nargo prove` and use the string in `proof/.proof` (adding the hex `0x` prefix). We can also copy the public input from `Verifier.toml`, as it will be properly formatted as 32-byte strings: - -``` -0x...... , [0x0000.....02] -``` - -A programmatic example of how the `verify` function is called can be seen in the example zk voting application [here](https://github.com/noir-lang/noir-examples/blob/33e598c257e2402ea3a6b68dd4c5ad492bce1b0a/foundry-voting/src/zkVote.sol#L35): - -```solidity -function castVote(bytes calldata proof, uint proposalId, uint vote, bytes32 nullifierHash) public returns (bool) { - // ... - bytes32[] memory publicInputs = new bytes32[](4); - publicInputs[0] = merkleRoot; - publicInputs[1] = bytes32(proposalId); - publicInputs[2] = bytes32(vote); - publicInputs[3] = nullifierHash; - require(verifier.verify(proof, publicInputs), "Invalid proof"); -``` - -:::info[Return Values] - -A circuit doesn't have the concept of a return value. Return values are just syntactic sugar in -Noir. - -Under the hood, the return value is passed as an input to the circuit and is checked at the end of -the circuit program. - -For example, if you have Noir program like this: - -```rust -fn main( - // Public inputs - pubkey_x: pub Field, - pubkey_y: pub Field, - // Private inputs - priv_key: Field, -) -> pub Field -``` - -the `verify` function will expect the public inputs array (second function parameter) to be of length 3, the two inputs and the return value. Like before, these values are populated in Verifier.toml after running `nargo prove`. - -Passing only two inputs will result in an error such as `PUBLIC_INPUT_COUNT_INVALID(3, 2)`. - -In this case, the inputs parameter to `verify` would be an array ordered as `[pubkey_x, pubkey_y, return]`. - -::: - -:::tip[Structs] - -You can pass structs to the verifier contract. They will be flattened so that the array of inputs is 1-dimensional array. - -For example, consider the following program: - -```rust -struct Type1 { - val1: Field, - val2: Field, -} - -struct Nested { - t1: Type1, - is_true: bool, -} - -fn main(x: pub Field, nested: pub Nested, y: pub Field) { - //... -} -``` - -The order of these inputs would be flattened to: `[x, nested.t1.val1, nested.t1.val2, nested.is_true, y]` - -::: - -The other function you can call is our entrypoint `verify` function, as defined above. - -:::tip - -It's worth noticing that the `verify` function is actually a `view` function. A `view` function does not alter the blockchain state, so it doesn't need to be distributed (i.e. it will run only on the executing node), and therefore doesn't cost any gas. - -This can be particularly useful in some situations. If Alice generated a proof and wants Bob to verify its correctness, Bob doesn't need to run Nargo, NoirJS, or any Noir specific infrastructure. He can simply make a call to the blockchain with the proof and verify it is correct without paying any gas. - -It would be incorrect to say that a Noir proof verification costs any gas at all. However, most of the time the result of `verify` is used to modify state (for example, to update a balance, a game state, etc). In that case the whole network needs to execute it, which does incur gas costs (calldata and execution, but not storage). - -::: - -## A Note on EVM chains - -ZK-SNARK verification depends on some precompiled cryptographic primitives such as Elliptic Curve Pairings (if you like complex math, you can read about EC Pairings [here](https://medium.com/@VitalikButerin/exploring-elliptic-curve-pairings-c73c1864e627)). Not all EVM chains support EC Pairings, notably some of the ZK-EVMs. This means that you won't be able to use the verifier contract in all of them. - -For example, chains like `zkSync ERA` and `Polygon zkEVM` do not currently support these precompiles, so proof verification via Solidity verifier contracts won't work. Here's a quick list of EVM chains that have been tested and are known to work: - -- Optimism -- Arbitrum -- Polygon PoS -- Scroll -- Celo - -If you test any other chains, please open a PR on this page to update the list. See [this doc](https://github.com/noir-lang/noir-starter/tree/main/with-foundry#testing-on-chain) for more info about testing verifier contracts on different EVM chains. - -## What's next - -Now that you know how to call a Noir Solidity Verifier on a smart contract using Remix, you should be comfortable with using it with some programmatic frameworks, such as [hardhat](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat) and [foundry](https://github.com/noir-lang/noir-starter/tree/main/with-foundry). - -You can find other tools, examples, boilerplates and libraries in the [awesome-noir](https://github.com/noir-lang/awesome-noir) repository. - -You should also be ready to write and deploy your first NoirJS app and start generating proofs on websites, phones, and NodeJS environments! Head on to the [NoirJS tutorial](../tutorials/noirjs_app.md) to learn how to do that. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/how_to/merkle-proof.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/how_to/merkle-proof.mdx deleted file mode 100644 index 003c7019a93..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/how_to/merkle-proof.mdx +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Prove Merkle Tree Membership -description: - Learn how to use merkle membership proof in Noir to prove that a given leaf is a member of a - merkle tree with a specified root, at a given index. -keywords: - [merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree] ---- - -Let's walk through an example of a merkle membership proof in Noir that proves that a given leaf is -in a merkle tree. - -```rust -use dep::std; - -fn main(message : [Field; 62], index : Field, hashpath : [Field; 40], root : Field) { - let leaf = std::hash::hash_to_field(message.as_slice()); - let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); - assert(merkle_root == root); -} - -``` - -The message is hashed using `hash_to_field`. The specific hash function that is being used is chosen -by the backend. The only requirement is that this hash function can heuristically be used as a -random oracle. If only collision resistance is needed, then one can call `std::hash::pedersen_hash` -instead. - -```rust -let leaf = std::hash::hash_to_field(message.as_slice()); -``` - -The leaf is then passed to a compute_merkle_root function with the root, index and hashpath. The returned root can then be asserted to be the same as the provided root. - -```rust -let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); -assert (merkle_root == root); -``` - -> **Note:** It is possible to re-implement the merkle tree implementation without standard library. -> However, for most usecases, it is enough. In general, the standard library will always opt to be -> as conservative as possible, while striking a balance with efficiency. - -An example, the merkle membership proof, only requires a hash function that has collision -resistance, hence a hash function like Pedersen is allowed, which in most cases is more efficient -than the even more conservative sha256. - -[View an example on the starter repo](https://github.com/noir-lang/noir-examples/blob/3ea09545cabfa464124ec2f3ea8e60c608abe6df/stealthdrop/circuits/src/main.nr#L20) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/how_to/using-devcontainers.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/how_to/using-devcontainers.mdx deleted file mode 100644 index 727ec6ca667..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/how_to/using-devcontainers.mdx +++ /dev/null @@ -1,110 +0,0 @@ ---- -title: Developer Containers and Codespaces -description: "Learn how to set up a devcontainer in your GitHub repository for a seamless coding experience with Codespaces. Follow our easy 8-step guide to create your own Noir environment without installing Nargo locally." -keywords: ["Devcontainer", "Codespaces", "GitHub", "Noir Environment", "Docker Image", "Development Environment", "Remote Coding", "GitHub Codespaces", "Noir Programming", "Nargo", "VSCode Extensions", "Noirup"] -sidebar_position: 1 ---- - -Adding a developer container configuration file to your Noir project is one of the easiest way to unlock coding in browser. - -## What's a devcontainer after all? - -A [Developer Container](https://containers.dev/) (devcontainer for short) is a Docker image that comes preloaded with tools, extensions, and other tools you need to quickly get started or continue a project, without having to install Nargo locally. Think of it as a development environment in a box. - -There are many advantages to this: - -- It's platform and architecture agnostic -- You don't need to have an IDE installed, or Nargo, or use a terminal at all -- It's safer for using on a public machine or public network - -One of the best ways of using devcontainers is... not using your machine at all, for maximum control, performance, and ease of use. -Enter Codespaces. - -## Codespaces - -If a devcontainer is just a Docker image, then what stops you from provisioning a `p3dn.24xlarge` AWS EC2 instance with 92 vCPUs and 768 GiB RAM and using it to prove your 10-gate SNARK proof? - -Nothing! Except perhaps the 30-40$ per hour it will cost you. - -The problem is that provisioning takes time, and I bet you don't want to see the AWS console every time you want to code something real quick. - -Fortunately, there's an easy and free way to get a decent remote machine ready and loaded in less than 2 minutes: Codespaces. [Codespaces is a Github feature](https://github.com/features/codespaces) that allows you to code in a remote machine by using devcontainers, and it's pretty cool: - -- You can start coding Noir in less than a minute -- It uses the resources of a remote machine, so you can code on your grandma's phone if needed be -- It makes it easy to share work with your frens -- It's fully reusable, you can stop and restart whenever you need to - -:::info - -Don't take out your wallet just yet. Free GitHub accounts get about [15-60 hours of coding](https://github.com/features/codespaces) for free per month, depending on the size of your provisioned machine. - -::: - -## Tell me it's _actually_ easy - -It is! - -Github comes with a default codespace and you can use it to code your own devcontainer. That's exactly what we will be doing in this guide. - - - -8 simple steps: - -#### 1. Create a new repository on GitHub. - -#### 2. Click "Start coding with Codespaces". This will use the default image. - -#### 3. Create a folder called `.devcontainer` in the root of your repository. - -#### 4. Create a Dockerfile in that folder, and paste the following code: - -```docker -FROM --platform=linux/amd64 node:lts-bookworm-slim -SHELL ["/bin/bash", "-c"] -RUN apt update && apt install -y curl bash git tar gzip libc++-dev -RUN curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -ENV PATH="/root/.nargo/bin:$PATH" -RUN noirup -ENTRYPOINT ["nargo"] -``` -#### 5. Create a file called `devcontainer.json` in the same folder, and paste the following code: - -```json -{ - "name": "Noir on Codespaces", - "build": { - "context": ".", - "dockerfile": "Dockerfile" - }, - "customizations": { - "vscode": { - "extensions": ["noir-lang.vscode-noir"] - } - } -} -``` -#### 6. Commit and push your changes - -This will pull the new image and build it, so it could take a minute or so - -#### 8. Done! -Just wait for the build to finish, and there's your easy Noir environment. - - -Refer to [noir-starter](https://github.com/noir-lang/noir-starter/) as an example of how devcontainers can be used together with codespaces. - - - -## How do I use it? - -Using the codespace is obviously much easier than setting it up. -Just navigate to your repository and click "Code" -> "Open with Codespaces". It should take a few seconds to load, and you're ready to go. - -:::info - -If you really like the experience, you can add a badge to your readme, links to existing codespaces, and more. -Check out the [official docs](https://docs.github.com/en/codespaces/setting-up-your-project-for-codespaces/setting-up-your-repository/facilitating-quick-creation-and-resumption-of-codespaces) for more info. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/index.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/index.mdx deleted file mode 100644 index 75086ddcdde..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/index.mdx +++ /dev/null @@ -1,67 +0,0 @@ ---- -title: Noir Lang -hide_title: true -description: - Learn about the public alpha release of Noir, a domain specific language heavily influenced by Rust that compiles to - an intermediate language which can be compiled to an arithmetic circuit or a rank-1 constraint system. -keywords: - [Noir, - Domain Specific Language, - Rust, - Intermediate Language, - Arithmetic Circuit, - Rank-1 Constraint System, - Ethereum Developers, - Protocol Developers, - Blockchain Developers, - Proving System, - Smart Contract Language] -sidebar_position: 0 ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -Noir Logo - -Noir is a Domain-Specific Language for SNARK proving systems developed by [Aztec Labs](https://aztec.network/). It allows you to generate complex Zero-Knowledge Programs (ZKP) by using simple and flexible syntax, requiring no previous knowledge on the underlying mathematics or cryptography. - -ZK programs are programs that can generate short proofs of a certain statement without revealing some details about it. You can read more about ZKPs [here](https://dev.to/spalladino/a-beginners-intro-to-coding-zero-knowledge-proofs-c56). - -## What's new about Noir? - -Noir works differently from most ZK languages by taking a two-pronged path. First, it compiles the program to an adaptable intermediate language known as ACIR. From there, depending on a given project's needs, ACIR can be further compiled into an arithmetic circuit for integration with the proving backend. - -:::info - -Noir is backend agnostic, which means it makes no assumptions on which proving backend powers the ZK proof. Being the language that powers [Aztec Contracts](https://docs.aztec.network/developers/contracts/main), it defaults to Aztec's Barretenberg proving backend. - -However, the ACIR output can be transformed to be compatible with other PLONK-based backends, or into a [rank-1 constraint system](https://www.rareskills.io/post/rank-1-constraint-system) suitable for backends such as Arkwork's Marlin. - -::: - -## Who is Noir for? - -Noir can be used both in complex cloud-based backends and in user's smartphones, requiring no knowledge on the underlying math or cryptography. From authorization systems that keep a password in the user's device, to complex on-chain verification of recursive proofs, Noir is designed to abstract away complexity without any significant overhead. Here are some examples of situations where Noir can be used: - - - - Noir Logo - - Aztec Contracts leverage Noir to allow for the storage and execution of private information. Writing an Aztec Contract is as easy as writing Noir, and Aztec developers can easily interact with the network storage and execution through the [Aztec.nr](https://docs.aztec.network/developers/contracts/main) library. - - - Soliditry Verifier Example - Noir can auto-generate Solidity verifier contracts that verify Noir proofs. This allows for non-interactive verification of proofs containing private information in an immutable system. This feature powers a multitude of use-case scenarios, from P2P chess tournaments, to [Aztec Layer-2 Blockchain](https://docs.aztec.network/) - - - Aztec Labs developed NoirJS, an easy interface to generate and verify Noir proofs in a Javascript environment. This allows for Noir to be used in webpages, mobile apps, games, and any other environment supporting JS execution in a standalone manner. - - - - -## Libraries - -Noir is meant to be easy to extend by simply importing Noir libraries just like in Rust. -The [awesome-noir repo](https://github.com/noir-lang/awesome-noir#libraries) is a collection of libraries developed by the Noir community. -Writing a new library is easy and makes code be composable and easy to reuse. See the section on [dependencies](noir/modules_packages_crates/dependencies.md) for more information. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/migration_notes.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/migration_notes.md deleted file mode 100644 index 6bd740024e5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/migration_notes.md +++ /dev/null @@ -1,105 +0,0 @@ ---- -title: Migration notes -description: Read about migration notes from previous versions, which could solve problems while updating -keywords: [Noir, notes, migration, updating, upgrading] ---- - -Noir is in full-speed development. Things break fast, wild, and often. This page attempts to leave some notes on errors you might encounter when upgrading and how to resolve them until proper patches are built. - -### `backend encountered an error: libc++.so.1` - -Depending on your OS, you may encounter the following error when running `nargo prove` for the first time: - -```text -The backend encountered an error: "/home/codespace/.nargo/backends/acvm-backend-barretenberg/backend_binary: error while loading shared libraries: libc++.so.1: cannot open shared object file: No such file or directory\n" -``` - -Install the `libc++-dev` library with: - -```bash -sudo apt install libc++-dev -``` - -## ≥0.19 - -### Enforcing `compiler_version` - -From this version on, the compiler will check for the `compiler_version` field in `Nargo.toml`, and will error if it doesn't match the current Nargo version in use. - -To update, please make sure this field in `Nargo.toml` matches the output of `nargo --version`. - -## ≥0.14 - -The index of the [for loops](noir/concepts/control_flow.md#loops) is now of type `u64` instead of `Field`. An example refactor would be: - -```rust -for i in 0..10 { - let i = i as Field; -} -``` - -## ≥v0.11.0 and Nargo backend - -From this version onwards, Nargo starts managing backends through the `nargo backend` command. Upgrading to the versions per usual steps might lead to: - -### `backend encountered an error` - -This is likely due to the existing locally installed version of proving backend (e.g. barretenberg) is incompatible with the version of Nargo in use. - -To fix the issue: - -1. Uninstall the existing backend - -```bash -nargo backend uninstall acvm-backend-barretenberg -``` - -You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. - -2. Reinstall a compatible version of the proving backend. - -If you are using the default barretenberg backend, simply run: - -``` -nargo prove -``` - -with your Noir program. - -This will trigger the download and installation of the latest version of barretenberg compatible with your Nargo in use. - -### `backend encountered an error: illegal instruction` - -On certain Intel-based systems, an `illegal instruction` error may arise due to incompatibility of barretenberg with certain CPU instructions. - -To fix the issue: - -1. Uninstall the existing backend - -```bash -nargo backend uninstall acvm-backend-barretenberg -``` - -You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. - -2. Reinstall a compatible version of the proving backend. - -If you are using the default barretenberg backend, simply run: - -``` -nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/barretenberg-js-binary/raw/master/run-bb.tar.gz -``` - -This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. - -The gzipped file is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. - -Then run: - -``` -DESIRED_BINARY_VERSION=0.8.1 nargo info -``` - -This overrides the bb native binary with a bb.js node application instead, which should be compatible with most if not all hardware. This does come with the drawback of being generally slower than native binary. - -0.8.1 indicates bb.js version 0.8.1, so if you change that it will update to a different version or the default version in the script if none was supplied. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/_category_.json deleted file mode 100644 index 7da08f8a8c5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Concepts", - "position": 0, - "collapsible": true, - "collapsed": true -} \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/assert.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/assert.md deleted file mode 100644 index bcff613a695..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/assert.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Assert Function -description: - Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or - comparison expression that follows to be true, and what happens if the expression is false at - runtime. -keywords: [Noir programming language, assert statement, predicate expression, comparison expression] -sidebar_position: 4 ---- - -Noir includes a special `assert` function which will explicitly constrain the predicate/comparison -expression that follows to be true. If this expression is false at runtime, the program will fail to -be proven. Example: - -```rust -fn main(x : Field, y : Field) { - assert(x == y); -} -``` - -> Assertions only work for predicate operations, such as `==`. If there's any ambiguity on the operation, the program will fail to compile. For example, it is unclear if `assert(x + y)` would check for `x + y == 0` or simply would return `true`. - -You can optionally provide a message to be logged when the assertion fails: - -```rust -assert(x == y, "x and y are not equal"); -``` - -Aside string literals, the optional message can be a format string or any other type supported as input for Noir's [print](../standard_library/logging.md) functions. This feature lets you incorporate runtime variables into your failed assertion logs: - -```rust -assert(x == y, f"Expected x == y, but got {x} == {y}"); -``` - -Using a variable as an assertion message directly: - -```rust -struct myStruct { - myField: Field -} - -let s = myStruct { myField: y }; -assert(s.myField == x, s); -``` - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/comments.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/comments.md deleted file mode 100644 index b51a85f5c94..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/comments.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Comments -description: - Learn how to write comments in Noir programming language. A comment is a line of code that is - ignored by the compiler, but it can be read by programmers. Single-line and multi-line comments - are supported in Noir. -keywords: [Noir programming language, comments, single-line comments, multi-line comments] -sidebar_position: 10 ---- - -A comment is a line in your codebase which the compiler ignores, however it can be read by -programmers. - -Here is a single line comment: - -```rust -// This is a comment and is ignored -``` - -`//` is used to tell the compiler to ignore the rest of the line. - -Noir also supports multi-line block comments. Start a block comment with `/*` and end the block with `*/`. - -Noir does not natively support doc comments. You may be able to use [Rust doc comments](https://doc.rust-lang.org/reference/comments.html) in your code to leverage some Rust documentation build tools with Noir code. - -```rust -/* - This is a block comment describing a complex function. -*/ -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/_category_.json deleted file mode 100644 index 5d694210bbf..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 0, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/booleans.md deleted file mode 100644 index 7211716f63e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/booleans.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Booleans -description: - Delve into the Boolean data type in Noir. Understand its methods, practical examples, and best practices for using Booleans in your Noir programs. -keywords: - [ - noir, - boolean type, - methods, - examples, - logical operations, - ] -sidebar_position: 2 ---- - - -The `bool` type in Noir has two possible values: `true` and `false`: - -```rust -fn main() { - let t = true; - let f: bool = false; -} -``` - -> **Note:** When returning a boolean value, it will show up as a value of 1 for `true` and 0 for -> `false` in _Verifier.toml_. - -The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and -[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/fields.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/fields.md deleted file mode 100644 index a10a4810788..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/fields.md +++ /dev/null @@ -1,192 +0,0 @@ ---- -title: Fields -description: - Dive deep into the Field data type in Noir. Understand its methods, practical examples, and best practices to effectively use Fields in your Noir programs. -keywords: - [ - noir, - field type, - methods, - examples, - best practices, - ] -sidebar_position: 0 ---- - -The field type corresponds to the native field type of the proving backend. - -The size of a Noir field depends on the elliptic curve's finite field for the proving backend -adopted. For example, a field would be a 254-bit integer when paired with the default backend that -spans the Grumpkin curve. - -Fields support integer arithmetic and are often used as the default numeric type in Noir: - -```rust -fn main(x : Field, y : Field) { - let z = x + y; -} -``` - -`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new -private value `z` constrained to be equal to `x + y`. - -If proving efficiency is of priority, fields should be used as a default for solving problems. -Smaller integer types (e.g. `u64`) incur extra range constraints. - -## Methods - -After declaring a Field, you can use these common methods on it: - -### to_le_bits - -Transforms the field into an array of bits, Little Endian. - -```rust -fn to_le_bits(_x : Field, _bit_size: u32) -> [u1] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_le_bits(32); -} -``` - -### to_be_bits - -Transforms the field into an array of bits, Big Endian. - -```rust -fn to_be_bits(_x : Field, _bit_size: u32) -> [u1] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_be_bits(32); -} -``` - -### to_le_bytes - -Transforms into an array of bytes, Little Endian - -```rust -fn to_le_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_le_bytes(4); -} -``` - -### to_be_bytes - -Transforms into an array of bytes, Big Endian - -```rust -fn to_be_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_be_bytes(4); -} -``` - -### to_le_radix - -Decomposes into a vector over the specified base, Little Endian - -```rust -fn to_le_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_le_radix(256, 4); -} -``` - -### to_be_radix - -Decomposes into a vector over the specified base, Big Endian - -```rust -fn to_be_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_be_radix(256, 4); -} -``` - -### pow_32 - -Returns the value to the power of the specified exponent - -```rust -fn pow_32(self, exponent: Field) -> Field -``` - -example: - -```rust -fn main() { - let field = 2 - let pow = field.pow_32(4); - assert(pow == 16); -} -``` - -### assert_max_bit_size - -Adds a constraint to specify that the field can be represented with `bit_size` number of bits - -```rust -fn assert_max_bit_size(self, bit_size: u32) -``` - -example: - -```rust -fn main() { - let field = 2 - field.assert_max_bit_size(32); -} -``` - -### sgn0 - -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. - -```rust -fn sgn0(self) -> u1 -``` - - -### lt - -Returns true if the field is less than the other field - -```rust -pub fn lt(self, another: Field) -> bool -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/function_types.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/function_types.md deleted file mode 100644 index f6121af17e2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/function_types.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Function types -sidebar_position: 10 ---- - -Noir supports higher-order functions. The syntax for a function type is as follows: - -```rust -fn(arg1_type, arg2_type, ...) -> return_type -``` - -Example: - -```rust -fn assert_returns_100(f: fn() -> Field) { // f takes no args and returns a Field - assert(f() == 100); -} - -fn main() { - assert_returns_100(|| 100); // ok - assert_returns_100(|| 150); // fails -} -``` - -A function type also has an optional capture environment - this is necessary to support closures. -See [Lambdas](../lambdas.md) for more details. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/integers.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/integers.md deleted file mode 100644 index 1c6b375db49..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/integers.md +++ /dev/null @@ -1,155 +0,0 @@ ---- -title: Integers -description: Explore the Integer data type in Noir. Learn about its methods, see real-world examples, and grasp how to efficiently use Integers in your Noir code. -keywords: [noir, integer types, methods, examples, arithmetic] -sidebar_position: 1 ---- - -An integer type is a range constrained field type. The Noir frontend supports both unsigned and signed integer types. The allowed sizes are 1, 8, 32 and 64 bits. - -:::info - -When an integer is defined in Noir without a specific type, it will default to `Field`. - -The one exception is for loop indices which default to `u64` since comparisons on `Field`s are not possible. - -::: - -## Unsigned Integers - -An unsigned integer type is specified first with the letter `u` (indicating its unsigned nature) followed by its bit size (e.g. `8`): - -```rust -fn main() { - let x: u8 = 1; - let y: u8 = 1; - let z = x + y; - assert (z == 2); -} -``` - -The bit size determines the maximum value the integer type can store. For example, a `u8` variable can store a value in the range of 0 to 255 (i.e. $\\2^{8}-1\\$). - -## Signed Integers - -A signed integer type is specified first with the letter `i` (which stands for integer) followed by its bit size (e.g. `8`): - -```rust -fn main() { - let x: i8 = -1; - let y: i8 = -1; - let z = x + y; - assert (z == -2); -} -``` - -The bit size determines the maximum and minimum range of value the integer type can store. For example, an `i8` variable can store a value in the range of -128 to 127 (i.e. $\\-2^{7}\\$ to $\\2^{7}-1\\$). - -## 128 bits Unsigned Integers - -The built-in structure `U128` allows you to use 128-bit unsigned integers almost like a native integer type. However, there are some differences to keep in mind: -- You cannot cast between a native integer and `U128` -- There is a higher performance cost when using `U128`, compared to a native type. - -Conversion between unsigned integer types and U128 are done through the use of `from_integer` and `to_integer` functions. `from_integer` also accepts the `Field` type as input. - -```rust -fn main() { - let x = U128::from_integer(23); - let y = U128::from_hex("0x7"); - let z = x + y; - assert(z.to_integer() == 30); -} -``` - -`U128` is implemented with two 64 bits limbs, representing the low and high bits, which explains the performance cost. You should expect `U128` to be twice more costly for addition and four times more costly for multiplication. -You can construct a U128 from its limbs: -```rust -fn main(x: u64, y: u64) { - let x = U128::from_u64s_be(x,y); - assert(z.hi == x as Field); - assert(z.lo == y as Field); -} -``` - -Note that the limbs are stored as Field elements in order to avoid unnecessary conversions. -Apart from this, most operations will work as usual: - -```rust -fn main(x: U128, y: U128) { - // multiplication - let c = x * y; - // addition and subtraction - let c = c - x + y; - // division - let c = x / y; - // bit operation; - let c = x & y | y; - // bit shift - let c = x << y; - // comparisons; - let c = x < y; - let c = x == y; -} -``` - -## Overflows - -Computations that exceed the type boundaries will result in overflow errors. This happens with both signed and unsigned integers. For example, attempting to prove: - -```rust -fn main(x: u8, y: u8) { - let z = x + y; -} -``` - -With: - -```toml -x = "255" -y = "1" -``` - -Would result in: - -``` -$ nargo prove -error: Assertion failed: 'attempt to add with overflow' -┌─ ~/src/main.nr:9:13 -│ -│ let z = x + y; -│ ----- -│ -= Call stack: - ... -``` - -A similar error would happen with signed integers: - -```rust -fn main() { - let x: i8 = -118; - let y: i8 = -11; - let z = x + y; -} -``` - -### Wrapping methods - -Although integer overflow is expected to error, some use-cases rely on wrapping. For these use-cases, the standard library provides `wrapping` variants of certain common operations: - -```rust -fn wrapping_add(x: T, y: T) -> T; -fn wrapping_sub(x: T, y: T) -> T; -fn wrapping_mul(x: T, y: T) -> T; -``` - -Example of how it is used: - -```rust -use dep::std; - -fn main(x: u8, y: u8) -> pub u8 { - std::wrapping_add(x, y) -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/references.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/references.md deleted file mode 100644 index a5293d11cfb..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/references.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: References -sidebar_position: 9 ---- - -Noir supports first-class references. References are a bit like pointers: they point to a specific address that can be followed to access the data stored at that address. You can use Rust-like syntax to use pointers in Noir: the `&` operator references the variable, the `*` operator dereferences it. - -Example: - -```rust -fn main() { - let mut x = 2; - - // you can reference x as &mut and pass it to multiplyBy2 - multiplyBy2(&mut x); -} - -// you can access &mut here -fn multiplyBy2(x: &mut Field) { - // and dereference it with * - *x = *x * 2; -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/slices.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/slices.mdx deleted file mode 100644 index 828faf4a8f8..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/slices.mdx +++ /dev/null @@ -1,170 +0,0 @@ ---- -title: Slices -description: Explore the Slice data type in Noir. Understand its methods, see real-world examples, and learn how to effectively use Slices in your Noir programs. -keywords: [noir, slice type, methods, examples, subarrays] -sidebar_position: 5 ---- - -import Experimental from '@site/src/components/Notes/_experimental.mdx'; - - - -A slice is a dynamically-sized view into a sequence of elements. They can be resized at runtime, but because they don't own the data, they cannot be returned from a circuit. You can treat slices as arrays without a constrained size. - -```rust -use dep::std::slice; - -fn main() -> pub Field { - let mut slice: [Field] = &[0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -To write a slice literal, use a preceeding ampersand as in: `&[0; 2]` or -`&[1, 2, 3]`. - -It is important to note that slices are not references to arrays. In Noir, -`&[..]` is more similar to an immutable, growable vector. - -View the corresponding test file [here][test-file]. - -[test-file]: https://github.com/noir-lang/noir/blob/f387ec1475129732f72ba294877efdf6857135ac/crates/nargo_cli/tests/test_data_ssa_refactor/slices/src/main.nr - -## Methods - -For convenience, the STD provides some ready-to-use, common methods for slices: - -### push_back - -Pushes a new element to the end of the slice, returning a new slice with a length one greater than the original unmodified slice. - -```rust -fn push_back(_self: [T], _elem: T) -> [T] -``` - -example: - -```rust -fn main() -> pub Field { - let mut slice: [Field] = &[0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -View the corresponding test file [here][test-file]. - -### push_front - -Returns a new array with the specified element inserted at index 0. The existing elements indexes are incremented by 1. - -```rust -fn push_front(_self: Self, _elem: T) -> Self -``` - -Example: - -```rust -let mut new_slice: [Field] = &[]; -new_slice = new_slice.push_front(20); -assert(new_slice[0] == 20); // returns true -``` - -View the corresponding test file [here][test-file]. - -### pop_front - -Returns a tuple of two items, the first element of the array and the rest of the array. - -```rust -fn pop_front(_self: Self) -> (T, Self) -``` - -Example: - -```rust -let (first_elem, rest_of_slice) = slice.pop_front(); -``` - -View the corresponding test file [here][test-file]. - -### pop_back - -Returns a tuple of two items, the beginning of the array with the last element omitted and the last element. - -```rust -fn pop_back(_self: Self) -> (Self, T) -``` - -Example: - -```rust -let (popped_slice, last_elem) = slice.pop_back(); -``` - -View the corresponding test file [here][test-file]. - -### append - -Loops over a slice and adds it to the end of another. - -```rust -fn append(mut self, other: Self) -> Self -``` - -Example: - -```rust -let append = &[1, 2].append(&[3, 4, 5]); -``` - -### insert - -Inserts an element at a specified index and shifts all following elements by 1. - -```rust -fn insert(_self: Self, _index: Field, _elem: T) -> Self -``` - -Example: - -```rust -new_slice = rest_of_slice.insert(2, 100); -assert(new_slice[2] == 100); -``` - -View the corresponding test file [here][test-file]. - -### remove - -Remove an element at a specified index, shifting all elements after it to the left, returning the altered slice and the removed element. - -```rust -fn remove(_self: Self, _index: Field) -> (Self, T) -``` - -Example: - -```rust -let (remove_slice, removed_elem) = slice.remove(3); -``` - -### len - -Returns the length of a slice - -```rust -fn len(self) -> Field -``` - -Example: - -```rust -fn main() { - let slice = &[42, 42]; - assert(slice.len() == 2); -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/strings.md deleted file mode 100644 index 8ab5825a4c4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/strings.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: Strings -description: - Discover the String data type in Noir. Learn about its methods, see real-world examples, and understand how to effectively manipulate and use Strings in Noir. -keywords: - [ - noir, - string type, - methods, - examples, - concatenation, - ] -sidebar_position: 3 ---- - - -The string type is a fixed length value defined with `str`. - -You can use strings in `assert()` functions or print them with -`println()`. See more about [Logging](../../standard_library/logging.md). - -```rust -use dep::std; - -fn main(message : pub str<11>, hex_as_string : str<4>) { - println(message); - assert(message == "hello world"); - assert(hex_as_string == "0x41"); -} -``` - -You can convert a `str` to a byte array by calling `as_bytes()` -or a vector by calling `as_bytes_vec()`. - -```rust -fn main() { - let message = "hello world"; - let message_bytes = message.as_bytes(); - let mut message_vec = message.as_bytes_vec(); - assert(message_bytes.len() == 11); - assert(message_bytes[0] == 104); - assert(message_bytes[0] == message_vec.get(0)); -} -``` - -## Escape characters - -You can use escape characters for your strings: - -| Escape Sequence | Description | -|-----------------|-----------------| -| `\r` | Carriage Return | -| `\n` | Newline | -| `\t` | Tab | -| `\0` | Null Character | -| `\"` | Double Quote | -| `\\` | Backslash | - -Example: - -```rust -let s = "Hello \"world" // prints "Hello "world" -let s = "hey \tyou"; // prints "hey you" -``` - -## Raw strings - -A raw string begins with the letter `r` and is optionally delimited by a number of hashes `#`. - -Escape characters are *not* processed within raw strings. All contents are interpreted literally. - -Example: - -```rust -let s = r"Hello world"; -let s = r#"Simon says "hello world""#; - -// Any number of hashes may be used (>= 1) as long as the string also terminates with the same number of hashes -let s = r#####"One "#, Two "##, Three "###, Four "####, Five will end the string."#####; -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/structs.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/structs.md deleted file mode 100644 index dbf68c99813..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/structs.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -title: Structs -description: - Explore the Struct data type in Noir. Learn about its methods, see real-world examples, and grasp how to effectively define and use Structs in your Noir programs. -keywords: - [ - noir, - struct type, - methods, - examples, - data structures, - ] -sidebar_position: 8 ---- - -A struct also allows for grouping multiple values of different types. Unlike tuples, we can also -name each field. - -> **Note:** The usage of _field_ here refers to each element of the struct and is unrelated to the -> field type of Noir. - -Defining a struct requires giving it a name and listing each field within as `: ` pairs: - -```rust -struct Animal { - hands: Field, - legs: Field, - eyes: u8, -} -``` - -An instance of a struct can then be created with actual values in `: ` pairs in any -order. Struct fields are accessible using their given names: - -```rust -fn main() { - let legs = 4; - - let dog = Animal { - eyes: 2, - hands: 0, - legs, - }; - - let zero = dog.hands; -} -``` - -Structs can also be destructured in a pattern, binding each field to a new variable: - -```rust -fn main() { - let Animal { hands, legs: feet, eyes } = get_octopus(); - - let ten = hands + feet + eyes as u8; -} - -fn get_octopus() -> Animal { - let octopus = Animal { - hands: 0, - legs: 8, - eyes: 2, - }; - - octopus -} -``` - -The new variables can be bound with names different from the original struct field names, as -showcased in the `legs --> feet` binding in the example above. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/tuples.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/tuples.md deleted file mode 100644 index 2ec5c9c4113..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/tuples.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Tuples -description: - Dive into the Tuple data type in Noir. Understand its methods, practical examples, and best practices for efficiently using Tuples in your Noir code. -keywords: - [ - noir, - tuple type, - methods, - examples, - multi-value containers, - ] -sidebar_position: 7 ---- - -A tuple collects multiple values like an array, but with the added ability to collect values of -different types: - -```rust -fn main() { - let tup: (u8, u64, Field) = (255, 500, 1000); -} -``` - -One way to access tuple elements is via destructuring using pattern matching: - -```rust -fn main() { - let tup = (1, 2); - - let (one, two) = tup; - - let three = one + two; -} -``` - -Another way to access tuple elements is via direct member access, using a period (`.`) followed by -the index of the element we want to access. Index `0` corresponds to the first tuple element, `1` to -the second and so on: - -```rust -fn main() { - let tup = (5, 6, 7, 8); - - let five = tup.0; - let eight = tup.3; -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/distinct.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/distinct.md deleted file mode 100644 index 6c993b8b5e0..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/distinct.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: Distinct Witnesses -sidebar_position: 11 ---- - -The `distinct` keyword prevents repetitions of witness indices in the program's ABI. This ensures -that the witnesses being returned as public inputs are all unique. - -The `distinct` keyword is only used for return values on program entry points (usually the `main()` -function). - -When using `distinct` and `pub` simultaneously, `distinct` comes first. See the example below. - -You can read more about the problem this solves -[here](https://github.com/noir-lang/noir/issues/1183). - -## Example - -Without the `distinct` keyword, the following program - -```rust -fn main(x : pub Field, y : pub Field) -> pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - "return_witnesses": [3, 2, 4, 4] - } -} -``` - -Whereas (with the `distinct` keyword) - -```rust -fn main(x : pub Field, y : pub Field) -> distinct pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - //... - "return_witnesses": [3, 4, 5, 6] - } -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/functions.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/functions.md deleted file mode 100644 index 2c9bc33fdfc..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/functions.md +++ /dev/null @@ -1,226 +0,0 @@ ---- -title: Functions -description: - Learn how to declare functions and methods in Noir, a programming language with Rust semantics. - This guide covers parameter declaration, return types, call expressions, and more. -keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] -sidebar_position: 1 ---- - -Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. - -To declare a function the `fn` keyword is used. - -```rust -fn foo() {} -``` - -By default, functions are visible only within the package they are defined. To make them visible outside of that package (for example, as part of a [library](../modules_packages_crates/crates_and_packages.md#libraries)), you should mark them as `pub`: - -```rust -pub fn foo() {} -``` - -You can also restrict the visibility of the function to only the crate it was defined in, by specifying `pub(crate)`: - -```rust -pub(crate) fn foo() {} //foo can only be called within its crate -``` - -All parameters in a function must have a type and all types are known at compile time. The parameter -is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. - -```rust -fn foo(x : Field, y : Field){} -``` - -The return type of a function can be stated by using the `->` arrow notation. The function below -states that the foo function must return a `Field`. If the function returns no value, then the arrow -is omitted. - -```rust -fn foo(x : Field, y : Field) -> Field { - x + y -} -``` - -Note that a `return` keyword is unneeded in this case - the last expression in a function's body is -returned. - -## Main function - -If you're writing a binary, the `main` function is the starting point of your program. You can pass all types of expressions to it, as long as they have a fixed size at compile time: - -```rust -fn main(x : Field) // this is fine: passing a Field -fn main(x : [Field; 2]) // this is also fine: passing a Field with known size at compile-time -fn main(x : (Field, bool)) // 👌: passing a (Field, bool) tuple means size 2 -fn main(x : str<5>) // this is fine, as long as you pass a string of size 5 - -fn main(x : Vec) // can't compile, has variable size -fn main(x : [Field]) // can't compile, has variable size -fn main(....// i think you got it by now -``` - -Keep in mind [tests](../../getting_started/tooling/testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: - -```rust -fn main(x : [Field]) { - assert(x[0] == 1); -} - -#[test] -fn test_one() { - main(&[1, 2]); -} -``` - -```bash -$ nargo test -[testing] Running 1 test functions -[testing] Testing test_one... ok -[testing] All tests passed - -$ nargo check -The application panicked (crashed). -Message: Cannot have variable sized arrays as a parameter to main -``` - -## Call Expressions - -Calling a function in Noir is executed by using the function name and passing in the necessary -arguments. - -Below we show how to call the `foo` function from the `main` function using a call expression: - -```rust -fn main(x : Field, y : Field) { - let z = foo(x); -} - -fn foo(x : Field) -> Field { - x + x -} -``` - -## Methods - -You can define methods in Noir on any struct type in scope. - -```rust -struct MyStruct { - foo: Field, - bar: Field, -} - -impl MyStruct { - fn new(foo: Field) -> MyStruct { - MyStruct { - foo, - bar: 2, - } - } - - fn sum(self) -> Field { - self.foo + self.bar - } -} - -fn main() { - let s = MyStruct::new(40); - assert(s.sum() == 42); -} -``` - -Methods are just syntactic sugar for functions, so if we wanted to we could also call `sum` as -follows: - -```rust -assert(MyStruct::sum(s) == 42); -``` - -It is also possible to specialize which method is chosen depending on the [generic](./generics.md) type that is used. In this example, the `foo` function returns different values depending on its type: - -```rust -struct Foo {} - -impl Foo { - fn foo(self) -> Field { 1 } -} - -impl Foo { - fn foo(self) -> Field { 2 } -} - -fn main() { - let f1: Foo = Foo{}; - let f2: Foo = Foo{}; - assert(f1.foo() + f2.foo() == 3); -} -``` - -Also note that impls with the same method name defined in them cannot overlap. For example, if we already have `foo` defined for `Foo` and `Foo` like we do above, we cannot also define `foo` in an `impl Foo` since it would be ambiguous which version of `foo` to choose. - -```rust -// Including this impl in the same project as the above snippet would -// cause an overlapping impls error -impl Foo { - fn foo(self) -> Field { 3 } -} -``` - -## Lambdas - -Lambdas are anonymous functions. They follow the syntax of Rust - `|arg1, arg2, ..., argN| return_expression`. - -```rust -let add_50 = |val| val + 50; -assert(add_50(100) == 150); -``` - -See [Lambdas](./lambdas.md) for more details. - -## Attributes - -Attributes are metadata that can be applied to a function, using the following syntax: `#[attribute(value)]`. - -Supported attributes include: - -- **builtin**: the function is implemented by the compiler, for efficiency purposes. -- **deprecated**: mark the function as _deprecated_. Calling the function will generate a warning: `warning: use of deprecated function` -- **field**: Used to enable conditional compilation of code depending on the field size. See below for more details -- **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./unconstrained.md) and [NoirJS](../../reference/NoirJS/noir_js/index.md) for more details. -- **test**: mark the function as unit tests. See [Tests](../../getting_started/tooling/testing.md) for more details - -### Field Attribute - -The field attribute defines which field the function is compatible for. The function is conditionally compiled, under the condition that the field attribute matches the Noir native field. -The field can be defined implicitly, by using the name of the elliptic curve usually associated to it - for instance bn254, bls12_381 - or explicitly by using the field (prime) order, in decimal or hexadecimal form. -As a result, it is possible to define multiple versions of a function with each version specialized for a different field attribute. This can be useful when a function requires different parameters depending on the underlying elliptic curve. - -Example: we define the function `foo()` three times below. Once for the default Noir bn254 curve, once for the field $\mathbb F_{23}$, which will normally never be used by Noir, and once again for the bls12_381 curve. - -```rust -#[field(bn254)] -fn foo() -> u32 { - 1 -} - -#[field(23)] -fn foo() -> u32 { - 2 -} - -// This commented code would not compile as foo would be defined twice because it is the same field as bn254 -// #[field(21888242871839275222246405745257275088548364400416034343698204186575808495617)] -// fn foo() -> u32 { -// 2 -// } - -#[field(bls12_381)] -fn foo() -> u32 { - 3 -} -``` - -If the field name is not known to Noir, it will discard the function. Field names are case insensitive. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/generics.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/generics.md deleted file mode 100644 index 0c1c27a2221..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/generics.md +++ /dev/null @@ -1,106 +0,0 @@ ---- -title: Generics -description: Learn how to use Generics in Noir -keywords: [Noir, Rust, generics, functions, structs] -sidebar_position: 7 ---- - -Generics allow you to use the same functions with multiple different concrete data types. You can -read more about the concept of generics in the Rust documentation -[here](https://doc.rust-lang.org/book/ch10-01-syntax.html). - -Here is a trivial example showing the identity function that supports any type. In Rust, it is -common to refer to the most general type as `T`. We follow the same convention in Noir. - -```rust -fn id(x: T) -> T { - x -} -``` - -## In Structs - -Generics are useful for specifying types in structs. For example, we can specify that a field in a -struct will be of a certain generic type. In this case `value` is of type `T`. - -```rust -struct RepeatedValue { - value: T, - count: Field, -} - -impl RepeatedValue { - fn print(self) { - for _i in 0 .. self.count { - println(self.value); - } - } -} - -fn main() { - let repeated = RepeatedValue { value: "Hello!", count: 2 }; - repeated.print(); -} -``` - -The `print` function will print `Hello!` an arbitrary number of times, twice in this case. - -If we want to be generic over array lengths (which are type-level integers), we can use numeric -generics. Using these looks just like using regular generics, but these generics can resolve to -integers at compile-time, rather than resolving to types. Here's an example of a struct that is -generic over the size of the array it contains internally: - -```rust -struct BigInt { - limbs: [u32; N], -} - -impl BigInt { - // `N` is in scope of all methods in the impl - fn first(first: BigInt, second: BigInt) -> Self { - assert(first.limbs != second.limbs); - first - - fn second(first: BigInt, second: Self) -> Self { - assert(first.limbs != second.limbs); - second - } -} -``` - -## Calling functions on generic parameters - -Since a generic type `T` can represent any type, how can we call functions on the underlying type? -In other words, how can we go from "any type `T`" to "any type `T` that has certain methods available?" - -This is what [traits](../concepts/traits.md) are for in Noir. Here's an example of a function generic over -any type `T` that implements the `Eq` trait for equality: - -```rust -fn first_element_is_equal(array1: [T; N], array2: [T; N]) -> bool - where T: Eq -{ - if (array1.len() == 0) | (array2.len() == 0) { - true - } else { - array1[0] == array2[0] - } -} - -fn main() { - assert(first_element_is_equal([1, 2, 3], [1, 5, 6])); - - // We can use first_element_is_equal for arrays of any type - // as long as we have an Eq impl for the types we pass in - let array = [MyStruct::new(), MyStruct::new()]; - assert(array_eq(array, array, MyStruct::eq)); -} - -impl Eq for MyStruct { - fn eq(self, other: MyStruct) -> bool { - self.foo == other.foo - } -} -``` - -You can find more details on traits and trait implementations on the [traits page](../concepts/traits.md). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/globals.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/globals.md deleted file mode 100644 index 063a3d89248..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/globals.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -title: Global Variables -description: - Learn about global variables in Noir. Discover how - to declare, modify, and use them in your programs. -keywords: [noir programming language, globals, global variables, constants] -sidebar_position: 8 ---- - -## Globals - - -Noir supports global variables. The global's type can be inferred by the compiler entirely: - -```rust -global N = 5; // Same as `global N: Field = 5` - -global TUPLE = (3, 2); - -fn main() { - assert(N == 5); - assert(N == TUPLE.0 + TUPLE.1); -} -``` - -:::info - -Globals can be defined as any expression, so long as they don't depend on themselves - otherwise there would be a dependency cycle! For example: - -```rust -global T = foo(T); // dependency error -``` - -::: - - -If they are initialized to a literal integer, globals can be used to specify an array's length: - -```rust -global N: Field = 2; - -fn main(y : [Field; N]) { - assert(y[0] == y[1]) -} -``` - -A global from another module can be imported or referenced externally like any other name: - -```rust -global N = 20; - -fn main() { - assert(my_submodule::N != N); -} - -mod my_submodule { - global N: Field = 10; -} -``` - -When a global is used, Noir replaces the name with its definition on each occurrence. -This means globals defined using function calls will repeat the call each time they're used: - -```rust -global RESULT = foo(); - -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. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/lambdas.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/lambdas.md deleted file mode 100644 index be3c7e0b5ca..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/lambdas.md +++ /dev/null @@ -1,81 +0,0 @@ ---- -title: Lambdas -description: Learn how to use anonymous functions in Noir programming language. -keywords: [Noir programming language, lambda, closure, function, anonymous function] -sidebar_position: 9 ---- - -## Introduction - -Lambdas are anonymous functions. The syntax is `|arg1, arg2, ..., argN| return_expression`. - -```rust -let add_50 = |val| val + 50; -assert(add_50(100) == 150); -``` - -A block can be used as the body of a lambda, allowing you to declare local variables inside it: - -```rust -let cool = || { - let x = 100; - let y = 100; - x + y -} - -assert(cool() == 200); -``` - -## Closures - -Inside the body of a lambda, you can use variables defined in the enclosing function. Such lambdas are called **closures**. In this example `x` is defined inside `main` and is accessed from within the lambda: - -```rust -fn main() { - let x = 100; - let closure = || x + 150; - assert(closure() == 250); -} -``` - -## Passing closures to higher-order functions - -It may catch you by surprise that the following code fails to compile: - -```rust -fn foo(f: fn () -> Field) -> Field { - f() -} - -fn main() { - let (x, y) = (50, 50); - assert(foo(|| x + y) == 100); // error :( -} -``` - -The reason is that the closure's capture environment affects its type - we have a closure that captures two Fields and `foo` -expects a regular function as an argument - those are incompatible. -:::note - -Variables contained within the `||` are the closure's parameters, and the expression that follows it is the closure's body. The capture environment is comprised of any variables used in the closure's body that are not parameters. - -E.g. in |x| x + y, y would be a captured variable, but x would not be, since it is a parameter of the closure. - -::: -The syntax for the type of a closure is `fn[env](args) -> ret_type`, where `env` is the capture environment of the closure - -in this example that's `(Field, Field)`. - -The best solution in our case is to make `foo` generic over the environment type of its parameter, so that it can be called -with closures with any environment, as well as with regular functions: - -```rust -fn foo(f: fn[Env]() -> Field) -> Field { - f() -} - -fn main() { - let (x, y) = (50, 50); - assert(foo(|| x + y) == 100); // compiles fine - assert(foo(|| 60) == 60); // compiles fine -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/mutability.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/mutability.md deleted file mode 100644 index fdeef6a87c5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/mutability.md +++ /dev/null @@ -1,121 +0,0 @@ ---- -title: Mutability -description: - Learn about mutable variables in Noir. Discover how - to declare, modify, and use them in your programs. -keywords: [noir programming language, mutability in noir, mutable variables] -sidebar_position: 8 ---- - -Variables in noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned -to via an assignment expression. - -```rust -let x = 2; -x = 3; // error: x must be mutable to be assigned to - -let mut y = 3; -let y = 4; // OK -``` - -The `mut` modifier can also apply to patterns: - -```rust -let (a, mut b) = (1, 2); -a = 11; // error: a must be mutable to be assigned to -b = 12; // OK - -let mut (c, d) = (3, 4); -c = 13; // OK -d = 14; // OK - -// etc. -let MyStruct { x: mut y } = MyStruct { x: a }; -// y is now in scope -``` - -Note that mutability in noir is local and everything is passed by value, so if a called function -mutates its parameters then the parent function will keep the old value of the parameters. - -```rust -fn main() -> pub Field { - let x = 3; - helper(x); - x // x is still 3 -} - -fn helper(mut x: i32) { - x = 4; -} -``` - -## Non-local mutability - -Non-local mutability can be achieved through the mutable reference type `&mut T`: - -```rust -fn set_to_zero(x: &mut Field) { - *x = 0; -} - -fn main() { - let mut y = 42; - set_to_zero(&mut y); - assert(*y == 0); -} -``` - -When creating a mutable reference, the original variable being referred to (`y` in this -example) must also be mutable. Since mutable references are a reference type, they must -be explicitly dereferenced via `*` to retrieve the underlying value. Note that this yields -a copy of the value, so mutating this copy will not change the original value behind the -reference: - -```rust -fn main() { - let mut x = 1; - let x_ref = &mut x; - - let mut y = *x_ref; - let y_ref = &mut y; - - x = 2; - *x_ref = 3; - - y = 4; - *y_ref = 5; - - assert(x == 3); - assert(*x_ref == 3); - assert(y == 5); - assert(*y_ref == 5); -} -``` - -Note that types in Noir are actually deeply immutable so the copy that occurs when -dereferencing is only a conceptual copy - no additional constraints will occur. - -Mutable references can also be stored within structs. Note that there is also -no lifetime parameter on these unlike rust. This is because the allocated memory -always lasts the entire program - as if it were an array of one element. - -```rust -struct Foo { - x: &mut Field -} - -impl Foo { - fn incr(mut self) { - *self.x += 1; - } -} - -fn main() { - let foo = Foo { x: &mut 0 }; - foo.incr(); - assert(*foo.x == 1); -} -``` - -In general, you should avoid non-local & shared mutability unless it is needed. Sticking -to only local mutability will improve readability and potentially improve compiler optimizations as well. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/ops.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/ops.md deleted file mode 100644 index 60425cb8994..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/ops.md +++ /dev/null @@ -1,98 +0,0 @@ ---- -title: Logical Operations -description: - Learn about the supported arithmetic and logical operations in the Noir programming language. - Discover how to perform operations on private input types, integers, and booleans. -keywords: - [ - Noir programming language, - supported operations, - arithmetic operations, - logical operations, - predicate operators, - bitwise operations, - short-circuiting, - backend, - ] -sidebar_position: 3 ---- - -# Operations - -## Table of Supported Operations - -| Operation | Description | Requirements | -| :-------- | :------------------------------------------------------------: | -------------------------------------: | -| + | Adds two private input types together | Types must be private input | -| - | Subtracts two private input types together | Types must be private input | -| \* | Multiplies two private input types together | Types must be private input | -| / | Divides two private input types together | Types must be private input | -| ^ | XOR two private input types together | Types must be integer | -| & | AND two private input types together | Types must be integer | -| \| | OR two private input types together | Types must be integer | -| \<\< | Left shift an integer by another integer amount | Types must be integer | -| >> | Right shift an integer by another integer amount | Types must be integer | -| ! | Bitwise not of a value | Type must be integer or boolean | -| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | -| > | returns a bool if one value is more than the other | Upper bound must have a known bit size | -| >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | -| == | returns a bool if one value is equal to the other | Both types must not be constants | -| != | returns a bool if one value is not equal to the other | Both types must not be constants | - -### Predicate Operators - -`<,<=, !=, == , >, >=` are known as predicate/comparison operations because they compare two values. -This differs from the operations such as `+` where the operands are used in _computation_. - -### Bitwise Operations Example - -```rust -fn main(x : Field) { - let y = x as u32; - let z = y & y; -} -``` - -`z` is implicitly constrained to be the result of `y & y`. The `&` operand is used to denote bitwise -`&`. - -> `x & x` would not compile as `x` is a `Field` and not an integer type. - -### Logical Operators - -Noir has no support for the logical operators `||` and `&&`. This is because encoding the -short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can -use the bitwise operators `|` and `&` which operate identically for booleans, just without the -short-circuiting. - -```rust -let my_val = 5; - -let mut flag = 1; -if (my_val > 6) | (my_val == 0) { - flag = 0; -} -assert(flag == 1); - -if (my_val != 10) & (my_val < 50) { - flag = 0; -} -assert(flag == 0); -``` - -### Shorthand operators - -Noir shorthand operators for most of the above operators, namely `+=, -=, *=, /=, %=, &=, |=, ^=, <<=`, and `>>=`. These allow for more concise syntax. For example: - -```rust -let mut i = 0; -i = i + 1; -``` - -could be written as: - -```rust -let mut i = 0; -i += 1; -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/oracles.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/oracles.md deleted file mode 100644 index 2e6a6818d48..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/oracles.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: Oracles -description: Dive into how Noir supports Oracles via RPC calls, and learn how to declare an Oracle in Noir with our comprehensive guide. -keywords: - - Noir - - Oracles - - RPC Calls - - Unconstrained Functions - - Programming - - Blockchain -sidebar_position: 6 ---- - -Noir has support for Oracles via RPC calls. This means Noir will make an RPC call and use the return value for proof generation. - -Since Oracles are not resolved by Noir, they are [`unconstrained` functions](./unconstrained.md) - -You can declare an Oracle through the `#[oracle()]` flag. Example: - -```rust -#[oracle(get_number_sequence)] -unconstrained fn get_number_sequence(_size: Field) -> [Field] {} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/shadowing.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/shadowing.md deleted file mode 100644 index 5ce6130d201..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/shadowing.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Shadowing -sidebar_position: 12 ---- - -Noir allows for inheriting variables' values and re-declaring them with the same name similar to Rust, known as shadowing. - -For example, the following function is valid in Noir: - -```rust -fn main() { - let x = 5; - - { - let x = x * 2; - assert (x == 10); - } - - assert (x == 5); -} -``` - -In this example, a variable x is first defined with the value 5. - -The local scope that follows shadows the original x, i.e. creates a local mutable x based on the value of the original x. It is given a value of 2 times the original x. - -When we return to the main scope, x once again refers to just the original x, which stays at the value of 5. - -## Temporal mutability - -One way that shadowing is useful, in addition to ergonomics across scopes, is for temporarily mutating variables. - -```rust -fn main() { - let age = 30; - // age = age + 5; // Would error as `age` is immutable by default. - - let mut age = age + 5; // Temporarily mutates `age` with a new value. - - let age = age; // Locks `age`'s mutability again. - - assert (age == 35); -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/traits.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/traits.md deleted file mode 100644 index ef1445a5907..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/traits.md +++ /dev/null @@ -1,389 +0,0 @@ ---- -title: Traits -description: - Traits in Noir can be used to abstract out a common interface for functions across - several data types. -keywords: [noir programming language, traits, interfaces, generic, protocol] -sidebar_position: 14 ---- - -## Overview - -Traits in Noir are a useful abstraction similar to interfaces or protocols in other languages. Each trait defines -the interface of several methods contained within the trait. Types can then implement this trait by providing -implementations for these methods. For example in the program: - -```rust -struct Rectangle { - width: Field, - height: Field, -} - -impl Rectangle { - fn area(self) -> Field { - self.width * self.height - } -} - -fn log_area(r: Rectangle) { - println(r.area()); -} -``` - -We have a function `log_area` to log the area of a `Rectangle`. Now how should we change the program if we want this -function to work on `Triangle`s as well?: - -```rust -struct Triangle { - width: Field, - height: Field, -} - -impl Triangle { - fn area(self) -> Field { - self.width * self.height / 2 - } -} -``` - -Making `log_area` generic over all types `T` would be invalid since not all types have an `area` method. Instead, we can -introduce a new `Area` trait and make `log_area` generic over all types `T` that implement `Area`: - -```rust -trait Area { - fn area(self) -> Field; -} - -fn log_area(shape: T) where T: Area { - println(shape.area()); -} -``` - -We also need to explicitly implement `Area` for `Rectangle` and `Triangle`. We can do that by changing their existing -impls slightly. Note that the parameter types and return type of each of our `area` methods must match those defined -by the `Area` trait. - -```rust -impl Area for Rectangle { - fn area(self) -> Field { - self.width * self.height - } -} - -impl Area for Triangle { - fn area(self) -> Field { - self.width * self.height / 2 - } -} -``` - -Now we have a working program that is generic over any type of Shape that is used! Others can even use this program -as a library with their own types - such as `Circle` - as long as they also implement `Area` for these types. - -## Where Clauses - -As seen in `log_area` above, when we want to create a function or method that is generic over any type that implements -a trait, we can add a where clause to the generic function. - -```rust -fn log_area(shape: T) where T: Area { - println(shape.area()); -} -``` - -It is also possible to apply multiple trait constraints on the same variable at once by combining traits with the `+` -operator. Similarly, we can have multiple trait constraints by separating each with a comma: - -```rust -fn foo(elements: [T], thing: U) where - T: Default + Add + Eq, - U: Bar, -{ - let mut sum = T::default(); - - for element in elements { - sum += element; - } - - if sum == T::default() { - thing.bar(); - } -} -``` - -## Generic Implementations - -You can add generics to a trait implementation by adding the generic list after the `impl` keyword: - -```rust -trait Second { - fn second(self) -> Field; -} - -impl Second for (T, Field) { - fn second(self) -> Field { - self.1 - } -} -``` - -You can also implement a trait for every type this way: - -```rust -trait Debug { - fn debug(self); -} - -impl Debug for T { - fn debug(self) { - println(self); - } -} - -fn main() { - 1.debug(); -} -``` - -### Generic Trait Implementations With Where Clauses - -Where clauses can also be placed on trait implementations themselves to restrict generics in a similar way. -For example, while `impl Foo for T` implements the trait `Foo` for every type, `impl Foo for T where T: Bar` -will implement `Foo` only for types that also implement `Bar`. This is often used for implementing generic types. -For example, here is the implementation for array equality: - -```rust -impl Eq for [T; N] where T: Eq { - // Test if two arrays have the same elements. - // Because both arrays must have length N, we know their lengths already match. - fn eq(self, other: Self) -> bool { - let mut result = true; - - for i in 0 .. self.len() { - // The T: Eq constraint is needed to call == on the array elements here - result &= self[i] == other[i]; - } - - result - } -} -``` - -## Generic Traits - -Traits themselves can also be generic by placing the generic arguments after the trait name. These generics are in -scope of every item within the trait. - -```rust -trait Into { - // Convert `self` to type `T` - fn into(self) -> T; -} -``` - -When implementing generic traits the generic arguments of the trait must be specified. This is also true anytime -when referencing a generic trait (e.g. in a `where` clause). - -```rust -struct MyStruct { - array: [Field; 2], -} - -impl Into<[Field; 2]> for MyStruct { - fn into(self) -> [Field; 2] { - self.array - } -} - -fn as_array(x: T) -> [Field; 2] - where T: Into<[Field; 2]> -{ - x.into() -} - -fn main() { - let array = [1, 2]; - let my_struct = MyStruct { array }; - - assert_eq(as_array(my_struct), array); -} -``` - -## Trait Methods With No `self` - -A trait can contain any number of methods, each of which have access to the `Self` type which represents each type -that eventually implements the trait. Similarly, the `self` variable is available as well but is not required to be used. -For example, we can define a trait to create a default value for a type. This trait will need to return the `Self` type -but doesn't need to take any parameters: - -```rust -trait Default { - fn default() -> Self; -} -``` - -Implementing this trait can be done similarly to any other trait: - -```rust -impl Default for Field { - fn default() -> Field { - 0 - } -} - -struct MyType {} - -impl Default for MyType { - fn default() -> Field { - MyType {} - } -} -``` - -However, since there is no `self` parameter, we cannot call it via the method call syntax `object.method()`. -Instead, we'll need to refer to the function directly. This can be done either by referring to the -specific impl `MyType::default()` or referring to the trait itself `Default::default()`. In the later -case, type inference determines the impl that is selected. - -```rust -let my_struct = MyStruct::default(); - -let x: Field = Default::default(); -let result = x + Default::default(); -``` - -:::warning - -```rust -let _ = Default::default(); -``` - -If type inference cannot select which impl to use because of an ambiguous `Self` type, an impl will be -arbitrarily selected. This occurs most often when the result of a trait function call with no parameters -is unused. To avoid this, when calling a trait function with no `self` or `Self` parameters or return type, -always refer to it via the implementation type's namespace - e.g. `MyType::default()`. -This is set to change to an error in future Noir versions. - -::: - -## Default Method Implementations - -A trait can also have default implementations of its methods by giving a body to the desired functions. -Note that this body must be valid for all types that may implement the trait. As a result, the only -valid operations on `self` will be operations valid for any type or other operations on the trait itself. - -```rust -trait Numeric { - fn add(self, other: Self) -> Self; - - // Default implementation of double is (self + self) - fn double(self) -> Self { - self.add(self) - } -} -``` - -When implementing a trait with default functions, a type may choose to implement only the required functions: - -```rust -impl Numeric for Field { - fn add(self, other: Field) -> Field { - self + other - } -} -``` - -Or it may implement the optional methods as well: - -```rust -impl Numeric for u32 { - fn add(self, other: u32) -> u32 { - self + other - } - - fn double(self) -> u32 { - self * 2 - } -} -``` - -## Impl Specialization - -When implementing traits for a generic type it is possible to implement the trait for only a certain combination -of generics. This can be either as an optimization or because those specific generics are required to implement the trait. - -```rust -trait Sub { - fn sub(self, other: Self) -> Self; -} - -struct NonZero { - value: T, -} - -impl Sub for NonZero { - fn sub(self, other: Self) -> Self { - let value = self.value - other.value; - assert(value != 0); - NonZero { value } - } -} -``` - -## Overlapping Implementations - -Overlapping implementations are disallowed by Noir to ensure Noir's decision on which impl to select is never ambiguous. -This means if a trait `Foo` is already implemented -by a type `Bar` for all `T`, then we cannot also have a separate impl for `Bar` (or any other -type argument). Similarly, if there is an impl for all `T` such as `impl Debug for T`, we cannot create -any more impls to `Debug` for other types since it would be ambiguous which impl to choose for any given -method call. - -```rust -trait Trait {} - -// Previous impl defined here -impl Trait for (A, B) {} - -// error: Impl for type `(Field, Field)` overlaps with existing impl -impl Trait for (Field, Field) {} -``` - -## Trait Coherence - -Another restriction on trait implementations is coherence. This restriction ensures other crates cannot create -impls that may overlap with other impls, even if several unrelated crates are used as dependencies in the same -program. - -The coherence restriction is: to implement a trait, either the trait itself or the object type must be declared -in the crate the impl is in. - -In practice this often comes up when using types provided by libraries. If a library provides a type `Foo` that does -not implement a trait in the standard library such as `Default`, you may not `impl Default for Foo` in your own crate. -While restrictive, this prevents later issues or silent changes in the program if the `Foo` library later added its -own impl for `Default`. If you are a user of the `Foo` library in this scenario and need a trait not implemented by the -library your choices are to either submit a patch to the library or use the newtype pattern. - -### The Newtype Pattern - -The newtype pattern gets around the coherence restriction by creating a new wrapper type around the library type -that we cannot create `impl`s for. Since the new wrapper type is defined in our current crate, we can create -impls for any trait we need on it. - -```rust -struct Wrapper { - foo: dep::some_library::Foo, -} - -impl Default for Wrapper { - fn default() -> Wrapper { - Wrapper { - foo: dep::some_library::Foo::new(), - } - } -} -``` - -Since we have an impl for our own type, the behavior of this code will not change even if `some_library` is updated -to provide its own `impl Default for Foo`. The downside of this pattern is that it requires extra wrapping and -unwrapping of values when converting to and from the `Wrapper` and `Foo` types. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/_category_.json deleted file mode 100644 index 1debcfe7675..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Modules, Packages and Crates", - "position": 2, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/crates_and_packages.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/crates_and_packages.md deleted file mode 100644 index 95ee9f52ab2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/crates_and_packages.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Crates and Packages -description: Learn how to use Crates and Packages in your Noir project -keywords: [Nargo, dependencies, package management, crates, package] -sidebar_position: 0 ---- - -## Crates - -A crate is the smallest amount of code that the Noir compiler considers at a time. -Crates can contain modules, and the modules may be defined in other files that get compiled with the crate, as we’ll see in the coming sections. - -### Crate Types - -A Noir crate can come in several forms: binaries, libraries or contracts. - -#### Binaries - -_Binary crates_ are programs which you can compile to an ACIR circuit which you can then create proofs against. Each must have a function called `main` that defines the ACIR circuit which is to be proved. - -#### Libraries - -_Library crates_ don't have a `main` function and they don't compile down to ACIR. Instead they define functionality intended to be shared with multiple projects, and eventually included in a binary crate. - -#### Contracts - -Contract crates are similar to binary crates in that they compile to ACIR which you can create proofs against. They are different in that they do not have a single `main` function, but are a collection of functions to be deployed to the [Aztec network](https://aztec.network). You can learn more about the technical details of Aztec in the [monorepo](https://github.com/AztecProtocol/aztec-packages) or contract [examples](https://github.com/AztecProtocol/aztec-packages/tree/master/noir-projects/noir-contracts/contracts). - -### Crate Root - -Every crate has a root, which is the source file that the compiler starts, this is also known as the root module. The Noir compiler does not enforce any conditions on the name of the file which is the crate root, however if you are compiling via Nargo the crate root must be called `lib.nr` or `main.nr` for library or binary crates respectively. - -## Packages - -A Nargo _package_ is a collection of one of more crates that provides a set of functionality. A package must include a Nargo.toml file. - -A package _must_ contain either a library or a binary crate, but not both. - -### Differences from Cargo Packages - -One notable difference between Rust's Cargo and Noir's Nargo is that while Cargo allows a package to contain an unlimited number of binary crates and a single library crate, Nargo currently only allows a package to contain a single crate. - -In future this restriction may be lifted to allow a Nargo package to contain both a binary and library crate or multiple binary crates. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/dependencies.md deleted file mode 100644 index 2c028d85853..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/dependencies.md +++ /dev/null @@ -1,124 +0,0 @@ ---- -title: Dependencies -description: - Learn how to specify and manage dependencies in Nargo, allowing you to upload packages to GitHub - and use them easily in your project. -keywords: [Nargo, dependencies, GitHub, package management, versioning] -sidebar_position: 1 ---- - -Nargo allows you to upload packages to GitHub and use them as dependencies. - -## Specifying a dependency - -Specifying a dependency requires a tag to a specific commit and the git url to the url containing -the package. - -Currently, there are no requirements on the tag contents. If requirements are added, it would follow -semver 2.0 guidelines. - -> Note: Without a `tag` , there would be no versioning and dependencies would change each time you -> compile your project. - -For example, to add the [ecrecover-noir library](https://github.com/colinnielsen/ecrecover-noir) to your project, add it to `Nargo.toml`: - -```toml -# Nargo.toml - -[dependencies] -ecrecover = {tag = "v0.8.0", git = "https://github.com/colinnielsen/ecrecover-noir"} -``` - -If the module is in a subdirectory, you can define a subdirectory in your git repository, for example: - -```toml -# Nargo.toml - -[dependencies] -easy_private_token_contract = {tag ="v0.1.0-alpha62", git = "https://github.com/AztecProtocol/aztec-packages", directory = "noir-contracts/contracts/easy_private_token_contract"} -``` - -## Specifying a local dependency - -You can also specify dependencies that are local to your machine. - -For example, this file structure has a library and binary crate - -```tree -├── binary_crate -│   ├── Nargo.toml -│   └── src -│   └── main.nr -└── lib_a - ├── Nargo.toml - └── src - └── lib.nr -``` - -Inside of the binary crate, you can specify: - -```toml -# Nargo.toml - -[dependencies] -lib_a = { path = "../lib_a" } -``` - -## Importing dependencies - -You can import a dependency to a Noir file using the following syntax. For example, to import the -ecrecover-noir library and local lib_a referenced above: - -```rust -use dep::ecrecover; -use dep::lib_a; -``` - -You can also import only the specific parts of dependency that you want to use, like so: - -```rust -use dep::std::hash::sha256; -use dep::std::scalar_mul::fixed_base_embedded_curve; -``` - -Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you -can import multiple items in the same line by enclosing them in curly braces: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; -``` - -We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. - -Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. - -## Dependencies of Dependencies - -Note that when you import a dependency, you also get access to all of the dependencies of that package. - -For example, the [phy_vector](https://github.com/resurgencelabs/phy_vector) library imports an [fraction](https://github.com/resurgencelabs/fraction) library. If you're importing the phy_vector library, then you can access the functions in fractions library like so: - -```rust -use dep::phy_vector; - -fn main(x : Field, y : pub Field) { - //... - let f = phy_vector::fraction::toFraction(true, 2, 1); - //... -} -``` - -## Available Libraries - -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). - -Some libraries that are available today include: - -- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library -- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) -- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers -- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address -- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees -- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir -- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/modules.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/modules.md deleted file mode 100644 index ae822a1cff4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/modules.md +++ /dev/null @@ -1,105 +0,0 @@ ---- -title: Modules -description: - Learn how to organize your files using modules in Noir, following the same convention as Rust's - module system. Examples included. -keywords: [Noir, Rust, modules, organizing files, sub-modules] -sidebar_position: 2 ---- - -Noir's module system follows the same convention as the _newer_ version of Rust's module system. - -## Purpose of Modules - -Modules are used to organize files. Without modules all of your code would need to live in a single -file. In Noir, the compiler does not automatically scan all of your files to detect modules. This -must be done explicitly by the developer. - -## Examples - -### Importing a module in the crate root - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::hello_world(); -} -``` - -Filename : `src/foo.nr` - -```rust -fn from_foo() {} -``` - -In the above snippet, the crate root is the `src/main.nr` file. The compiler sees the module -declaration `mod foo` which prompts it to look for a foo.nr file. - -Visually this module hierarchy looks like the following : - -``` -crate - ├── main - │ - └── foo - └── from_foo - -``` - -### Importing a module throughout the tree - -All modules are accessible from the `crate::` namespace. - -``` -crate - ├── bar - ├── foo - └── main - -``` - -In the above snippet, if `bar` would like to use functions in `foo`, it can do so by `use crate::foo::function_name`. - -### Sub-modules - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::from_foo(); -} -``` - -Filename : `src/foo.nr` - -```rust -mod bar; -fn from_foo() {} -``` - -Filename : `src/foo/bar.nr` - -```rust -fn from_bar() {} -``` - -In the above snippet, we have added an extra module to the module tree; `bar`. `bar` is a submodule -of `foo` hence we declare bar in `foo.nr` with `mod bar`. Since `foo` is not the crate root, the -compiler looks for the file associated with the `bar` module in `src/foo/bar.nr` - -Visually the module hierarchy looks as follows: - -``` -crate - ├── main - │ - └── foo - ├── from_foo - └── bar - └── from_bar -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/workspaces.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/workspaces.md deleted file mode 100644 index 513497f12bf..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/workspaces.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Workspaces -sidebar_position: 3 ---- - -Workspaces are a feature of nargo that allow you to manage multiple related Noir packages in a single repository. A workspace is essentially a group of related projects that share common build output directories and configurations. - -Each Noir project (with it's own Nargo.toml file) can be thought of as a package. Each package is expected to contain exactly one "named circuit", being the "name" defined in Nargo.toml with the program logic defined in `./src/main.nr`. - -For a project with the following structure: - -```tree -├── crates -│ ├── a -│ │ ├── Nargo.toml -│ │ └── Prover.toml -│ │ └── src -│ │ └── main.nr -│ └── b -│ ├── Nargo.toml -│ └── Prover.toml -│ └── src -│ └── main.nr -│ -└── Nargo.toml -``` - -You can define a workspace in Nargo.toml like so: - -```toml -[workspace] -members = ["crates/a", "crates/b"] -default-member = "crates/a" -``` - -`members` indicates which packages are included in the workspace. As such, all member packages of a workspace will be processed when the `--workspace` flag is used with various commands or if a `default-member` is not specified. - -`default-member` indicates which package various commands process by default. - -Libraries can be defined in a workspace. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. - -Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/_category_.json deleted file mode 100644 index af04c0933fd..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Standard Library", - "position": 1, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/bigint.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/bigint.md deleted file mode 100644 index da6a7cdfd81..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/bigint.md +++ /dev/null @@ -1,119 +0,0 @@ ---- -title: Big Integers -description: How to use big integers from Noir standard library -keywords: - [ - Big Integer, - Noir programming language, - Noir libraries, - ] ---- - -The BigInt module in the standard library exposes some class of integers which do not fit (well) into a Noir native field. It implements modulo arithmetic, modulo a 'big' prime number. - -:::note - -The module can currently be considered as `Field`s with fixed modulo sizes used by a set of elliptic curves, in addition to just the native curve. [More work](https://github.com/noir-lang/noir/issues/510) is needed to achieve arbitrarily sized big integers. - -::: - -Currently 6 classes of integers (i.e 'big' prime numbers) are available in the module, namely: - -- BN254 Fq: Bn254Fq -- BN254 Fr: Bn254Fr -- Secp256k1 Fq: Secpk1Fq -- Secp256k1 Fr: Secpk1Fr -- Secp256r1 Fr: Secpr1Fr -- Secp256r1 Fq: Secpr1Fq - -Where XXX Fq and XXX Fr denote respectively the order of the base and scalar field of the (usual) elliptic curve XXX. -For instance the big integer 'Secpk1Fq' in the standard library refers to integers modulo $2^{256}-2^{32}-977$. - -Feel free to explore the source code for the other primes: - -```rust title="big_int_definition" showLineNumbers -struct BigInt { - pointer: u32, - modulus: u32, -} -``` -> Source code: noir_stdlib/src/bigint.nr#L16-L21 - - -## Example usage - -A common use-case is when constructing a big integer from its bytes representation, and performing arithmetic operations on it: - -```rust title="big_int_example" showLineNumbers -fn big_int_example(x: u8, y: u8) { - let a = Secpk1Fq::from_le_bytes(&[x, y, 0, 45, 2]); - let b = Secpk1Fq::from_le_bytes(&[y, x, 9]); - let c = (a + b) * b / a; - let d = c.to_le_bytes(); - println(d[0]); -} -``` -> Source code: test_programs/execution_success/bigint/src/main.nr#L20-L28 - - -## Methods - -The available operations for each big integer are: - -### from_le_bytes - -Construct a big integer from its little-endian bytes representation. Example: - -```rust - let a = Secpk1Fq::from_le_bytes(&[x, y, 0, 45, 2]); - ``` - -Sure, here's the formatted version of the remaining methods: - -### to_le_bytes - -Return the little-endian bytes representation of a big integer. Example: - -```rust -let bytes = a.to_le_bytes(); -``` - -### add - -Add two big integers. Example: - -```rust -let sum = a + b; -``` - -### sub - -Subtract two big integers. Example: - -```rust -let difference = a - b; -``` - -### mul - -Multiply two big integers. Example: - -```rust -let product = a * b; -``` - -### div - -Divide two big integers. Note that division is field division and not euclidean division. Example: - -```rust -let quotient = a / b; -``` - -### eq - -Compare two big integers. Example: - -```rust -let are_equal = a == b; -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/black_box_fns.md deleted file mode 100644 index e8b62f21d4e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/black_box_fns.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Black Box Functions -description: Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. -keywords: [noir, black box functions] ---- - -Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. This makes certain zk-snark unfriendly computations cheaper than if they were implemented in Noir. - -The ACVM spec defines a set of blackbox functions which backends will be expected to implement. This allows backends to use optimized implementations of these constraints if they have them, however they may also fallback to less efficient naive implementations if not. - -## Function list - -Here is a list of the current black box functions: - -- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) -- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) -- [Blake3](./cryptographic_primitives/hashes.mdx#blake3) -- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash) -- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx) -- AND -- XOR -- RANGE -- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion.md) - -Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. - -You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/noir/blob/master/acvm-repo/acir/src/circuit/black_box_functions.rs). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/bn254.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/bn254.md deleted file mode 100644 index 3294f005dbb..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/bn254.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: Bn254 Field Library ---- - -Noir provides a module in standard library with some optimized functions for bn254 Fr in `std::field::bn254`. - -## decompose - -```rust -fn decompose(x: Field) -> (Field, Field) {} -``` - -Decomposes a single field into two fields, low and high. The low field contains the lower 16 bytes of the input field and the high field contains the upper 16 bytes of the input field. Both field results are range checked to 128 bits. - - -## assert_gt - -```rust -fn assert_gt(a: Field, b: Field) {} -``` - -Asserts that a > b. This will generate less constraints than using `assert(gt(a, b))`. - -## assert_lt - -```rust -fn assert_lt(a: Field, b: Field) {} -``` - -Asserts that a < b. This will generate less constraints than using `assert(lt(a, b))`. - -## gt - -```rust -fn gt(a: Field, b: Field) -> bool {} -``` - -Returns true if a > b. - -## lt - -```rust -fn lt(a: Field, b: Field) -> bool {} -``` - -Returns true if a < b. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/containers/boundedvec.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/containers/boundedvec.md deleted file mode 100644 index ce4529f6e57..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/containers/boundedvec.md +++ /dev/null @@ -1,326 +0,0 @@ ---- -title: Bounded Vectors -keywords: [noir, vector, bounded vector, slice] -sidebar_position: 1 ---- - -A `BoundedVec` is a growable storage similar to a `Vec` except that it -is bounded with a maximum possible length. Unlike `Vec`, `BoundedVec` is not implemented -via slices and thus is not subject to the same restrictions slices are (notably, nested -slices - and thus nested vectors as well - are disallowed). - -Since a BoundedVec is backed by a normal array under the hood, growing the BoundedVec by -pushing an additional element is also more efficient - the length only needs to be increased -by one. - -For these reasons `BoundedVec` should generally be preferred over `Vec` when there -is a reasonable maximum bound that can be placed on the vector. - -Example: - -```rust -let mut vector: BoundedVec = BoundedVec::new(); -for i in 0..5 { - vector.push(i); -} -assert(vector.len() == 5); -assert(vector.max_len() == 10); -``` - -## Methods - -### new - -```rust -pub fn new() -> Self -``` - -Creates a new, empty vector of length zero. - -Since this container is backed by an array internally, it still needs an initial value -to give each element. To resolve this, each element is zeroed internally. This value -is guaranteed to be inaccessible unless `get_unchecked` is used. - -Example: - -```rust -let empty_vector: BoundedVec = BoundedVec::new(); -assert(empty_vector.len() == 0); -``` - -Note that whenever calling `new` the maximum length of the vector should always be specified -via a type signature: - -```rust title="new_example" showLineNumbers -fn foo() -> BoundedVec { - // Ok! MaxLen is specified with a type annotation - let v1: BoundedVec = BoundedVec::new(); - let v2 = BoundedVec::new(); - - // Ok! MaxLen is known from the type of foo's return value - v2 -} - -fn bad() { - let mut v3 = BoundedVec::new(); - - // Not Ok! We don't know if v3's MaxLen is at least 1, and the compiler often infers 0 by default. - v3.push(5); -} -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L11-L27 - - -This defaulting of `MaxLen` (and numeric generics in general) to zero may change in future noir versions -but for now make sure to use type annotations when using bounded vectors. Otherwise, you will receive a constraint failure at runtime when the vec is pushed to. - -### get - -```rust -pub fn get(mut self: Self, index: u64) -> T { -``` - -Retrieves an element from the vector at the given index, starting from zero. - -If the given index is equal to or greater than the length of the vector, this -will issue a constraint failure. - -Example: - -```rust -fn foo(v: BoundedVec) { - let first = v.get(0); - let last = v.get(v.len() - 1); - assert(first != last); -} -``` - -### get_unchecked - -```rust -pub fn get_unchecked(mut self: Self, index: u64) -> T { -``` - -Retrieves an element from the vector at the given index, starting from zero, without -performing a bounds check. - -Since this function does not perform a bounds check on length before accessing the element, -it is unsafe! Use at your own risk! - -Example: - -```rust title="get_unchecked_example" showLineNumbers -fn sum_of_first_three(v: BoundedVec) -> u32 { - // Always ensure the length is larger than the largest - // index passed to get_unchecked - assert(v.len() > 2); - let first = v.get_unchecked(0); - let second = v.get_unchecked(1); - let third = v.get_unchecked(2); - first + second + third -} -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L54-L64 - - - -### push - -```rust -pub fn push(&mut self, elem: T) { -``` - -Pushes an element to the end of the vector. This increases the length -of the vector by one. - -Panics if the new length of the vector will be greater than the max length. - -Example: - -```rust title="bounded-vec-push-example" showLineNumbers -let mut v: BoundedVec = BoundedVec::new(); - - v.push(1); - v.push(2); - - // Panics with failed assertion "push out of bounds" - v.push(3); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L68-L76 - - -### pop - -```rust -pub fn pop(&mut self) -> T -``` - -Pops the element at the end of the vector. This will decrease the length -of the vector by one. - -Panics if the vector is empty. - -Example: - -```rust title="bounded-vec-pop-example" showLineNumbers -let mut v: BoundedVec = BoundedVec::new(); - v.push(1); - v.push(2); - - let two = v.pop(); - let one = v.pop(); - - assert(two == 2); - assert(one == 1); - // error: cannot pop from an empty vector - // let _ = v.pop(); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L81-L93 - - -### len - -```rust -pub fn len(self) -> u64 { -``` - -Returns the current length of this vector - -Example: - -```rust title="bounded-vec-len-example" showLineNumbers -let mut v: BoundedVec = BoundedVec::new(); - assert(v.len() == 0); - - v.push(100); - assert(v.len() == 1); - - v.push(200); - v.push(300); - v.push(400); - assert(v.len() == 4); - - let _ = v.pop(); - let _ = v.pop(); - assert(v.len() == 2); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L98-L113 - - -### max_len - -```rust -pub fn max_len(_self: BoundedVec) -> u64 { -``` - -Returns the maximum length of this vector. This is always -equal to the `MaxLen` parameter this vector was initialized with. - -Example: - -```rust title="bounded-vec-max-len-example" showLineNumbers -let mut v: BoundedVec = BoundedVec::new(); - - assert(v.max_len() == 5); - v.push(10); - assert(v.max_len() == 5); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L118-L124 - - -### storage - -```rust -pub fn storage(self) -> [T; MaxLen] { -``` - -Returns the internal array within this vector. -Since arrays in Noir are immutable, mutating the returned storage array will not mutate -the storage held internally by this vector. - -Note that uninitialized elements may be zeroed out! - -Example: - -```rust title="bounded-vec-storage-example" showLineNumbers -let mut v: BoundedVec = BoundedVec::new(); - - assert(v.storage() == [0, 0, 0, 0, 0]); - - v.push(57); - assert(v.storage() == [57, 0, 0, 0, 0]); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L129-L136 - - -### extend_from_array - -```rust -pub fn extend_from_array(&mut self, array: [T; Len]) -``` - -Pushes each element from the given array to this vector. - -Panics if pushing each element would cause the length of this vector -to exceed the maximum length. - -Example: - -```rust title="bounded-vec-extend-from-array-example" showLineNumbers -let mut vec: BoundedVec = BoundedVec::new(); - vec.extend_from_array([2, 4]); - - assert(vec.len == 2); - assert(vec.get(0) == 2); - assert(vec.get(1) == 4); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L141-L148 - - -### extend_from_bounded_vec - -```rust -pub fn extend_from_bounded_vec(&mut self, vec: BoundedVec) -``` - -Pushes each element from the other vector to this vector. The length of -the other vector is left unchanged. - -Panics if pushing each element would cause the length of this vector -to exceed the maximum length. - -Example: - -```rust title="bounded-vec-extend-from-bounded-vec-example" showLineNumbers -let mut v1: BoundedVec = BoundedVec::new(); - let mut v2: BoundedVec = BoundedVec::new(); - - v2.extend_from_array([1, 2, 3]); - v1.extend_from_bounded_vec(v2); - - assert(v1.storage() == [1, 2, 3, 0, 0]); - assert(v2.storage() == [1, 2, 3, 0, 0, 0, 0]); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L153-L162 - - -### any - -```rust -pub fn any(self, predicate: fn[Env](T) -> bool) -> bool -``` - -Returns true if the given predicate returns true for any element -in this vector. - -Example: - -```rust title="bounded-vec-any-example" showLineNumbers -let mut v: BoundedVec = BoundedVec::new(); - v.extend_from_array([2, 4, 6]); - - let all_even = !v.any(|elem: u32| elem % 2 != 0); - assert(all_even); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L229-L235 - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/containers/hashmap.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/containers/hashmap.md deleted file mode 100644 index 91604af765d..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/containers/hashmap.md +++ /dev/null @@ -1,569 +0,0 @@ ---- -title: HashMap -keywords: [noir, map, hash, hashmap] -sidebar_position: 1 ---- - -`HashMap` is used to efficiently store and look up key-value pairs. - -`HashMap` is a bounded type which can store anywhere from zero to `MaxLen` total elements. -Note that due to hash collisions, the actual maximum number of elements stored by any particular -hashmap is likely lower than `MaxLen`. This is true even with cryptographic hash functions since -every hash value will be performed modulo `MaxLen`. - -When creating `HashMap`s, the `MaxLen` generic should always be specified if it is not already -known. Otherwise, the compiler may infer a different value for `MaxLen` (such as zero), which -will likely change the result of the program. This behavior is set to become an error in future -versions instead. - -Example: - -```rust -// Create a mapping from Fields to u32s with a maximum length of 12 -// using a pedersen hash -let mut map: HashMap> = HashMap::default(); - -map.insert(1, 2); -map.insert(3, 4); - -let two = map.get(1).unwrap(); -``` - -## Methods - -### default - -```rust title="default" showLineNumbers -impl Default for HashMap -where - B: BuildHasher + Default, - H: Hasher + Default -{ - fn default() -> Self { -``` -> Source code: noir_stdlib/src/collections/map.nr#L462-L469 - - -Creates a fresh, empty HashMap. - -When using this function, always make sure to specify the maximum size of the hash map. - -This is the same `default` from the `Default` implementation given further below. It is -repeated here for convenience since it is the recommended way to create a hashmap. - -Example: - -```rust title="default_example" showLineNumbers -let hashmap: HashMap> = HashMap::default(); - assert(hashmap.is_empty()); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L202-L205 - - -Because `HashMap` has so many generic arguments that are likely to be the same throughout -your program, it may be helpful to create a type alias: - -```rust title="type_alias" showLineNumbers -type MyMap = HashMap>; -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L196-L198 - - -### with_hasher - -```rust title="with_hasher" showLineNumbers -pub fn with_hasher(_build_hasher: B) -> Self - where - B: BuildHasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L82-L86 - - -Creates a hashmap with an existing `BuildHasher`. This can be used to ensure multiple -hashmaps are created with the same hasher instance. - -Example: - -```rust title="with_hasher_example" showLineNumbers -let my_hasher: BuildHasherDefault = Default::default(); - let hashmap: HashMap> = HashMap::with_hasher(my_hasher); - assert(hashmap.is_empty()); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L207-L211 - - -### get - -```rust title="get" showLineNumbers -pub fn get( - self, - key: K - ) -> Option - where - K: Eq + Hash, - B: BuildHasher, - H: Hasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L278-L287 - - -Retrieves a value from the hashmap, returning `Option::none()` if it was not found. - -Example: - -```rust title="get_example" showLineNumbers -fn get_example(map: HashMap>) { - let x = map.get(12); - - if x.is_some() { - assert(x.unwrap() == 42); - } -} -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L299-L307 - - -### insert - -```rust title="insert" showLineNumbers -pub fn insert( - &mut self, - key: K, - value: V - ) - where - K: Eq + Hash, - B: BuildHasher, - H: Hasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L313-L323 - - -Inserts a new key-value pair into the map. If the key was already in the map, its -previous value will be overridden with the newly provided one. - -Example: - -```rust title="insert_example" showLineNumbers -let mut map: HashMap> = HashMap::default(); - map.insert(12, 42); - assert(map.len() == 1); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L213-L217 - - -### remove - -```rust title="remove" showLineNumbers -pub fn remove( - &mut self, - key: K - ) - where - K: Eq + Hash, - B: BuildHasher, - H: Hasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L356-L365 - - -Removes the given key-value pair from the map. If the key was not already present -in the map, this does nothing. - -Example: - -```rust title="remove_example" showLineNumbers -map.remove(12); - assert(map.is_empty()); - - // If a key was not present in the map, remove does nothing - map.remove(12); - assert(map.is_empty()); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L221-L228 - - -### is_empty - -```rust title="is_empty" showLineNumbers -pub fn is_empty(self) -> bool { -``` -> Source code: noir_stdlib/src/collections/map.nr#L115-L117 - - -True if the length of the hash map is empty. - -Example: - -```rust title="is_empty_example" showLineNumbers -assert(map.is_empty()); - - map.insert(1, 2); - assert(!map.is_empty()); - - map.remove(1); - assert(map.is_empty()); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L230-L238 - - -### len - -```rust title="len" showLineNumbers -pub fn len(self) -> u64 { -``` -> Source code: noir_stdlib/src/collections/map.nr#L264-L266 - - -Returns the current length of this hash map. - -Example: - -```rust title="len_example" showLineNumbers -// This is equivalent to checking map.is_empty() - assert(map.len() == 0); - - map.insert(1, 2); - map.insert(3, 4); - map.insert(5, 6); - assert(map.len() == 3); - - // 3 was already present as a key in the hash map, so the length is unchanged - map.insert(3, 7); - assert(map.len() == 3); - - map.remove(1); - assert(map.len() == 2); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L240-L255 - - -### capacity - -```rust title="capacity" showLineNumbers -pub fn capacity(_self: Self) -> u64 { -``` -> Source code: noir_stdlib/src/collections/map.nr#L271-L273 - - -Returns the maximum capacity of this hashmap. This is always equal to the capacity -specified in the hashmap's type. - -Unlike hashmaps in general purpose programming languages, hashmaps in Noir have a -static capacity that does not increase as the map grows larger. Thus, this capacity -is also the maximum possible element count that can be inserted into the hashmap. -Due to hash collisions (modulo the hashmap length), it is likely the actual maximum -element count will be lower than the full capacity. - -Example: - -```rust title="capacity_example" showLineNumbers -let empty_map: HashMap> = HashMap::default(); - assert(empty_map.len() == 0); - assert(empty_map.capacity() == 42); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L257-L261 - - -### clear - -```rust title="clear" showLineNumbers -pub fn clear(&mut self) { -``` -> Source code: noir_stdlib/src/collections/map.nr#L93-L95 - - -Clears the hashmap, removing all key-value pairs from it. - -Example: - -```rust title="clear_example" showLineNumbers -assert(!map.is_empty()); - map.clear(); - assert(map.is_empty()); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L263-L267 - - -### contains_key - -```rust title="contains_key" showLineNumbers -pub fn contains_key( - self, - key: K - ) -> bool - where - K: Hash + Eq, - B: BuildHasher, - H: Hasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L101-L110 - - -True if the hashmap contains the given key. Unlike `get`, this will not also return -the value associated with the key. - -Example: - -```rust title="contains_key_example" showLineNumbers -if map.contains_key(7) { - let value = map.get(7); - assert(value.is_some()); - } else { - println("No value for key 7!"); - } -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L269-L276 - - -### entries - -```rust title="entries" showLineNumbers -pub fn entries(self) -> BoundedVec<(K, V), N> { -``` -> Source code: noir_stdlib/src/collections/map.nr#L123-L125 - - -Returns a vector of each key-value pair present in the hashmap. - -The length of the returned vector is always equal to the length of the hashmap. - -Example: - -```rust title="entries_example" showLineNumbers -let entries = map.entries(); - - // The length of a hashmap may not be compile-time known, so we - // need to loop over its capacity instead - for i in 0..map.capacity() { - if i < entries.len() { - let (key, value) = entries.get(i); - println(f"{key} -> {value}"); - } - } -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L310-L321 - - -### keys - -```rust title="keys" showLineNumbers -pub fn keys(self) -> BoundedVec { -``` -> Source code: noir_stdlib/src/collections/map.nr#L144-L146 - - -Returns a vector of each key present in the hashmap. - -The length of the returned vector is always equal to the length of the hashmap. - -Example: - -```rust title="keys_example" showLineNumbers -let keys = map.keys(); - - for i in 0..keys.max_len() { - if i < keys.len() { - let key = keys.get_unchecked(i); - let value = map.get(key).unwrap_unchecked(); - println(f"{key} -> {value}"); - } - } -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L323-L333 - - -### values - -```rust title="values" showLineNumbers -pub fn values(self) -> BoundedVec { -``` -> Source code: noir_stdlib/src/collections/map.nr#L164-L166 - - -Returns a vector of each value present in the hashmap. - -The length of the returned vector is always equal to the length of the hashmap. - -Example: - -```rust title="values_example" showLineNumbers -let values = map.values(); - - for i in 0..values.max_len() { - if i < values.len() { - let value = values.get_unchecked(i); - println(f"Found value {value}"); - } - } -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L335-L344 - - -### iter_mut - -```rust title="iter_mut" showLineNumbers -pub fn iter_mut( - &mut self, - f: fn(K, V) -> (K, V) - ) - where - K: Eq + Hash, - B: BuildHasher, - H: Hasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L183-L192 - - -Iterates through each key-value pair of the HashMap, setting each key-value pair to the -result returned from the given function. - -Note that since keys can be mutated, the HashMap needs to be rebuilt as it is iterated -through. If this is not desired, use `iter_values_mut` if only values need to be mutated, -or `entries` if neither keys nor values need to be mutated. - -The iteration order is left unspecified. As a result, if two keys are mutated to become -equal, which of the two values that will be present for the key in the resulting map is also unspecified. - -Example: - -```rust title="iter_mut_example" showLineNumbers -// Add 1 to each key in the map, and double the value associated with that key. - map.iter_mut(|k, v| (k + 1, v * 2)); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L348-L351 - - -### iter_keys_mut - -```rust title="iter_keys_mut" showLineNumbers -pub fn iter_keys_mut( - &mut self, - f: fn(K) -> K - ) - where - K: Eq + Hash, - B: BuildHasher, - H: Hasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L208-L217 - - -Iterates through the HashMap, mutating each key to the result returned from -the given function. - -Note that since keys can be mutated, the HashMap needs to be rebuilt as it is iterated -through. If only iteration is desired and the keys are not intended to be mutated, -prefer using `entries` instead. - -The iteration order is left unspecified. As a result, if two keys are mutated to become -equal, which of the two values that will be present for the key in the resulting map is also unspecified. - -Example: - -```rust title="iter_keys_mut_example" showLineNumbers -// Double each key, leaving the value associated with that key untouched - map.iter_keys_mut(|k| k * 2); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L353-L356 - - -### iter_values_mut - -```rust title="iter_values_mut" showLineNumbers -pub fn iter_values_mut(&mut self, f: fn(V) -> V) { -``` -> Source code: noir_stdlib/src/collections/map.nr#L233-L235 - - -Iterates through the HashMap, applying the given function to each value and mutating the -value to equal the result. This function is more efficient than `iter_mut` and `iter_keys_mut` -because the keys are untouched and the underlying hashmap thus does not need to be reordered. - -Example: - -```rust title="iter_values_mut_example" showLineNumbers -// Halve each value - map.iter_values_mut(|v| v / 2); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L358-L361 - - -### retain - -```rust title="retain" showLineNumbers -pub fn retain(&mut self, f: fn(K, V) -> bool) { -``` -> Source code: noir_stdlib/src/collections/map.nr#L247-L249 - - -Retains only the key-value pairs for which the given function returns true. -Any key-value pairs for which the function returns false will be removed from the map. - -Example: - -```rust title="retain_example" showLineNumbers -map.retain(|k, v| (k != 0) & (v != 0)); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L281-L283 - - -## Trait Implementations - -### default - -```rust title="default" showLineNumbers -impl Default for HashMap -where - B: BuildHasher + Default, - H: Hasher + Default -{ - fn default() -> Self { -``` -> Source code: noir_stdlib/src/collections/map.nr#L462-L469 - - -Constructs an empty HashMap. - -Example: - -```rust title="default_example" showLineNumbers -let hashmap: HashMap> = HashMap::default(); - assert(hashmap.is_empty()); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L202-L205 - - -### eq - -```rust title="eq" showLineNumbers -impl Eq for HashMap -where - K: Eq + Hash, - V: Eq, - B: BuildHasher, - H: Hasher -{ - fn eq(self, other: HashMap) -> bool { -``` -> Source code: noir_stdlib/src/collections/map.nr#L426-L435 - - -Checks if two HashMaps are equal. - -Example: - -```rust title="eq_example" showLineNumbers -let mut map1: HashMap> = HashMap::default(); - let mut map2: HashMap> = HashMap::default(); - - map1.insert(1, 2); - map1.insert(3, 4); - - map2.insert(3, 4); - map2.insert(1, 2); - - assert(map1 == map2); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L285-L296 - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/containers/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/containers/index.md deleted file mode 100644 index ea84c6d5c21..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/containers/index.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Containers -description: Container types provided by Noir's standard library for storing and retrieving data -keywords: [containers, data types, vec, hashmap] ---- diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/containers/vec.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/containers/vec.mdx deleted file mode 100644 index fcfd7e07aa0..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/containers/vec.mdx +++ /dev/null @@ -1,151 +0,0 @@ ---- -title: Vectors -description: Delve into the Vec data type in Noir. Learn about its methods, practical examples, and best practices for using Vectors in your Noir code. -keywords: [noir, vector type, methods, examples, dynamic arrays] -sidebar_position: 6 ---- - -import Experimental from '@site/src/components/Notes/_experimental.mdx'; - - - -A vector is a collection type similar to Rust's `Vec` type. In Noir, it is a convenient way to use slices as mutable arrays. - -Example: - -```rust -let mut vector: Vec = Vec::new(); -for i in 0..5 { - vector.push(i); -} -assert(vector.len() == 5); -``` - -## Methods - -### new - -Creates a new, empty vector. - -```rust -pub fn new() -> Self -``` - -Example: - -```rust -let empty_vector: Vec = Vec::new(); -assert(empty_vector.len() == 0); -``` - -### from_slice - -Creates a vector containing each element from a given slice. Mutations to the resulting vector will not affect the original slice. - -```rust -pub fn from_slice(slice: [T]) -> Self -``` - -Example: - -```rust -let slice: [Field] = &[1, 2, 3]; -let vector_from_slice = Vec::from_slice(slice); -assert(vector_from_slice.len() == 3); -``` - -### len - -Returns the number of elements in the vector. - -```rust -pub fn len(self) -> Field -``` - -Example: - -```rust -let empty_vector: Vec = Vec::new(); -assert(empty_vector.len() == 0); -``` - -### get - -Retrieves an element from the vector at a given index. Panics if the index points beyond the vector's end. - -```rust -pub fn get(self, index: Field) -> T -``` - -Example: - -```rust -let vector: Vec = Vec::from_slice(&[10, 20, 30]); -assert(vector.get(1) == 20); -``` - -### push - -Adds a new element to the vector's end, returning a new vector with a length one greater than the original unmodified vector. - -```rust -pub fn push(&mut self, elem: T) -``` - -Example: - -```rust -let mut vector: Vec = Vec::new(); -vector.push(10); -assert(vector.len() == 1); -``` - -### pop - -Removes an element from the vector's end, returning a new vector with a length one less than the original vector, along with the removed element. Panics if the vector's length is zero. - -```rust -pub fn pop(&mut self) -> T -``` - -Example: - -```rust -let mut vector = Vec::from_slice(&[10, 20]); -let popped_elem = vector.pop(); -assert(popped_elem == 20); -assert(vector.len() == 1); -``` - -### insert - -Inserts an element at a specified index, shifting subsequent elements to the right. - -```rust -pub fn insert(&mut self, index: Field, elem: T) -``` - -Example: - -```rust -let mut vector = Vec::from_slice(&[10, 30]); -vector.insert(1, 20); -assert(vector.get(1) == 20); -``` - -### remove - -Removes an element at a specified index, shifting subsequent elements to the left, and returns the removed element. - -```rust -pub fn remove(&mut self, index: Field) -> T -``` - -Example: - -```rust -let mut vector = Vec::from_slice(&[10, 20, 30]); -let removed_elem = vector.remove(1); -assert(removed_elem == 20); -assert(vector.len() == 2); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/_category_.json deleted file mode 100644 index 5d694210bbf..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 0, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/ec_primitives.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/ec_primitives.md deleted file mode 100644 index aa679fa1086..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/ec_primitives.md +++ /dev/null @@ -1,102 +0,0 @@ ---- -title: Elliptic Curve Primitives -keywords: [cryptographic primitives, Noir project] -sidebar_position: 4 ---- - -Data structures and methods on them that allow you to carry out computations involving elliptic -curves over the (mathematical) field corresponding to `Field`. For the field currently at our -disposal, applications would involve a curve embedded in BN254, e.g. the -[Baby Jubjub curve](https://eips.ethereum.org/EIPS/eip-2494). - -## Data structures - -### Elliptic curve configurations - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Curve`), i.e. the specific elliptic -curve you want to use, which would be specified using any one of the methods -`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::new` which take the coefficients in the -defining equation together with a generator point as parameters. You can find more detail in the -comments in -[`noir_stdlib/src/ec.nr`](https://github.com/noir-lang/noir/blob/v0.26.0/noir_stdlib/src/ec.nr), but -the gist of it is that the elliptic curves of interest are usually expressed in one of the standard -forms implemented here (Twisted Edwards, Montgomery and Short Weierstraß), and in addition to that, -you could choose to use `affine` coordinates (Cartesian coordinates - the usual (x,y) - possibly -together with a point at infinity) or `curvegroup` coordinates (some form of projective coordinates -requiring more coordinates but allowing for more efficient implementations of elliptic curve -operations). Conversions between all of these forms are provided, and under the hood these -conversions are done whenever an operation is more efficient in a different representation (or a -mixed coordinate representation is employed). - -### Points - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Point`), i.e. points lying on the -elliptic curve. For a curve configuration `c` and a point `p`, it may be checked that `p` -does indeed lie on `c` by calling `c.contains(p1)`. - -## Methods - -(given a choice of curve representation, e.g. use `std::ec::tecurve::affine::Curve` and use -`std::ec::tecurve::affine::Point`) - -- The **zero element** is given by `Point::zero()`, and we can verify whether a point `p: Point` is - zero by calling `p.is_zero()`. -- **Equality**: Points `p1: Point` and `p2: Point` may be checked for equality by calling - `p1.eq(p2)`. -- **Addition**: For `c: Curve` and points `p1: Point` and `p2: Point` on the curve, adding these two - points is accomplished by calling `c.add(p1,p2)`. -- **Negation**: For a point `p: Point`, `p.negate()` is its negation. -- **Subtraction**: For `c` and `p1`, `p2` as above, subtracting `p2` from `p1` is accomplished by - calling `c.subtract(p1,p2)`. -- **Scalar multiplication**: For `c` as above, `p: Point` a point on the curve and `n: Field`, - scalar multiplication is given by `c.mul(n,p)`. If instead `n :: [u1; N]`, i.e. `n` is a bit - array, the `bit_mul` method may be used instead: `c.bit_mul(n,p)` -- **Multi-scalar multiplication**: For `c` as above and arrays `n: [Field; N]` and `p: [Point; N]`, - multi-scalar multiplication is given by `c.msm(n,p)`. -- **Coordinate representation conversions**: The `into_group` method converts a point or curve - configuration in the affine representation to one in the CurveGroup representation, and - `into_affine` goes in the other direction. -- **Curve representation conversions**: `tecurve` and `montcurve` curves and points are equivalent - and may be converted between one another by calling `into_montcurve` or `into_tecurve` on their - configurations or points. `swcurve` is more general and a curve c of one of the other two types - may be converted to this representation by calling `c.into_swcurve()`, whereas a point `p` lying - on the curve given by `c` may be mapped to its corresponding `swcurve` point by calling - `c.map_into_swcurve(p)`. -- **Map-to-curve methods**: The Elligator 2 method of mapping a field element `n: Field` into a - `tecurve` or `montcurve` with configuration `c` may be called as `c.elligator2_map(n)`. For all of - the curve configurations, the SWU map-to-curve method may be called as `c.swu_map(z,n)`, where - `z: Field` depends on `Field` and `c` and must be chosen by the user (the conditions it needs to - satisfy are specified in the comments - [here](https://github.com/noir-lang/noir/blob/v0.26.0/noir_stdlib/src/ec.nr). - -## Examples - -The -[ec_baby_jubjub test](https://github.com/noir-lang/noir/blob/master/test_programs/compile_success_empty/ec_baby_jubjub/src/main.nr) -illustrates all of the above primitives on various forms of the Baby Jubjub curve. A couple of more -interesting examples in Noir would be: - -Public-key cryptography: Given an elliptic curve and a 'base point' on it, determine the public key -from the private key. This is a matter of using scalar multiplication. In the case of Baby Jubjub, -for example, this code would do: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; - -fn bjj_pub_key(priv_key: Field) -> Point -{ - - let bjj = Curve::new(168700, 168696, G::new(995203441582195749578291179787384436505546430278305826713579947235728471134,5472060717959818805561601436314318772137091100104008585924551046643952123905)); - - let base_pt = Point::new(5299619240641551281634865583518297030282874472190772894086521144482721001553, 16950150798460657717958625567821834550301663161624707787222815936182638968203); - - bjj.mul(priv_key,base_pt) -} -``` - -This would come in handy in a Merkle proof. - -- EdDSA signature verification: This is a matter of combining these primitives with a suitable hash - function. See - [feat(stdlib): EdDSA sig verification noir#1136](https://github.com/noir-lang/noir/pull/1136) for - the case of Baby Jubjub and the Poseidon hash function. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx deleted file mode 100644 index 4394b48f907..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx +++ /dev/null @@ -1,98 +0,0 @@ ---- -title: ECDSA Signature Verification -description: Learn about the cryptographic primitives regarding ECDSA over the secp256k1 and secp256r1 curves -keywords: [cryptographic primitives, Noir project, ecdsa, secp256k1, secp256r1, signatures] -sidebar_position: 3 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -Noir supports ECDSA signatures verification over the secp256k1 and secp256r1 curves. - -## ecdsa_secp256k1::verify_signature - -Verifier for ECDSA Secp256k1 signatures. -See ecdsa_secp256k1::verify_signature_slice for a version that accepts slices directly. - -```rust title="ecdsa_secp256k1" showLineNumbers -pub fn verify_signature( - public_key_x: [u8; 32], - public_key_y: [u8; 32], - signature: [u8; 64], - message_hash: [u8; N] -) -> bool -``` -> Source code: noir_stdlib/src/ecdsa_secp256k1.nr#L2-L9 - - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - - - -## ecdsa_secp256k1::verify_signature_slice - -Verifier for ECDSA Secp256k1 signatures where the message is a slice. - -```rust title="ecdsa_secp256k1_slice" showLineNumbers -pub fn verify_signature_slice( - public_key_x: [u8; 32], - public_key_y: [u8; 32], - signature: [u8; 64], - message_hash: [u8] -) -> bool -``` -> Source code: noir_stdlib/src/ecdsa_secp256k1.nr#L13-L20 - - - - -## ecdsa_secp256r1::verify_signature - -Verifier for ECDSA Secp256r1 signatures. -See ecdsa_secp256r1::verify_signature_slice for a version that accepts slices directly. - -```rust title="ecdsa_secp256r1" showLineNumbers -pub fn verify_signature( - public_key_x: [u8; 32], - public_key_y: [u8; 32], - signature: [u8; 64], - message_hash: [u8; N] -) -> bool -``` -> Source code: noir_stdlib/src/ecdsa_secp256r1.nr#L2-L9 - - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - - - -## ecdsa_secp256r1::verify_signature - -Verifier for ECDSA Secp256r1 signatures where the message is a slice. - -```rust title="ecdsa_secp256r1_slice" showLineNumbers -pub fn verify_signature_slice( - public_key_x: [u8; 32], - public_key_y: [u8; 32], - signature: [u8; 64], - message_hash: [u8] -) -> bool -``` -> Source code: noir_stdlib/src/ecdsa_secp256r1.nr#L13-L20 - - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/eddsa.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/eddsa.mdx deleted file mode 100644 index c2c0624dfad..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/eddsa.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: EdDSA Verification -description: Learn about the cryptographic primitives regarding EdDSA -keywords: [cryptographic primitives, Noir project, eddsa, signatures] -sidebar_position: 5 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## eddsa::eddsa_poseidon_verify - -Verifier for EdDSA signatures - -```rust -fn eddsa_poseidon_verify(public_key_x : Field, public_key_y : Field, signature_s: Field, signature_r8_x: Field, signature_r8_y: Field, message: Field) -> bool -``` - -It is also possible to specify the hash algorithm used for the signature by using the `eddsa_verify_with_hasher` function with a parameter implementing the Hasher trait. For instance, if you want to use Poseidon2 instead, you can do the following: -```rust -use dep::std::hash::poseidon2::Poseidon2Hasher; - -let mut hasher = Poseidon2Hasher::default(); -eddsa_verify_with_hasher(pub_key_a.x, pub_key_a.y, s_a, r8_a.x, r8_a.y, msg, &mut hasher); -``` - - - -## eddsa::eddsa_to_pub - -Private to public key conversion. - -Returns `(pub_key_x, pub_key_y)` - -```rust -fn eddsa_to_pub(secret : Field) -> (Field, Field) -``` - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/hashes.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/hashes.mdx deleted file mode 100644 index 695c7d9406f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/hashes.mdx +++ /dev/null @@ -1,331 +0,0 @@ ---- -title: Hash methods -description: - Learn about the cryptographic primitives ready to use for any Noir project, including sha256, - blake2s, pedersen, mimc_bn254 and mimc -keywords: - [cryptographic primitives, Noir project, sha256, blake2s, pedersen, mimc_bn254, mimc, hash] -sidebar_position: 0 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## sha256 - -Given an array of bytes, returns the resulting sha256 hash. -See sha256_slice for a version that works directly on slices. - -```rust title="sha256" showLineNumbers -pub fn sha256(input: [u8; N]) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L10-L12 - - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::sha256(x); -} -``` - - - -## sha256_slice - -A version of sha256 specialized to slices: - -```rust title="sha256_slice" showLineNumbers -pub fn sha256_slice(input: [u8]) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L16-L18 - - - - -## blake2s - -Given an array of bytes, returns an array with the Blake2 hash -See blake2s_slice for a version that works directly on slices. - -```rust title="blake2s" showLineNumbers -pub fn blake2s(input: [u8; N]) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L22-L24 - - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::blake2s(x); -} -``` - - - -## blake2s_slice - -A version of blake2s specialized to slices: - -```rust title="blake2s_slice" showLineNumbers -pub fn blake2s_slice(input: [u8]) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L28-L30 - - - - -## blake3 - -Given an array of bytes, returns an array with the Blake3 hash -See blake3_slice for a version that works directly on slices. - -```rust title="blake3" showLineNumbers -pub fn blake3(input: [u8; N]) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L34-L36 - - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::blake3(x); -} -``` - - - -## blake3_slice - -A version of blake3 specialized to slices: - -```rust title="blake3_slice" showLineNumbers -pub fn blake3_slice(input: [u8]) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L40-L42 - - - - -## pedersen_hash - -Given an array of Fields, returns the Pedersen hash. -See pedersen_hash_slice for a version that works directly on slices. - -```rust title="pedersen_hash" showLineNumbers -pub fn pedersen_hash(input: [Field; N]) -> Field -``` -> Source code: noir_stdlib/src/hash.nr#L78-L80 - - -example: - -```rust title="pedersen-hash" showLineNumbers -use dep::std; - -fn main(x: Field, y: Field, expected_hash: Field) { - let hash = std::hash::pedersen_hash([x, y]); - assert_eq(hash, expected_hash); -} -``` -> Source code: test_programs/execution_success/pedersen_hash/src/main.nr#L1-L8 - - - - -## pedersen_hash_slice - -Given a slice of Fields, returns the Pedersen hash. - -```rust title="pedersen_hash_slice" showLineNumbers -pub fn pedersen_hash_slice(input: [Field]) -> Field -``` -> Source code: noir_stdlib/src/hash.nr#L85-L87 - - - - -## pedersen_commitment - -Given an array of Fields, returns the Pedersen commitment. -See pedersen_commitment_slice for a version that works directly on slices. - -```rust title="pedersen_commitment" showLineNumbers -struct PedersenPoint { - x : Field, - y : Field, -} - -pub fn pedersen_commitment(input: [Field; N]) -> PedersenPoint { -``` -> Source code: noir_stdlib/src/hash.nr#L45-L52 - - -example: - -```rust title="pedersen-commitment" showLineNumbers -use dep::std; - -fn main(x: Field, y: Field, expected_commitment: std::hash::PedersenPoint) { - let commitment = std::hash::pedersen_commitment([x, y]); - assert_eq(commitment.x, expected_commitment.x); - assert_eq(commitment.y, expected_commitment.y); -} -``` -> Source code: test_programs/execution_success/pedersen_commitment/src/main.nr#L1-L9 - - - - -## pedersen_commitment_slice - -Given a slice of Fields, returns the Pedersen commitment. - -```rust title="pedersen_commitment_slice" showLineNumbers -pub fn pedersen_commitment_slice(input: [Field]) -> PedersenPoint { - pedersen_commitment_with_separator_slice(input, 0) -} -``` -> Source code: noir_stdlib/src/hash.nr#L56-L60 - - - - -## keccak256 - -Given an array of bytes (`u8`), returns the resulting keccak hash as an array of -32 bytes (`[u8; 32]`). Specify a message_size to hash only the first -`message_size` bytes of the input. See keccak256_slice for a version that works -directly on slices. - -```rust title="keccak256" showLineNumbers -pub fn keccak256(input: [u8; N], message_size: u32) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L113-L115 - - -example: - -```rust title="keccak256" showLineNumbers -use dep::std; - -fn main(x: Field, result: [u8; 32]) { - // We use the `as` keyword here to denote the fact that we want to take just the first byte from the x Field - // The padding is taken care of by the program - let digest = std::hash::keccak256([x as u8], 1); - assert(digest == result); - - //#1399: variable message size - let message_size = 4; - let hash_a = std::hash::keccak256([1, 2, 3, 4], message_size); - let hash_b = std::hash::keccak256([1, 2, 3, 4, 0, 0, 0, 0], message_size); - - assert(hash_a == hash_b); - - let message_size_big = 8; - let hash_c = std::hash::keccak256([1, 2, 3, 4, 0, 0, 0, 0], message_size_big); - - assert(hash_a != hash_c); -} -``` -> Source code: test_programs/execution_success/keccak256/src/main.nr#L1-L22 - - - - -## keccak256_slice - -Given a slice of bytes (`u8`), returns the resulting keccak hash as an array of -32 bytes (`[u8; 32]`). - -```rust title="keccak256_slice" showLineNumbers -pub fn keccak256_slice(input: [u8], message_size: u32) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L119-L121 - - - - -## poseidon - -Given an array of Fields, returns a new Field with the Poseidon Hash. Mind that you need to specify -how many inputs are there to your Poseidon function. - -```rust -// example for hash_1, hash_2 accepts an array of length 2, etc -fn hash_1(input: [Field; 1]) -> Field -``` - -example: - -```rust title="poseidon" showLineNumbers -use dep::std::hash::poseidon; -use dep::std::hash::poseidon2; - -fn main(x1: [Field; 2], y1: pub Field, x2: [Field; 4], y2: pub Field, x3: [Field; 4], y3: Field) { - let hash1 = poseidon::bn254::hash_2(x1); - assert(hash1 == y1); - - let hash2 = poseidon::bn254::hash_4(x2); - assert(hash2 == y2); - - let hash3 = poseidon2::Poseidon2::hash(x3, x3.len()); - assert(hash3 == y3); -} -``` -> Source code: test_programs/execution_success/poseidon_bn254_hash/src/main.nr#L1-L15 - - -## poseidon 2 - -Given an array of Fields, returns a new Field with the Poseidon2 Hash. Contrary to the Poseidon -function, there is only one hash and you can specify a message_size to hash only the first -`message_size` bytes of the input, - -```rust -// example for hashing the first three elements of the input -Poseidon2::hash(input, 3); -``` - -The above example for Poseidon also includes Poseidon2. - -## mimc_bn254 and mimc - -`mimc_bn254` is `mimc`, but with hardcoded parameters for the BN254 curve. You can use it by -providing an array of Fields, and it returns a Field with the hash. You can use the `mimc` method if -you're willing to input your own constants: - -```rust -fn mimc(x: Field, k: Field, constants: [Field; N], exp : Field) -> Field -``` - -otherwise, use the `mimc_bn254` method: - -```rust -fn mimc_bn254(array: [Field; N]) -> Field -``` - -example: - -```rust - -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::mimc::mimc_bn254(x); -} -``` - -## hash_to_field - -```rust -fn hash_to_field(_input : [Field]) -> Field {} -``` - -Calculates the `blake2s` hash of the inputs and returns the hash modulo the field modulus to return -a value which can be represented as a `Field`. - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/index.md deleted file mode 100644 index 650f30165d5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/index.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Cryptographic Primitives -description: - Learn about the cryptographic primitives ready to use for any Noir project -keywords: - [ - cryptographic primitives, - Noir project, - ] ---- - -The Noir team is progressively adding new cryptographic primitives to the standard library. Reach out for news or if you would be interested in adding more of these calculations in Noir. - -Some methods are available thanks to the Aztec backend, not being performed using Noir. When using other backends, these methods may or may not be supplied. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/scalar.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/scalar.mdx deleted file mode 100644 index df411ca5443..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/scalar.mdx +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Scalar multiplication -description: See how you can perform scalar multiplications over a fixed base in Noir -keywords: [cryptographic primitives, Noir project, scalar multiplication] -sidebar_position: 1 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## scalar_mul::fixed_base_embedded_curve - -Performs scalar multiplication over the embedded curve whose coordinates are defined by the -configured noir field. For the BN254 scalar field, this is BabyJubJub or Grumpkin. - -```rust title="fixed_base_embedded_curve" showLineNumbers -pub fn fixed_base_embedded_curve( - low: Field, - high: Field -) -> [Field; 2] -``` -> Source code: noir_stdlib/src/scalar_mul.nr#L27-L32 - - -example - -```rust -fn main(x : Field) { - let scal = std::scalar_mul::fixed_base_embedded_curve(x); - println(scal); -} -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/logging.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/logging.md deleted file mode 100644 index db75ef9f86f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/logging.md +++ /dev/null @@ -1,78 +0,0 @@ ---- -title: Logging -description: - Learn how to use the println statement for debugging in Noir with this tutorial. Understand the - basics of logging in Noir and how to implement it in your code. -keywords: - [ - noir logging, - println statement, - print statement, - debugging in noir, - noir std library, - logging tutorial, - basic logging in noir, - noir logging implementation, - noir debugging techniques, - rust, - ] ---- - -The standard library provides two familiar statements you can use: `println` and `print`. Despite being a limited implementation of rust's `println!` and `print!` macros, these constructs can be useful for debugging. - -You can print the output of both statements in your Noir code by using the `nargo execute` command or the `--show-output` flag when using `nargo test` (provided there are print statements in your tests). - -It is recommended to use `nargo execute` if you want to debug failing constraints with `println` or `print` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). Neither `println`, nor `print` are callable for failed constraints caught at compile time. - -Both `print` and `println` are generic functions which can work on integers, fields, strings, and even structs or expressions. Note however, that slices are currently unsupported. For example: - -```rust -struct Person { - age: Field, - height: Field, -} - -fn main(age: Field, height: Field) { - let person = Person { - age: age, - height: height, - }; - println(person); - println(age + height); - println("Hello world!"); -} -``` - -You can print different types in the same statement (including strings) with a type called `fmtstr`. It can be specified in the same way as a normal string, just prepended with an "f" character: - -```rust - let fmt_str = f"i: {i}, j: {j}"; - println(fmt_str); - - let s = myStruct { y: x, x: y }; - println(s); - - println(f"i: {i}, s: {s}"); - - println(x); - println([x, y]); - - let foo = fooStruct { my_struct: s, foo: 15 }; - println(f"s: {s}, foo: {foo}"); - - println(15); // prints 0x0f, implicit Field - println(-1 as u8); // prints 255 - println(-1 as i8); // prints -1 -``` - -Examples shown above are interchangeable between the two `print` statements: - -```rust -let person = Person { age : age, height : height }; - -println(person); -print(person); - -println("Hello world!"); // Prints with a newline at the end of the input -print("Hello world!"); // Prints the input and keeps cursor on the same line -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/options.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/options.md deleted file mode 100644 index a1bd4e1de5f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/options.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -title: Option Type ---- - -The `Option` type is a way to express that a value might be present (`Some(T))` or absent (`None`). It's a safer way to handle potential absence of values, compared to using nulls in many other languages. - -```rust -struct Option { - None, - Some(T), -} -``` - -The `Option` type, already imported into your Noir program, can be used directly: - -```rust -fn main() { - let none = Option::none(); - let some = Option::some(3); -} -``` - -See [this test](https://github.com/noir-lang/noir/blob/5cbfb9c4a06c8865c98ff2b594464b037d821a5c/crates/nargo_cli/tests/test_data/option/src/main.nr) for a more comprehensive set of examples of each of the methods described below. - -## Methods - -### none - -Constructs a none value. - -### some - -Constructs a some wrapper around a given value. - -### is_none - -Returns true if the Option is None. - -### is_some - -Returns true of the Option is Some. - -### unwrap - -Asserts `self.is_some()` and returns the wrapped value. - -### unwrap_unchecked - -Returns the inner value without asserting `self.is_some()`. This method can be useful within an if condition when we already know that `option.is_some()`. If the option is None, there is no guarantee what value will be returned, only that it will be of type T for an `Option`. - -### unwrap_or - -Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value. - -### unwrap_or_else - -Returns the wrapped value if `self.is_some()`. Otherwise, calls the given function to return a default value. - -### expect - -Asserts `self.is_some()` with a provided custom message and returns the contained `Some` value. The custom message is expected to be a format string. - -### map - -If self is `Some(x)`, this returns `Some(f(x))`. Otherwise, this returns `None`. - -### map_or - -If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns the given default value. - -### map_or_else - -If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns `default()`. - -### and - -Returns None if self is None. Otherwise, this returns `other`. - -### and_then - -If self is None, this returns None. Otherwise, this calls the given function with the Some value contained within self, and returns the result of that call. In some languages this function is called `flat_map` or `bind`. - -### or - -If self is Some, return self. Otherwise, return `other`. - -### or_else - -If self is Some, return self. Otherwise, return `default()`. - -### xor - -If only one of the two Options is Some, return that option. Otherwise, if both options are Some or both are None, None is returned. - -### filter - -Returns `Some(x)` if self is `Some(x)` and `predicate(x)` is true. Otherwise, this returns `None`. - -### flatten - -Flattens an `Option>` into a `Option`. This returns `None` if the outer Option is None. Otherwise, this returns the inner Option. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/recursion.md deleted file mode 100644 index f33c285cf4e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/recursion.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -title: Recursive Proofs -description: Learn about how to write recursive proofs in Noir. -keywords: [recursion, recursive proofs, verification_key, verify_proof] ---- - -Noir supports recursively verifying proofs, meaning you verify the proof of a Noir program in another Noir program. This enables creating proofs of arbitrary size by doing step-wise verification of smaller components of a large proof. - -Read [the explainer on recursion](../../explainers/explainer-recursion.md) to know more about this function and the [guide on how to use it.](../../how_to/how-to-recursion.md) - -## The `#[recursive]` Attribute - -In Noir, the `#[recursive]` attribute is used to indicate that a circuit is designed for recursive proof generation. When applied, it informs the compiler and the tooling that the circuit should be compiled in a way that makes its proofs suitable for recursive verification. This attribute eliminates the need for manual flagging of recursion at the tooling level, streamlining the proof generation process for recursive circuits. - -### Example usage with `#[recursive]` - -```rust -#[recursive] -fn main(x: Field, y: pub Field) { - assert(x == y, "x and y are not equal"); -} - -// This marks the circuit as recursion-friendly and indicates that proofs generated from this circuit -// are intended for recursive verification. -``` - -By incorporating this attribute directly in the circuit's definition, tooling like Nargo and NoirJS can automatically execute recursive-specific duties for Noir programs (e.g. recursive-friendly proof artifact generation) without additional flags or configurations. - -## Verifying Recursive Proofs - -```rust -#[foreign(recursive_aggregation)] -pub fn verify_proof(verification_key: [Field], proof: [Field], public_inputs: [Field], key_hash: Field) {} -``` - -:::info - -This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. - -::: - -## Example usage - -```rust -use dep::std; - -fn main( - verification_key : [Field; 114], - proof : [Field; 93], - public_inputs : [Field; 1], - key_hash : Field, - proof_b : [Field; 93], -) { - std::verify_proof( - verification_key.as_slice(), - proof.as_slice(), - public_inputs.as_slice(), - key_hash - ); - - std::verify_proof( - verification_key.as_slice(), - proof_b.as_slice(), - public_inputs.as_slice(), - key_hash - ); -} -``` - -You can see a full example of recursive proofs in [this example recursion demo repo](https://github.com/noir-lang/noir-examples/tree/master/recursion). - -## Parameters - -### `verification_key` - -The verification key for the zk program that is being verified. - -### `proof` - -The proof for the zk program that is being verified. - -### `public_inputs` - -These represent the public inputs of the proof we are verifying. - -### `key_hash` - -A key hash is used to check the validity of the verification key. The circuit implementing this opcode can use this hash to ensure that the key provided to the circuit matches the key produced by the circuit creator. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/traits.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/traits.md deleted file mode 100644 index 68a9dc3d54b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/traits.md +++ /dev/null @@ -1,408 +0,0 @@ ---- -title: Traits -description: Noir's stdlib provides a few commonly used traits. -keywords: [traits, trait, interface, protocol, default, add, eq] ---- - -## `std::default` - -### `std::default::Default` - -```rust title="default-trait" showLineNumbers -trait Default { - fn default() -> Self; -} -``` -> Source code: noir_stdlib/src/default.nr#L1-L5 - - -Constructs a default value of a type. - -Implementations: -```rust -impl Default for Field { .. } - -impl Default for i8 { .. } -impl Default for i16 { .. } -impl Default for i32 { .. } -impl Default for i64 { .. } - -impl Default for u8 { .. } -impl Default for u16 { .. } -impl Default for u32 { .. } -impl Default for u64 { .. } - -impl Default for () { .. } -impl Default for bool { .. } - -impl Default for [T; N] - where T: Default { .. } - -impl Default for [T] { .. } - -impl Default for (A, B) - where A: Default, B: Default { .. } - -impl Default for (A, B, C) - where A: Default, B: Default, C: Default { .. } - -impl Default for (A, B, C, D) - where A: Default, B: Default, C: Default, D: Default { .. } - -impl Default for (A, B, C, D, E) - where A: Default, B: Default, C: Default, D: Default, E: Default { .. } -``` - -For primitive integer types, the return value of `default` is `0`. Container -types such as arrays are filled with default values of their element type, -except slices whose length is unknown and thus defaulted to zero. - - -## `std::convert` - -### `std::convert::From` - -```rust title="from-trait" showLineNumbers -trait From { - fn from(input: T) -> Self; -} -``` -> Source code: noir_stdlib/src/convert.nr#L1-L5 - - -The `From` trait defines how to convert from a given type `T` to the type on which the trait is implemented. - -The Noir standard library provides a number of implementations of `From` between primitive types. -```rust title="from-impls" showLineNumbers -// Unsigned integers - -impl From for u32 { fn from(value: u8) -> u32 { value as u32 } } - -impl From for u64 { fn from(value: u8) -> u64 { value as u64 } } -impl From for u64 { fn from(value: u32) -> u64 { value as u64 } } - -impl From for Field { fn from(value: u8) -> Field { value as Field } } -impl From for Field { fn from(value: u32) -> Field { value as Field } } -impl From for Field { fn from(value: u64) -> Field { value as Field } } - -// Signed integers - -impl From for i32 { fn from(value: i8) -> i32 { value as i32 } } - -impl From for i64 { fn from(value: i8) -> i64 { value as i64 } } -impl From for i64 { fn from(value: i32) -> i64 { value as i64 } } - -// Booleans -impl From for u8 { fn from(value: bool) -> u8 { value as u8 } } -impl From for u32 { fn from(value: bool) -> u32 { value as u32 } } -impl From for u64 { fn from(value: bool) -> u64 { value as u64 } } -impl From for i8 { fn from(value: bool) -> i8 { value as i8 } } -impl From for i32 { fn from(value: bool) -> i32 { value as i32 } } -impl From for i64 { fn from(value: bool) -> i64 { value as i64 } } -impl From for Field { fn from(value: bool) -> Field { value as Field } } -``` -> Source code: noir_stdlib/src/convert.nr#L25-L52 - - -#### When to implement `From` - -As a general rule of thumb, `From` may be implemented in the [situations where it would be suitable in Rust](https://doc.rust-lang.org/std/convert/trait.From.html#when-to-implement-from): - -- The conversion is *infallible*: Noir does not provide an equivalent to Rust's `TryFrom`, if the conversion can fail then provide a named method instead. -- The conversion is *lossless*: semantically, it should not lose or discard information. For example, `u32: From` can losslessly convert any `u16` into a valid `u32` such that the original `u16` can be recovered. On the other hand, `u16: From` should not be implemented as `2**16` is a `u32` which cannot be losslessly converted into a `u16`. -- The conversion is *value-preserving*: the conceptual kind and meaning of the resulting value is the same, even though the Noir type and technical representation might be different. While it's possible to infallibly and losslessly convert a `u8` into a `str<2>` hex representation, `4u8` and `"04"` are too different for `str<2>: From` to be implemented. -- The conversion is *obvious*: it's the only reasonable conversion between the two types. If there's ambiguity on how to convert between them such that the same input could potentially map to two different values then a named method should be used. For instance rather than implementing `U128: From<[u8; 16]>`, the methods `U128::from_le_bytes` and `U128::from_be_bytes` are used as otherwise the endianness of the array would be ambiguous, resulting in two potential values of `U128` from the same byte array. - -One additional recommendation specific to Noir is: -- The conversion is *efficient*: it's relatively cheap to convert between the two types. Due to being a ZK DSL, it's more important to avoid unnecessary computation compared to Rust. If the implementation of `From` would encourage users to perform unnecessary conversion, resulting in additional proving time, then it may be preferable to expose functionality such that this conversion may be avoided. - -### `std::convert::Into` - -The `Into` trait is defined as the reciprocal of `From`. It should be easy to convince yourself that if we can convert to type `A` from type `B`, then it's possible to convert type `B` into type `A`. - -For this reason, implementing `From` on a type will automatically generate a matching `Into` implementation. One should always prefer implementing `From` over `Into` as implementing `Into` will not generate a matching `From` implementation. - -```rust title="into-trait" showLineNumbers -trait Into { - fn into(input: Self) -> T; -} - -impl Into for U where T: From { - fn into(input: U) -> T { - T::from(input) - } -} -``` -> Source code: noir_stdlib/src/convert.nr#L13-L23 - - -`Into` is most useful when passing function arguments where the types don't quite match up with what the function expects. In this case, the compiler has enough type information to perform the necessary conversion by just appending `.into()` onto the arguments in question. - - -## `std::cmp` - -### `std::cmp::Eq` - -```rust title="eq-trait" showLineNumbers -trait Eq { - fn eq(self, other: Self) -> bool; -} -``` -> Source code: noir_stdlib/src/cmp.nr#L1-L5 - - -Returns `true` if `self` is equal to `other`. Implementing this trait on a type -allows the type to be used with `==` and `!=`. - -Implementations: -```rust -impl Eq for Field { .. } - -impl Eq for i8 { .. } -impl Eq for i16 { .. } -impl Eq for i32 { .. } -impl Eq for i64 { .. } - -impl Eq for u8 { .. } -impl Eq for u16 { .. } -impl Eq for u32 { .. } -impl Eq for u64 { .. } - -impl Eq for () { .. } -impl Eq for bool { .. } - -impl Eq for [T; N] - where T: Eq { .. } - -impl Eq for [T] - where T: Eq { .. } - -impl Eq for (A, B) - where A: Eq, B: Eq { .. } - -impl Eq for (A, B, C) - where A: Eq, B: Eq, C: Eq { .. } - -impl Eq for (A, B, C, D) - where A: Eq, B: Eq, C: Eq, D: Eq { .. } - -impl Eq for (A, B, C, D, E) - where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq { .. } -``` - -### `std::cmp::Ord` - -```rust title="ord-trait" showLineNumbers -trait Ord { - fn cmp(self, other: Self) -> Ordering; -} -``` -> Source code: noir_stdlib/src/cmp.nr#L102-L106 - - -`a.cmp(b)` compares two values returning `Ordering::less()` if `a < b`, -`Ordering::equal()` if `a == b`, or `Ordering::greater()` if `a > b`. -Implementing this trait on a type allows `<`, `<=`, `>`, and `>=` to be -used on values of the type. - -Implementations: - -```rust -impl Ord for u8 { .. } -impl Ord for u16 { .. } -impl Ord for u32 { .. } -impl Ord for u64 { .. } - -impl Ord for i8 { .. } -impl Ord for i16 { .. } -impl Ord for i32 { .. } - -impl Ord for i64 { .. } - -impl Ord for () { .. } -impl Ord for bool { .. } - -impl Ord for [T; N] - where T: Ord { .. } - -impl Ord for [T] - where T: Ord { .. } - -impl Ord for (A, B) - where A: Ord, B: Ord { .. } - -impl Ord for (A, B, C) - where A: Ord, B: Ord, C: Ord { .. } - -impl Ord for (A, B, C, D) - where A: Ord, B: Ord, C: Ord, D: Ord { .. } - -impl Ord for (A, B, C, D, E) - where A: Ord, B: Ord, C: Ord, D: Ord, E: Ord { .. } -``` - -## `std::ops` - -### `std::ops::Add`, `std::ops::Sub`, `std::ops::Mul`, and `std::ops::Div` - -These traits abstract over addition, subtraction, multiplication, and division respectively. -Implementing these traits for a given type will also allow that type to be used with the corresponding operator -for that trait (`+` for Add, etc) in addition to the normal method names. - -```rust title="add-trait" showLineNumbers -trait Add { - fn add(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L1-L5 - -```rust title="sub-trait" showLineNumbers -trait Sub { - fn sub(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L17-L21 - -```rust title="mul-trait" showLineNumbers -trait Mul { - fn mul(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L33-L37 - -```rust title="div-trait" showLineNumbers -trait Div { - fn div(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L49-L53 - - -The implementations block below is given for the `Add` trait, but the same types that implement -`Add` also implement `Sub`, `Mul`, and `Div`. - -Implementations: -```rust -impl Add for Field { .. } - -impl Add for i8 { .. } -impl Add for i16 { .. } -impl Add for i32 { .. } -impl Add for i64 { .. } - -impl Add for u8 { .. } -impl Add for u16 { .. } -impl Add for u32 { .. } -impl Add for u64 { .. } -``` - -### `std::ops::Rem` - -```rust title="rem-trait" showLineNumbers -trait Rem{ - fn rem(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L65-L69 - - -`Rem::rem(a, b)` is the remainder function returning the result of what is -left after dividing `a` and `b`. Implementing `Rem` allows the `%` operator -to be used with the implementation type. - -Unlike other numeric traits, `Rem` is not implemented for `Field`. - -Implementations: -```rust -impl Rem for u8 { fn rem(self, other: u8) -> u8 { self % other } } -impl Rem for u16 { fn rem(self, other: u16) -> u16 { self % other } } -impl Rem for u32 { fn rem(self, other: u32) -> u32 { self % other } } -impl Rem for u64 { fn rem(self, other: u64) -> u64 { self % other } } - -impl Rem for i8 { fn rem(self, other: i8) -> i8 { self % other } } -impl Rem for i16 { fn rem(self, other: i16) -> i16 { self % other } } -impl Rem for i32 { fn rem(self, other: i32) -> i32 { self % other } } -impl Rem for i64 { fn rem(self, other: i64) -> i64 { self % other } } -``` - -### `std::ops::{ BitOr, BitAnd, BitXor }` - -```rust title="bitor-trait" showLineNumbers -trait BitOr { - fn bitor(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L79-L83 - -```rust title="bitand-trait" showLineNumbers -trait BitAnd { - fn bitand(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L95-L99 - -```rust title="bitxor-trait" showLineNumbers -trait BitXor { - fn bitxor(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L111-L115 - - -Traits for the bitwise operations `|`, `&`, and `^`. - -Implementing `BitOr`, `BitAnd` or `BitXor` for a type allows the `|`, `&`, or `^` operator respectively -to be used with the type. - -The implementations block below is given for the `BitOr` trait, but the same types that implement -`BitOr` also implement `BitAnd` and `BitXor`. - -Implementations: -```rust -impl BitOr for bool { fn bitor(self, other: bool) -> bool { self | other } } - -impl BitOr for u8 { fn bitor(self, other: u8) -> u8 { self | other } } -impl BitOr for u16 { fn bitor(self, other: u16) -> u16 { self | other } } -impl BitOr for u32 { fn bitor(self, other: u32) -> u32 { self | other } } -impl BitOr for u64 { fn bitor(self, other: u64) -> u64 { self | other } } - -impl BitOr for i8 { fn bitor(self, other: i8) -> i8 { self | other } } -impl BitOr for i16 { fn bitor(self, other: i16) -> i16 { self | other } } -impl BitOr for i32 { fn bitor(self, other: i32) -> i32 { self | other } } -impl BitOr for i64 { fn bitor(self, other: i64) -> i64 { self | other } } -``` - -### `std::ops::{ Shl, Shr }` - -```rust title="shl-trait" showLineNumbers -trait Shl { - fn shl(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L127-L131 - -```rust title="shr-trait" showLineNumbers -trait Shr { - fn shr(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L142-L146 - - -Traits for a bit shift left and bit shift right. - -Implementing `Shl` for a type allows the left shift operator (`<<`) to be used with the implementation type. -Similarly, implementing `Shr` allows the right shift operator (`>>`) to be used with the type. - -Note that bit shifting is not currently implemented for signed types. - -The implementations block below is given for the `Shl` trait, but the same types that implement -`Shl` also implement `Shr`. - -Implementations: -```rust -impl Shl for u8 { fn shl(self, other: u8) -> u8 { self << other } } -impl Shl for u16 { fn shl(self, other: u16) -> u16 { self << other } } -impl Shl for u32 { fn shl(self, other: u32) -> u32 { self << other } } -impl Shl for u64 { fn shl(self, other: u64) -> u64 { self << other } } -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/backend_barretenberg/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/backend_barretenberg/.nojekyll deleted file mode 100644 index e2ac6616add..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/backend_barretenberg/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/backend_barretenberg/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/backend_barretenberg/index.md deleted file mode 100644 index c146316a915..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/backend_barretenberg/index.md +++ /dev/null @@ -1,58 +0,0 @@ -# backend_barretenberg - -## Exports - -### Classes - -| Class | Description | -| :------ | :------ | -| [BarretenbergBackend](classes/BarretenbergBackend.md) | - | - -### Type Aliases - -| Type alias | Description | -| :------ | :------ | -| [BackendOptions](type-aliases/BackendOptions.md) | - | - -## References - -### CompiledCircuit - -Renames and re-exports [Backend](index.md#backend) - -*** - -### ProofData - -Renames and re-exports [Backend](index.md#backend) - -## Variables - -### Backend - -```ts -Backend: any; -``` - -## Functions - -### publicInputsToWitnessMap() - -```ts -publicInputsToWitnessMap(publicInputs, abi): Backend -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `publicInputs` | `string`[] | -| `abi` | `Abi` | - -#### Returns - -[`Backend`](index.md#backend) - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md deleted file mode 100644 index b49a479f4f4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md +++ /dev/null @@ -1,21 +0,0 @@ -# BackendOptions - -```ts -type BackendOptions: object; -``` - -## Description - -An options object, currently only used to specify the number of threads to use. - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `memory` | `object` | - | -| `memory.maximum` | `number` | - | -| `threads` | `number` | **Description**

Number of threads | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs deleted file mode 100644 index 339353b9862..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend","label":"BarretenbergBackend"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions","label":"BackendOptions"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/.nojekyll deleted file mode 100644 index e2ac6616add..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/classes/Noir.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/classes/Noir.md deleted file mode 100644 index 45dd62ee57e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/classes/Noir.md +++ /dev/null @@ -1,132 +0,0 @@ -# Noir - -## Constructors - -### new Noir(circuit, backend) - -```ts -new Noir(circuit, backend?): Noir -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `circuit` | `CompiledCircuit` | -| `backend`? | `any` | - -#### Returns - -[`Noir`](Noir.md) - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Description - -Destroys the underlying backend instance. - -#### Example - -```typescript -await noir.destroy(); -``` - -*** - -### execute() - -```ts -execute(inputs, foreignCallHandler?): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `inputs` | `InputMap` | -| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | - -#### Returns - -`Promise`\<`object`\> - -#### Description - -Allows to execute a circuit to get its witness and return value. - -#### Example - -```typescript -async execute(inputs) -``` - -*** - -### generateProof() - -```ts -generateProof(inputs, foreignCallHandler?): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `inputs` | `InputMap` | -| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | - -#### Returns - -`Promise`\<`ProofData`\> - -#### Description - -Generates a witness and a proof given an object as input. - -#### Example - -```typescript -async generateProof(input) -``` - -*** - -### verifyProof() - -```ts -verifyProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | `ProofData` | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Instantiates the verification key and verifies a proof. - -#### Example - -```typescript -async verifyProof(proof) -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/and.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/and.md deleted file mode 100644 index c783283e396..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/and.md +++ /dev/null @@ -1,22 +0,0 @@ -# and() - -```ts -and(lhs, rhs): string -``` - -Performs a bitwise AND operation between `lhs` and `rhs` - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `lhs` | `string` | | -| `rhs` | `string` | | - -## Returns - -`string` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/blake2s256.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/blake2s256.md deleted file mode 100644 index 7882d0da8d5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/blake2s256.md +++ /dev/null @@ -1,21 +0,0 @@ -# blake2s256() - -```ts -blake2s256(inputs): Uint8Array -``` - -Calculates the Blake2s256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md deleted file mode 100644 index 5e3cd53e9d3..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md +++ /dev/null @@ -1,28 +0,0 @@ -# ecdsa\_secp256k1\_verify() - -```ts -ecdsa_secp256k1_verify( - hashed_msg, - public_key_x_bytes, - public_key_y_bytes, - signature): boolean -``` - -Verifies a ECDSA signature over the secp256k1 curve. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `hashed_msg` | `Uint8Array` | | -| `public_key_x_bytes` | `Uint8Array` | | -| `public_key_y_bytes` | `Uint8Array` | | -| `signature` | `Uint8Array` | | - -## Returns - -`boolean` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md deleted file mode 100644 index 0b20ff68957..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md +++ /dev/null @@ -1,28 +0,0 @@ -# ecdsa\_secp256r1\_verify() - -```ts -ecdsa_secp256r1_verify( - hashed_msg, - public_key_x_bytes, - public_key_y_bytes, - signature): boolean -``` - -Verifies a ECDSA signature over the secp256r1 curve. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `hashed_msg` | `Uint8Array` | | -| `public_key_x_bytes` | `Uint8Array` | | -| `public_key_y_bytes` | `Uint8Array` | | -| `signature` | `Uint8Array` | | - -## Returns - -`boolean` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/keccak256.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/keccak256.md deleted file mode 100644 index d10f155ce86..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/keccak256.md +++ /dev/null @@ -1,21 +0,0 @@ -# keccak256() - -```ts -keccak256(inputs): Uint8Array -``` - -Calculates the Keccak256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/sha256.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/sha256.md deleted file mode 100644 index 6ba4ecac022..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/sha256.md +++ /dev/null @@ -1,21 +0,0 @@ -# sha256() - -```ts -sha256(inputs): Uint8Array -``` - -Calculates the SHA256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/xor.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/xor.md deleted file mode 100644 index 8d762b895d3..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/xor.md +++ /dev/null @@ -1,22 +0,0 @@ -# xor() - -```ts -xor(lhs, rhs): string -``` - -Performs a bitwise XOR operation between `lhs` and `rhs` - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `lhs` | `string` | | -| `rhs` | `string` | | - -## Returns - -`string` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/index.md deleted file mode 100644 index cca6b3ace41..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/index.md +++ /dev/null @@ -1,54 +0,0 @@ -# noir_js - -## Exports - -### Classes - -| Class | Description | -| :------ | :------ | -| [Noir](classes/Noir.md) | - | - -### Type Aliases - -| Type alias | Description | -| :------ | :------ | -| [ForeignCallHandler](type-aliases/ForeignCallHandler.md) | A callback which performs an foreign call and returns the response. | -| [ForeignCallInput](type-aliases/ForeignCallInput.md) | - | -| [ForeignCallOutput](type-aliases/ForeignCallOutput.md) | - | -| [WitnessMap](type-aliases/WitnessMap.md) | - | - -### Functions - -| Function | Description | -| :------ | :------ | -| [and](functions/and.md) | Performs a bitwise AND operation between `lhs` and `rhs` | -| [blake2s256](functions/blake2s256.md) | Calculates the Blake2s256 hash of the input bytes | -| [ecdsa\_secp256k1\_verify](functions/ecdsa_secp256k1_verify.md) | Verifies a ECDSA signature over the secp256k1 curve. | -| [ecdsa\_secp256r1\_verify](functions/ecdsa_secp256r1_verify.md) | Verifies a ECDSA signature over the secp256r1 curve. | -| [keccak256](functions/keccak256.md) | Calculates the Keccak256 hash of the input bytes | -| [sha256](functions/sha256.md) | Calculates the SHA256 hash of the input bytes | -| [xor](functions/xor.md) | Performs a bitwise XOR operation between `lhs` and `rhs` | - -## References - -### CompiledCircuit - -Renames and re-exports [InputMap](index.md#inputmap) - -*** - -### ProofData - -Renames and re-exports [InputMap](index.md#inputmap) - -## Variables - -### InputMap - -```ts -InputMap: any; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md deleted file mode 100644 index 812b8b16481..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md +++ /dev/null @@ -1,24 +0,0 @@ -# ForeignCallHandler - -```ts -type ForeignCallHandler: (name, inputs) => Promise; -``` - -A callback which performs an foreign call and returns the response. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `name` | `string` | The identifier for the type of foreign call being performed. | -| `inputs` | [`ForeignCallInput`](ForeignCallInput.md)[] | An array of hex encoded inputs to the foreign call. | - -## Returns - -`Promise`\<[`ForeignCallOutput`](ForeignCallOutput.md)[]\> - -outputs - An array of hex encoded outputs containing the results of the foreign call. - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md deleted file mode 100644 index dd95809186a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md +++ /dev/null @@ -1,9 +0,0 @@ -# ForeignCallInput - -```ts -type ForeignCallInput: string[]; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md deleted file mode 100644 index b71fb78a946..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md +++ /dev/null @@ -1,9 +0,0 @@ -# ForeignCallOutput - -```ts -type ForeignCallOutput: string | string[]; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md deleted file mode 100644 index 258c46f9d0c..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md +++ /dev/null @@ -1,9 +0,0 @@ -# WitnessMap - -```ts -type WitnessMap: Map; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs deleted file mode 100644 index c6d8125eaad..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/noir_js/classes/Noir","label":"Noir"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallHandler","label":"ForeignCallHandler"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallInput","label":"ForeignCallInput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallOutput","label":"ForeignCallOutput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/WitnessMap","label":"WitnessMap"}]},{"type":"category","label":"Functions","items":[{"type":"doc","id":"reference/NoirJS/noir_js/functions/and","label":"and"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/blake2s256","label":"blake2s256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify","label":"ecdsa_secp256k1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify","label":"ecdsa_secp256r1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/keccak256","label":"keccak256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/sha256","label":"sha256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/xor","label":"xor"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/.nojekyll deleted file mode 100644 index e2ac6616add..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/functions/compile.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/functions/compile.md deleted file mode 100644 index 6faf763b37f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/functions/compile.md +++ /dev/null @@ -1,51 +0,0 @@ -# compile() - -```ts -compile( - fileManager, - projectPath?, - logFn?, -debugLogFn?): Promise -``` - -Compiles a Noir project - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `fileManager` | `FileManager` | The file manager to use | -| `projectPath`? | `string` | The path to the project inside the file manager. Defaults to the root of the file manager | -| `logFn`? | `LogFn` | A logging function. If not provided, console.log will be used | -| `debugLogFn`? | `LogFn` | A debug logging function. If not provided, logFn will be used | - -## Returns - -`Promise`\<[`ProgramCompilationArtifacts`](../index.md#programcompilationartifacts)\> - -## Example - -```typescript -// Node.js - -import { compile_program, createFileManager } from '@noir-lang/noir_wasm'; - -const fm = createFileManager(myProjectPath); -const myCompiledCode = await compile_program(fm); -``` - -```typescript -// Browser - -import { compile_program, createFileManager } from '@noir-lang/noir_wasm'; - -const fm = createFileManager('/'); -for (const path of files) { - await fm.writeFile(path, await getFileAsStream(path)); -} -const myCompiledCode = await compile_program(fm); -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/functions/compile_contract.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/functions/compile_contract.md deleted file mode 100644 index 7d0b39a43ef..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/functions/compile_contract.md +++ /dev/null @@ -1,51 +0,0 @@ -# compile\_contract() - -```ts -compile_contract( - fileManager, - projectPath?, - logFn?, -debugLogFn?): Promise -``` - -Compiles a Noir project - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `fileManager` | `FileManager` | The file manager to use | -| `projectPath`? | `string` | The path to the project inside the file manager. Defaults to the root of the file manager | -| `logFn`? | `LogFn` | A logging function. If not provided, console.log will be used | -| `debugLogFn`? | `LogFn` | A debug logging function. If not provided, logFn will be used | - -## Returns - -`Promise`\<[`ContractCompilationArtifacts`](../index.md#contractcompilationartifacts)\> - -## Example - -```typescript -// Node.js - -import { compile_contract, createFileManager } from '@noir-lang/noir_wasm'; - -const fm = createFileManager(myProjectPath); -const myCompiledCode = await compile_contract(fm); -``` - -```typescript -// Browser - -import { compile_contract, createFileManager } from '@noir-lang/noir_wasm'; - -const fm = createFileManager('/'); -for (const path of files) { - await fm.writeFile(path, await getFileAsStream(path)); -} -const myCompiledCode = await compile_contract(fm); -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/functions/createFileManager.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/functions/createFileManager.md deleted file mode 100644 index 7e65c1d69c7..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/functions/createFileManager.md +++ /dev/null @@ -1,21 +0,0 @@ -# createFileManager() - -```ts -createFileManager(dataDir): FileManager -``` - -Creates a new FileManager instance based on fs in node and memfs in the browser (via webpack alias) - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `dataDir` | `string` | root of the file system | - -## Returns - -`FileManager` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md deleted file mode 100644 index fcea9275341..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md +++ /dev/null @@ -1,21 +0,0 @@ -# inflateDebugSymbols() - -```ts -inflateDebugSymbols(debugSymbols): any -``` - -Decompresses and decodes the debug symbols - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `debugSymbols` | `string` | The base64 encoded debug symbols | - -## Returns - -`any` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/index.md deleted file mode 100644 index b6e0f9d1bc0..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/index.md +++ /dev/null @@ -1,49 +0,0 @@ -# noir_wasm - -## Exports - -### Functions - -| Function | Description | -| :------ | :------ | -| [compile](functions/compile.md) | Compiles a Noir project | -| [compile\_contract](functions/compile_contract.md) | Compiles a Noir project | -| [createFileManager](functions/createFileManager.md) | Creates a new FileManager instance based on fs in node and memfs in the browser (via webpack alias) | -| [inflateDebugSymbols](functions/inflateDebugSymbols.md) | Decompresses and decodes the debug symbols | - -## References - -### compile\_program - -Renames and re-exports [compile](functions/compile.md) - -## Interfaces - -### ContractCompilationArtifacts - -The compilation artifacts of a given contract. - -#### Properties - -| Property | Type | Description | -| :------ | :------ | :------ | -| `contract` | `ContractArtifact` | The compiled contract. | -| `warnings` | `unknown`[] | Compilation warnings. | - -*** - -### ProgramCompilationArtifacts - -The compilation artifacts of a given program. - -#### Properties - -| Property | Type | Description | -| :------ | :------ | :------ | -| `name` | `string` | not part of the compilation output, injected later | -| `program` | `ProgramArtifact` | The compiled contract. | -| `warnings` | `unknown`[] | Compilation warnings. | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs deleted file mode 100644 index e0870710349..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"doc","id":"reference/NoirJS/noir_wasm/index","label":"API"},{"type":"category","label":"Functions","items":[{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/compile","label":"compile"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/compile_contract","label":"compile_contract"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/createFileManager","label":"createFileManager"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/inflateDebugSymbols","label":"inflateDebugSymbols"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/_category_.json deleted file mode 100644 index 5b6a20a609a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 4, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/nargo_commands.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/nargo_commands.md deleted file mode 100644 index 218fcfb0c8c..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/nargo_commands.md +++ /dev/null @@ -1,381 +0,0 @@ ---- -title: Nargo -description: - Noir CLI Commands for Noir Prover and Verifier to create, execute, prove and verify programs, - generate Solidity verifier smart contract and compile into JSON file containing ACIR - representation and ABI of circuit. -keywords: - [ - Nargo, - Noir CLI, - Noir Prover, - Noir Verifier, - generate Solidity verifier, - compile JSON file, - ACIR representation, - ABI of circuit, - TypeScript, - ] -sidebar_position: 0 ---- - -# Command-Line Help for `nargo` - -This document contains the help content for the `nargo` command-line program. - -**Command Overview:** - -* [`nargo`↴](#nargo) -* [`nargo backend`↴](#nargo-backend) -* [`nargo backend current`↴](#nargo-backend-current) -* [`nargo backend ls`↴](#nargo-backend-ls) -* [`nargo backend use`↴](#nargo-backend-use) -* [`nargo backend install`↴](#nargo-backend-install) -* [`nargo backend uninstall`↴](#nargo-backend-uninstall) -* [`nargo check`↴](#nargo-check) -* [`nargo fmt`↴](#nargo-fmt) -* [`nargo codegen-verifier`↴](#nargo-codegen-verifier) -* [`nargo compile`↴](#nargo-compile) -* [`nargo new`↴](#nargo-new) -* [`nargo init`↴](#nargo-init) -* [`nargo execute`↴](#nargo-execute) -* [`nargo prove`↴](#nargo-prove) -* [`nargo verify`↴](#nargo-verify) -* [`nargo test`↴](#nargo-test) -* [`nargo info`↴](#nargo-info) -* [`nargo lsp`↴](#nargo-lsp) - -## `nargo` - -Noir's package manager - -**Usage:** `nargo ` - -###### **Subcommands:** - -* `backend` — Install and select custom backends used to generate and verify proofs -* `check` — Checks the constraint system for errors -* `fmt` — Format the Noir files in a workspace -* `codegen-verifier` — Generates a Solidity verifier smart contract for the program -* `compile` — Compile the program and its secret execution trace into ACIR format -* `new` — Create a Noir project in a new directory -* `init` — Create a Noir project in the current directory -* `execute` — Executes a circuit to calculate its return value -* `prove` — Create proof for this program. The proof is returned as a hex encoded string -* `verify` — Given a proof and a program, verify whether the proof is valid -* `test` — Run the tests for this program -* `info` — Provides detailed information on each of a program's function (represented by a single circuit) -* `lsp` — Starts the Noir LSP server - -###### **Options:** - - - - -## `nargo backend` - -Install and select custom backends used to generate and verify proofs - -**Usage:** `nargo backend ` - -###### **Subcommands:** - -* `current` — Prints the name of the currently active backend -* `ls` — Prints the list of currently installed backends -* `use` — Select the backend to use -* `install` — Install a new backend from a URL -* `uninstall` — Uninstalls a backend - - - -## `nargo backend current` - -Prints the name of the currently active backend - -**Usage:** `nargo backend current` - - - -## `nargo backend ls` - -Prints the list of currently installed backends - -**Usage:** `nargo backend ls` - - - -## `nargo backend use` - -Select the backend to use - -**Usage:** `nargo backend use ` - -###### **Arguments:** - -* `` - - - -## `nargo backend install` - -Install a new backend from a URL - -**Usage:** `nargo backend install ` - -###### **Arguments:** - -* `` — The name of the backend to install -* `` — The URL from which to download the backend - - - -## `nargo backend uninstall` - -Uninstalls a backend - -**Usage:** `nargo backend uninstall ` - -###### **Arguments:** - -* `` — The name of the backend to uninstall - - - -## `nargo check` - -Checks the constraint system for errors - -**Usage:** `nargo check [OPTIONS]` - -###### **Options:** - -* `--package ` — The name of the package to check -* `--workspace` — Check all packages in the workspace -* `--overwrite` — Force overwrite of existing files -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings - - - -## `nargo fmt` - -Format the Noir files in a workspace - -**Usage:** `nargo fmt [OPTIONS]` - -###### **Options:** - -* `--check` — Run noirfmt in check mode - - - -## `nargo codegen-verifier` - -Generates a Solidity verifier smart contract for the program - -**Usage:** `nargo codegen-verifier [OPTIONS]` - -###### **Options:** - -* `--package ` — The name of the package to codegen -* `--workspace` — Codegen all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings - - - -## `nargo compile` - -Compile the program and its secret execution trace into ACIR format - -**Usage:** `nargo compile [OPTIONS]` - -###### **Options:** - -* `--package ` — The name of the package to compile -* `--workspace` — Compile all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings - - - -## `nargo new` - -Create a Noir project in a new directory - -**Usage:** `nargo new [OPTIONS] ` - -###### **Arguments:** - -* `` — The path to save the new project - -###### **Options:** - -* `--name ` — Name of the package [default: package directory name] -* `--lib` — Use a library template -* `--bin` — Use a binary template [default] -* `--contract` — Use a contract template - - - -## `nargo init` - -Create a Noir project in the current directory - -**Usage:** `nargo init [OPTIONS]` - -###### **Options:** - -* `--name ` — Name of the package [default: current directory name] -* `--lib` — Use a library template -* `--bin` — Use a binary template [default] -* `--contract` — Use a contract template - - - -## `nargo execute` - -Executes a circuit to calculate its return value - -**Usage:** `nargo execute [OPTIONS] [WITNESS_NAME]` - -###### **Arguments:** - -* `` — Write the execution witness to named file - -###### **Options:** - -* `-p`, `--prover-name ` — The name of the toml file which contains the inputs for the prover - - Default value: `Prover` -* `--package ` — The name of the package to execute -* `--workspace` — Execute all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings -* `--oracle-resolver ` — JSON RPC url to solve oracle calls - - - -## `nargo prove` - -Create proof for this program. The proof is returned as a hex encoded string - -**Usage:** `nargo prove [OPTIONS]` - -###### **Options:** - -* `-p`, `--prover-name ` — The name of the toml file which contains the inputs for the prover - - Default value: `Prover` -* `-v`, `--verifier-name ` — The name of the toml file which contains the inputs for the verifier - - Default value: `Verifier` -* `--verify` — Verify proof after proving -* `--package ` — The name of the package to prove -* `--workspace` — Prove all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings -* `--oracle-resolver ` — JSON RPC url to solve oracle calls - - - -## `nargo verify` - -Given a proof and a program, verify whether the proof is valid - -**Usage:** `nargo verify [OPTIONS]` - -###### **Options:** - -* `-v`, `--verifier-name ` — The name of the toml file which contains the inputs for the verifier - - Default value: `Verifier` -* `--package ` — The name of the package verify -* `--workspace` — Verify all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings - - - -## `nargo test` - -Run the tests for this program - -**Usage:** `nargo test [OPTIONS] [TEST_NAME]` - -###### **Arguments:** - -* `` — If given, only tests with names containing this string will be run - -###### **Options:** - -* `--show-output` — Display output of `println` statements -* `--exact` — Only run tests that match exactly -* `--package ` — The name of the package to test -* `--workspace` — Test all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings -* `--oracle-resolver ` — JSON RPC url to solve oracle calls - - - -## `nargo info` - -Provides detailed information on each of a program's function (represented by a single circuit) - -Current information provided per circuit: 1. The number of ACIR opcodes 2. Counts the final number gates in the circuit used by a backend - -**Usage:** `nargo info [OPTIONS]` - -###### **Options:** - -* `--package ` — The name of the package to detail -* `--workspace` — Detail all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings - - - -## `nargo lsp` - -Starts the Noir LSP server - -Starts an LSP server which allows IDEs such as VS Code to display diagnostics in Noir source. - -VS Code Noir Language Support: https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir - -**Usage:** `nargo lsp` - - - -
- - - This document was generated automatically by - clap-markdown. - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/tutorials/noirjs_app.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/tutorials/noirjs_app.md deleted file mode 100644 index a6dda7e08c3..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/tutorials/noirjs_app.md +++ /dev/null @@ -1,324 +0,0 @@ ---- -title: Building a web app with NoirJS -description: Learn how to setup a new app that uses Noir to generate and verify zero-knowledge SNARK proofs in a typescript or javascript environment. -keywords: [how to, guide, javascript, typescript, noir, barretenberg, zero-knowledge, proofs, app] -sidebar_position: 0 -pagination_next: noir/concepts/data_types/index ---- - -NoirJS is a set of packages meant to work both in a browser and a server environment. In this tutorial, we will build a simple web app using them. From here, you should get an idea on how to proceed with your own Noir projects! - -You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). - -## Setup - -:::note - -Feel free to use whatever versions, just keep in mind that Nargo and the NoirJS packages are meant to be in sync. For example, Nargo 0.26.x matches `noir_js@0.26.x`, etc. - -In this guide, we will be pinned to 0.26.0. - -::: - -Before we start, we want to make sure we have Node and Nargo installed. - -We start by opening a terminal and executing `node --version`. If we don't get an output like `v20.10.0`, that means node is not installed. Let's do that by following the handy [nvm guide](https://github.com/nvm-sh/nvm?tab=readme-ov-file#install--update-script). - -As for `Nargo`, we can follow the [Nargo guide](../getting_started/installation/index.md) to install it. If you're lazy, just paste this on a terminal and run `noirup`: - -```sh -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -Easy enough. Onwards! - -## Our project - -ZK is a powerful technology. An app that doesn't reveal one of the inputs to _anyone_ is almost unbelievable, yet Noir makes it as easy as a single line of code. - -In fact, it's so simple that it comes nicely packaged in `nargo`. Let's do that! - -### Nargo - -Run: - -`nargo new circuit` - -And... That's about it. Your program is ready to be compiled and run. - -To compile, let's `cd` into the `circuit` folder to enter our project, and call: - -`nargo compile` - -This compiles our circuit into `json` format and add it to a new `target` folder. - -:::info - -At this point in the tutorial, your folder structure should look like this: - -```tree -. -└── circuit <---- our working directory - ├── Nargo.toml - ├── src - │ └── main.nr - └── target - └── circuit.json -``` - -::: - -### Node and Vite - -If you want to explore Nargo, feel free to go on a side-quest now and follow the steps in the -[getting started](../getting_started/hello_noir/index.md) guide. However, we want our app to run on the browser, so we need Vite. - -Vite is a powerful tool to generate static websites. While it provides all kinds of features, let's just go barebones with some good old vanilla JS. - -To do this this, go back to the previous folder (`cd ..`) and create a new vite project by running `npm create vite` and choosing "Vanilla" and "Javascript". - -A wild `vite-project` directory should now appear in your root folder! Let's not waste any time and dive right in: - -```bash -cd vite-project -``` - -### Setting Up Vite and Configuring the Project - -Before we proceed with any coding, let's get our environment tailored for Noir. We'll start by laying down the foundations with a `vite.config.js` file. This little piece of configuration is our secret sauce for making sure everything meshes well with the NoirJS libraries and other special setups we might need, like handling WebAssembly modules. Here’s how you get that going: - -#### Creating the vite.config.js - -In your freshly minted `vite-project` folder, create a new file named `vite.config.js` and open it in your code editor. Paste the following to set the stage: - -```javascript -import { defineConfig } from "vite"; -import copy from "rollup-plugin-copy"; - -export default defineConfig({ - esbuild: { - target: "esnext", - }, - optimizeDeps: { - esbuildOptions: { - target: "esnext", - }, - }, - plugins: [ - copy({ - targets: [ - { src: "node_modules/**/*.wasm", dest: "node_modules/.vite/dist" }, - ], - copySync: true, - hook: "buildStart", - }), - ], - server: { - port: 3000, - }, -}); -``` - -#### Install Dependencies - -Now that our stage is set, install the necessary NoirJS packages along with our other dependencies: - -```bash -npm install && npm install @noir-lang/backend_barretenberg@0.26.0 @noir-lang/noir_js@0.26.0 -npm install rollup-plugin-copy --save-dev -``` - -:::info - -At this point in the tutorial, your folder structure should look like this: - -```tree -. -└── circuit - └── ...etc... -└── vite-project <---- our working directory - └── ...etc... -``` - -::: - -#### Some cleanup - -`npx create vite` is amazing but it creates a bunch of files we don't really need for our simple example. Actually, let's just delete everything except for `vite.config.js`, `index.html`, `main.js` and `package.json`. I feel lighter already. - -![my heart is ready for you, noir.js](@site/static/img/memes/titanic.jpeg) - -## HTML - -Our app won't run like this, of course. We need some working HTML, at least. Let's open our broken-hearted `index.html` and replace everything with this code snippet: - -```html - - - - - - -

Noir app

-
- - -
-
-

Logs

-

Proof

-
- - -``` - -It _could_ be a beautiful UI... Depending on which universe you live in. - -## Some good old vanilla Javascript - -Our love for Noir needs undivided attention, so let's just open `main.js` and delete everything (this is where the romantic scenery becomes a bit creepy). - -Start by pasting in this boilerplate code: - -```js -const setup = async () => { - await Promise.all([ - import('@noir-lang/noirc_abi').then((module) => - module.default(new URL('@noir-lang/noirc_abi/web/noirc_abi_wasm_bg.wasm', import.meta.url).toString()), - ), - import('@noir-lang/acvm_js').then((module) => - module.default(new URL('@noir-lang/acvm_js/web/acvm_js_bg.wasm', import.meta.url).toString()), - ), - ]); -}; - -function display(container, msg) { - const c = document.getElementById(container); - const p = document.createElement('p'); - p.textContent = msg; - c.appendChild(p); -} - -document.getElementById('submitGuess').addEventListener('click', async () => { - try { - // here's where love happens - } catch (err) { - display('logs', 'Oh 💔 Wrong guess'); - } -}); -``` - -The display function doesn't do much. We're simply manipulating our website to see stuff happening. For example, if the proof fails, it will simply log a broken heart 😢 - -As for the `setup` function, it's just a sad reminder that dealing with `wasm` on the browser is not as easy as it should. Just copy, paste, and forget. - -:::info - -At this point in the tutorial, your folder structure should look like this: - -```tree -. -└── circuit - └── ...same as above -└── vite-project - └── vite.config.js - ├── main.js - ├── package.json - └── index.html -``` - -You'll see other files and folders showing up (like `package-lock.json`, `node_modules`) but you shouldn't have to care about those. - -::: - -## Some NoirJS - -We're starting with the good stuff now. If you've compiled the circuit as described above, you should have a `json` file we want to import at the very top of our `main.js` file: - -```ts -import circuit from '../circuit/target/circuit.json'; -``` - -[Noir is backend-agnostic](../index.mdx#whats-new-about-noir). We write Noir, but we also need a proving backend. That's why we need to import and instantiate the two dependencies we installed above: `BarretenbergBackend` and `Noir`. Let's import them right below: - -```js -import { BarretenbergBackend } from '@noir-lang/backend_barretenberg'; -import { Noir } from '@noir-lang/noir_js'; -``` - -And instantiate them inside our try-catch block: - -```ts -// try { -const backend = new BarretenbergBackend(circuit); -const noir = new Noir(circuit, backend); -// } -``` - -:::note - -For the remainder of the tutorial, everything will be happening inside the `try` block - -::: - -## Our app - -Now for the app itself. We're capturing whatever is in the input when people press the submit button. Just add this: - -```js -const x = parseInt(document.getElementById('guessInput').value); -const input = { x, y: 2 }; -``` - -Now we're ready to prove stuff! Let's feed some inputs to our circuit and calculate the proof: - -```js -await setup(); // let's squeeze our wasm inits here - -display('logs', 'Generating proof... ⌛'); -const proof = await noir.generateProof(input); -display('logs', 'Generating proof... ✅'); -display('results', proof.proof); -``` - -You're probably eager to see stuff happening, so go and run your app now! - -From your terminal, run `npm run dev`. If it doesn't open a browser for you, just visit `localhost:5173`. You should now see the worst UI ever, with an ugly input. - -![Getting Started 0](@site/static/img/noir_getting_started_1.png) - -Now, our circuit says `fn main(x: Field, y: pub Field)`. This means only the `y` value is public, and it's hardcoded above: `input = { x, y: 2 }`. In other words, you won't need to send your secret`x` to the verifier! - -By inputting any number other than 2 in the input box and clicking "submit", you should get a valid proof. Otherwise the proof won't even generate correctly. By the way, if you're human, you shouldn't be able to understand anything on the "proof" box. That's OK. We like you, human ❤️. - -## Verifying - -Time to celebrate, yes! But we shouldn't trust machines so blindly. Let's add these lines to see our proof being verified: - -```js -display('logs', 'Verifying proof... ⌛'); -const verification = await noir.verifyProof(proof); -if (verification) display('logs', 'Verifying proof... ✅'); -``` - -You have successfully generated a client-side Noir web app! - -![coded app without math knowledge](@site/static/img/memes/flextape.jpeg) - -## Further Reading - -You can see how noirjs is used in a full stack Next.js hardhat application in the [noir-starter repo here](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat). The example shows how to calculate a proof in the browser and verify it with a deployed Solidity verifier contract from noirjs. - -You should also check out the more advanced examples in the [noir-examples repo](https://github.com/noir-lang/noir-examples), where you'll find reference usage for some cool apps. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/explainers/explainer-oracle.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/explainers/explainer-oracle.md deleted file mode 100644 index b84ca5dd986..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/explainers/explainer-oracle.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: Oracles -description: This guide provides an in-depth understanding of how Oracles work in Noir programming. Learn how to use outside calculations in your programs, constrain oracles, and understand their uses and limitations. -keywords: - - Noir Programming - - Oracles - - JSON-RPC - - Foreign Call Handlers - - Constrained Functions - - Blockchain Programming -sidebar_position: 1 ---- - -If you've seen "The Matrix" you may recall "The Oracle" as Gloria Foster smoking cigarettes and baking cookies. While she appears to "know things", she is actually providing a calculation of a pre-determined future. Noir Oracles are similar, in a way. They don't calculate the future (yet), but they allow you to use outside calculations in your programs. - -![matrix oracle prediction](@site/static/img/memes/matrix_oracle.jpeg) - -A Noir program is usually self-contained. You can pass certain inputs to it, and it will generate a deterministic output for those inputs. But what if you wanted to defer some calculation to an outside process or source? - -Oracles are functions that provide this feature. - -## Use cases - -An example usage for Oracles is proving something on-chain. For example, proving that the ETH-USDC quote was below a certain target at a certain block time. Or even making more complex proofs like proving the ownership of an NFT as an anonymous login method. - -Another interesting use case is to defer expensive calculations to be made outside of the Noir program, and then constraining the result; similar to the use of [unconstrained functions](../noir/concepts//unconstrained.md). - -In short, anything that can be constrained in a Noir program but needs to be fetched from an external source is a great candidate to be used in oracles. - -## Constraining oracles - -Just like in The Matrix, Oracles are powerful. But with great power, comes great responsibility. Just because you're using them in a Noir program doesn't mean they're true. Noir has no superpowers. If you want to prove that Portugal won the Euro Cup 2016, you're still relying on potentially untrusted information. - -To give a concrete example, Alice wants to login to the [NounsDAO](https://nouns.wtf/) forum with her username "noir_nouner" by proving she owns a noun without revealing her ethereum address. Her Noir program could have a oracle call like this: - -```rust -#[oracle(getNoun)] -unconstrained fn get_noun(address: Field) -> Field -``` - -This oracle could naively resolve with the number of Nouns she possesses. However, it is useless as a trusted source, as the oracle could resolve to anything Alice wants. In order to make this oracle call actually useful, Alice would need to constrain the response from the oracle, by proving her address and the noun count belongs to the state tree of the contract. - -In short, **Oracles don't prove anything. Your Noir program does.** - -:::danger - -If you don't constrain the return of your oracle, you could be clearly opening an attack vector on your Noir program. Make double-triple sure that the return of an oracle call is constrained! - -::: - -## How to use Oracles - -On CLI, Nargo resolves oracles by making JSON RPC calls, which means it would require an RPC node to be running. - -In JavaScript, NoirJS accepts and resolves arbitrary call handlers (that is, not limited to JSON) as long as they matches the expected types the developer defines. Refer to [Foreign Call Handler](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) to learn more about NoirJS's call handling. - -If you want to build using oracles, follow through to the [oracle guide](../how_to/how-to-oracles.md) for a simple example on how to do that. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/explainers/explainer-recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/explainers/explainer-recursion.md deleted file mode 100644 index 18846176ca7..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/explainers/explainer-recursion.md +++ /dev/null @@ -1,176 +0,0 @@ ---- -title: Recursive proofs -description: Explore the concept of recursive proofs in Zero-Knowledge programming. Understand how recursion works in Noir, a language for writing smart contracts on the EVM blockchain. Learn through practical examples like Alice and Bob's guessing game, Charlie's recursive merkle tree, and Daniel's reusable components. Discover how to use recursive proofs to optimize computational resources and improve efficiency. - -keywords: - [ - "Recursive Proofs", - "Zero-Knowledge Programming", - "Noir", - "EVM Blockchain", - "Smart Contracts", - "Recursion in Noir", - "Alice and Bob Guessing Game", - "Recursive Merkle Tree", - "Reusable Components", - "Optimizing Computational Resources", - "Improving Efficiency", - "Verification Key", - "Aggregation", - "Recursive zkSNARK schemes", - "PLONK", - "Proving and Verification Keys" - ] -sidebar_position: 1 -pagination_next: how_to/how-to-recursion ---- - -In programming, we tend to think of recursion as something calling itself. A classic example would be the calculation of the factorial of a number: - -```js -function factorial(n) { - if (n === 0 || n === 1) { - return 1; - } else { - return n * factorial(n - 1); - } -} -``` - -In this case, while `n` is not `1`, this function will keep calling itself until it hits the base case, bubbling up the result on the call stack: - -```md - Is `n` 1? <--------- - /\ / - / \ n = n -1 - / \ / - Yes No -------- -``` - -In Zero-Knowledge, recursion has some similarities. - -It is not a Noir function calling itself, but a proof being used as an input to another circuit. In short, you verify one proof *inside* another proof, returning the proof that both proofs are valid. - -This means that, given enough computational resources, you can prove the correctness of any arbitrary number of proofs in a single proof. This could be useful to design state channels (for which a common example would be [Bitcoin's Lightning Network](https://en.wikipedia.org/wiki/Lightning_Network)), to save on gas costs by settling one proof on-chain, or simply to make business logic less dependent on a consensus mechanism. - -## Examples - -Let us look at some of these examples - -### Alice and Bob - Guessing game - -Alice and Bob are friends, and they like guessing games. They want to play a guessing game online, but for that, they need a trusted third-party that knows both of their secrets and finishes the game once someone wins. - -So, they use zero-knowledge proofs. Alice tries to guess Bob's number, and Bob will generate a ZK proof stating whether she succeeded or failed. - -This ZK proof can go on a smart contract, revealing the winner and even giving prizes. However, this means every turn needs to be verified on-chain. This incurs some cost and waiting time that may simply make the game too expensive or time-consuming to be worth it. - -As a solution, Alice proposes the following: "what if Bob generates his proof, and instead of sending it on-chain, I verify it *within* my own proof before playing my own turn?". - -She can then generate a proof that she verified his proof, and so on. - -```md - Did you fail? <-------------------------- - / \ / - / \ n = n -1 - / \ / - Yes No / - | | / - | | / - | You win / - | / - | / -Generate proof of that / - + / - my own guess ---------------- -``` - -### Charlie - Recursive merkle tree - -Charlie is a concerned citizen, and wants to be sure his vote in an election is accounted for. He votes with a ZK proof, but he has no way of knowing that his ZK proof was included in the total vote count! - -If the vote collector puts all of the votes into a [Merkle tree](https://en.wikipedia.org/wiki/Merkle_tree), everyone can prove the verification of two proofs within one proof, as such: - -```md - abcd - __________|______________ - | | - ab cd - _____|_____ ______|______ - | | | | - alice bob charlie daniel -``` - -Doing this recursively allows us to arrive on a final proof `abcd` which if true, verifies the correctness of all the votes. - -### Daniel - Reusable components - -Daniel has a big circuit and a big headache. A part of his circuit is a setup phase that finishes with some assertions that need to be made. But that section alone takes most of the proving time, and is largely independent of the rest of the circuit. - -He might find it more efficient to generate a proof for that setup phase separately, and verify that proof recursively in the actual business logic section of his circuit. This will allow for parallelization of both proofs, which results in a considerable speedup. - -## What params do I need - -As you can see in the [recursion reference](noir/standard_library/recursion.md), a simple recursive proof requires: - -- The proof to verify -- The Verification Key of the circuit that generated the proof -- A hash of this verification key, as it's needed for some backends -- The public inputs for the proof - -:::info - -Recursive zkSNARK schemes do not necessarily "verify a proof" in the sense that you expect a true or false to be spit out by the verifier. Rather an aggregation object is built over the public inputs. - -So, taking the example of Alice and Bob and their guessing game: - -- Alice makes her guess. Her proof is *not* recursive: it doesn't verify any proof within it! It's just a standard `assert(x != y)` circuit -- Bob verifies Alice's proof and makes his own guess. In this circuit, he doesn't exactly *prove* the verification of Alice's proof. Instead, he *aggregates* his proof to Alice's proof. The actual verification is done when the full proof is verified, for example when using `nargo verify` or through the verifier smart contract. - -We can imagine recursive proofs a [relay race](https://en.wikipedia.org/wiki/Relay_race). The first runner doesn't have to receive the baton from anyone else, as he/she already starts with it. But when his/her turn is over, the next runner needs to receive it, run a bit more, and pass it along. Even though every runner could theoretically verify the baton mid-run (why not? 🏃🔍), only at the end of the race does the referee verify that the whole race is valid. - -::: - -## Some architecture - -As with everything in computer science, there's no one-size-fits all. But there are some patterns that could help understanding and implementing them. To give three examples: - -### Adding some logic to a proof verification - -This would be an approach for something like our guessing game, where proofs are sent back and forth and are verified by each opponent. This circuit would be divided in two sections: - -- A `recursive verification` section, which would be just the call to `std::verify_proof`, and that would be skipped on the first move (since there's no proof to verify) -- A `guessing` section, which is basically the logic part where the actual guessing happens - -In such a situation, and assuming Alice is first, she would skip the first part and try to guess Bob's number. Bob would then verify her proof on the first section of his run, and try to guess Alice's number on the second part, and so on. - -### Aggregating proofs - -In some one-way interaction situations, recursion would allow for aggregation of simple proofs that don't need to be immediately verified on-chain or elsewhere. - -To give a practical example, a barman wouldn't need to verify a "proof-of-age" on-chain every time he serves alcohol to a customer. Instead, the architecture would comprise two circuits: - -- A `main`, non-recursive circuit with some logic -- A `recursive` circuit meant to verify two proofs in one proof - -The customer's proofs would be intermediate, and made on their phones, and the barman could just verify them locally. He would then aggregate them into a final proof sent on-chain (or elsewhere) at the end of the day. - -### Recursively verifying different circuits - -Nothing prevents you from verifying different circuits in a recursive proof, for example: - -- A `circuit1` circuit -- A `circuit2` circuit -- A `recursive` circuit - -In this example, a regulator could verify that taxes were paid for a specific purchase by aggregating both a `payer` circuit (proving that a purchase was made and taxes were paid), and a `receipt` circuit (proving that the payment was received) - -## How fast is it - -At the time of writing, verifying recursive proofs is surprisingly fast. This is because most of the time is spent on generating the verification key that will be used to generate the next proof. So you are able to cache the verification key and reuse it later. - -Currently, Noir JS packages don't expose the functionality of loading proving and verification keys, but that feature exists in the underlying `bb.js` package. - -## How can I try it - -Learn more about using recursion in Nargo and NoirJS in the [how-to guide](../how_to/how-to-recursion.md) and see a full example in [noir-examples](https://github.com/noir-lang/noir-examples). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/_category_.json deleted file mode 100644 index 5d694210bbf..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 0, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/hello_noir/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/hello_noir/_category_.json deleted file mode 100644 index 23b560f610b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/hello_noir/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 1, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/hello_noir/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/hello_noir/index.md deleted file mode 100644 index 743c4d8d634..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/hello_noir/index.md +++ /dev/null @@ -1,142 +0,0 @@ ---- -title: Creating a Project -description: - Learn how to create and verify your first Noir program using Nargo, a programming language for - zero-knowledge proofs. -keywords: - [ - Nargo, - Noir, - zero-knowledge proofs, - programming language, - create Noir program, - verify Noir program, - step-by-step guide, - ] -sidebar_position: 1 - ---- - -Now that we have installed Nargo, it is time to make our first hello world program! - -## Create a Project Directory - -Noir code can live anywhere on your computer. Let us create a _projects_ folder in the home -directory to house our Noir programs. - -For Linux, macOS, and Windows PowerShell, create the directory and change directory into it by -running: - -```sh -mkdir ~/projects -cd ~/projects -``` - -## Create Our First Nargo Project - -Now that we are in the projects directory, create a new Nargo project by running: - -```sh -nargo new hello_world -``` - -> **Note:** `hello_world` can be any arbitrary project name, we are simply using `hello_world` for -> demonstration. -> -> In production, the common practice is to name the project folder as `circuits` for better -> identifiability when sitting alongside other folders in the codebase (e.g. `contracts`, `scripts`, -> `test`). - -A `hello_world` folder would be created. Similar to Rust, the folder houses _src/main.nr_ and -_Nargo.toml_ which contain the source code and environmental options of your Noir program -respectively. - -### Intro to Noir Syntax - -Let us take a closer look at _main.nr_. The default _main.nr_ generated should look like this: - -```rust -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` - -The first line of the program specifies the program's inputs: - -```rust -x : Field, y : pub Field -``` - -Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the -keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](../../noir/concepts/data_types/index.md) section. - -The next line of the program specifies its body: - -```rust -assert(x != y); -``` - -The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. - -For more Noir syntax, check the [Language Concepts](../../noir/concepts/comments.md) chapter. - -## Build In/Output Files - -Change directory into _hello_world_ and build in/output files for your Noir program by running: - -```sh -cd hello_world -nargo check -``` - -Two additional files would be generated in your project directory: - -_Prover.toml_ houses input values, and _Verifier.toml_ houses public values. - -## Prove Our Noir Program - -Now that the project is set up, we can create a proof of correct execution of our Noir program. - -Fill in input values for execution in the _Prover.toml_ file. For example: - -```toml -x = "1" -y = "2" -``` - -Prove the valid execution of your Noir program: - -```sh -nargo prove -``` - -A new folder _proofs_ would then be generated in your project directory, containing the proof file -`.proof`, where the project name is defined in Nargo.toml. - -The _Verifier.toml_ file would also be updated with the public values computed from program -execution (in this case the value of `y`): - -```toml -y = "0x0000000000000000000000000000000000000000000000000000000000000002" -``` - -> **Note:** Values in _Verifier.toml_ are computed as 32-byte hex values. - -## Verify Our Noir Program - -Once a proof is generated, we can verify correct execution of our Noir program by verifying the -proof file. - -Verify your proof by running: - -```sh -nargo verify -``` - -The verification will complete in silence if it is successful. If it fails, it will log the -corresponding error instead. - -Congratulations, you have now created and verified a proof for your very first Noir program! - -In the [next section](./project_breakdown.md), we will go into more detail on each step performed. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/hello_noir/project_breakdown.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/hello_noir/project_breakdown.md deleted file mode 100644 index 6160a102c6c..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/hello_noir/project_breakdown.md +++ /dev/null @@ -1,199 +0,0 @@ ---- -title: Project Breakdown -description: - Learn about the anatomy of a Nargo project, including the purpose of the Prover and Verifier TOML - files, and how to prove and verify your program. -keywords: - [Nargo, Nargo project, Prover.toml, Verifier.toml, proof verification, private asset transfer] -sidebar_position: 2 ---- - -This section breaks down our hello world program from the previous section. We elaborate on the project -structure and what the `prove` and `verify` commands did. - -## Anatomy of a Nargo Project - -Upon creating a new project with `nargo new` and building the in/output files with `nargo check` -commands, you would get a minimal Nargo project of the following structure: - - - src - - Prover.toml - - Verifier.toml - - Nargo.toml - -The source directory _src_ holds the source code for your Noir program. By default only a _main.nr_ -file will be generated within it. - -### Prover.toml - -_Prover.toml_ is used for specifying the input values for executing and proving the program. You can specify `toml` files with different names by using the `--prover-name` or `-p` flags, see the [Prover](#provertoml) section below. Optionally you may specify expected output values for prove-time checking as well. - -### Verifier.toml - -_Verifier.toml_ contains public in/output values computed when executing the Noir program. - -### Nargo.toml - -_Nargo.toml_ contains the environmental options of your project. It contains a "package" section and a "dependencies" section. - -Example Nargo.toml: - -```toml -[package] -name = "noir_starter" -type = "bin" -authors = ["Alice"] -compiler_version = "0.9.0" -description = "Getting started with Noir" -entry = "circuit/main.nr" -license = "MIT" - -[dependencies] -ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} -``` - -Nargo.toml for a [workspace](../../noir/modules_packages_crates/workspaces.md) will look a bit different. For example: - -```toml -[workspace] -members = ["crates/a", "crates/b"] -default-member = "crates/a" -``` - -#### Package section - -The package section defines a number of fields including: - -- `name` (**required**) - the name of the package -- `type` (**required**) - can be "bin", "lib", or "contract" to specify whether its a binary, library or Aztec contract -- `authors` (optional) - authors of the project -- `compiler_version` - specifies the version of the compiler to use. This is enforced by the compiler and follow's [Rust's versioning](https://doc.rust-lang.org/cargo/reference/manifest.html#the-version-field), so a `compiler_version = 0.18.0` will enforce Nargo version 0.18.0, `compiler_version = ^0.18.0` will enforce anything above 0.18.0 but below 0.19.0, etc. For more information, see how [Rust handles these operators](https://docs.rs/semver/latest/semver/enum.Op.html) -- `description` (optional) -- `entry` (optional) - a relative filepath to use as the entry point into your package (overrides the default of `src/lib.nr` or `src/main.nr`) -- `backend` (optional) -- `license` (optional) - -#### Dependencies section - -This is where you will specify any dependencies for your project. See the [Dependencies page](../../noir/modules_packages_crates/dependencies.md) for more info. - -`./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or -verifier contract respectively. - -### main.nr - -The _main.nr_ file contains a `main` method, this method is the entry point into your Noir program. - -In our sample program, _main.nr_ looks like this: - -```rust -fn main(x : Field, y : Field) { - assert(x != y); -} -``` - -The parameters `x` and `y` can be seen as the API for the program and must be supplied by the -prover. Since neither `x` nor `y` is marked as public, the verifier does not supply any inputs, when -verifying the proof. - -The prover supplies the values for `x` and `y` in the _Prover.toml_ file. - -As for the program body, `assert` ensures that the condition to be satisfied (e.g. `x != y`) is -constrained by the proof of the execution of said program (i.e. if the condition was not met, the -verifier would reject the proof as an invalid proof). - -### Prover.toml - -The _Prover.toml_ file is a file which the prover uses to supply his witness values(both private and -public). - -In our hello world program the _Prover.toml_ file looks like this: - -```toml -x = "1" -y = "2" -``` - -When the command `nargo prove` is executed, two processes happen: - -1. Noir creates a proof that `x`, which holds the value of `1`, and `y`, which holds the value of `2`, - is not equal. This inequality constraint is due to the line `assert(x != y)`. - -2. Noir creates and stores the proof of this statement in the _proofs_ directory in a file called your-project.proof. So if your project is named "private_voting" (defined in the project Nargo.toml), the proof will be saved at `./proofs/private_voting.proof`. Opening this file will display the proof in hex format. - -#### Arrays of Structs - -The following code shows how to pass an array of structs to a Noir program to generate a proof. - -```rust -// main.nr -struct Foo { - bar: Field, - baz: Field, -} - -fn main(foos: [Foo; 3]) -> pub Field { - foos[2].bar + foos[2].baz -} -``` - -Prover.toml: - -```toml -[[foos]] # foos[0] -bar = 0 -baz = 0 - -[[foos]] # foos[1] -bar = 0 -baz = 0 - -[[foos]] # foos[2] -bar = 1 -baz = 2 -``` - -#### Custom toml files - -You can specify a `toml` file with a different name to use for proving by using the `--prover-name` or `-p` flags. - -This command looks for proof inputs in the default **Prover.toml** and generates the proof and saves it at `./proofs/.proof`: - -```bash -nargo prove -``` - -This command looks for proof inputs in the custom **OtherProver.toml** and generates proof and saves it at `./proofs/.proof`: - -```bash -nargo prove -p OtherProver -``` - -## Verifying a Proof - -When the command `nargo verify` is executed, two processes happen: - -1. Noir checks in the _proofs_ directory for a proof file with the project name (eg. test_project.proof) - -2. If that file is found, the proof's validity is checked - -> **Note:** The validity of the proof is linked to the current Noir program; if the program is -> changed and the verifier verifies the proof, it will fail because the proof is not valid for the -> _modified_ Noir program. - -In production, the prover and the verifier are usually two separate entities. A prover would -retrieve the necessary inputs, execute the Noir program, generate a proof and pass it to the -verifier. The verifier would then retrieve the public inputs, usually from external sources, and -verify the validity of the proof against it. - -Take a private asset transfer as an example: - -A person using a browser as the prover would retrieve private inputs locally (e.g. the user's private key) and -public inputs (e.g. the user's encrypted balance on-chain), compute the transfer, generate a proof -and submit it to the verifier smart contract. - -The verifier contract would then draw the user's encrypted balance directly from the blockchain and -verify the proof submitted against it. If the verification passes, additional functions in the -verifier contract could trigger (e.g. approve the asset transfer). - -Now that you understand the concepts, you'll probably want some editor feedback while you are writing more complex code. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/installation/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/installation/_category_.json deleted file mode 100644 index 0c02fb5d4d7..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/installation/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "position": 0, - "label": "Install Nargo", - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/installation/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/installation/index.md deleted file mode 100644 index 4ef86aa5914..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/installation/index.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Nargo Installation -description: - nargo is a command line tool for interacting with Noir programs. This page is a quick guide on how to install Nargo through the most common and easy method, noirup -keywords: [ - Nargo - Noir - Rust - Cargo - Noirup - Installation - Terminal Commands - Version Check - Nightlies - Specific Versions - Branches - Noirup Repository -] -pagination_next: getting_started/hello_noir/index ---- - -`nargo` is the one-stop-shop for almost everything related with Noir. The name comes from our love for Rust and its package manager `cargo`. - -With `nargo`, you can start new projects, compile, execute, prove, verify, test, generate solidity contracts, and do pretty much all that is available in Noir. - -Similarly to `rustup`, we also maintain an easy installation method that covers most machines: `noirup`. - -## Installing Noirup - -Open a terminal on your machine, and write: - -```bash -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -Close the terminal, open another one, and run - -```bash -noirup -``` - -Done. That's it. You should have the latest version working. You can check with `nargo --version`. - -You can also install nightlies, specific versions -or branches. Check out the [noirup repository](https://github.com/noir-lang/noirup) for more -information. - -Now we're ready to start working on [our first Noir program!](../hello_noir/index.md) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/installation/other_install_methods.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/installation/other_install_methods.md deleted file mode 100644 index 3634723562b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/installation/other_install_methods.md +++ /dev/null @@ -1,102 +0,0 @@ ---- -title: Alternative Installations -description: There are different ways to install Nargo, the one-stop shop and command-line tool for developing Noir programs. This guide explains how to specify which version to install when using noirup, and using WSL for windows. -keywords: [ - Installation - Nargo - Noirup - Binaries - Compiling from Source - WSL for Windows - macOS - Linux - Nix - Direnv - Uninstalling Nargo - ] -sidebar_position: 1 ---- - -## Encouraged Installation Method: Noirup - -Noirup is the endorsed method for installing Nargo, streamlining the process of fetching binaries or compiling from source. It supports a range of options to cater to your specific needs, from nightly builds and specific versions to compiling from various sources. - -### Installing Noirup - -First, ensure you have `noirup` installed: - -```sh -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -### Fetching Binaries - -With `noirup`, you can easily switch between different Nargo versions, including nightly builds: - -- **Nightly Version**: Install the latest nightly build. - - ```sh - noirup --version nightly - ``` - -- **Specific Version**: Install a specific version of Nargo. - ```sh - noirup --version - ``` - -### Compiling from Source - -`noirup` also enables compiling Nargo from various sources: - -- **From a Specific Branch**: Install from the latest commit on a branch. - - ```sh - noirup --branch - ``` - -- **From a Fork**: Install from the main branch of a fork. - - ```sh - noirup --repo - ``` - -- **From a Specific Branch in a Fork**: Install from a specific branch in a fork. - - ```sh - noirup --repo --branch - ``` - -- **From a Specific Pull Request**: Install from a specific PR. - - ```sh - noirup --pr - ``` - -- **From a Specific Commit**: Install from a specific commit. - - ```sh - noirup -C - ``` - -- **From Local Source**: Compile and install from a local directory. - ```sh - noirup --path ./path/to/local/source - ``` - -## Installation on Windows - -The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed natively. However, it is available by using Windows Subsystem for Linux (WSL). - -Step 1: Follow the instructions [here](https://learn.microsoft.com/en-us/windows/wsl/install) to install and run WSL. - -step 2: Follow the [Noirup instructions](#encouraged-installation-method-noirup). - -## Uninstalling Nargo - -If you installed Nargo with `noirup`, you can uninstall Nargo by removing the files in `~/.nargo`, `~/nargo`, and `~/noir_cache`. This ensures that all installed binaries, configurations, and cache related to Nargo are fully removed from your system. - -```bash -rm -r ~/.nargo -rm -r ~/nargo -rm -r ~/noir_cache -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/tooling/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/tooling/_category_.json deleted file mode 100644 index 55804c03a71..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/tooling/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "position": 2, - "label": "Tooling", - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/tooling/index.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/tooling/index.mdx deleted file mode 100644 index ec9ccea4115..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/tooling/index.mdx +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: Tooling -Description: This section provides information about the various tools and utilities available for Noir development. It covers IDE tools, Codespaces, and community projects. -Keywords: [Noir, Development, Playground, IDE Tools, Language Service Provider, VS Code Extension, Codespaces, noir-starter, Community Projects, Awesome Noir Repository, Developer Tooling] ---- - -Noir is meant to be easy to develop with. For that reason, a number of utilities have been put together to ease the development process as much as feasible in the zero-knowledge world. - -## IDE tools - -When you install Nargo, you're also installing a Language Service Provider (LSP), which can be used by IDEs to provide syntax highlighting, codelens, warnings, and more. - -The easiest way to use these tools is by installing the [Noir VS Code extension](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). - -## Codespaces - -Some Noir repos have leveraged Codespaces in order to ease the development process. You can visit the [noir-starter](https://github.com/noir-lang/noir-starter) for an example. - - - -## GitHub Actions - -You can use `noirup` with GitHub Actions for CI/CD and automated testing. It is as simple as -installing `noirup` and running tests in your GitHub Action `yml` file. - -See the -[config file in the Noir repo](https://github.com/TomAFrench/noir-hashes/blob/master/.github/workflows/noir.yml) for an example usage. - -## Community projects - -As an open-source project, Noir has received many contributions over time. Some of them are related with developer tooling, and you can see some of them in [Awesome Noir repository](https://github.com/noir-lang/awesome-noir#dev-tools) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/tooling/language_server.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/tooling/language_server.md deleted file mode 100644 index 81e0356ef8a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/tooling/language_server.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Language Server -description: Learn about the Noir Language Server, how to install the components, and configuration that may be required. -keywords: [Nargo, Language Server, LSP, VSCode, Visual Studio Code] -sidebar_position: 0 ---- - -This section helps you install and configure the Noir Language Server. - -The Language Server Protocol (LSP) has two components, the [Server](#language-server) and the [Client](#language-client). Below we describe each in the context of Noir. - -## Language Server - -The Server component is provided by the Nargo command line tool that you installed at the beginning of this guide. -As long as Nargo is installed and you've used it to run other commands in this guide, it should be good to go! - -If you'd like to verify that the `nargo lsp` command is available, you can run `nargo --help` and look for `lsp` in the list of commands. If you see it, you're using a version of Noir with LSP support. - -## Language Client - -The Client component is usually an editor plugin that launches the Server. It communicates LSP messages between the editor and the Server. For example, when you save a file, the Client will alert the Server, so it can try to compile the project and report any errors. - -Currently, Noir provides a Language Client for Visual Studio Code via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). - -> **Note:** Noir's Language Server Protocol support currently assumes users' VSCode workspace root to be the same as users' Noir project root (i.e. where Nargo.toml lies). -> -> If LSP features seem to be missing / malfunctioning, make sure you are opening your Noir project directly (instead of as a sub-folder) in your VSCode instance. - -When your language server is running correctly and the VSCode plugin is installed, you should see handy codelens buttons for compilation, measuring circuit size, execution, and tests: - -![Compile and Execute](@site/static/img/codelens_compile_execute.png) -![Run test](@site/static/img/codelens_run_test.png) - -You should also see your tests in the `testing` panel: - -![Testing panel](@site/static/img/codelens_testing_panel.png) - -### Configuration - -- **Noir: Enable LSP** - If checked, the extension will launch the Language Server via `nargo lsp` and communicate with it. -- **Noir: Nargo Flags** - Additional flags may be specified if you require them to be added when the extension calls `nargo lsp`. -- **Noir: Nargo Path** - An absolute path to a Nargo binary with the `lsp` command. This may be useful if Nargo is not within the `PATH` of your editor. -- **Noir > Trace: Server** - Setting this to `"messages"` or `"verbose"` will log LSP messages between the Client and Server. Useful for debugging. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/tooling/noir_codegen.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/tooling/noir_codegen.md deleted file mode 100644 index d65151da0ab..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/tooling/noir_codegen.md +++ /dev/null @@ -1,113 +0,0 @@ ---- -title: Noir Codegen for TypeScript -description: Learn how to use Noir codegen to generate TypeScript bindings -keywords: [Nargo, Noir, compile, TypeScript] -sidebar_position: 2 ---- - -When using TypeScript, it is extra work to interpret Noir program outputs in a type-safe way. Third party libraries may exist for popular Noir programs, but they are either hard to find or unmaintained. - -Now you can generate TypeScript bindings for your Noir programs in two steps: -1. Exporting Noir functions using `nargo export` -2. Using the TypeScript module `noir_codegen` to generate TypeScript binding - -**Note:** you can only export functions from a Noir *library* (not binary or contract program types). - -## Installation - -### Your TypeScript project - -If you don't already have a TypeScript project you can add the module with `yarn` (or `npm`), then initialize it: - -```bash -yarn add typescript -D -npx tsc --init -``` - -### Add TypeScript module - `noir_codegen` - -The following command will add the module to your project's devDependencies: - -```bash -yarn add @noir-lang/noir_codegen -D -``` - -### Nargo library -Make sure you have Nargo, v0.25.0 or greater, installed. If you don't, follow the [installation guide](../installation/index.md). - -If you're in a new project, make a `circuits` folder and create a new Noir library: - -```bash -mkdir circuits && cd circuits -nargo new --lib myNoirLib -``` - -## Usage - -### Export ABI of specified functions - -First go to the `.nr` files in your Noir library, and add the `#[export]` macro to each function that you want to use in TypeScript. - -```rust -#[export] -fn your_function(... -``` - -From your Noir library (where `Nargo.toml` is), run the following command: - -```bash -nargo export -``` - -You will now have an `export` directory with a .json file per exported function. - -You can also specify the directory of Noir programs using `--program-dir`, for example: - -```bash -nargo export --program-dir=./circuits/myNoirLib -``` - -### Generate TypeScript bindings from exported functions - -To use the `noir-codegen` package we added to the TypeScript project: - -```bash -yarn noir-codegen ./export/your_function.json -``` - -This creates an `exports` directory with an `index.ts` file containing all exported functions. - -**Note:** adding `--out-dir` allows you to specify an output dir for your TypeScript bindings to go. Eg: - -```bash -yarn noir-codegen ./export/*.json --out-dir ./path/to/output/dir -``` - -## Example .nr function to .ts output - -Consider a Noir library with this function: - -```rust -#[export] -fn not_equal(x: Field, y: Field) -> bool { - x != y -} -``` - -After the export and codegen steps, you should have an `index.ts` like: - -```typescript -export type Field = string; - - -export const is_equal_circuit: CompiledCircuit = {"abi":{"parameters":[{"name":"x","type":{"kind":"field"},"visibility":"private"},{"name":"y","type":{"kind":"field"},"visibility":"private"}],"param_witnesses":{"x":[{"start":0,"end":1}],"y":[{"start":1,"end":2}]},"return_type":{"abi_type":{"kind":"boolean"},"visibility":"private"},"return_witnesses":[4]},"bytecode":"H4sIAAAAAAAA/7WUMQ7DIAxFQ0Krrr2JjSGYLVcpKrn/CaqqDQN12WK+hPBgmWd/wEyHbF1SS923uhOs3pfoChI+wKXMAXzIKyNj4PB0TFTYc0w5RUjoqeAeEu1wqK0F54RGkWvW44LPzExnlkbMEs4JNZmN8PxS42uHv82T8a3Jeyn2Ks+VLPcO558HmyLMCDOXAXXtpPt4R/Rt9T36ss6dS9HGPx/eG17nGegKBQAA"}; - -export async function is_equal(x: Field, y: Field, foreignCallHandler?: ForeignCallHandler): Promise { - const program = new Noir(is_equal_circuit); - const args: InputMap = { x, y }; - const { returnValue } = await program.execute(args, foreignCallHandler); - return returnValue as boolean; -} -``` - -Now the `is_equal()` function and relevant types are readily available for use in TypeScript. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/tooling/testing.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/tooling/testing.md deleted file mode 100644 index d3e0c522473..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/tooling/testing.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -title: Testing in Noir -description: Learn how to use Nargo to test your Noir program in a quick and easy way -keywords: [Nargo, testing, Noir, compile, test] -sidebar_position: 1 ---- - -You can test your Noir programs using Noir circuits. - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. - -For example if you have a program like: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test] -fn test_add() { - assert(add(2,2) == 4); - assert(add(0,1) == 1); - assert(add(1,0) == 1); -} -``` - -Running `nargo test` will test that the `test_add` function can be executed while satisfying all -the constraints which allows you to test that add returns the expected values. Test functions can't -have any arguments currently. - -### Test fail - -You can write tests that are expected to fail by using the decorator `#[test(should_fail)]`. For example: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test(should_fail)] -fn test_add() { - assert(add(2,2) == 5); -} -``` - -You can be more specific and make it fail with a specific reason by using `should_fail_with = "`: - -```rust -fn main(african_swallow_avg_speed : Field) { - assert(african_swallow_avg_speed == 65, "What is the airspeed velocity of an unladen swallow"); -} - -#[test] -fn test_king_arthur() { - main(65); -} - -#[test(should_fail_with = "What is the airspeed velocity of an unladen swallow")] -fn test_bridgekeeper() { - main(32); -} - -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/how_to/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/how_to/_category_.json deleted file mode 100644 index 23b560f610b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/how_to/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 1, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/how_to/how-to-oracles.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/how_to/how-to-oracles.md deleted file mode 100644 index 8cf8035a5c4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/how_to/how-to-oracles.md +++ /dev/null @@ -1,276 +0,0 @@ ---- -title: How to use Oracles -description: Learn how to use oracles in your Noir program with examples in both Nargo and NoirJS. This guide also covers writing a JSON RPC server and providing custom foreign call handlers for NoirJS. -keywords: - - Noir Programming - - Oracles - - Nargo - - NoirJS - - JSON RPC Server - - Foreign Call Handlers -sidebar_position: 1 ---- - -This guide shows you how to use oracles in your Noir program. For the sake of clarity, it assumes that: - -- You have read the [explainer on Oracles](../explainers/explainer-oracle.md) and are comfortable with the concept. -- You have a Noir program to add oracles to. You can create one using the [vite-hardhat starter](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat) as a boilerplate. -- You understand the concept of a JSON-RPC server. Visit the [JSON-RPC website](https://www.jsonrpc.org/) if you need a refresher. -- You are comfortable with server-side JavaScript (e.g. Node.js, managing packages, etc.). - -For reference, you can find the snippets used in this tutorial on the [Aztec DevRel Repository](https://github.com/AztecProtocol/dev-rel/tree/main/code-snippets/how-to-oracles). - -## Rundown - -This guide has 3 major steps: - -1. How to modify our Noir program to make use of oracle calls as unconstrained functions -2. How to write a JSON RPC Server to resolve these oracle calls with Nargo -3. How to use them in Nargo and how to provide a custom resolver in NoirJS - -## Step 1 - Modify your Noir program - -An oracle is defined in a Noir program by defining two methods: - -- An unconstrained method - This tells the compiler that it is executing an [unconstrained functions](../noir/concepts//unconstrained.md). -- A decorated oracle method - This tells the compiler that this method is an RPC call. - -An example of an oracle that returns a `Field` would be: - -```rust -#[oracle(getSqrt)] -unconstrained fn sqrt(number: Field) -> Field { } - -unconstrained fn get_sqrt(number: Field) -> Field { - sqrt(number) -} -``` - -In this example, we're wrapping our oracle function in a unconstrained method, and decorating it with `oracle(getSqrt)`. We can then call the unconstrained function as we would call any other function: - -```rust -fn main(input: Field) { - let sqrt = get_sqrt(input); -} -``` - -In the next section, we will make this `getSqrt` (defined on the `sqrt` decorator) be a method of the RPC server Noir will use. - -:::danger - -As explained in the [Oracle Explainer](../explainers/explainer-oracle.md), this `main` function is unsafe unless you constrain its return value. For example: - -```rust -fn main(input: Field) { - let sqrt = get_sqrt(input); - assert(sqrt.pow_32(2) as u64 == input as u64); // <---- constrain the return of an oracle! -} -``` - -::: - -:::info - -Currently, oracles only work with single params or array params. For example: - -```rust -#[oracle(getSqrt)] -unconstrained fn sqrt([Field; 2]) -> [Field; 2] { } -``` - -::: - -## Step 2 - Write an RPC server - -Brillig will call *one* RPC server. Most likely you will have to write your own, and you can do it in whatever language you prefer. In this guide, we will do it in Javascript. - -Let's use the above example of an oracle that consumes an array with two `Field` and returns their square roots: - -```rust -#[oracle(getSqrt)] -unconstrained fn sqrt(input: [Field; 2]) -> [Field; 2] { } - -unconstrained fn get_sqrt(input: [Field; 2]) -> [Field; 2] { - sqrt(input) -} - -fn main(input: [Field; 2]) { - let sqrt = get_sqrt(input); - assert(sqrt[0].pow_32(2) as u64 == input[0] as u64); - assert(sqrt[1].pow_32(2) as u64 == input[1] as u64); -} -``` - -:::info - -Why square root? - -In general, computing square roots is computationally more expensive than multiplications, which takes a toll when speaking about ZK applications. In this case, instead of calculating the square root in Noir, we are using our oracle to offload that computation to be made in plain. In our circuit we can simply multiply the two values. - -::: - -Now, we should write the correspondent RPC server, starting with the [default JSON-RPC 2.0 boilerplate](https://www.npmjs.com/package/json-rpc-2.0#example): - -```js -import { JSONRPCServer } from "json-rpc-2.0"; -import express from "express"; -import bodyParser from "body-parser"; - -const app = express(); -app.use(bodyParser.json()); - -const server = new JSONRPCServer(); -app.post("/", (req, res) => { - const jsonRPCRequest = req.body; - server.receive(jsonRPCRequest).then((jsonRPCResponse) => { - if (jsonRPCResponse) { - res.json(jsonRPCResponse); - } else { - res.sendStatus(204); - } - }); -}); - -app.listen(5555); -``` - -Now, we will add our `getSqrt` method, as expected by the `#[oracle(getSqrt)]` decorator in our Noir code. It maps through the params array and returns their square roots: - -```js -server.addMethod("getSqrt", async (params) => { - const values = params[0].Array.map((field) => { - return `${Math.sqrt(parseInt(field, 16))}`; - }); - return { values: [{ Array: values }] }; -}); -``` - -:::tip - -Brillig expects an object with an array of values. Each value is an object declaring to be `Single` or `Array` and returning a field element *as a string*. For example: - -```json -{ "values": [{ "Array": ["1", "2"] }]} -{ "values": [{ "Single": "1" }]} -{ "values": [{ "Single": "1" }, { "Array": ["1", "2"] }]} -``` - -If you're using Typescript, the following types may be helpful in understanding the expected return value and making sure they're easy to follow: - -```js -interface SingleForeignCallParam { - Single: string, -} - -interface ArrayForeignCallParam { - Array: string[], -} - -type ForeignCallParam = SingleForeignCallParam | ArrayForeignCallParam; - -interface ForeignCallResult { - values: ForeignCallParam[], -} -``` - -::: - -## Step 3 - Usage with Nargo - -Using the [`nargo` CLI tool](../getting_started/installation/index.md), you can use oracles in the `nargo test`, `nargo execute` and `nargo prove` commands by passing a value to `--oracle-resolver`. For example: - -```bash -nargo test --oracle-resolver http://localhost:5555 -``` - -This tells `nargo` to use your RPC Server URL whenever it finds an oracle decorator. - -## Step 4 - Usage with NoirJS - -In a JS environment, an RPC server is not strictly necessary, as you may want to resolve your oracles without needing any JSON call at all. NoirJS simply expects that you pass a callback function when you generate proofs, and that callback function can be anything. - -For example, if your Noir program expects the host machine to provide CPU pseudo-randomness, you could simply pass it as the `foreignCallHandler`. You don't strictly need to create an RPC server to serve pseudo-randomness, as you may as well get it directly in your app: - -```js -const foreignCallHandler = (name, inputs) => crypto.randomBytes(16) // etc - -await noir.generateProof(inputs, foreignCallHandler) -``` - -As one can see, in NoirJS, the [`foreignCallHandler`](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) function simply means "a callback function that returns a value of type [`ForeignCallOutput`](../reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md). It doesn't have to be an RPC call like in the case for Nargo. - -:::tip - -Does this mean you don't have to write an RPC server like in [Step #2](#step-2---write-an-rpc-server)? - -You don't technically have to, but then how would you run `nargo test` or `nargo prove`? To use both `Nargo` and `NoirJS` in your development flow, you will have to write a JSON RPC server. - -::: - -In this case, let's make `foreignCallHandler` call the JSON RPC Server we created in [Step #2](#step-2---write-an-rpc-server), by making it a JSON RPC Client. - -For example, using the same `getSqrt` program in [Step #1](#step-1---modify-your-noir-program) (comments in the code): - -```js -import { JSONRPCClient } from "json-rpc-2.0"; - -// declaring the JSONRPCClient -const client = new JSONRPCClient((jsonRPCRequest) => { -// hitting the same JSON RPC Server we coded above - return fetch("http://localhost:5555", { - method: "POST", - headers: { - "content-type": "application/json", - }, - body: JSON.stringify(jsonRPCRequest), - }).then((response) => { - if (response.status === 200) { - return response - .json() - .then((jsonRPCResponse) => client.receive(jsonRPCResponse)); - } else if (jsonRPCRequest.id !== undefined) { - return Promise.reject(new Error(response.statusText)); - } - }); -}); - -// declaring a function that takes the name of the foreign call (getSqrt) and the inputs -const foreignCallHandler = async (name, input) => { - // notice that the "inputs" parameter contains *all* the inputs - // in this case we to make the RPC request with the first parameter "numbers", which would be input[0] - const oracleReturn = await client.request(name, [ - { Array: input[0].map((i) => i.toString("hex")) }, - ]); - return [oracleReturn.values[0].Array]; -}; - -// the rest of your NoirJS code -const input = { input: [4, 16] }; -const { witness } = await noir.execute(numbers, foreignCallHandler); -``` - -:::tip - -If you're in a NoirJS environment running your RPC server together with a frontend app, you'll probably hit a familiar problem in full-stack development: requests being blocked by [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) policy. For development only, you can simply install and use the [`cors` npm package](https://www.npmjs.com/package/cors) to get around the problem: - -```bash -yarn add cors -``` - -and use it as a middleware: - -```js -import cors from "cors"; - -const app = express(); -app.use(cors()) -``` - -::: - -## Conclusion - -Hopefully by the end of this guide, you should be able to: - -- Write your own logic around Oracles and how to write a JSON RPC server to make them work with your Nargo commands. -- Provide custom foreign call handlers for NoirJS. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/how_to/how-to-recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/how_to/how-to-recursion.md deleted file mode 100644 index 4c45bb87ae2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/how_to/how-to-recursion.md +++ /dev/null @@ -1,179 +0,0 @@ ---- -title: How to use recursion on NoirJS -description: Learn how to implement recursion with NoirJS, a powerful tool for creating smart contracts on the EVM blockchain. This guide assumes familiarity with NoirJS, solidity verifiers, and the Barretenberg proving backend. Discover how to generate both final and intermediate proofs using `noir_js` and `backend_barretenberg`. -keywords: - [ - "NoirJS", - "EVM blockchain", - "smart contracts", - "recursion", - "solidity verifiers", - "Barretenberg backend", - "noir_js", - "backend_barretenberg", - "intermediate proofs", - "final proofs", - "nargo compile", - "json import", - "recursive circuit", - "recursive app" - ] -sidebar_position: 1 ---- - -This guide shows you how to use recursive proofs in your NoirJS app. For the sake of clarity, it is assumed that: - -- You already have a NoirJS app. If you don't, please visit the [NoirJS tutorial](../tutorials/noirjs_app.md) and the [reference](../reference/NoirJS/noir_js/index.md). -- You are familiar with what are recursive proofs and you have read the [recursion explainer](../explainers/explainer-recursion.md) -- You already built a recursive circuit following [the reference](../noir/standard_library/recursion.md), and understand how it works. - -It is also assumed that you're not using `noir_wasm` for compilation, and instead you've used [`nargo compile`](../reference/nargo_commands.md) to generate the `json` you're now importing into your project. However, the guide should work just the same if you're using `noir_wasm`. - -:::info - -As you've read in the [explainer](../explainers/explainer-recursion.md), a recursive proof is an intermediate proof. This means that it doesn't necessarily generate the final step that makes it verifiable in a smart contract. However, it is easy to verify within another circuit. - -While "standard" usage of NoirJS packages abstracts final proofs, it currently lacks the necessary interface to abstract away intermediate proofs. This means that these proofs need to be created by using the backend directly. - -In short: - -- `noir_js` generates *only* final proofs -- `backend_barretenberg` generates both types of proofs - -::: - -In a standard recursive app, you're also dealing with at least two circuits. For the purpose of this guide, we will assume the following: - -- `main`: a circuit of type `assert(x != y)`, where `main` is marked with a `#[recursive]` attribute. This attribute states that the backend should generate proofs that are friendly for verification within another circuit. -- `recursive`: a circuit that verifies `main` - -For a full example on how recursive proofs work, please refer to the [noir-examples](https://github.com/noir-lang/noir-examples) repository. We will *not* be using it as a reference for this guide. - -## Step 1: Setup - -In a common NoirJS app, you need to instantiate a backend with something like `const backend = new Backend(circuit)`. Then you feed it to the `noir_js` interface. - -For recursion, this doesn't happen, and the only need for `noir_js` is only to `execute` a circuit and get its witness and return value. Everything else is not interfaced, so it needs to happen on the `backend` object. - -It is also recommended that you instantiate the backend with as many threads as possible, to allow for maximum concurrency: - -```js -const backend = new Backend(circuit, { threads: 8 }) -``` - -:::tip -You can use the [`os.cpus()`](https://nodejs.org/api/os.html#oscpus) object in `nodejs` or [`navigator.hardwareConcurrency`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/hardwareConcurrency) on the browser to make the most out of those glorious cpu cores -::: - -## Step 2: Generating the witness and the proof for `main` - -After instantiating the backend, you should also instantiate `noir_js`. We will use it to execute the circuit and get the witness. - -```js -const noir = new Noir(circuit, backend) -const { witness } = noir.execute(input) -``` - -With this witness, you are now able to generate the intermediate proof for the main circuit: - -```js -const { proof, publicInputs } = await backend.generateProof(witness) -``` - -:::warning - -Always keep in mind what is actually happening on your development process, otherwise you'll quickly become confused about what circuit we are actually running and why! - -In this case, you can imagine that Alice (running the `main` circuit) is proving something to Bob (running the `recursive` circuit), and Bob is verifying her proof within his proof. - -With this in mind, it becomes clear that our intermediate proof is the one *meant to be verified within another circuit*, so it must be Alice's. Actually, the only final proof in this theoretical scenario would be the last one, sent on-chain. - -::: - -## Step 3 - Verification and proof artifacts - -Optionally, you are able to verify the intermediate proof: - -```js -const verified = await backend.verifyProof({ proof, publicInputs }) -``` - -This can be useful to make sure our intermediate proof was correctly generated. But the real goal is to do it within another circuit. For that, we need to generate recursive proof artifacts that will be passed to the circuit that is verifying the proof we just generated. Instead of passing the proof and verification key as a byte array, we pass them as fields which makes it cheaper to verify in a circuit: - -```js -const { proofAsFields, vkAsFields, vkHash } = await backend.generateRecursiveProofArtifacts( { publicInputs, proof }, publicInputsCount) -``` - -This call takes the public inputs and the proof, but also the public inputs count. While this is easily retrievable by simply counting the `publicInputs` length, the backend interface doesn't currently abstract it away. - -:::info - -The `proofAsFields` has a constant size `[Field; 93]` and verification keys in Barretenberg are always `[Field; 114]`. - -::: - -:::warning - -One common mistake is to forget *who* makes this call. - -In a situation where Alice is generating the `main` proof, if she generates the proof artifacts and sends them to Bob, which gladly takes them as true, this would mean Alice could prove anything! - -Instead, Bob needs to make sure *he* extracts the proof artifacts, using his own instance of the `main` circuit backend. This way, Alice has to provide a valid proof for the correct `main` circuit. - -::: - -## Step 4 - Recursive proof generation - -With the artifacts, generating a recursive proof is no different from a normal proof. You simply use the `backend` (with the recursive circuit) to generate it: - -```js -const recursiveInputs = { - verification_key: vkAsFields, // array of length 114 - proof: proofAsFields, // array of length 93 + size of public inputs - publicInputs: [mainInput.y], // using the example above, where `y` is the only public input - key_hash: vkHash, -} - -const { witness, returnValue } = noir.execute(recursiveInputs) // we're executing the recursive circuit now! -const { proof, publicInputs } = backend.generateProof(witness) -const verified = backend.verifyProof({ proof, publicInputs }) -``` - -You can obviously chain this proof into another proof. In fact, if you're using recursive proofs, you're probably interested of using them this way! - -:::tip - -Managing circuits and "who does what" can be confusing. To make sure your naming is consistent, you can keep them in an object. For example: - -```js -const circuits = { - main: mainJSON, - recursive: recursiveJSON -} -const backends = { - main: new BarretenbergBackend(circuits.main), - recursive: new BarretenbergBackend(circuits.recursive) -} -const noir_programs = { - main: new Noir(circuits.main, backends.main), - recursive: new Noir(circuits.recursive, backends.recursive) -} -``` - -This allows you to neatly call exactly the method you want without conflicting names: - -```js -// Alice runs this 👇 -const { witness: mainWitness } = await noir_programs.main.execute(input) -const proof = await backends.main.generateProof(mainWitness) - -// Bob runs this 👇 -const verified = await backends.main.verifyProof(proof) -const { proofAsFields, vkAsFields, vkHash } = await backends.main.generateRecursiveProofArtifacts( - proof, - numPublicInputs, -); -const recursiveProof = await noir_programs.recursive.generateProof(recursiveInputs) -``` - -::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/how_to/how-to-solidity-verifier.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/how_to/how-to-solidity-verifier.md deleted file mode 100644 index e3c7c1065da..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/how_to/how-to-solidity-verifier.md +++ /dev/null @@ -1,231 +0,0 @@ ---- -title: Generate a Solidity Verifier -description: - Learn how to run the verifier as a smart contract on the blockchain. Compile a Solidity verifier - contract for your Noir program and deploy it on any EVM blockchain acting as a verifier smart - contract. Read more to find out -keywords: - [ - solidity verifier, - smart contract, - blockchain, - compiler, - plonk_vk.sol, - EVM blockchain, - verifying Noir programs, - proving backend, - Barretenberg, - ] -sidebar_position: 0 -pagination_next: tutorials/noirjs_app ---- - -Noir has the ability to generate a verifier contract in Solidity, which can be deployed in many EVM-compatible blockchains such as Ethereum. - -This allows for a powerful feature set, as one can make use of the conciseness and the privacy provided by Noir in an immutable ledger. Applications can range from simple P2P guessing games, to complex private DeFi interactions. - -This guide shows you how to generate a Solidity Verifier and deploy it on the [Remix IDE](https://remix.ethereum.org/). It is assumed that: - -- You are comfortable with the Solidity programming language and understand how contracts are deployed on the Ethereum network -- You have Noir installed and you have a Noir program. If you don't, [get started](../getting_started/installation/index.md) with Nargo and the example Hello Noir circuit -- You are comfortable navigating RemixIDE. If you aren't or you need a refresher, you can find some video tutorials [here](https://www.youtube.com/channel/UCjTUPyFEr2xDGN6Cg8nKDaA) that could help you. - -## Rundown - -Generating a Solidity Verifier contract is actually a one-command process. However, compiling it and deploying it can have some caveats. Here's the rundown of this guide: - -1. How to generate a solidity smart contract -2. How to compile the smart contract in the RemixIDE -3. How to deploy it to a testnet - -## Step 1 - Generate a contract - -This is by far the most straight-forward step. Just run: - -```sh -nargo codegen-verifier -``` - -A new `contract` folder would then be generated in your project directory, containing the Solidity -file `plonk_vk.sol`. It can be deployed to any EVM blockchain acting as a verifier smart contract. - -:::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. - -Barretenberg, the default proving backend for Nargo, supports generation of verifier contracts, for the time being these are only in Solidity. -::: - -## Step 2 - Compiling - -We will mostly skip the details of RemixIDE, as the UI can change from version to version. For now, we can just open -Remix and create a blank workspace. - -![Create Workspace](@site/static/img/how-tos/solidity_verifier_1.png) - -We will create a new file to contain the contract Nargo generated, and copy-paste its content. - -:::warning - -You'll likely see a warning advising you to not trust pasted code. While it is an important warning, it is irrelevant in the context of this guide and can be ignored. We will not be deploying anywhere near a mainnet. - -::: - -To compile our the verifier, we can navigate to the compilation tab: - -![Compilation Tab](@site/static/img/how-tos/solidity_verifier_2.png) - -Remix should automatically match a suitable compiler version. However, hitting the "Compile" button will most likely generate a "Stack too deep" error: - -![Stack too deep](@site/static/img/how-tos/solidity_verifier_3.png) - -This is due to the verify function needing to put many variables on the stack, but enabling the optimizer resolves the issue. To do this, let's open the "Advanced Configurations" tab and enable optimization. The default 200 runs will suffice. - -:::info - -This time we will see a warning about an unused function parameter. This is expected, as the `verify` function doesn't use the `_proof` parameter inside a solidity block, it is loaded from calldata and used in assembly. - -::: - -![Compilation success](@site/static/img/how-tos/solidity_verifier_4.png) - -## Step 3 - Deploying - -At this point we should have a compiled contract read to deploy. If we navigate to the deploy section in Remix, we will see many different environments we can deploy to. The steps to deploy on each environment would be out-of-scope for this guide, so we will just use the default Remix VM. - -Looking closely, we will notice that our "Solidity Verifier" is actually three contracts working together: - -- An `UltraVerificationKey` library which simply stores the verification key for our circuit. -- An abstract contract `BaseUltraVerifier` containing most of the verifying logic. -- A main `UltraVerifier` contract that inherits from the Base and uses the Key contract. - -Remix will take care of the dependencies for us so we can simply deploy the UltraVerifier contract by selecting it and hitting "deploy": - -![Deploying UltraVerifier](@site/static/img/how-tos/solidity_verifier_5.png) - -A contract will show up in the "Deployed Contracts" section, where we can retrieve the Verification Key Hash. This is particularly useful for double-checking the deployer contract is the correct one. - -:::note - -Why "UltraVerifier"? - -To be precise, the Noir compiler (`nargo`) doesn't generate the verifier contract directly. It compiles the Noir code into an intermediate language (ACIR), which is then executed by the backend. So it is the backend that returns the verifier smart contract, not Noir. - -In this case, the Barretenberg Backend uses the UltraPlonk proving system, hence the "UltraVerifier" name. - -::: - -## Step 4 - Verifying - -To verify a proof using the Solidity verifier contract, we call the `verify` function in this extended contract: - -```solidity -function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) -``` - -When using the default example in the [Hello Noir](../getting_started/hello_noir/index.md) guide, the easiest way to confirm that the verifier contract is doing its job is by calling the `verify` function via remix with the required parameters. For `_proof`, run `nargo prove` and use the string in `proof/.proof` (adding the hex `0x` prefix). We can also copy the public input from `Verifier.toml`, as it will be properly formatted as 32-byte strings: - -``` -0x...... , [0x0000.....02] -``` - -A programmatic example of how the `verify` function is called can be seen in the example zk voting application [here](https://github.com/noir-lang/noir-examples/blob/33e598c257e2402ea3a6b68dd4c5ad492bce1b0a/foundry-voting/src/zkVote.sol#L35): - -```solidity -function castVote(bytes calldata proof, uint proposalId, uint vote, bytes32 nullifierHash) public returns (bool) { - // ... - bytes32[] memory publicInputs = new bytes32[](4); - publicInputs[0] = merkleRoot; - publicInputs[1] = bytes32(proposalId); - publicInputs[2] = bytes32(vote); - publicInputs[3] = nullifierHash; - require(verifier.verify(proof, publicInputs), "Invalid proof"); -``` - -:::info[Return Values] - -A circuit doesn't have the concept of a return value. Return values are just syntactic sugar in -Noir. - -Under the hood, the return value is passed as an input to the circuit and is checked at the end of -the circuit program. - -For example, if you have Noir program like this: - -```rust -fn main( - // Public inputs - pubkey_x: pub Field, - pubkey_y: pub Field, - // Private inputs - priv_key: Field, -) -> pub Field -``` - -the `verify` function will expect the public inputs array (second function parameter) to be of length 3, the two inputs and the return value. Like before, these values are populated in Verifier.toml after running `nargo prove`. - -Passing only two inputs will result in an error such as `PUBLIC_INPUT_COUNT_INVALID(3, 2)`. - -In this case, the inputs parameter to `verify` would be an array ordered as `[pubkey_x, pubkey_y, return]`. - -::: - -:::tip[Structs] - -You can pass structs to the verifier contract. They will be flattened so that the array of inputs is 1-dimensional array. - -For example, consider the following program: - -```rust -struct Type1 { - val1: Field, - val2: Field, -} - -struct Nested { - t1: Type1, - is_true: bool, -} - -fn main(x: pub Field, nested: pub Nested, y: pub Field) { - //... -} -``` - -The order of these inputs would be flattened to: `[x, nested.t1.val1, nested.t1.val2, nested.is_true, y]` - -::: - -The other function you can call is our entrypoint `verify` function, as defined above. - -:::tip - -It's worth noticing that the `verify` function is actually a `view` function. A `view` function does not alter the blockchain state, so it doesn't need to be distributed (i.e. it will run only on the executing node), and therefore doesn't cost any gas. - -This can be particularly useful in some situations. If Alice generated a proof and wants Bob to verify its correctness, Bob doesn't need to run Nargo, NoirJS, or any Noir specific infrastructure. He can simply make a call to the blockchain with the proof and verify it is correct without paying any gas. - -It would be incorrect to say that a Noir proof verification costs any gas at all. However, most of the time the result of `verify` is used to modify state (for example, to update a balance, a game state, etc). In that case the whole network needs to execute it, which does incur gas costs (calldata and execution, but not storage). - -::: - -## A Note on EVM chains - -ZK-SNARK verification depends on some precompiled cryptographic primitives such as Elliptic Curve Pairings (if you like complex math, you can read about EC Pairings [here](https://medium.com/@VitalikButerin/exploring-elliptic-curve-pairings-c73c1864e627)). Not all EVM chains support EC Pairings, notably some of the ZK-EVMs. This means that you won't be able to use the verifier contract in all of them. - -For example, chains like `zkSync ERA` and `Polygon zkEVM` do not currently support these precompiles, so proof verification via Solidity verifier contracts won't work. Here's a quick list of EVM chains that have been tested and are known to work: - -- Optimism -- Arbitrum -- Polygon PoS -- Scroll -- Celo - -If you test any other chains, please open a PR on this page to update the list. See [this doc](https://github.com/noir-lang/noir-starter/tree/main/with-foundry#testing-on-chain) for more info about testing verifier contracts on different EVM chains. - -## What's next - -Now that you know how to call a Noir Solidity Verifier on a smart contract using Remix, you should be comfortable with using it with some programmatic frameworks, such as [hardhat](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat) and [foundry](https://github.com/noir-lang/noir-starter/tree/main/with-foundry). - -You can find other tools, examples, boilerplates and libraries in the [awesome-noir](https://github.com/noir-lang/awesome-noir) repository. - -You should also be ready to write and deploy your first NoirJS app and start generating proofs on websites, phones, and NodeJS environments! Head on to the [NoirJS tutorial](../tutorials/noirjs_app.md) to learn how to do that. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/how_to/merkle-proof.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/how_to/merkle-proof.mdx deleted file mode 100644 index 003c7019a93..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/how_to/merkle-proof.mdx +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Prove Merkle Tree Membership -description: - Learn how to use merkle membership proof in Noir to prove that a given leaf is a member of a - merkle tree with a specified root, at a given index. -keywords: - [merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree] ---- - -Let's walk through an example of a merkle membership proof in Noir that proves that a given leaf is -in a merkle tree. - -```rust -use dep::std; - -fn main(message : [Field; 62], index : Field, hashpath : [Field; 40], root : Field) { - let leaf = std::hash::hash_to_field(message.as_slice()); - let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); - assert(merkle_root == root); -} - -``` - -The message is hashed using `hash_to_field`. The specific hash function that is being used is chosen -by the backend. The only requirement is that this hash function can heuristically be used as a -random oracle. If only collision resistance is needed, then one can call `std::hash::pedersen_hash` -instead. - -```rust -let leaf = std::hash::hash_to_field(message.as_slice()); -``` - -The leaf is then passed to a compute_merkle_root function with the root, index and hashpath. The returned root can then be asserted to be the same as the provided root. - -```rust -let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); -assert (merkle_root == root); -``` - -> **Note:** It is possible to re-implement the merkle tree implementation without standard library. -> However, for most usecases, it is enough. In general, the standard library will always opt to be -> as conservative as possible, while striking a balance with efficiency. - -An example, the merkle membership proof, only requires a hash function that has collision -resistance, hence a hash function like Pedersen is allowed, which in most cases is more efficient -than the even more conservative sha256. - -[View an example on the starter repo](https://github.com/noir-lang/noir-examples/blob/3ea09545cabfa464124ec2f3ea8e60c608abe6df/stealthdrop/circuits/src/main.nr#L20) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/how_to/using-devcontainers.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/how_to/using-devcontainers.mdx deleted file mode 100644 index 727ec6ca667..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/how_to/using-devcontainers.mdx +++ /dev/null @@ -1,110 +0,0 @@ ---- -title: Developer Containers and Codespaces -description: "Learn how to set up a devcontainer in your GitHub repository for a seamless coding experience with Codespaces. Follow our easy 8-step guide to create your own Noir environment without installing Nargo locally." -keywords: ["Devcontainer", "Codespaces", "GitHub", "Noir Environment", "Docker Image", "Development Environment", "Remote Coding", "GitHub Codespaces", "Noir Programming", "Nargo", "VSCode Extensions", "Noirup"] -sidebar_position: 1 ---- - -Adding a developer container configuration file to your Noir project is one of the easiest way to unlock coding in browser. - -## What's a devcontainer after all? - -A [Developer Container](https://containers.dev/) (devcontainer for short) is a Docker image that comes preloaded with tools, extensions, and other tools you need to quickly get started or continue a project, without having to install Nargo locally. Think of it as a development environment in a box. - -There are many advantages to this: - -- It's platform and architecture agnostic -- You don't need to have an IDE installed, or Nargo, or use a terminal at all -- It's safer for using on a public machine or public network - -One of the best ways of using devcontainers is... not using your machine at all, for maximum control, performance, and ease of use. -Enter Codespaces. - -## Codespaces - -If a devcontainer is just a Docker image, then what stops you from provisioning a `p3dn.24xlarge` AWS EC2 instance with 92 vCPUs and 768 GiB RAM and using it to prove your 10-gate SNARK proof? - -Nothing! Except perhaps the 30-40$ per hour it will cost you. - -The problem is that provisioning takes time, and I bet you don't want to see the AWS console every time you want to code something real quick. - -Fortunately, there's an easy and free way to get a decent remote machine ready and loaded in less than 2 minutes: Codespaces. [Codespaces is a Github feature](https://github.com/features/codespaces) that allows you to code in a remote machine by using devcontainers, and it's pretty cool: - -- You can start coding Noir in less than a minute -- It uses the resources of a remote machine, so you can code on your grandma's phone if needed be -- It makes it easy to share work with your frens -- It's fully reusable, you can stop and restart whenever you need to - -:::info - -Don't take out your wallet just yet. Free GitHub accounts get about [15-60 hours of coding](https://github.com/features/codespaces) for free per month, depending on the size of your provisioned machine. - -::: - -## Tell me it's _actually_ easy - -It is! - -Github comes with a default codespace and you can use it to code your own devcontainer. That's exactly what we will be doing in this guide. - - - -8 simple steps: - -#### 1. Create a new repository on GitHub. - -#### 2. Click "Start coding with Codespaces". This will use the default image. - -#### 3. Create a folder called `.devcontainer` in the root of your repository. - -#### 4. Create a Dockerfile in that folder, and paste the following code: - -```docker -FROM --platform=linux/amd64 node:lts-bookworm-slim -SHELL ["/bin/bash", "-c"] -RUN apt update && apt install -y curl bash git tar gzip libc++-dev -RUN curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -ENV PATH="/root/.nargo/bin:$PATH" -RUN noirup -ENTRYPOINT ["nargo"] -``` -#### 5. Create a file called `devcontainer.json` in the same folder, and paste the following code: - -```json -{ - "name": "Noir on Codespaces", - "build": { - "context": ".", - "dockerfile": "Dockerfile" - }, - "customizations": { - "vscode": { - "extensions": ["noir-lang.vscode-noir"] - } - } -} -``` -#### 6. Commit and push your changes - -This will pull the new image and build it, so it could take a minute or so - -#### 8. Done! -Just wait for the build to finish, and there's your easy Noir environment. - - -Refer to [noir-starter](https://github.com/noir-lang/noir-starter/) as an example of how devcontainers can be used together with codespaces. - - - -## How do I use it? - -Using the codespace is obviously much easier than setting it up. -Just navigate to your repository and click "Code" -> "Open with Codespaces". It should take a few seconds to load, and you're ready to go. - -:::info - -If you really like the experience, you can add a badge to your readme, links to existing codespaces, and more. -Check out the [official docs](https://docs.github.com/en/codespaces/setting-up-your-project-for-codespaces/setting-up-your-repository/facilitating-quick-creation-and-resumption-of-codespaces) for more info. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/index.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/index.mdx deleted file mode 100644 index 75086ddcdde..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/index.mdx +++ /dev/null @@ -1,67 +0,0 @@ ---- -title: Noir Lang -hide_title: true -description: - Learn about the public alpha release of Noir, a domain specific language heavily influenced by Rust that compiles to - an intermediate language which can be compiled to an arithmetic circuit or a rank-1 constraint system. -keywords: - [Noir, - Domain Specific Language, - Rust, - Intermediate Language, - Arithmetic Circuit, - Rank-1 Constraint System, - Ethereum Developers, - Protocol Developers, - Blockchain Developers, - Proving System, - Smart Contract Language] -sidebar_position: 0 ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -Noir Logo - -Noir is a Domain-Specific Language for SNARK proving systems developed by [Aztec Labs](https://aztec.network/). It allows you to generate complex Zero-Knowledge Programs (ZKP) by using simple and flexible syntax, requiring no previous knowledge on the underlying mathematics or cryptography. - -ZK programs are programs that can generate short proofs of a certain statement without revealing some details about it. You can read more about ZKPs [here](https://dev.to/spalladino/a-beginners-intro-to-coding-zero-knowledge-proofs-c56). - -## What's new about Noir? - -Noir works differently from most ZK languages by taking a two-pronged path. First, it compiles the program to an adaptable intermediate language known as ACIR. From there, depending on a given project's needs, ACIR can be further compiled into an arithmetic circuit for integration with the proving backend. - -:::info - -Noir is backend agnostic, which means it makes no assumptions on which proving backend powers the ZK proof. Being the language that powers [Aztec Contracts](https://docs.aztec.network/developers/contracts/main), it defaults to Aztec's Barretenberg proving backend. - -However, the ACIR output can be transformed to be compatible with other PLONK-based backends, or into a [rank-1 constraint system](https://www.rareskills.io/post/rank-1-constraint-system) suitable for backends such as Arkwork's Marlin. - -::: - -## Who is Noir for? - -Noir can be used both in complex cloud-based backends and in user's smartphones, requiring no knowledge on the underlying math or cryptography. From authorization systems that keep a password in the user's device, to complex on-chain verification of recursive proofs, Noir is designed to abstract away complexity without any significant overhead. Here are some examples of situations where Noir can be used: - - - - Noir Logo - - Aztec Contracts leverage Noir to allow for the storage and execution of private information. Writing an Aztec Contract is as easy as writing Noir, and Aztec developers can easily interact with the network storage and execution through the [Aztec.nr](https://docs.aztec.network/developers/contracts/main) library. - - - Soliditry Verifier Example - Noir can auto-generate Solidity verifier contracts that verify Noir proofs. This allows for non-interactive verification of proofs containing private information in an immutable system. This feature powers a multitude of use-case scenarios, from P2P chess tournaments, to [Aztec Layer-2 Blockchain](https://docs.aztec.network/) - - - Aztec Labs developed NoirJS, an easy interface to generate and verify Noir proofs in a Javascript environment. This allows for Noir to be used in webpages, mobile apps, games, and any other environment supporting JS execution in a standalone manner. - - - - -## Libraries - -Noir is meant to be easy to extend by simply importing Noir libraries just like in Rust. -The [awesome-noir repo](https://github.com/noir-lang/awesome-noir#libraries) is a collection of libraries developed by the Noir community. -Writing a new library is easy and makes code be composable and easy to reuse. See the section on [dependencies](noir/modules_packages_crates/dependencies.md) for more information. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/migration_notes.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/migration_notes.md deleted file mode 100644 index 6bd740024e5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/migration_notes.md +++ /dev/null @@ -1,105 +0,0 @@ ---- -title: Migration notes -description: Read about migration notes from previous versions, which could solve problems while updating -keywords: [Noir, notes, migration, updating, upgrading] ---- - -Noir is in full-speed development. Things break fast, wild, and often. This page attempts to leave some notes on errors you might encounter when upgrading and how to resolve them until proper patches are built. - -### `backend encountered an error: libc++.so.1` - -Depending on your OS, you may encounter the following error when running `nargo prove` for the first time: - -```text -The backend encountered an error: "/home/codespace/.nargo/backends/acvm-backend-barretenberg/backend_binary: error while loading shared libraries: libc++.so.1: cannot open shared object file: No such file or directory\n" -``` - -Install the `libc++-dev` library with: - -```bash -sudo apt install libc++-dev -``` - -## ≥0.19 - -### Enforcing `compiler_version` - -From this version on, the compiler will check for the `compiler_version` field in `Nargo.toml`, and will error if it doesn't match the current Nargo version in use. - -To update, please make sure this field in `Nargo.toml` matches the output of `nargo --version`. - -## ≥0.14 - -The index of the [for loops](noir/concepts/control_flow.md#loops) is now of type `u64` instead of `Field`. An example refactor would be: - -```rust -for i in 0..10 { - let i = i as Field; -} -``` - -## ≥v0.11.0 and Nargo backend - -From this version onwards, Nargo starts managing backends through the `nargo backend` command. Upgrading to the versions per usual steps might lead to: - -### `backend encountered an error` - -This is likely due to the existing locally installed version of proving backend (e.g. barretenberg) is incompatible with the version of Nargo in use. - -To fix the issue: - -1. Uninstall the existing backend - -```bash -nargo backend uninstall acvm-backend-barretenberg -``` - -You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. - -2. Reinstall a compatible version of the proving backend. - -If you are using the default barretenberg backend, simply run: - -``` -nargo prove -``` - -with your Noir program. - -This will trigger the download and installation of the latest version of barretenberg compatible with your Nargo in use. - -### `backend encountered an error: illegal instruction` - -On certain Intel-based systems, an `illegal instruction` error may arise due to incompatibility of barretenberg with certain CPU instructions. - -To fix the issue: - -1. Uninstall the existing backend - -```bash -nargo backend uninstall acvm-backend-barretenberg -``` - -You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. - -2. Reinstall a compatible version of the proving backend. - -If you are using the default barretenberg backend, simply run: - -``` -nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/barretenberg-js-binary/raw/master/run-bb.tar.gz -``` - -This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. - -The gzipped file is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. - -Then run: - -``` -DESIRED_BINARY_VERSION=0.8.1 nargo info -``` - -This overrides the bb native binary with a bb.js node application instead, which should be compatible with most if not all hardware. This does come with the drawback of being generally slower than native binary. - -0.8.1 indicates bb.js version 0.8.1, so if you change that it will update to a different version or the default version in the script if none was supplied. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/_category_.json deleted file mode 100644 index 7da08f8a8c5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Concepts", - "position": 0, - "collapsible": true, - "collapsed": true -} \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/assert.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/assert.md deleted file mode 100644 index bcff613a695..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/assert.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Assert Function -description: - Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or - comparison expression that follows to be true, and what happens if the expression is false at - runtime. -keywords: [Noir programming language, assert statement, predicate expression, comparison expression] -sidebar_position: 4 ---- - -Noir includes a special `assert` function which will explicitly constrain the predicate/comparison -expression that follows to be true. If this expression is false at runtime, the program will fail to -be proven. Example: - -```rust -fn main(x : Field, y : Field) { - assert(x == y); -} -``` - -> Assertions only work for predicate operations, such as `==`. If there's any ambiguity on the operation, the program will fail to compile. For example, it is unclear if `assert(x + y)` would check for `x + y == 0` or simply would return `true`. - -You can optionally provide a message to be logged when the assertion fails: - -```rust -assert(x == y, "x and y are not equal"); -``` - -Aside string literals, the optional message can be a format string or any other type supported as input for Noir's [print](../standard_library/logging.md) functions. This feature lets you incorporate runtime variables into your failed assertion logs: - -```rust -assert(x == y, f"Expected x == y, but got {x} == {y}"); -``` - -Using a variable as an assertion message directly: - -```rust -struct myStruct { - myField: Field -} - -let s = myStruct { myField: y }; -assert(s.myField == x, s); -``` - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/comments.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/comments.md deleted file mode 100644 index b51a85f5c94..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/comments.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Comments -description: - Learn how to write comments in Noir programming language. A comment is a line of code that is - ignored by the compiler, but it can be read by programmers. Single-line and multi-line comments - are supported in Noir. -keywords: [Noir programming language, comments, single-line comments, multi-line comments] -sidebar_position: 10 ---- - -A comment is a line in your codebase which the compiler ignores, however it can be read by -programmers. - -Here is a single line comment: - -```rust -// This is a comment and is ignored -``` - -`//` is used to tell the compiler to ignore the rest of the line. - -Noir also supports multi-line block comments. Start a block comment with `/*` and end the block with `*/`. - -Noir does not natively support doc comments. You may be able to use [Rust doc comments](https://doc.rust-lang.org/reference/comments.html) in your code to leverage some Rust documentation build tools with Noir code. - -```rust -/* - This is a block comment describing a complex function. -*/ -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/control_flow.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/control_flow.md deleted file mode 100644 index 045d3c3a5f5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/control_flow.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -title: Control Flow -description: - Learn how to use loops and if expressions in the Noir programming language. Discover the syntax - and examples for for loops and if-else statements. -keywords: [Noir programming language, loops, for loop, if-else statements, Rust syntax] -sidebar_position: 2 ---- - -## If Expressions - -Noir supports `if-else` statements. The syntax is most similar to Rust's where it is not required -for the statement's conditional to be surrounded by parentheses. - -```rust -let a = 0; -let mut x: u32 = 0; - -if a == 0 { - if a != 0 { - x = 6; - } else { - x = 2; - } -} else { - x = 5; - assert(x == 5); -} -assert(x == 2); -``` - -## Loops - -Noir has one kind of loop: the `for` loop. `for` loops allow you to repeat a block of code multiple -times. - -The following block of code between the braces is run 10 times. - -```rust -for i in 0..10 { - // do something -} -``` - -The index for loops is of type `u64`. - -### Break and Continue - -In unconstrained code, `break` and `continue` are also allowed in `for` loops. These are only allowed -in unconstrained code since normal constrained code requires that Noir knows exactly how many iterations -a loop may have. `break` and `continue` can be used like so: - -```rust -for i in 0 .. 10 { - println("Iteration start") - - if i == 2 { - continue; - } - - if i == 5 { - break; - } - - println(i); -} -println("Loop end") -``` - -When used, `break` will end the current loop early and jump to the statement after the for loop. In the example -above, the `break` will stop the loop and jump to the `println("Loop end")`. - -`continue` will stop the current iteration of the loop, and jump to the start of the next iteration. In the example -above, `continue` will jump to `println("Iteration start")` when used. Note that the loop continues as normal after this. -The iteration variable `i` is still increased by one as normal when `continue` is used. - -`break` and `continue` cannot currently be used to jump out of more than a single loop at a time. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_bus.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_bus.md deleted file mode 100644 index e54fc861257..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_bus.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: Data Bus -sidebar_position: 13 ---- -**Disclaimer** this feature is experimental, do not use it! - -The data bus is an optimization that the backend can use to make recursion more efficient. -In order to use it, you must define some inputs of the program entry points (usually the `main()` -function) with the `call_data` modifier, and the return values with the `return_data` modifier. -These modifiers are incompatible with `pub` and `mut` modifiers. - -## Example - -```rust -fn main(mut x: u32, y: call_data u32, z: call_data [u32;4] ) -> return_data u32 { - let a = z[x]; - a+y -} -``` - -As a result, both call_data and return_data will be treated as private inputs and encapsulated into a read-only array each, for the backend to process. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/_category_.json deleted file mode 100644 index 5d694210bbf..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 0, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/arrays.md deleted file mode 100644 index 9b02d52e8a8..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/arrays.md +++ /dev/null @@ -1,253 +0,0 @@ ---- -title: Arrays -description: - Dive into the Array data type in Noir. Grasp its methods, practical examples, and best practices for efficiently using Arrays in your Noir code. -keywords: - [ - noir, - array type, - methods, - examples, - indexing, - ] -sidebar_position: 4 ---- - -An array is one way of grouping together values into one compound type. Array types can be inferred -or explicitly specified via the syntax `[; ]`: - -```rust -fn main(x : Field, y : Field) { - let my_arr = [x, y]; - let your_arr: [Field; 2] = [x, y]; -} -``` - -Here, both `my_arr` and `your_arr` are instantiated as an array containing two `Field` elements. - -Array elements can be accessed using indexing: - -```rust -fn main() { - let a = [1, 2, 3, 4, 5]; - - let first = a[0]; - let second = a[1]; -} -``` - -All elements in an array must be of the same type (i.e. homogeneous). That is, an array cannot group -a `Field` value and a `u8` value together for example. - -You can write mutable arrays, like: - -```rust -fn main() { - let mut arr = [1, 2, 3, 4, 5]; - assert(arr[0] == 1); - - arr[0] = 42; - assert(arr[0] == 42); -} -``` - -You can instantiate a new array of a fixed size with the same value repeated for each element. The following example instantiates an array of length 32 where each element is of type Field and has the value 0. - -```rust -let array: [Field; 32] = [0; 32]; -``` - -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: - -```rust -let array: [Field; 32] = [0; 32]; -let sl = array.as_slice() -``` - -You can define multidimensional arrays: - -```rust -let array : [[Field; 2]; 2]; -let element = array[0][0]; -``` - -However, multidimensional slices are not supported. For example, the following code will error at compile time: - -```rust -let slice : [[Field]] = &[]; -``` - -## Types - -You can create arrays of primitive types or structs. There is not yet support for nested arrays -(arrays of arrays) or arrays of structs that contain arrays. - -## Methods - -For convenience, the STD provides some ready-to-use, common methods for arrays. -Each of these functions are located within the generic impl `impl [T; N] {`. -So anywhere `self` appears, it refers to the variable `self: [T; N]`. - -### len - -Returns the length of an array - -```rust -fn len(self) -> Field -``` - -example - -```rust -fn main() { - let array = [42, 42]; - assert(array.len() == 2); -} -``` - -### sort - -Returns a new sorted array. The original array remains untouched. Notice that this function will -only work for arrays of fields or integers, not for any arbitrary type. This is because the sorting -logic it uses internally is optimized specifically for these values. If you need a sort function to -sort any type, you should use the function `sort_via` described below. - -```rust -fn sort(self) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32]; - let sorted = arr.sort(); - assert(sorted == [32, 42]); -} -``` - -### sort_via - -Sorts the array with a custom comparison function - -```rust -fn sort_via(self, ordering: fn(T, T) -> bool) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32] - let sorted_ascending = arr.sort_via(|a, b| a <= b); - assert(sorted_ascending == [32, 42]); // verifies - - let sorted_descending = arr.sort_via(|a, b| a >= b); - assert(sorted_descending == [32, 42]); // does not verify -} -``` - -### map - -Applies a function to each element of the array, returning a new array containing the mapped elements. - -```rust -fn map(self, f: fn(T) -> U) -> [U; N] -``` - -example - -```rust -let a = [1, 2, 3]; -let b = a.map(|a| a * 2); // b is now [2, 4, 6] -``` - -### fold - -Applies a function to each element of the array, returning the final accumulated value. The first -parameter is the initial value. - -```rust -fn fold(self, mut accumulator: U, f: fn(U, T) -> U) -> U -``` - -This is a left fold, so the given function will be applied to the accumulator and first element of -the array, then the second, and so on. For a given call the expected result would be equivalent to: - -```rust -let a1 = [1]; -let a2 = [1, 2]; -let a3 = [1, 2, 3]; - -let f = |a, b| a - b; -a1.fold(10, f) //=> f(10, 1) -a2.fold(10, f) //=> f(f(10, 1), 2) -a3.fold(10, f) //=> f(f(f(10, 1), 2), 3) -``` - -example: - -```rust - -fn main() { - let arr = [2, 2, 2, 2, 2]; - let folded = arr.fold(0, |a, b| a + b); - assert(folded == 10); -} - -``` - -### reduce - -Same as fold, but uses the first element as starting element. - -```rust -fn reduce(self, f: fn(T, T) -> T) -> T -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let reduced = arr.reduce(|a, b| a + b); - assert(reduced == 10); -} -``` - -### all - -Returns true if all the elements satisfy the given predicate - -```rust -fn all(self, predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let all = arr.all(|a| a == 2); - assert(all); -} -``` - -### any - -Returns true if any of the elements satisfy the given predicate - -```rust -fn any(self, predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 5]; - let any = arr.any(|a| a == 5); - assert(any); -} - -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/booleans.md deleted file mode 100644 index 7211716f63e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/booleans.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Booleans -description: - Delve into the Boolean data type in Noir. Understand its methods, practical examples, and best practices for using Booleans in your Noir programs. -keywords: - [ - noir, - boolean type, - methods, - examples, - logical operations, - ] -sidebar_position: 2 ---- - - -The `bool` type in Noir has two possible values: `true` and `false`: - -```rust -fn main() { - let t = true; - let f: bool = false; -} -``` - -> **Note:** When returning a boolean value, it will show up as a value of 1 for `true` and 0 for -> `false` in _Verifier.toml_. - -The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and -[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/fields.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/fields.md deleted file mode 100644 index a10a4810788..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/fields.md +++ /dev/null @@ -1,192 +0,0 @@ ---- -title: Fields -description: - Dive deep into the Field data type in Noir. Understand its methods, practical examples, and best practices to effectively use Fields in your Noir programs. -keywords: - [ - noir, - field type, - methods, - examples, - best practices, - ] -sidebar_position: 0 ---- - -The field type corresponds to the native field type of the proving backend. - -The size of a Noir field depends on the elliptic curve's finite field for the proving backend -adopted. For example, a field would be a 254-bit integer when paired with the default backend that -spans the Grumpkin curve. - -Fields support integer arithmetic and are often used as the default numeric type in Noir: - -```rust -fn main(x : Field, y : Field) { - let z = x + y; -} -``` - -`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new -private value `z` constrained to be equal to `x + y`. - -If proving efficiency is of priority, fields should be used as a default for solving problems. -Smaller integer types (e.g. `u64`) incur extra range constraints. - -## Methods - -After declaring a Field, you can use these common methods on it: - -### to_le_bits - -Transforms the field into an array of bits, Little Endian. - -```rust -fn to_le_bits(_x : Field, _bit_size: u32) -> [u1] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_le_bits(32); -} -``` - -### to_be_bits - -Transforms the field into an array of bits, Big Endian. - -```rust -fn to_be_bits(_x : Field, _bit_size: u32) -> [u1] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_be_bits(32); -} -``` - -### to_le_bytes - -Transforms into an array of bytes, Little Endian - -```rust -fn to_le_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_le_bytes(4); -} -``` - -### to_be_bytes - -Transforms into an array of bytes, Big Endian - -```rust -fn to_be_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_be_bytes(4); -} -``` - -### to_le_radix - -Decomposes into a vector over the specified base, Little Endian - -```rust -fn to_le_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_le_radix(256, 4); -} -``` - -### to_be_radix - -Decomposes into a vector over the specified base, Big Endian - -```rust -fn to_be_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_be_radix(256, 4); -} -``` - -### pow_32 - -Returns the value to the power of the specified exponent - -```rust -fn pow_32(self, exponent: Field) -> Field -``` - -example: - -```rust -fn main() { - let field = 2 - let pow = field.pow_32(4); - assert(pow == 16); -} -``` - -### assert_max_bit_size - -Adds a constraint to specify that the field can be represented with `bit_size` number of bits - -```rust -fn assert_max_bit_size(self, bit_size: u32) -``` - -example: - -```rust -fn main() { - let field = 2 - field.assert_max_bit_size(32); -} -``` - -### sgn0 - -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. - -```rust -fn sgn0(self) -> u1 -``` - - -### lt - -Returns true if the field is less than the other field - -```rust -pub fn lt(self, another: Field) -> bool -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/function_types.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/function_types.md deleted file mode 100644 index f6121af17e2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/function_types.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Function types -sidebar_position: 10 ---- - -Noir supports higher-order functions. The syntax for a function type is as follows: - -```rust -fn(arg1_type, arg2_type, ...) -> return_type -``` - -Example: - -```rust -fn assert_returns_100(f: fn() -> Field) { // f takes no args and returns a Field - assert(f() == 100); -} - -fn main() { - assert_returns_100(|| 100); // ok - assert_returns_100(|| 150); // fails -} -``` - -A function type also has an optional capture environment - this is necessary to support closures. -See [Lambdas](../lambdas.md) for more details. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/index.md deleted file mode 100644 index 357813c147a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/index.md +++ /dev/null @@ -1,110 +0,0 @@ ---- -title: Data Types -description: - Get a clear understanding of the two categories of Noir data types - primitive types and compound - types. Learn about their characteristics, differences, and how to use them in your Noir - programming. -keywords: - [ - noir, - data types, - primitive types, - compound types, - private types, - public types, - ] ---- - -Every value in Noir has a type, which determines which operations are valid for it. - -All values in Noir are fundamentally composed of `Field` elements. For a more approachable -developing experience, abstractions are added on top to introduce different data types in Noir. - -Noir has two category of data types: primitive types (e.g. `Field`, integers, `bool`) and compound -types that group primitive types (e.g. arrays, tuples, structs). Each value can either be private or -public. - -## Private & Public Types - -A **private value** is known only to the Prover, while a **public value** is known by both the -Prover and Verifier. Mark values as `private` when the value should only be known to the prover. All -primitive types (including individual fields of compound types) in Noir are private by default, and -can be marked public when certain values are intended to be revealed to the Verifier. - -> **Note:** For public values defined in Noir programs paired with smart contract verifiers, once -> the proofs are verified on-chain the values can be considered known to everyone that has access to -> that blockchain. - -Public data types are treated no differently to private types apart from the fact that their values -will be revealed in proofs generated. Simply changing the value of a public type will not change the -circuit (where the same goes for changing values of private types as well). - -_Private values_ are also referred to as _witnesses_ sometimes. - -> **Note:** The terms private and public when applied to a type (e.g. `pub Field`) have a different -> meaning than when applied to a function (e.g. `pub fn foo() {}`). -> -> The former is a visibility modifier for the Prover to interpret if a value should be made known to -> the Verifier, while the latter is a visibility modifier for the compiler to interpret if a -> function should be made accessible to external Noir programs like in other languages. - -### pub Modifier - -All data types in Noir are private by default. Types are explicitly declared as public using the -`pub` modifier: - -```rust -fn main(x : Field, y : pub Field) -> pub Field { - x + y -} -``` - -In this example, `x` is **private** while `y` and `x + y` (the return value) are **public**. Note -that visibility is handled **per variable**, so it is perfectly valid to have one input that is -private and another that is public. - -> **Note:** Public types can only be declared through parameters on `main`. - -## Type Aliases - -A type alias is a new name for an existing type. Type aliases are declared with the keyword `type`: - -```rust -type Id = u8; - -fn main() { - let id: Id = 1; - let zero: u8 = 0; - assert(zero + 1 == id); -} -``` - -Type aliases can also be used with [generics](../generics.md): - -```rust -type Id = Size; - -fn main() { - let id: Id = 1; - let zero: u32 = 0; - assert(zero + 1 == id); -} -``` - -Type aliases can even refer to other aliases. An error will be issued if they form a cycle: - -```rust -// Ok! -type A = B; -type B = Field; - -type Bad1 = Bad2; - -// error: Dependency cycle found -type Bad2 = Bad1; -// ^^^^^^^^^^^ 'Bad2' recursively depends on itself: Bad2 -> Bad1 -> Bad2 -``` - -### BigInt - -You can achieve BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/integers.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/integers.md deleted file mode 100644 index 1c6b375db49..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/integers.md +++ /dev/null @@ -1,155 +0,0 @@ ---- -title: Integers -description: Explore the Integer data type in Noir. Learn about its methods, see real-world examples, and grasp how to efficiently use Integers in your Noir code. -keywords: [noir, integer types, methods, examples, arithmetic] -sidebar_position: 1 ---- - -An integer type is a range constrained field type. The Noir frontend supports both unsigned and signed integer types. The allowed sizes are 1, 8, 32 and 64 bits. - -:::info - -When an integer is defined in Noir without a specific type, it will default to `Field`. - -The one exception is for loop indices which default to `u64` since comparisons on `Field`s are not possible. - -::: - -## Unsigned Integers - -An unsigned integer type is specified first with the letter `u` (indicating its unsigned nature) followed by its bit size (e.g. `8`): - -```rust -fn main() { - let x: u8 = 1; - let y: u8 = 1; - let z = x + y; - assert (z == 2); -} -``` - -The bit size determines the maximum value the integer type can store. For example, a `u8` variable can store a value in the range of 0 to 255 (i.e. $\\2^{8}-1\\$). - -## Signed Integers - -A signed integer type is specified first with the letter `i` (which stands for integer) followed by its bit size (e.g. `8`): - -```rust -fn main() { - let x: i8 = -1; - let y: i8 = -1; - let z = x + y; - assert (z == -2); -} -``` - -The bit size determines the maximum and minimum range of value the integer type can store. For example, an `i8` variable can store a value in the range of -128 to 127 (i.e. $\\-2^{7}\\$ to $\\2^{7}-1\\$). - -## 128 bits Unsigned Integers - -The built-in structure `U128` allows you to use 128-bit unsigned integers almost like a native integer type. However, there are some differences to keep in mind: -- You cannot cast between a native integer and `U128` -- There is a higher performance cost when using `U128`, compared to a native type. - -Conversion between unsigned integer types and U128 are done through the use of `from_integer` and `to_integer` functions. `from_integer` also accepts the `Field` type as input. - -```rust -fn main() { - let x = U128::from_integer(23); - let y = U128::from_hex("0x7"); - let z = x + y; - assert(z.to_integer() == 30); -} -``` - -`U128` is implemented with two 64 bits limbs, representing the low and high bits, which explains the performance cost. You should expect `U128` to be twice more costly for addition and four times more costly for multiplication. -You can construct a U128 from its limbs: -```rust -fn main(x: u64, y: u64) { - let x = U128::from_u64s_be(x,y); - assert(z.hi == x as Field); - assert(z.lo == y as Field); -} -``` - -Note that the limbs are stored as Field elements in order to avoid unnecessary conversions. -Apart from this, most operations will work as usual: - -```rust -fn main(x: U128, y: U128) { - // multiplication - let c = x * y; - // addition and subtraction - let c = c - x + y; - // division - let c = x / y; - // bit operation; - let c = x & y | y; - // bit shift - let c = x << y; - // comparisons; - let c = x < y; - let c = x == y; -} -``` - -## Overflows - -Computations that exceed the type boundaries will result in overflow errors. This happens with both signed and unsigned integers. For example, attempting to prove: - -```rust -fn main(x: u8, y: u8) { - let z = x + y; -} -``` - -With: - -```toml -x = "255" -y = "1" -``` - -Would result in: - -``` -$ nargo prove -error: Assertion failed: 'attempt to add with overflow' -┌─ ~/src/main.nr:9:13 -│ -│ let z = x + y; -│ ----- -│ -= Call stack: - ... -``` - -A similar error would happen with signed integers: - -```rust -fn main() { - let x: i8 = -118; - let y: i8 = -11; - let z = x + y; -} -``` - -### Wrapping methods - -Although integer overflow is expected to error, some use-cases rely on wrapping. For these use-cases, the standard library provides `wrapping` variants of certain common operations: - -```rust -fn wrapping_add(x: T, y: T) -> T; -fn wrapping_sub(x: T, y: T) -> T; -fn wrapping_mul(x: T, y: T) -> T; -``` - -Example of how it is used: - -```rust -use dep::std; - -fn main(x: u8, y: u8) -> pub u8 { - std::wrapping_add(x, y) -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/references.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/references.md deleted file mode 100644 index a5293d11cfb..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/references.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: References -sidebar_position: 9 ---- - -Noir supports first-class references. References are a bit like pointers: they point to a specific address that can be followed to access the data stored at that address. You can use Rust-like syntax to use pointers in Noir: the `&` operator references the variable, the `*` operator dereferences it. - -Example: - -```rust -fn main() { - let mut x = 2; - - // you can reference x as &mut and pass it to multiplyBy2 - multiplyBy2(&mut x); -} - -// you can access &mut here -fn multiplyBy2(x: &mut Field) { - // and dereference it with * - *x = *x * 2; -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/slices.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/slices.mdx deleted file mode 100644 index 828faf4a8f8..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/slices.mdx +++ /dev/null @@ -1,170 +0,0 @@ ---- -title: Slices -description: Explore the Slice data type in Noir. Understand its methods, see real-world examples, and learn how to effectively use Slices in your Noir programs. -keywords: [noir, slice type, methods, examples, subarrays] -sidebar_position: 5 ---- - -import Experimental from '@site/src/components/Notes/_experimental.mdx'; - - - -A slice is a dynamically-sized view into a sequence of elements. They can be resized at runtime, but because they don't own the data, they cannot be returned from a circuit. You can treat slices as arrays without a constrained size. - -```rust -use dep::std::slice; - -fn main() -> pub Field { - let mut slice: [Field] = &[0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -To write a slice literal, use a preceeding ampersand as in: `&[0; 2]` or -`&[1, 2, 3]`. - -It is important to note that slices are not references to arrays. In Noir, -`&[..]` is more similar to an immutable, growable vector. - -View the corresponding test file [here][test-file]. - -[test-file]: https://github.com/noir-lang/noir/blob/f387ec1475129732f72ba294877efdf6857135ac/crates/nargo_cli/tests/test_data_ssa_refactor/slices/src/main.nr - -## Methods - -For convenience, the STD provides some ready-to-use, common methods for slices: - -### push_back - -Pushes a new element to the end of the slice, returning a new slice with a length one greater than the original unmodified slice. - -```rust -fn push_back(_self: [T], _elem: T) -> [T] -``` - -example: - -```rust -fn main() -> pub Field { - let mut slice: [Field] = &[0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -View the corresponding test file [here][test-file]. - -### push_front - -Returns a new array with the specified element inserted at index 0. The existing elements indexes are incremented by 1. - -```rust -fn push_front(_self: Self, _elem: T) -> Self -``` - -Example: - -```rust -let mut new_slice: [Field] = &[]; -new_slice = new_slice.push_front(20); -assert(new_slice[0] == 20); // returns true -``` - -View the corresponding test file [here][test-file]. - -### pop_front - -Returns a tuple of two items, the first element of the array and the rest of the array. - -```rust -fn pop_front(_self: Self) -> (T, Self) -``` - -Example: - -```rust -let (first_elem, rest_of_slice) = slice.pop_front(); -``` - -View the corresponding test file [here][test-file]. - -### pop_back - -Returns a tuple of two items, the beginning of the array with the last element omitted and the last element. - -```rust -fn pop_back(_self: Self) -> (Self, T) -``` - -Example: - -```rust -let (popped_slice, last_elem) = slice.pop_back(); -``` - -View the corresponding test file [here][test-file]. - -### append - -Loops over a slice and adds it to the end of another. - -```rust -fn append(mut self, other: Self) -> Self -``` - -Example: - -```rust -let append = &[1, 2].append(&[3, 4, 5]); -``` - -### insert - -Inserts an element at a specified index and shifts all following elements by 1. - -```rust -fn insert(_self: Self, _index: Field, _elem: T) -> Self -``` - -Example: - -```rust -new_slice = rest_of_slice.insert(2, 100); -assert(new_slice[2] == 100); -``` - -View the corresponding test file [here][test-file]. - -### remove - -Remove an element at a specified index, shifting all elements after it to the left, returning the altered slice and the removed element. - -```rust -fn remove(_self: Self, _index: Field) -> (Self, T) -``` - -Example: - -```rust -let (remove_slice, removed_elem) = slice.remove(3); -``` - -### len - -Returns the length of a slice - -```rust -fn len(self) -> Field -``` - -Example: - -```rust -fn main() { - let slice = &[42, 42]; - assert(slice.len() == 2); -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/strings.md deleted file mode 100644 index 8ab5825a4c4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/strings.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: Strings -description: - Discover the String data type in Noir. Learn about its methods, see real-world examples, and understand how to effectively manipulate and use Strings in Noir. -keywords: - [ - noir, - string type, - methods, - examples, - concatenation, - ] -sidebar_position: 3 ---- - - -The string type is a fixed length value defined with `str`. - -You can use strings in `assert()` functions or print them with -`println()`. See more about [Logging](../../standard_library/logging.md). - -```rust -use dep::std; - -fn main(message : pub str<11>, hex_as_string : str<4>) { - println(message); - assert(message == "hello world"); - assert(hex_as_string == "0x41"); -} -``` - -You can convert a `str` to a byte array by calling `as_bytes()` -or a vector by calling `as_bytes_vec()`. - -```rust -fn main() { - let message = "hello world"; - let message_bytes = message.as_bytes(); - let mut message_vec = message.as_bytes_vec(); - assert(message_bytes.len() == 11); - assert(message_bytes[0] == 104); - assert(message_bytes[0] == message_vec.get(0)); -} -``` - -## Escape characters - -You can use escape characters for your strings: - -| Escape Sequence | Description | -|-----------------|-----------------| -| `\r` | Carriage Return | -| `\n` | Newline | -| `\t` | Tab | -| `\0` | Null Character | -| `\"` | Double Quote | -| `\\` | Backslash | - -Example: - -```rust -let s = "Hello \"world" // prints "Hello "world" -let s = "hey \tyou"; // prints "hey you" -``` - -## Raw strings - -A raw string begins with the letter `r` and is optionally delimited by a number of hashes `#`. - -Escape characters are *not* processed within raw strings. All contents are interpreted literally. - -Example: - -```rust -let s = r"Hello world"; -let s = r#"Simon says "hello world""#; - -// Any number of hashes may be used (>= 1) as long as the string also terminates with the same number of hashes -let s = r#####"One "#, Two "##, Three "###, Four "####, Five will end the string."#####; -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/structs.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/structs.md deleted file mode 100644 index dbf68c99813..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/structs.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -title: Structs -description: - Explore the Struct data type in Noir. Learn about its methods, see real-world examples, and grasp how to effectively define and use Structs in your Noir programs. -keywords: - [ - noir, - struct type, - methods, - examples, - data structures, - ] -sidebar_position: 8 ---- - -A struct also allows for grouping multiple values of different types. Unlike tuples, we can also -name each field. - -> **Note:** The usage of _field_ here refers to each element of the struct and is unrelated to the -> field type of Noir. - -Defining a struct requires giving it a name and listing each field within as `: ` pairs: - -```rust -struct Animal { - hands: Field, - legs: Field, - eyes: u8, -} -``` - -An instance of a struct can then be created with actual values in `: ` pairs in any -order. Struct fields are accessible using their given names: - -```rust -fn main() { - let legs = 4; - - let dog = Animal { - eyes: 2, - hands: 0, - legs, - }; - - let zero = dog.hands; -} -``` - -Structs can also be destructured in a pattern, binding each field to a new variable: - -```rust -fn main() { - let Animal { hands, legs: feet, eyes } = get_octopus(); - - let ten = hands + feet + eyes as u8; -} - -fn get_octopus() -> Animal { - let octopus = Animal { - hands: 0, - legs: 8, - eyes: 2, - }; - - octopus -} -``` - -The new variables can be bound with names different from the original struct field names, as -showcased in the `legs --> feet` binding in the example above. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/tuples.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/tuples.md deleted file mode 100644 index 2ec5c9c4113..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/tuples.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Tuples -description: - Dive into the Tuple data type in Noir. Understand its methods, practical examples, and best practices for efficiently using Tuples in your Noir code. -keywords: - [ - noir, - tuple type, - methods, - examples, - multi-value containers, - ] -sidebar_position: 7 ---- - -A tuple collects multiple values like an array, but with the added ability to collect values of -different types: - -```rust -fn main() { - let tup: (u8, u64, Field) = (255, 500, 1000); -} -``` - -One way to access tuple elements is via destructuring using pattern matching: - -```rust -fn main() { - let tup = (1, 2); - - let (one, two) = tup; - - let three = one + two; -} -``` - -Another way to access tuple elements is via direct member access, using a period (`.`) followed by -the index of the element we want to access. Index `0` corresponds to the first tuple element, `1` to -the second and so on: - -```rust -fn main() { - let tup = (5, 6, 7, 8); - - let five = tup.0; - let eight = tup.3; -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/distinct.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/distinct.md deleted file mode 100644 index 6c993b8b5e0..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/distinct.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: Distinct Witnesses -sidebar_position: 11 ---- - -The `distinct` keyword prevents repetitions of witness indices in the program's ABI. This ensures -that the witnesses being returned as public inputs are all unique. - -The `distinct` keyword is only used for return values on program entry points (usually the `main()` -function). - -When using `distinct` and `pub` simultaneously, `distinct` comes first. See the example below. - -You can read more about the problem this solves -[here](https://github.com/noir-lang/noir/issues/1183). - -## Example - -Without the `distinct` keyword, the following program - -```rust -fn main(x : pub Field, y : pub Field) -> pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - "return_witnesses": [3, 2, 4, 4] - } -} -``` - -Whereas (with the `distinct` keyword) - -```rust -fn main(x : pub Field, y : pub Field) -> distinct pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - //... - "return_witnesses": [3, 4, 5, 6] - } -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/functions.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/functions.md deleted file mode 100644 index 2c9bc33fdfc..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/functions.md +++ /dev/null @@ -1,226 +0,0 @@ ---- -title: Functions -description: - Learn how to declare functions and methods in Noir, a programming language with Rust semantics. - This guide covers parameter declaration, return types, call expressions, and more. -keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] -sidebar_position: 1 ---- - -Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. - -To declare a function the `fn` keyword is used. - -```rust -fn foo() {} -``` - -By default, functions are visible only within the package they are defined. To make them visible outside of that package (for example, as part of a [library](../modules_packages_crates/crates_and_packages.md#libraries)), you should mark them as `pub`: - -```rust -pub fn foo() {} -``` - -You can also restrict the visibility of the function to only the crate it was defined in, by specifying `pub(crate)`: - -```rust -pub(crate) fn foo() {} //foo can only be called within its crate -``` - -All parameters in a function must have a type and all types are known at compile time. The parameter -is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. - -```rust -fn foo(x : Field, y : Field){} -``` - -The return type of a function can be stated by using the `->` arrow notation. The function below -states that the foo function must return a `Field`. If the function returns no value, then the arrow -is omitted. - -```rust -fn foo(x : Field, y : Field) -> Field { - x + y -} -``` - -Note that a `return` keyword is unneeded in this case - the last expression in a function's body is -returned. - -## Main function - -If you're writing a binary, the `main` function is the starting point of your program. You can pass all types of expressions to it, as long as they have a fixed size at compile time: - -```rust -fn main(x : Field) // this is fine: passing a Field -fn main(x : [Field; 2]) // this is also fine: passing a Field with known size at compile-time -fn main(x : (Field, bool)) // 👌: passing a (Field, bool) tuple means size 2 -fn main(x : str<5>) // this is fine, as long as you pass a string of size 5 - -fn main(x : Vec) // can't compile, has variable size -fn main(x : [Field]) // can't compile, has variable size -fn main(....// i think you got it by now -``` - -Keep in mind [tests](../../getting_started/tooling/testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: - -```rust -fn main(x : [Field]) { - assert(x[0] == 1); -} - -#[test] -fn test_one() { - main(&[1, 2]); -} -``` - -```bash -$ nargo test -[testing] Running 1 test functions -[testing] Testing test_one... ok -[testing] All tests passed - -$ nargo check -The application panicked (crashed). -Message: Cannot have variable sized arrays as a parameter to main -``` - -## Call Expressions - -Calling a function in Noir is executed by using the function name and passing in the necessary -arguments. - -Below we show how to call the `foo` function from the `main` function using a call expression: - -```rust -fn main(x : Field, y : Field) { - let z = foo(x); -} - -fn foo(x : Field) -> Field { - x + x -} -``` - -## Methods - -You can define methods in Noir on any struct type in scope. - -```rust -struct MyStruct { - foo: Field, - bar: Field, -} - -impl MyStruct { - fn new(foo: Field) -> MyStruct { - MyStruct { - foo, - bar: 2, - } - } - - fn sum(self) -> Field { - self.foo + self.bar - } -} - -fn main() { - let s = MyStruct::new(40); - assert(s.sum() == 42); -} -``` - -Methods are just syntactic sugar for functions, so if we wanted to we could also call `sum` as -follows: - -```rust -assert(MyStruct::sum(s) == 42); -``` - -It is also possible to specialize which method is chosen depending on the [generic](./generics.md) type that is used. In this example, the `foo` function returns different values depending on its type: - -```rust -struct Foo {} - -impl Foo { - fn foo(self) -> Field { 1 } -} - -impl Foo { - fn foo(self) -> Field { 2 } -} - -fn main() { - let f1: Foo = Foo{}; - let f2: Foo = Foo{}; - assert(f1.foo() + f2.foo() == 3); -} -``` - -Also note that impls with the same method name defined in them cannot overlap. For example, if we already have `foo` defined for `Foo` and `Foo` like we do above, we cannot also define `foo` in an `impl Foo` since it would be ambiguous which version of `foo` to choose. - -```rust -// Including this impl in the same project as the above snippet would -// cause an overlapping impls error -impl Foo { - fn foo(self) -> Field { 3 } -} -``` - -## Lambdas - -Lambdas are anonymous functions. They follow the syntax of Rust - `|arg1, arg2, ..., argN| return_expression`. - -```rust -let add_50 = |val| val + 50; -assert(add_50(100) == 150); -``` - -See [Lambdas](./lambdas.md) for more details. - -## Attributes - -Attributes are metadata that can be applied to a function, using the following syntax: `#[attribute(value)]`. - -Supported attributes include: - -- **builtin**: the function is implemented by the compiler, for efficiency purposes. -- **deprecated**: mark the function as _deprecated_. Calling the function will generate a warning: `warning: use of deprecated function` -- **field**: Used to enable conditional compilation of code depending on the field size. See below for more details -- **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./unconstrained.md) and [NoirJS](../../reference/NoirJS/noir_js/index.md) for more details. -- **test**: mark the function as unit tests. See [Tests](../../getting_started/tooling/testing.md) for more details - -### Field Attribute - -The field attribute defines which field the function is compatible for. The function is conditionally compiled, under the condition that the field attribute matches the Noir native field. -The field can be defined implicitly, by using the name of the elliptic curve usually associated to it - for instance bn254, bls12_381 - or explicitly by using the field (prime) order, in decimal or hexadecimal form. -As a result, it is possible to define multiple versions of a function with each version specialized for a different field attribute. This can be useful when a function requires different parameters depending on the underlying elliptic curve. - -Example: we define the function `foo()` three times below. Once for the default Noir bn254 curve, once for the field $\mathbb F_{23}$, which will normally never be used by Noir, and once again for the bls12_381 curve. - -```rust -#[field(bn254)] -fn foo() -> u32 { - 1 -} - -#[field(23)] -fn foo() -> u32 { - 2 -} - -// This commented code would not compile as foo would be defined twice because it is the same field as bn254 -// #[field(21888242871839275222246405745257275088548364400416034343698204186575808495617)] -// fn foo() -> u32 { -// 2 -// } - -#[field(bls12_381)] -fn foo() -> u32 { - 3 -} -``` - -If the field name is not known to Noir, it will discard the function. Field names are case insensitive. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/generics.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/generics.md deleted file mode 100644 index 0c1c27a2221..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/generics.md +++ /dev/null @@ -1,106 +0,0 @@ ---- -title: Generics -description: Learn how to use Generics in Noir -keywords: [Noir, Rust, generics, functions, structs] -sidebar_position: 7 ---- - -Generics allow you to use the same functions with multiple different concrete data types. You can -read more about the concept of generics in the Rust documentation -[here](https://doc.rust-lang.org/book/ch10-01-syntax.html). - -Here is a trivial example showing the identity function that supports any type. In Rust, it is -common to refer to the most general type as `T`. We follow the same convention in Noir. - -```rust -fn id(x: T) -> T { - x -} -``` - -## In Structs - -Generics are useful for specifying types in structs. For example, we can specify that a field in a -struct will be of a certain generic type. In this case `value` is of type `T`. - -```rust -struct RepeatedValue { - value: T, - count: Field, -} - -impl RepeatedValue { - fn print(self) { - for _i in 0 .. self.count { - println(self.value); - } - } -} - -fn main() { - let repeated = RepeatedValue { value: "Hello!", count: 2 }; - repeated.print(); -} -``` - -The `print` function will print `Hello!` an arbitrary number of times, twice in this case. - -If we want to be generic over array lengths (which are type-level integers), we can use numeric -generics. Using these looks just like using regular generics, but these generics can resolve to -integers at compile-time, rather than resolving to types. Here's an example of a struct that is -generic over the size of the array it contains internally: - -```rust -struct BigInt { - limbs: [u32; N], -} - -impl BigInt { - // `N` is in scope of all methods in the impl - fn first(first: BigInt, second: BigInt) -> Self { - assert(first.limbs != second.limbs); - first - - fn second(first: BigInt, second: Self) -> Self { - assert(first.limbs != second.limbs); - second - } -} -``` - -## Calling functions on generic parameters - -Since a generic type `T` can represent any type, how can we call functions on the underlying type? -In other words, how can we go from "any type `T`" to "any type `T` that has certain methods available?" - -This is what [traits](../concepts/traits.md) are for in Noir. Here's an example of a function generic over -any type `T` that implements the `Eq` trait for equality: - -```rust -fn first_element_is_equal(array1: [T; N], array2: [T; N]) -> bool - where T: Eq -{ - if (array1.len() == 0) | (array2.len() == 0) { - true - } else { - array1[0] == array2[0] - } -} - -fn main() { - assert(first_element_is_equal([1, 2, 3], [1, 5, 6])); - - // We can use first_element_is_equal for arrays of any type - // as long as we have an Eq impl for the types we pass in - let array = [MyStruct::new(), MyStruct::new()]; - assert(array_eq(array, array, MyStruct::eq)); -} - -impl Eq for MyStruct { - fn eq(self, other: MyStruct) -> bool { - self.foo == other.foo - } -} -``` - -You can find more details on traits and trait implementations on the [traits page](../concepts/traits.md). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/globals.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/globals.md deleted file mode 100644 index 063a3d89248..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/globals.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -title: Global Variables -description: - Learn about global variables in Noir. Discover how - to declare, modify, and use them in your programs. -keywords: [noir programming language, globals, global variables, constants] -sidebar_position: 8 ---- - -## Globals - - -Noir supports global variables. The global's type can be inferred by the compiler entirely: - -```rust -global N = 5; // Same as `global N: Field = 5` - -global TUPLE = (3, 2); - -fn main() { - assert(N == 5); - assert(N == TUPLE.0 + TUPLE.1); -} -``` - -:::info - -Globals can be defined as any expression, so long as they don't depend on themselves - otherwise there would be a dependency cycle! For example: - -```rust -global T = foo(T); // dependency error -``` - -::: - - -If they are initialized to a literal integer, globals can be used to specify an array's length: - -```rust -global N: Field = 2; - -fn main(y : [Field; N]) { - assert(y[0] == y[1]) -} -``` - -A global from another module can be imported or referenced externally like any other name: - -```rust -global N = 20; - -fn main() { - assert(my_submodule::N != N); -} - -mod my_submodule { - global N: Field = 10; -} -``` - -When a global is used, Noir replaces the name with its definition on each occurrence. -This means globals defined using function calls will repeat the call each time they're used: - -```rust -global RESULT = foo(); - -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. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/lambdas.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/lambdas.md deleted file mode 100644 index be3c7e0b5ca..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/lambdas.md +++ /dev/null @@ -1,81 +0,0 @@ ---- -title: Lambdas -description: Learn how to use anonymous functions in Noir programming language. -keywords: [Noir programming language, lambda, closure, function, anonymous function] -sidebar_position: 9 ---- - -## Introduction - -Lambdas are anonymous functions. The syntax is `|arg1, arg2, ..., argN| return_expression`. - -```rust -let add_50 = |val| val + 50; -assert(add_50(100) == 150); -``` - -A block can be used as the body of a lambda, allowing you to declare local variables inside it: - -```rust -let cool = || { - let x = 100; - let y = 100; - x + y -} - -assert(cool() == 200); -``` - -## Closures - -Inside the body of a lambda, you can use variables defined in the enclosing function. Such lambdas are called **closures**. In this example `x` is defined inside `main` and is accessed from within the lambda: - -```rust -fn main() { - let x = 100; - let closure = || x + 150; - assert(closure() == 250); -} -``` - -## Passing closures to higher-order functions - -It may catch you by surprise that the following code fails to compile: - -```rust -fn foo(f: fn () -> Field) -> Field { - f() -} - -fn main() { - let (x, y) = (50, 50); - assert(foo(|| x + y) == 100); // error :( -} -``` - -The reason is that the closure's capture environment affects its type - we have a closure that captures two Fields and `foo` -expects a regular function as an argument - those are incompatible. -:::note - -Variables contained within the `||` are the closure's parameters, and the expression that follows it is the closure's body. The capture environment is comprised of any variables used in the closure's body that are not parameters. - -E.g. in |x| x + y, y would be a captured variable, but x would not be, since it is a parameter of the closure. - -::: -The syntax for the type of a closure is `fn[env](args) -> ret_type`, where `env` is the capture environment of the closure - -in this example that's `(Field, Field)`. - -The best solution in our case is to make `foo` generic over the environment type of its parameter, so that it can be called -with closures with any environment, as well as with regular functions: - -```rust -fn foo(f: fn[Env]() -> Field) -> Field { - f() -} - -fn main() { - let (x, y) = (50, 50); - assert(foo(|| x + y) == 100); // compiles fine - assert(foo(|| 60) == 60); // compiles fine -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/mutability.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/mutability.md deleted file mode 100644 index fdeef6a87c5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/mutability.md +++ /dev/null @@ -1,121 +0,0 @@ ---- -title: Mutability -description: - Learn about mutable variables in Noir. Discover how - to declare, modify, and use them in your programs. -keywords: [noir programming language, mutability in noir, mutable variables] -sidebar_position: 8 ---- - -Variables in noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned -to via an assignment expression. - -```rust -let x = 2; -x = 3; // error: x must be mutable to be assigned to - -let mut y = 3; -let y = 4; // OK -``` - -The `mut` modifier can also apply to patterns: - -```rust -let (a, mut b) = (1, 2); -a = 11; // error: a must be mutable to be assigned to -b = 12; // OK - -let mut (c, d) = (3, 4); -c = 13; // OK -d = 14; // OK - -// etc. -let MyStruct { x: mut y } = MyStruct { x: a }; -// y is now in scope -``` - -Note that mutability in noir is local and everything is passed by value, so if a called function -mutates its parameters then the parent function will keep the old value of the parameters. - -```rust -fn main() -> pub Field { - let x = 3; - helper(x); - x // x is still 3 -} - -fn helper(mut x: i32) { - x = 4; -} -``` - -## Non-local mutability - -Non-local mutability can be achieved through the mutable reference type `&mut T`: - -```rust -fn set_to_zero(x: &mut Field) { - *x = 0; -} - -fn main() { - let mut y = 42; - set_to_zero(&mut y); - assert(*y == 0); -} -``` - -When creating a mutable reference, the original variable being referred to (`y` in this -example) must also be mutable. Since mutable references are a reference type, they must -be explicitly dereferenced via `*` to retrieve the underlying value. Note that this yields -a copy of the value, so mutating this copy will not change the original value behind the -reference: - -```rust -fn main() { - let mut x = 1; - let x_ref = &mut x; - - let mut y = *x_ref; - let y_ref = &mut y; - - x = 2; - *x_ref = 3; - - y = 4; - *y_ref = 5; - - assert(x == 3); - assert(*x_ref == 3); - assert(y == 5); - assert(*y_ref == 5); -} -``` - -Note that types in Noir are actually deeply immutable so the copy that occurs when -dereferencing is only a conceptual copy - no additional constraints will occur. - -Mutable references can also be stored within structs. Note that there is also -no lifetime parameter on these unlike rust. This is because the allocated memory -always lasts the entire program - as if it were an array of one element. - -```rust -struct Foo { - x: &mut Field -} - -impl Foo { - fn incr(mut self) { - *self.x += 1; - } -} - -fn main() { - let foo = Foo { x: &mut 0 }; - foo.incr(); - assert(*foo.x == 1); -} -``` - -In general, you should avoid non-local & shared mutability unless it is needed. Sticking -to only local mutability will improve readability and potentially improve compiler optimizations as well. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/ops.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/ops.md deleted file mode 100644 index 60425cb8994..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/ops.md +++ /dev/null @@ -1,98 +0,0 @@ ---- -title: Logical Operations -description: - Learn about the supported arithmetic and logical operations in the Noir programming language. - Discover how to perform operations on private input types, integers, and booleans. -keywords: - [ - Noir programming language, - supported operations, - arithmetic operations, - logical operations, - predicate operators, - bitwise operations, - short-circuiting, - backend, - ] -sidebar_position: 3 ---- - -# Operations - -## Table of Supported Operations - -| Operation | Description | Requirements | -| :-------- | :------------------------------------------------------------: | -------------------------------------: | -| + | Adds two private input types together | Types must be private input | -| - | Subtracts two private input types together | Types must be private input | -| \* | Multiplies two private input types together | Types must be private input | -| / | Divides two private input types together | Types must be private input | -| ^ | XOR two private input types together | Types must be integer | -| & | AND two private input types together | Types must be integer | -| \| | OR two private input types together | Types must be integer | -| \<\< | Left shift an integer by another integer amount | Types must be integer | -| >> | Right shift an integer by another integer amount | Types must be integer | -| ! | Bitwise not of a value | Type must be integer or boolean | -| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | -| > | returns a bool if one value is more than the other | Upper bound must have a known bit size | -| >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | -| == | returns a bool if one value is equal to the other | Both types must not be constants | -| != | returns a bool if one value is not equal to the other | Both types must not be constants | - -### Predicate Operators - -`<,<=, !=, == , >, >=` are known as predicate/comparison operations because they compare two values. -This differs from the operations such as `+` where the operands are used in _computation_. - -### Bitwise Operations Example - -```rust -fn main(x : Field) { - let y = x as u32; - let z = y & y; -} -``` - -`z` is implicitly constrained to be the result of `y & y`. The `&` operand is used to denote bitwise -`&`. - -> `x & x` would not compile as `x` is a `Field` and not an integer type. - -### Logical Operators - -Noir has no support for the logical operators `||` and `&&`. This is because encoding the -short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can -use the bitwise operators `|` and `&` which operate identically for booleans, just without the -short-circuiting. - -```rust -let my_val = 5; - -let mut flag = 1; -if (my_val > 6) | (my_val == 0) { - flag = 0; -} -assert(flag == 1); - -if (my_val != 10) & (my_val < 50) { - flag = 0; -} -assert(flag == 0); -``` - -### Shorthand operators - -Noir shorthand operators for most of the above operators, namely `+=, -=, *=, /=, %=, &=, |=, ^=, <<=`, and `>>=`. These allow for more concise syntax. For example: - -```rust -let mut i = 0; -i = i + 1; -``` - -could be written as: - -```rust -let mut i = 0; -i += 1; -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/oracles.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/oracles.md deleted file mode 100644 index 2e6a6818d48..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/oracles.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: Oracles -description: Dive into how Noir supports Oracles via RPC calls, and learn how to declare an Oracle in Noir with our comprehensive guide. -keywords: - - Noir - - Oracles - - RPC Calls - - Unconstrained Functions - - Programming - - Blockchain -sidebar_position: 6 ---- - -Noir has support for Oracles via RPC calls. This means Noir will make an RPC call and use the return value for proof generation. - -Since Oracles are not resolved by Noir, they are [`unconstrained` functions](./unconstrained.md) - -You can declare an Oracle through the `#[oracle()]` flag. Example: - -```rust -#[oracle(get_number_sequence)] -unconstrained fn get_number_sequence(_size: Field) -> [Field] {} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/shadowing.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/shadowing.md deleted file mode 100644 index 5ce6130d201..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/shadowing.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Shadowing -sidebar_position: 12 ---- - -Noir allows for inheriting variables' values and re-declaring them with the same name similar to Rust, known as shadowing. - -For example, the following function is valid in Noir: - -```rust -fn main() { - let x = 5; - - { - let x = x * 2; - assert (x == 10); - } - - assert (x == 5); -} -``` - -In this example, a variable x is first defined with the value 5. - -The local scope that follows shadows the original x, i.e. creates a local mutable x based on the value of the original x. It is given a value of 2 times the original x. - -When we return to the main scope, x once again refers to just the original x, which stays at the value of 5. - -## Temporal mutability - -One way that shadowing is useful, in addition to ergonomics across scopes, is for temporarily mutating variables. - -```rust -fn main() { - let age = 30; - // age = age + 5; // Would error as `age` is immutable by default. - - let mut age = age + 5; // Temporarily mutates `age` with a new value. - - let age = age; // Locks `age`'s mutability again. - - assert (age == 35); -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/traits.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/traits.md deleted file mode 100644 index ef1445a5907..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/traits.md +++ /dev/null @@ -1,389 +0,0 @@ ---- -title: Traits -description: - Traits in Noir can be used to abstract out a common interface for functions across - several data types. -keywords: [noir programming language, traits, interfaces, generic, protocol] -sidebar_position: 14 ---- - -## Overview - -Traits in Noir are a useful abstraction similar to interfaces or protocols in other languages. Each trait defines -the interface of several methods contained within the trait. Types can then implement this trait by providing -implementations for these methods. For example in the program: - -```rust -struct Rectangle { - width: Field, - height: Field, -} - -impl Rectangle { - fn area(self) -> Field { - self.width * self.height - } -} - -fn log_area(r: Rectangle) { - println(r.area()); -} -``` - -We have a function `log_area` to log the area of a `Rectangle`. Now how should we change the program if we want this -function to work on `Triangle`s as well?: - -```rust -struct Triangle { - width: Field, - height: Field, -} - -impl Triangle { - fn area(self) -> Field { - self.width * self.height / 2 - } -} -``` - -Making `log_area` generic over all types `T` would be invalid since not all types have an `area` method. Instead, we can -introduce a new `Area` trait and make `log_area` generic over all types `T` that implement `Area`: - -```rust -trait Area { - fn area(self) -> Field; -} - -fn log_area(shape: T) where T: Area { - println(shape.area()); -} -``` - -We also need to explicitly implement `Area` for `Rectangle` and `Triangle`. We can do that by changing their existing -impls slightly. Note that the parameter types and return type of each of our `area` methods must match those defined -by the `Area` trait. - -```rust -impl Area for Rectangle { - fn area(self) -> Field { - self.width * self.height - } -} - -impl Area for Triangle { - fn area(self) -> Field { - self.width * self.height / 2 - } -} -``` - -Now we have a working program that is generic over any type of Shape that is used! Others can even use this program -as a library with their own types - such as `Circle` - as long as they also implement `Area` for these types. - -## Where Clauses - -As seen in `log_area` above, when we want to create a function or method that is generic over any type that implements -a trait, we can add a where clause to the generic function. - -```rust -fn log_area(shape: T) where T: Area { - println(shape.area()); -} -``` - -It is also possible to apply multiple trait constraints on the same variable at once by combining traits with the `+` -operator. Similarly, we can have multiple trait constraints by separating each with a comma: - -```rust -fn foo(elements: [T], thing: U) where - T: Default + Add + Eq, - U: Bar, -{ - let mut sum = T::default(); - - for element in elements { - sum += element; - } - - if sum == T::default() { - thing.bar(); - } -} -``` - -## Generic Implementations - -You can add generics to a trait implementation by adding the generic list after the `impl` keyword: - -```rust -trait Second { - fn second(self) -> Field; -} - -impl Second for (T, Field) { - fn second(self) -> Field { - self.1 - } -} -``` - -You can also implement a trait for every type this way: - -```rust -trait Debug { - fn debug(self); -} - -impl Debug for T { - fn debug(self) { - println(self); - } -} - -fn main() { - 1.debug(); -} -``` - -### Generic Trait Implementations With Where Clauses - -Where clauses can also be placed on trait implementations themselves to restrict generics in a similar way. -For example, while `impl Foo for T` implements the trait `Foo` for every type, `impl Foo for T where T: Bar` -will implement `Foo` only for types that also implement `Bar`. This is often used for implementing generic types. -For example, here is the implementation for array equality: - -```rust -impl Eq for [T; N] where T: Eq { - // Test if two arrays have the same elements. - // Because both arrays must have length N, we know their lengths already match. - fn eq(self, other: Self) -> bool { - let mut result = true; - - for i in 0 .. self.len() { - // The T: Eq constraint is needed to call == on the array elements here - result &= self[i] == other[i]; - } - - result - } -} -``` - -## Generic Traits - -Traits themselves can also be generic by placing the generic arguments after the trait name. These generics are in -scope of every item within the trait. - -```rust -trait Into { - // Convert `self` to type `T` - fn into(self) -> T; -} -``` - -When implementing generic traits the generic arguments of the trait must be specified. This is also true anytime -when referencing a generic trait (e.g. in a `where` clause). - -```rust -struct MyStruct { - array: [Field; 2], -} - -impl Into<[Field; 2]> for MyStruct { - fn into(self) -> [Field; 2] { - self.array - } -} - -fn as_array(x: T) -> [Field; 2] - where T: Into<[Field; 2]> -{ - x.into() -} - -fn main() { - let array = [1, 2]; - let my_struct = MyStruct { array }; - - assert_eq(as_array(my_struct), array); -} -``` - -## Trait Methods With No `self` - -A trait can contain any number of methods, each of which have access to the `Self` type which represents each type -that eventually implements the trait. Similarly, the `self` variable is available as well but is not required to be used. -For example, we can define a trait to create a default value for a type. This trait will need to return the `Self` type -but doesn't need to take any parameters: - -```rust -trait Default { - fn default() -> Self; -} -``` - -Implementing this trait can be done similarly to any other trait: - -```rust -impl Default for Field { - fn default() -> Field { - 0 - } -} - -struct MyType {} - -impl Default for MyType { - fn default() -> Field { - MyType {} - } -} -``` - -However, since there is no `self` parameter, we cannot call it via the method call syntax `object.method()`. -Instead, we'll need to refer to the function directly. This can be done either by referring to the -specific impl `MyType::default()` or referring to the trait itself `Default::default()`. In the later -case, type inference determines the impl that is selected. - -```rust -let my_struct = MyStruct::default(); - -let x: Field = Default::default(); -let result = x + Default::default(); -``` - -:::warning - -```rust -let _ = Default::default(); -``` - -If type inference cannot select which impl to use because of an ambiguous `Self` type, an impl will be -arbitrarily selected. This occurs most often when the result of a trait function call with no parameters -is unused. To avoid this, when calling a trait function with no `self` or `Self` parameters or return type, -always refer to it via the implementation type's namespace - e.g. `MyType::default()`. -This is set to change to an error in future Noir versions. - -::: - -## Default Method Implementations - -A trait can also have default implementations of its methods by giving a body to the desired functions. -Note that this body must be valid for all types that may implement the trait. As a result, the only -valid operations on `self` will be operations valid for any type or other operations on the trait itself. - -```rust -trait Numeric { - fn add(self, other: Self) -> Self; - - // Default implementation of double is (self + self) - fn double(self) -> Self { - self.add(self) - } -} -``` - -When implementing a trait with default functions, a type may choose to implement only the required functions: - -```rust -impl Numeric for Field { - fn add(self, other: Field) -> Field { - self + other - } -} -``` - -Or it may implement the optional methods as well: - -```rust -impl Numeric for u32 { - fn add(self, other: u32) -> u32 { - self + other - } - - fn double(self) -> u32 { - self * 2 - } -} -``` - -## Impl Specialization - -When implementing traits for a generic type it is possible to implement the trait for only a certain combination -of generics. This can be either as an optimization or because those specific generics are required to implement the trait. - -```rust -trait Sub { - fn sub(self, other: Self) -> Self; -} - -struct NonZero { - value: T, -} - -impl Sub for NonZero { - fn sub(self, other: Self) -> Self { - let value = self.value - other.value; - assert(value != 0); - NonZero { value } - } -} -``` - -## Overlapping Implementations - -Overlapping implementations are disallowed by Noir to ensure Noir's decision on which impl to select is never ambiguous. -This means if a trait `Foo` is already implemented -by a type `Bar` for all `T`, then we cannot also have a separate impl for `Bar` (or any other -type argument). Similarly, if there is an impl for all `T` such as `impl Debug for T`, we cannot create -any more impls to `Debug` for other types since it would be ambiguous which impl to choose for any given -method call. - -```rust -trait Trait {} - -// Previous impl defined here -impl Trait for (A, B) {} - -// error: Impl for type `(Field, Field)` overlaps with existing impl -impl Trait for (Field, Field) {} -``` - -## Trait Coherence - -Another restriction on trait implementations is coherence. This restriction ensures other crates cannot create -impls that may overlap with other impls, even if several unrelated crates are used as dependencies in the same -program. - -The coherence restriction is: to implement a trait, either the trait itself or the object type must be declared -in the crate the impl is in. - -In practice this often comes up when using types provided by libraries. If a library provides a type `Foo` that does -not implement a trait in the standard library such as `Default`, you may not `impl Default for Foo` in your own crate. -While restrictive, this prevents later issues or silent changes in the program if the `Foo` library later added its -own impl for `Default`. If you are a user of the `Foo` library in this scenario and need a trait not implemented by the -library your choices are to either submit a patch to the library or use the newtype pattern. - -### The Newtype Pattern - -The newtype pattern gets around the coherence restriction by creating a new wrapper type around the library type -that we cannot create `impl`s for. Since the new wrapper type is defined in our current crate, we can create -impls for any trait we need on it. - -```rust -struct Wrapper { - foo: dep::some_library::Foo, -} - -impl Default for Wrapper { - fn default() -> Wrapper { - Wrapper { - foo: dep::some_library::Foo::new(), - } - } -} -``` - -Since we have an impl for our own type, the behavior of this code will not change even if `some_library` is updated -to provide its own `impl Default for Foo`. The downside of this pattern is that it requires extra wrapping and -unwrapping of values when converting to and from the `Wrapper` and `Foo` types. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/unconstrained.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/unconstrained.md deleted file mode 100644 index 96f824c5e42..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/unconstrained.md +++ /dev/null @@ -1,99 +0,0 @@ ---- -title: Unconstrained Functions -description: "Learn about what unconstrained functions in Noir are, how to use them and when you'd want to." - -keywords: [Noir programming language, unconstrained, open] -sidebar_position: 5 ---- - -Unconstrained functions are functions which do not constrain any of the included computation and allow for non-deterministic computation. - -## Why? - -Zero-knowledge (ZK) domain-specific languages (DSL) enable developers to generate ZK proofs from their programs by compiling code down to the constraints of an NP complete language (such as R1CS or PLONKish languages). However, the hard bounds of a constraint system can be very limiting to the functionality of a ZK DSL. - -Enabling a circuit language to perform unconstrained execution is a powerful tool. Said another way, unconstrained execution lets developers generate witnesses from code that does not generate any constraints. Being able to execute logic outside of a circuit is critical for both circuit performance and constructing proofs on information that is external to a circuit. - -Fetching information from somewhere external to a circuit can also be used to enable developers to improve circuit efficiency. - -A ZK DSL does not just prove computation, but proves that some computation was handled correctly. Thus, it is necessary that when we switch from performing some operation directly inside of a circuit to inside of an unconstrained environment that the appropriate constraints are still laid down elsewhere in the circuit. - -## Example - -An in depth example might help drive the point home. This example comes from the excellent [post](https://discord.com/channels/1113924620781883405/1124022445054111926/1128747641853972590) by Tom in the Noir Discord. - -Let's look at how we can optimize a function to turn a `u72` into an array of `u8`s. - -```rust -fn main(num: u72) -> pub [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8)) as u72 & 0xff) as u8; - } - - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 91 -Backend circuit size: 3619 -``` - -A lot of the operations in this function are optimized away by the compiler (all the bit-shifts turn into divisions by constants). However we can save a bunch of gates by casting to u8 a bit earlier. This automatically truncates the bit-shifted value to fit in a u8 which allows us to remove the AND against 0xff. This saves us ~480 gates in total. - -```rust -fn main(num: u72) -> pub [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8)) as u8; - } - - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 75 -Backend circuit size: 3143 -``` - -Those are some nice savings already but we can do better. This code is all constrained so we're proving every step of calculating out using num, but we don't actually care about how we calculate this, just that it's correct. This is where brillig comes in. - -It turns out that truncating a u72 into a u8 is hard to do inside a snark, each time we do as u8 we lay down 4 ACIR opcodes which get converted into multiple gates. It's actually much easier to calculate num from out than the other way around. All we need to do is multiply each element of out by a constant and add them all together, both relatively easy operations inside a snark. - -We can then run u72_to_u8 as unconstrained brillig code in order to calculate out, then use that result in our constrained function and assert that if we were to do the reverse calculation we'd get back num. This looks a little like the below: - -```rust -fn main(num: u72) -> pub [u8; 8] { - let out = u72_to_u8(num); - - let mut reconstructed_num: u72 = 0; - for i in 0..8 { - reconstructed_num += (out[i] as u72 << (56 - (8 * i))); - } - assert(num == reconstructed_num); - out -} - -unconstrained fn u72_to_u8(num: u72) -> [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8))) as u8; - } - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 78 -Backend circuit size: 2902 -``` - -This ends up taking off another ~250 gates from our circuit! We've ended up with more ACIR opcodes than before but they're easier for the backend to prove (resulting in fewer gates). - -Generally we want to use brillig whenever there's something that's easy to verify but hard to compute within the circuit. For example, if you wanted to calculate a square root of a number it'll be a much better idea to calculate this in brillig and then assert that if you square the result you get back your number. - -## Break and Continue - -In addition to loops over runtime bounds, `break` and `continue` are also available in unconstrained code. See [break and continue](../concepts/control_flow.md#break-and-continue) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/_category_.json deleted file mode 100644 index 1debcfe7675..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Modules, Packages and Crates", - "position": 2, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/crates_and_packages.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/crates_and_packages.md deleted file mode 100644 index 95ee9f52ab2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/crates_and_packages.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Crates and Packages -description: Learn how to use Crates and Packages in your Noir project -keywords: [Nargo, dependencies, package management, crates, package] -sidebar_position: 0 ---- - -## Crates - -A crate is the smallest amount of code that the Noir compiler considers at a time. -Crates can contain modules, and the modules may be defined in other files that get compiled with the crate, as we’ll see in the coming sections. - -### Crate Types - -A Noir crate can come in several forms: binaries, libraries or contracts. - -#### Binaries - -_Binary crates_ are programs which you can compile to an ACIR circuit which you can then create proofs against. Each must have a function called `main` that defines the ACIR circuit which is to be proved. - -#### Libraries - -_Library crates_ don't have a `main` function and they don't compile down to ACIR. Instead they define functionality intended to be shared with multiple projects, and eventually included in a binary crate. - -#### Contracts - -Contract crates are similar to binary crates in that they compile to ACIR which you can create proofs against. They are different in that they do not have a single `main` function, but are a collection of functions to be deployed to the [Aztec network](https://aztec.network). You can learn more about the technical details of Aztec in the [monorepo](https://github.com/AztecProtocol/aztec-packages) or contract [examples](https://github.com/AztecProtocol/aztec-packages/tree/master/noir-projects/noir-contracts/contracts). - -### Crate Root - -Every crate has a root, which is the source file that the compiler starts, this is also known as the root module. The Noir compiler does not enforce any conditions on the name of the file which is the crate root, however if you are compiling via Nargo the crate root must be called `lib.nr` or `main.nr` for library or binary crates respectively. - -## Packages - -A Nargo _package_ is a collection of one of more crates that provides a set of functionality. A package must include a Nargo.toml file. - -A package _must_ contain either a library or a binary crate, but not both. - -### Differences from Cargo Packages - -One notable difference between Rust's Cargo and Noir's Nargo is that while Cargo allows a package to contain an unlimited number of binary crates and a single library crate, Nargo currently only allows a package to contain a single crate. - -In future this restriction may be lifted to allow a Nargo package to contain both a binary and library crate or multiple binary crates. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/dependencies.md deleted file mode 100644 index 2c028d85853..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/dependencies.md +++ /dev/null @@ -1,124 +0,0 @@ ---- -title: Dependencies -description: - Learn how to specify and manage dependencies in Nargo, allowing you to upload packages to GitHub - and use them easily in your project. -keywords: [Nargo, dependencies, GitHub, package management, versioning] -sidebar_position: 1 ---- - -Nargo allows you to upload packages to GitHub and use them as dependencies. - -## Specifying a dependency - -Specifying a dependency requires a tag to a specific commit and the git url to the url containing -the package. - -Currently, there are no requirements on the tag contents. If requirements are added, it would follow -semver 2.0 guidelines. - -> Note: Without a `tag` , there would be no versioning and dependencies would change each time you -> compile your project. - -For example, to add the [ecrecover-noir library](https://github.com/colinnielsen/ecrecover-noir) to your project, add it to `Nargo.toml`: - -```toml -# Nargo.toml - -[dependencies] -ecrecover = {tag = "v0.8.0", git = "https://github.com/colinnielsen/ecrecover-noir"} -``` - -If the module is in a subdirectory, you can define a subdirectory in your git repository, for example: - -```toml -# Nargo.toml - -[dependencies] -easy_private_token_contract = {tag ="v0.1.0-alpha62", git = "https://github.com/AztecProtocol/aztec-packages", directory = "noir-contracts/contracts/easy_private_token_contract"} -``` - -## Specifying a local dependency - -You can also specify dependencies that are local to your machine. - -For example, this file structure has a library and binary crate - -```tree -├── binary_crate -│   ├── Nargo.toml -│   └── src -│   └── main.nr -└── lib_a - ├── Nargo.toml - └── src - └── lib.nr -``` - -Inside of the binary crate, you can specify: - -```toml -# Nargo.toml - -[dependencies] -lib_a = { path = "../lib_a" } -``` - -## Importing dependencies - -You can import a dependency to a Noir file using the following syntax. For example, to import the -ecrecover-noir library and local lib_a referenced above: - -```rust -use dep::ecrecover; -use dep::lib_a; -``` - -You can also import only the specific parts of dependency that you want to use, like so: - -```rust -use dep::std::hash::sha256; -use dep::std::scalar_mul::fixed_base_embedded_curve; -``` - -Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you -can import multiple items in the same line by enclosing them in curly braces: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; -``` - -We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. - -Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. - -## Dependencies of Dependencies - -Note that when you import a dependency, you also get access to all of the dependencies of that package. - -For example, the [phy_vector](https://github.com/resurgencelabs/phy_vector) library imports an [fraction](https://github.com/resurgencelabs/fraction) library. If you're importing the phy_vector library, then you can access the functions in fractions library like so: - -```rust -use dep::phy_vector; - -fn main(x : Field, y : pub Field) { - //... - let f = phy_vector::fraction::toFraction(true, 2, 1); - //... -} -``` - -## Available Libraries - -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). - -Some libraries that are available today include: - -- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library -- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) -- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers -- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address -- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees -- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir -- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/modules.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/modules.md deleted file mode 100644 index ae822a1cff4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/modules.md +++ /dev/null @@ -1,105 +0,0 @@ ---- -title: Modules -description: - Learn how to organize your files using modules in Noir, following the same convention as Rust's - module system. Examples included. -keywords: [Noir, Rust, modules, organizing files, sub-modules] -sidebar_position: 2 ---- - -Noir's module system follows the same convention as the _newer_ version of Rust's module system. - -## Purpose of Modules - -Modules are used to organize files. Without modules all of your code would need to live in a single -file. In Noir, the compiler does not automatically scan all of your files to detect modules. This -must be done explicitly by the developer. - -## Examples - -### Importing a module in the crate root - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::hello_world(); -} -``` - -Filename : `src/foo.nr` - -```rust -fn from_foo() {} -``` - -In the above snippet, the crate root is the `src/main.nr` file. The compiler sees the module -declaration `mod foo` which prompts it to look for a foo.nr file. - -Visually this module hierarchy looks like the following : - -``` -crate - ├── main - │ - └── foo - └── from_foo - -``` - -### Importing a module throughout the tree - -All modules are accessible from the `crate::` namespace. - -``` -crate - ├── bar - ├── foo - └── main - -``` - -In the above snippet, if `bar` would like to use functions in `foo`, it can do so by `use crate::foo::function_name`. - -### Sub-modules - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::from_foo(); -} -``` - -Filename : `src/foo.nr` - -```rust -mod bar; -fn from_foo() {} -``` - -Filename : `src/foo/bar.nr` - -```rust -fn from_bar() {} -``` - -In the above snippet, we have added an extra module to the module tree; `bar`. `bar` is a submodule -of `foo` hence we declare bar in `foo.nr` with `mod bar`. Since `foo` is not the crate root, the -compiler looks for the file associated with the `bar` module in `src/foo/bar.nr` - -Visually the module hierarchy looks as follows: - -``` -crate - ├── main - │ - └── foo - ├── from_foo - └── bar - └── from_bar -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/workspaces.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/workspaces.md deleted file mode 100644 index 513497f12bf..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/workspaces.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Workspaces -sidebar_position: 3 ---- - -Workspaces are a feature of nargo that allow you to manage multiple related Noir packages in a single repository. A workspace is essentially a group of related projects that share common build output directories and configurations. - -Each Noir project (with it's own Nargo.toml file) can be thought of as a package. Each package is expected to contain exactly one "named circuit", being the "name" defined in Nargo.toml with the program logic defined in `./src/main.nr`. - -For a project with the following structure: - -```tree -├── crates -│ ├── a -│ │ ├── Nargo.toml -│ │ └── Prover.toml -│ │ └── src -│ │ └── main.nr -│ └── b -│ ├── Nargo.toml -│ └── Prover.toml -│ └── src -│ └── main.nr -│ -└── Nargo.toml -``` - -You can define a workspace in Nargo.toml like so: - -```toml -[workspace] -members = ["crates/a", "crates/b"] -default-member = "crates/a" -``` - -`members` indicates which packages are included in the workspace. As such, all member packages of a workspace will be processed when the `--workspace` flag is used with various commands or if a `default-member` is not specified. - -`default-member` indicates which package various commands process by default. - -Libraries can be defined in a workspace. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. - -Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/_category_.json deleted file mode 100644 index af04c0933fd..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Standard Library", - "position": 1, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/bigint.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/bigint.md deleted file mode 100644 index da6a7cdfd81..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/bigint.md +++ /dev/null @@ -1,119 +0,0 @@ ---- -title: Big Integers -description: How to use big integers from Noir standard library -keywords: - [ - Big Integer, - Noir programming language, - Noir libraries, - ] ---- - -The BigInt module in the standard library exposes some class of integers which do not fit (well) into a Noir native field. It implements modulo arithmetic, modulo a 'big' prime number. - -:::note - -The module can currently be considered as `Field`s with fixed modulo sizes used by a set of elliptic curves, in addition to just the native curve. [More work](https://github.com/noir-lang/noir/issues/510) is needed to achieve arbitrarily sized big integers. - -::: - -Currently 6 classes of integers (i.e 'big' prime numbers) are available in the module, namely: - -- BN254 Fq: Bn254Fq -- BN254 Fr: Bn254Fr -- Secp256k1 Fq: Secpk1Fq -- Secp256k1 Fr: Secpk1Fr -- Secp256r1 Fr: Secpr1Fr -- Secp256r1 Fq: Secpr1Fq - -Where XXX Fq and XXX Fr denote respectively the order of the base and scalar field of the (usual) elliptic curve XXX. -For instance the big integer 'Secpk1Fq' in the standard library refers to integers modulo $2^{256}-2^{32}-977$. - -Feel free to explore the source code for the other primes: - -```rust title="big_int_definition" showLineNumbers -struct BigInt { - pointer: u32, - modulus: u32, -} -``` -> Source code: noir_stdlib/src/bigint.nr#L16-L21 - - -## Example usage - -A common use-case is when constructing a big integer from its bytes representation, and performing arithmetic operations on it: - -```rust title="big_int_example" showLineNumbers -fn big_int_example(x: u8, y: u8) { - let a = Secpk1Fq::from_le_bytes(&[x, y, 0, 45, 2]); - let b = Secpk1Fq::from_le_bytes(&[y, x, 9]); - let c = (a + b) * b / a; - let d = c.to_le_bytes(); - println(d[0]); -} -``` -> Source code: test_programs/execution_success/bigint/src/main.nr#L20-L28 - - -## Methods - -The available operations for each big integer are: - -### from_le_bytes - -Construct a big integer from its little-endian bytes representation. Example: - -```rust - let a = Secpk1Fq::from_le_bytes(&[x, y, 0, 45, 2]); - ``` - -Sure, here's the formatted version of the remaining methods: - -### to_le_bytes - -Return the little-endian bytes representation of a big integer. Example: - -```rust -let bytes = a.to_le_bytes(); -``` - -### add - -Add two big integers. Example: - -```rust -let sum = a + b; -``` - -### sub - -Subtract two big integers. Example: - -```rust -let difference = a - b; -``` - -### mul - -Multiply two big integers. Example: - -```rust -let product = a * b; -``` - -### div - -Divide two big integers. Note that division is field division and not euclidean division. Example: - -```rust -let quotient = a / b; -``` - -### eq - -Compare two big integers. Example: - -```rust -let are_equal = a == b; -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/black_box_fns.md deleted file mode 100644 index e8b62f21d4e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/black_box_fns.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Black Box Functions -description: Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. -keywords: [noir, black box functions] ---- - -Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. This makes certain zk-snark unfriendly computations cheaper than if they were implemented in Noir. - -The ACVM spec defines a set of blackbox functions which backends will be expected to implement. This allows backends to use optimized implementations of these constraints if they have them, however they may also fallback to less efficient naive implementations if not. - -## Function list - -Here is a list of the current black box functions: - -- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) -- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) -- [Blake3](./cryptographic_primitives/hashes.mdx#blake3) -- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash) -- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx) -- AND -- XOR -- RANGE -- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion.md) - -Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. - -You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/noir/blob/master/acvm-repo/acir/src/circuit/black_box_functions.rs). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/bn254.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/bn254.md deleted file mode 100644 index 3294f005dbb..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/bn254.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: Bn254 Field Library ---- - -Noir provides a module in standard library with some optimized functions for bn254 Fr in `std::field::bn254`. - -## decompose - -```rust -fn decompose(x: Field) -> (Field, Field) {} -``` - -Decomposes a single field into two fields, low and high. The low field contains the lower 16 bytes of the input field and the high field contains the upper 16 bytes of the input field. Both field results are range checked to 128 bits. - - -## assert_gt - -```rust -fn assert_gt(a: Field, b: Field) {} -``` - -Asserts that a > b. This will generate less constraints than using `assert(gt(a, b))`. - -## assert_lt - -```rust -fn assert_lt(a: Field, b: Field) {} -``` - -Asserts that a < b. This will generate less constraints than using `assert(lt(a, b))`. - -## gt - -```rust -fn gt(a: Field, b: Field) -> bool {} -``` - -Returns true if a > b. - -## lt - -```rust -fn lt(a: Field, b: Field) -> bool {} -``` - -Returns true if a < b. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/containers/boundedvec.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/containers/boundedvec.md deleted file mode 100644 index ce4529f6e57..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/containers/boundedvec.md +++ /dev/null @@ -1,326 +0,0 @@ ---- -title: Bounded Vectors -keywords: [noir, vector, bounded vector, slice] -sidebar_position: 1 ---- - -A `BoundedVec` is a growable storage similar to a `Vec` except that it -is bounded with a maximum possible length. Unlike `Vec`, `BoundedVec` is not implemented -via slices and thus is not subject to the same restrictions slices are (notably, nested -slices - and thus nested vectors as well - are disallowed). - -Since a BoundedVec is backed by a normal array under the hood, growing the BoundedVec by -pushing an additional element is also more efficient - the length only needs to be increased -by one. - -For these reasons `BoundedVec` should generally be preferred over `Vec` when there -is a reasonable maximum bound that can be placed on the vector. - -Example: - -```rust -let mut vector: BoundedVec = BoundedVec::new(); -for i in 0..5 { - vector.push(i); -} -assert(vector.len() == 5); -assert(vector.max_len() == 10); -``` - -## Methods - -### new - -```rust -pub fn new() -> Self -``` - -Creates a new, empty vector of length zero. - -Since this container is backed by an array internally, it still needs an initial value -to give each element. To resolve this, each element is zeroed internally. This value -is guaranteed to be inaccessible unless `get_unchecked` is used. - -Example: - -```rust -let empty_vector: BoundedVec = BoundedVec::new(); -assert(empty_vector.len() == 0); -``` - -Note that whenever calling `new` the maximum length of the vector should always be specified -via a type signature: - -```rust title="new_example" showLineNumbers -fn foo() -> BoundedVec { - // Ok! MaxLen is specified with a type annotation - let v1: BoundedVec = BoundedVec::new(); - let v2 = BoundedVec::new(); - - // Ok! MaxLen is known from the type of foo's return value - v2 -} - -fn bad() { - let mut v3 = BoundedVec::new(); - - // Not Ok! We don't know if v3's MaxLen is at least 1, and the compiler often infers 0 by default. - v3.push(5); -} -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L11-L27 - - -This defaulting of `MaxLen` (and numeric generics in general) to zero may change in future noir versions -but for now make sure to use type annotations when using bounded vectors. Otherwise, you will receive a constraint failure at runtime when the vec is pushed to. - -### get - -```rust -pub fn get(mut self: Self, index: u64) -> T { -``` - -Retrieves an element from the vector at the given index, starting from zero. - -If the given index is equal to or greater than the length of the vector, this -will issue a constraint failure. - -Example: - -```rust -fn foo(v: BoundedVec) { - let first = v.get(0); - let last = v.get(v.len() - 1); - assert(first != last); -} -``` - -### get_unchecked - -```rust -pub fn get_unchecked(mut self: Self, index: u64) -> T { -``` - -Retrieves an element from the vector at the given index, starting from zero, without -performing a bounds check. - -Since this function does not perform a bounds check on length before accessing the element, -it is unsafe! Use at your own risk! - -Example: - -```rust title="get_unchecked_example" showLineNumbers -fn sum_of_first_three(v: BoundedVec) -> u32 { - // Always ensure the length is larger than the largest - // index passed to get_unchecked - assert(v.len() > 2); - let first = v.get_unchecked(0); - let second = v.get_unchecked(1); - let third = v.get_unchecked(2); - first + second + third -} -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L54-L64 - - - -### push - -```rust -pub fn push(&mut self, elem: T) { -``` - -Pushes an element to the end of the vector. This increases the length -of the vector by one. - -Panics if the new length of the vector will be greater than the max length. - -Example: - -```rust title="bounded-vec-push-example" showLineNumbers -let mut v: BoundedVec = BoundedVec::new(); - - v.push(1); - v.push(2); - - // Panics with failed assertion "push out of bounds" - v.push(3); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L68-L76 - - -### pop - -```rust -pub fn pop(&mut self) -> T -``` - -Pops the element at the end of the vector. This will decrease the length -of the vector by one. - -Panics if the vector is empty. - -Example: - -```rust title="bounded-vec-pop-example" showLineNumbers -let mut v: BoundedVec = BoundedVec::new(); - v.push(1); - v.push(2); - - let two = v.pop(); - let one = v.pop(); - - assert(two == 2); - assert(one == 1); - // error: cannot pop from an empty vector - // let _ = v.pop(); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L81-L93 - - -### len - -```rust -pub fn len(self) -> u64 { -``` - -Returns the current length of this vector - -Example: - -```rust title="bounded-vec-len-example" showLineNumbers -let mut v: BoundedVec = BoundedVec::new(); - assert(v.len() == 0); - - v.push(100); - assert(v.len() == 1); - - v.push(200); - v.push(300); - v.push(400); - assert(v.len() == 4); - - let _ = v.pop(); - let _ = v.pop(); - assert(v.len() == 2); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L98-L113 - - -### max_len - -```rust -pub fn max_len(_self: BoundedVec) -> u64 { -``` - -Returns the maximum length of this vector. This is always -equal to the `MaxLen` parameter this vector was initialized with. - -Example: - -```rust title="bounded-vec-max-len-example" showLineNumbers -let mut v: BoundedVec = BoundedVec::new(); - - assert(v.max_len() == 5); - v.push(10); - assert(v.max_len() == 5); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L118-L124 - - -### storage - -```rust -pub fn storage(self) -> [T; MaxLen] { -``` - -Returns the internal array within this vector. -Since arrays in Noir are immutable, mutating the returned storage array will not mutate -the storage held internally by this vector. - -Note that uninitialized elements may be zeroed out! - -Example: - -```rust title="bounded-vec-storage-example" showLineNumbers -let mut v: BoundedVec = BoundedVec::new(); - - assert(v.storage() == [0, 0, 0, 0, 0]); - - v.push(57); - assert(v.storage() == [57, 0, 0, 0, 0]); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L129-L136 - - -### extend_from_array - -```rust -pub fn extend_from_array(&mut self, array: [T; Len]) -``` - -Pushes each element from the given array to this vector. - -Panics if pushing each element would cause the length of this vector -to exceed the maximum length. - -Example: - -```rust title="bounded-vec-extend-from-array-example" showLineNumbers -let mut vec: BoundedVec = BoundedVec::new(); - vec.extend_from_array([2, 4]); - - assert(vec.len == 2); - assert(vec.get(0) == 2); - assert(vec.get(1) == 4); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L141-L148 - - -### extend_from_bounded_vec - -```rust -pub fn extend_from_bounded_vec(&mut self, vec: BoundedVec) -``` - -Pushes each element from the other vector to this vector. The length of -the other vector is left unchanged. - -Panics if pushing each element would cause the length of this vector -to exceed the maximum length. - -Example: - -```rust title="bounded-vec-extend-from-bounded-vec-example" showLineNumbers -let mut v1: BoundedVec = BoundedVec::new(); - let mut v2: BoundedVec = BoundedVec::new(); - - v2.extend_from_array([1, 2, 3]); - v1.extend_from_bounded_vec(v2); - - assert(v1.storage() == [1, 2, 3, 0, 0]); - assert(v2.storage() == [1, 2, 3, 0, 0, 0, 0]); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L153-L162 - - -### any - -```rust -pub fn any(self, predicate: fn[Env](T) -> bool) -> bool -``` - -Returns true if the given predicate returns true for any element -in this vector. - -Example: - -```rust title="bounded-vec-any-example" showLineNumbers -let mut v: BoundedVec = BoundedVec::new(); - v.extend_from_array([2, 4, 6]); - - let all_even = !v.any(|elem: u32| elem % 2 != 0); - assert(all_even); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L229-L235 - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/containers/hashmap.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/containers/hashmap.md deleted file mode 100644 index 91604af765d..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/containers/hashmap.md +++ /dev/null @@ -1,569 +0,0 @@ ---- -title: HashMap -keywords: [noir, map, hash, hashmap] -sidebar_position: 1 ---- - -`HashMap` is used to efficiently store and look up key-value pairs. - -`HashMap` is a bounded type which can store anywhere from zero to `MaxLen` total elements. -Note that due to hash collisions, the actual maximum number of elements stored by any particular -hashmap is likely lower than `MaxLen`. This is true even with cryptographic hash functions since -every hash value will be performed modulo `MaxLen`. - -When creating `HashMap`s, the `MaxLen` generic should always be specified if it is not already -known. Otherwise, the compiler may infer a different value for `MaxLen` (such as zero), which -will likely change the result of the program. This behavior is set to become an error in future -versions instead. - -Example: - -```rust -// Create a mapping from Fields to u32s with a maximum length of 12 -// using a pedersen hash -let mut map: HashMap> = HashMap::default(); - -map.insert(1, 2); -map.insert(3, 4); - -let two = map.get(1).unwrap(); -``` - -## Methods - -### default - -```rust title="default" showLineNumbers -impl Default for HashMap -where - B: BuildHasher + Default, - H: Hasher + Default -{ - fn default() -> Self { -``` -> Source code: noir_stdlib/src/collections/map.nr#L462-L469 - - -Creates a fresh, empty HashMap. - -When using this function, always make sure to specify the maximum size of the hash map. - -This is the same `default` from the `Default` implementation given further below. It is -repeated here for convenience since it is the recommended way to create a hashmap. - -Example: - -```rust title="default_example" showLineNumbers -let hashmap: HashMap> = HashMap::default(); - assert(hashmap.is_empty()); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L202-L205 - - -Because `HashMap` has so many generic arguments that are likely to be the same throughout -your program, it may be helpful to create a type alias: - -```rust title="type_alias" showLineNumbers -type MyMap = HashMap>; -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L196-L198 - - -### with_hasher - -```rust title="with_hasher" showLineNumbers -pub fn with_hasher(_build_hasher: B) -> Self - where - B: BuildHasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L82-L86 - - -Creates a hashmap with an existing `BuildHasher`. This can be used to ensure multiple -hashmaps are created with the same hasher instance. - -Example: - -```rust title="with_hasher_example" showLineNumbers -let my_hasher: BuildHasherDefault = Default::default(); - let hashmap: HashMap> = HashMap::with_hasher(my_hasher); - assert(hashmap.is_empty()); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L207-L211 - - -### get - -```rust title="get" showLineNumbers -pub fn get( - self, - key: K - ) -> Option - where - K: Eq + Hash, - B: BuildHasher, - H: Hasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L278-L287 - - -Retrieves a value from the hashmap, returning `Option::none()` if it was not found. - -Example: - -```rust title="get_example" showLineNumbers -fn get_example(map: HashMap>) { - let x = map.get(12); - - if x.is_some() { - assert(x.unwrap() == 42); - } -} -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L299-L307 - - -### insert - -```rust title="insert" showLineNumbers -pub fn insert( - &mut self, - key: K, - value: V - ) - where - K: Eq + Hash, - B: BuildHasher, - H: Hasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L313-L323 - - -Inserts a new key-value pair into the map. If the key was already in the map, its -previous value will be overridden with the newly provided one. - -Example: - -```rust title="insert_example" showLineNumbers -let mut map: HashMap> = HashMap::default(); - map.insert(12, 42); - assert(map.len() == 1); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L213-L217 - - -### remove - -```rust title="remove" showLineNumbers -pub fn remove( - &mut self, - key: K - ) - where - K: Eq + Hash, - B: BuildHasher, - H: Hasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L356-L365 - - -Removes the given key-value pair from the map. If the key was not already present -in the map, this does nothing. - -Example: - -```rust title="remove_example" showLineNumbers -map.remove(12); - assert(map.is_empty()); - - // If a key was not present in the map, remove does nothing - map.remove(12); - assert(map.is_empty()); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L221-L228 - - -### is_empty - -```rust title="is_empty" showLineNumbers -pub fn is_empty(self) -> bool { -``` -> Source code: noir_stdlib/src/collections/map.nr#L115-L117 - - -True if the length of the hash map is empty. - -Example: - -```rust title="is_empty_example" showLineNumbers -assert(map.is_empty()); - - map.insert(1, 2); - assert(!map.is_empty()); - - map.remove(1); - assert(map.is_empty()); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L230-L238 - - -### len - -```rust title="len" showLineNumbers -pub fn len(self) -> u64 { -``` -> Source code: noir_stdlib/src/collections/map.nr#L264-L266 - - -Returns the current length of this hash map. - -Example: - -```rust title="len_example" showLineNumbers -// This is equivalent to checking map.is_empty() - assert(map.len() == 0); - - map.insert(1, 2); - map.insert(3, 4); - map.insert(5, 6); - assert(map.len() == 3); - - // 3 was already present as a key in the hash map, so the length is unchanged - map.insert(3, 7); - assert(map.len() == 3); - - map.remove(1); - assert(map.len() == 2); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L240-L255 - - -### capacity - -```rust title="capacity" showLineNumbers -pub fn capacity(_self: Self) -> u64 { -``` -> Source code: noir_stdlib/src/collections/map.nr#L271-L273 - - -Returns the maximum capacity of this hashmap. This is always equal to the capacity -specified in the hashmap's type. - -Unlike hashmaps in general purpose programming languages, hashmaps in Noir have a -static capacity that does not increase as the map grows larger. Thus, this capacity -is also the maximum possible element count that can be inserted into the hashmap. -Due to hash collisions (modulo the hashmap length), it is likely the actual maximum -element count will be lower than the full capacity. - -Example: - -```rust title="capacity_example" showLineNumbers -let empty_map: HashMap> = HashMap::default(); - assert(empty_map.len() == 0); - assert(empty_map.capacity() == 42); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L257-L261 - - -### clear - -```rust title="clear" showLineNumbers -pub fn clear(&mut self) { -``` -> Source code: noir_stdlib/src/collections/map.nr#L93-L95 - - -Clears the hashmap, removing all key-value pairs from it. - -Example: - -```rust title="clear_example" showLineNumbers -assert(!map.is_empty()); - map.clear(); - assert(map.is_empty()); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L263-L267 - - -### contains_key - -```rust title="contains_key" showLineNumbers -pub fn contains_key( - self, - key: K - ) -> bool - where - K: Hash + Eq, - B: BuildHasher, - H: Hasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L101-L110 - - -True if the hashmap contains the given key. Unlike `get`, this will not also return -the value associated with the key. - -Example: - -```rust title="contains_key_example" showLineNumbers -if map.contains_key(7) { - let value = map.get(7); - assert(value.is_some()); - } else { - println("No value for key 7!"); - } -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L269-L276 - - -### entries - -```rust title="entries" showLineNumbers -pub fn entries(self) -> BoundedVec<(K, V), N> { -``` -> Source code: noir_stdlib/src/collections/map.nr#L123-L125 - - -Returns a vector of each key-value pair present in the hashmap. - -The length of the returned vector is always equal to the length of the hashmap. - -Example: - -```rust title="entries_example" showLineNumbers -let entries = map.entries(); - - // The length of a hashmap may not be compile-time known, so we - // need to loop over its capacity instead - for i in 0..map.capacity() { - if i < entries.len() { - let (key, value) = entries.get(i); - println(f"{key} -> {value}"); - } - } -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L310-L321 - - -### keys - -```rust title="keys" showLineNumbers -pub fn keys(self) -> BoundedVec { -``` -> Source code: noir_stdlib/src/collections/map.nr#L144-L146 - - -Returns a vector of each key present in the hashmap. - -The length of the returned vector is always equal to the length of the hashmap. - -Example: - -```rust title="keys_example" showLineNumbers -let keys = map.keys(); - - for i in 0..keys.max_len() { - if i < keys.len() { - let key = keys.get_unchecked(i); - let value = map.get(key).unwrap_unchecked(); - println(f"{key} -> {value}"); - } - } -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L323-L333 - - -### values - -```rust title="values" showLineNumbers -pub fn values(self) -> BoundedVec { -``` -> Source code: noir_stdlib/src/collections/map.nr#L164-L166 - - -Returns a vector of each value present in the hashmap. - -The length of the returned vector is always equal to the length of the hashmap. - -Example: - -```rust title="values_example" showLineNumbers -let values = map.values(); - - for i in 0..values.max_len() { - if i < values.len() { - let value = values.get_unchecked(i); - println(f"Found value {value}"); - } - } -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L335-L344 - - -### iter_mut - -```rust title="iter_mut" showLineNumbers -pub fn iter_mut( - &mut self, - f: fn(K, V) -> (K, V) - ) - where - K: Eq + Hash, - B: BuildHasher, - H: Hasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L183-L192 - - -Iterates through each key-value pair of the HashMap, setting each key-value pair to the -result returned from the given function. - -Note that since keys can be mutated, the HashMap needs to be rebuilt as it is iterated -through. If this is not desired, use `iter_values_mut` if only values need to be mutated, -or `entries` if neither keys nor values need to be mutated. - -The iteration order is left unspecified. As a result, if two keys are mutated to become -equal, which of the two values that will be present for the key in the resulting map is also unspecified. - -Example: - -```rust title="iter_mut_example" showLineNumbers -// Add 1 to each key in the map, and double the value associated with that key. - map.iter_mut(|k, v| (k + 1, v * 2)); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L348-L351 - - -### iter_keys_mut - -```rust title="iter_keys_mut" showLineNumbers -pub fn iter_keys_mut( - &mut self, - f: fn(K) -> K - ) - where - K: Eq + Hash, - B: BuildHasher, - H: Hasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L208-L217 - - -Iterates through the HashMap, mutating each key to the result returned from -the given function. - -Note that since keys can be mutated, the HashMap needs to be rebuilt as it is iterated -through. If only iteration is desired and the keys are not intended to be mutated, -prefer using `entries` instead. - -The iteration order is left unspecified. As a result, if two keys are mutated to become -equal, which of the two values that will be present for the key in the resulting map is also unspecified. - -Example: - -```rust title="iter_keys_mut_example" showLineNumbers -// Double each key, leaving the value associated with that key untouched - map.iter_keys_mut(|k| k * 2); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L353-L356 - - -### iter_values_mut - -```rust title="iter_values_mut" showLineNumbers -pub fn iter_values_mut(&mut self, f: fn(V) -> V) { -``` -> Source code: noir_stdlib/src/collections/map.nr#L233-L235 - - -Iterates through the HashMap, applying the given function to each value and mutating the -value to equal the result. This function is more efficient than `iter_mut` and `iter_keys_mut` -because the keys are untouched and the underlying hashmap thus does not need to be reordered. - -Example: - -```rust title="iter_values_mut_example" showLineNumbers -// Halve each value - map.iter_values_mut(|v| v / 2); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L358-L361 - - -### retain - -```rust title="retain" showLineNumbers -pub fn retain(&mut self, f: fn(K, V) -> bool) { -``` -> Source code: noir_stdlib/src/collections/map.nr#L247-L249 - - -Retains only the key-value pairs for which the given function returns true. -Any key-value pairs for which the function returns false will be removed from the map. - -Example: - -```rust title="retain_example" showLineNumbers -map.retain(|k, v| (k != 0) & (v != 0)); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L281-L283 - - -## Trait Implementations - -### default - -```rust title="default" showLineNumbers -impl Default for HashMap -where - B: BuildHasher + Default, - H: Hasher + Default -{ - fn default() -> Self { -``` -> Source code: noir_stdlib/src/collections/map.nr#L462-L469 - - -Constructs an empty HashMap. - -Example: - -```rust title="default_example" showLineNumbers -let hashmap: HashMap> = HashMap::default(); - assert(hashmap.is_empty()); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L202-L205 - - -### eq - -```rust title="eq" showLineNumbers -impl Eq for HashMap -where - K: Eq + Hash, - V: Eq, - B: BuildHasher, - H: Hasher -{ - fn eq(self, other: HashMap) -> bool { -``` -> Source code: noir_stdlib/src/collections/map.nr#L426-L435 - - -Checks if two HashMaps are equal. - -Example: - -```rust title="eq_example" showLineNumbers -let mut map1: HashMap> = HashMap::default(); - let mut map2: HashMap> = HashMap::default(); - - map1.insert(1, 2); - map1.insert(3, 4); - - map2.insert(3, 4); - map2.insert(1, 2); - - assert(map1 == map2); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L285-L296 - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/containers/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/containers/index.md deleted file mode 100644 index ea84c6d5c21..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/containers/index.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Containers -description: Container types provided by Noir's standard library for storing and retrieving data -keywords: [containers, data types, vec, hashmap] ---- diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/containers/vec.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/containers/vec.mdx deleted file mode 100644 index fcfd7e07aa0..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/containers/vec.mdx +++ /dev/null @@ -1,151 +0,0 @@ ---- -title: Vectors -description: Delve into the Vec data type in Noir. Learn about its methods, practical examples, and best practices for using Vectors in your Noir code. -keywords: [noir, vector type, methods, examples, dynamic arrays] -sidebar_position: 6 ---- - -import Experimental from '@site/src/components/Notes/_experimental.mdx'; - - - -A vector is a collection type similar to Rust's `Vec` type. In Noir, it is a convenient way to use slices as mutable arrays. - -Example: - -```rust -let mut vector: Vec = Vec::new(); -for i in 0..5 { - vector.push(i); -} -assert(vector.len() == 5); -``` - -## Methods - -### new - -Creates a new, empty vector. - -```rust -pub fn new() -> Self -``` - -Example: - -```rust -let empty_vector: Vec = Vec::new(); -assert(empty_vector.len() == 0); -``` - -### from_slice - -Creates a vector containing each element from a given slice. Mutations to the resulting vector will not affect the original slice. - -```rust -pub fn from_slice(slice: [T]) -> Self -``` - -Example: - -```rust -let slice: [Field] = &[1, 2, 3]; -let vector_from_slice = Vec::from_slice(slice); -assert(vector_from_slice.len() == 3); -``` - -### len - -Returns the number of elements in the vector. - -```rust -pub fn len(self) -> Field -``` - -Example: - -```rust -let empty_vector: Vec = Vec::new(); -assert(empty_vector.len() == 0); -``` - -### get - -Retrieves an element from the vector at a given index. Panics if the index points beyond the vector's end. - -```rust -pub fn get(self, index: Field) -> T -``` - -Example: - -```rust -let vector: Vec = Vec::from_slice(&[10, 20, 30]); -assert(vector.get(1) == 20); -``` - -### push - -Adds a new element to the vector's end, returning a new vector with a length one greater than the original unmodified vector. - -```rust -pub fn push(&mut self, elem: T) -``` - -Example: - -```rust -let mut vector: Vec = Vec::new(); -vector.push(10); -assert(vector.len() == 1); -``` - -### pop - -Removes an element from the vector's end, returning a new vector with a length one less than the original vector, along with the removed element. Panics if the vector's length is zero. - -```rust -pub fn pop(&mut self) -> T -``` - -Example: - -```rust -let mut vector = Vec::from_slice(&[10, 20]); -let popped_elem = vector.pop(); -assert(popped_elem == 20); -assert(vector.len() == 1); -``` - -### insert - -Inserts an element at a specified index, shifting subsequent elements to the right. - -```rust -pub fn insert(&mut self, index: Field, elem: T) -``` - -Example: - -```rust -let mut vector = Vec::from_slice(&[10, 30]); -vector.insert(1, 20); -assert(vector.get(1) == 20); -``` - -### remove - -Removes an element at a specified index, shifting subsequent elements to the left, and returns the removed element. - -```rust -pub fn remove(&mut self, index: Field) -> T -``` - -Example: - -```rust -let mut vector = Vec::from_slice(&[10, 20, 30]); -let removed_elem = vector.remove(1); -assert(removed_elem == 20); -assert(vector.len() == 2); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/_category_.json deleted file mode 100644 index 5d694210bbf..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 0, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/ec_primitives.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/ec_primitives.md deleted file mode 100644 index 042347cb98f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/ec_primitives.md +++ /dev/null @@ -1,102 +0,0 @@ ---- -title: Elliptic Curve Primitives -keywords: [cryptographic primitives, Noir project] -sidebar_position: 4 ---- - -Data structures and methods on them that allow you to carry out computations involving elliptic -curves over the (mathematical) field corresponding to `Field`. For the field currently at our -disposal, applications would involve a curve embedded in BN254, e.g. the -[Baby Jubjub curve](https://eips.ethereum.org/EIPS/eip-2494). - -## Data structures - -### Elliptic curve configurations - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Curve`), i.e. the specific elliptic -curve you want to use, which would be specified using any one of the methods -`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::new` which take the coefficients in the -defining equation together with a generator point as parameters. You can find more detail in the -comments in -[`noir_stdlib/src/ec.nr`](https://github.com/noir-lang/noir/blob/v0.27.0/noir_stdlib/src/ec.nr), but -the gist of it is that the elliptic curves of interest are usually expressed in one of the standard -forms implemented here (Twisted Edwards, Montgomery and Short Weierstraß), and in addition to that, -you could choose to use `affine` coordinates (Cartesian coordinates - the usual (x,y) - possibly -together with a point at infinity) or `curvegroup` coordinates (some form of projective coordinates -requiring more coordinates but allowing for more efficient implementations of elliptic curve -operations). Conversions between all of these forms are provided, and under the hood these -conversions are done whenever an operation is more efficient in a different representation (or a -mixed coordinate representation is employed). - -### Points - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Point`), i.e. points lying on the -elliptic curve. For a curve configuration `c` and a point `p`, it may be checked that `p` -does indeed lie on `c` by calling `c.contains(p1)`. - -## Methods - -(given a choice of curve representation, e.g. use `std::ec::tecurve::affine::Curve` and use -`std::ec::tecurve::affine::Point`) - -- The **zero element** is given by `Point::zero()`, and we can verify whether a point `p: Point` is - zero by calling `p.is_zero()`. -- **Equality**: Points `p1: Point` and `p2: Point` may be checked for equality by calling - `p1.eq(p2)`. -- **Addition**: For `c: Curve` and points `p1: Point` and `p2: Point` on the curve, adding these two - points is accomplished by calling `c.add(p1,p2)`. -- **Negation**: For a point `p: Point`, `p.negate()` is its negation. -- **Subtraction**: For `c` and `p1`, `p2` as above, subtracting `p2` from `p1` is accomplished by - calling `c.subtract(p1,p2)`. -- **Scalar multiplication**: For `c` as above, `p: Point` a point on the curve and `n: Field`, - scalar multiplication is given by `c.mul(n,p)`. If instead `n :: [u1; N]`, i.e. `n` is a bit - array, the `bit_mul` method may be used instead: `c.bit_mul(n,p)` -- **Multi-scalar multiplication**: For `c` as above and arrays `n: [Field; N]` and `p: [Point; N]`, - multi-scalar multiplication is given by `c.msm(n,p)`. -- **Coordinate representation conversions**: The `into_group` method converts a point or curve - configuration in the affine representation to one in the CurveGroup representation, and - `into_affine` goes in the other direction. -- **Curve representation conversions**: `tecurve` and `montcurve` curves and points are equivalent - and may be converted between one another by calling `into_montcurve` or `into_tecurve` on their - configurations or points. `swcurve` is more general and a curve c of one of the other two types - may be converted to this representation by calling `c.into_swcurve()`, whereas a point `p` lying - on the curve given by `c` may be mapped to its corresponding `swcurve` point by calling - `c.map_into_swcurve(p)`. -- **Map-to-curve methods**: The Elligator 2 method of mapping a field element `n: Field` into a - `tecurve` or `montcurve` with configuration `c` may be called as `c.elligator2_map(n)`. For all of - the curve configurations, the SWU map-to-curve method may be called as `c.swu_map(z,n)`, where - `z: Field` depends on `Field` and `c` and must be chosen by the user (the conditions it needs to - satisfy are specified in the comments - [here](https://github.com/noir-lang/noir/blob/v0.27.0/noir_stdlib/src/ec.nr). - -## Examples - -The -[ec_baby_jubjub test](https://github.com/noir-lang/noir/blob/master/test_programs/compile_success_empty/ec_baby_jubjub/src/main.nr) -illustrates all of the above primitives on various forms of the Baby Jubjub curve. A couple of more -interesting examples in Noir would be: - -Public-key cryptography: Given an elliptic curve and a 'base point' on it, determine the public key -from the private key. This is a matter of using scalar multiplication. In the case of Baby Jubjub, -for example, this code would do: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; - -fn bjj_pub_key(priv_key: Field) -> Point -{ - - let bjj = Curve::new(168700, 168696, G::new(995203441582195749578291179787384436505546430278305826713579947235728471134,5472060717959818805561601436314318772137091100104008585924551046643952123905)); - - let base_pt = Point::new(5299619240641551281634865583518297030282874472190772894086521144482721001553, 16950150798460657717958625567821834550301663161624707787222815936182638968203); - - bjj.mul(priv_key,base_pt) -} -``` - -This would come in handy in a Merkle proof. - -- EdDSA signature verification: This is a matter of combining these primitives with a suitable hash - function. See - [feat(stdlib): EdDSA sig verification noir#1136](https://github.com/noir-lang/noir/pull/1136) for - the case of Baby Jubjub and the Poseidon hash function. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/eddsa.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/eddsa.mdx deleted file mode 100644 index c2c0624dfad..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/eddsa.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: EdDSA Verification -description: Learn about the cryptographic primitives regarding EdDSA -keywords: [cryptographic primitives, Noir project, eddsa, signatures] -sidebar_position: 5 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## eddsa::eddsa_poseidon_verify - -Verifier for EdDSA signatures - -```rust -fn eddsa_poseidon_verify(public_key_x : Field, public_key_y : Field, signature_s: Field, signature_r8_x: Field, signature_r8_y: Field, message: Field) -> bool -``` - -It is also possible to specify the hash algorithm used for the signature by using the `eddsa_verify_with_hasher` function with a parameter implementing the Hasher trait. For instance, if you want to use Poseidon2 instead, you can do the following: -```rust -use dep::std::hash::poseidon2::Poseidon2Hasher; - -let mut hasher = Poseidon2Hasher::default(); -eddsa_verify_with_hasher(pub_key_a.x, pub_key_a.y, s_a, r8_a.x, r8_a.y, msg, &mut hasher); -``` - - - -## eddsa::eddsa_to_pub - -Private to public key conversion. - -Returns `(pub_key_x, pub_key_y)` - -```rust -fn eddsa_to_pub(secret : Field) -> (Field, Field) -``` - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/hashes.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/hashes.mdx deleted file mode 100644 index 695c7d9406f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/hashes.mdx +++ /dev/null @@ -1,331 +0,0 @@ ---- -title: Hash methods -description: - Learn about the cryptographic primitives ready to use for any Noir project, including sha256, - blake2s, pedersen, mimc_bn254 and mimc -keywords: - [cryptographic primitives, Noir project, sha256, blake2s, pedersen, mimc_bn254, mimc, hash] -sidebar_position: 0 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## sha256 - -Given an array of bytes, returns the resulting sha256 hash. -See sha256_slice for a version that works directly on slices. - -```rust title="sha256" showLineNumbers -pub fn sha256(input: [u8; N]) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L10-L12 - - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::sha256(x); -} -``` - - - -## sha256_slice - -A version of sha256 specialized to slices: - -```rust title="sha256_slice" showLineNumbers -pub fn sha256_slice(input: [u8]) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L16-L18 - - - - -## blake2s - -Given an array of bytes, returns an array with the Blake2 hash -See blake2s_slice for a version that works directly on slices. - -```rust title="blake2s" showLineNumbers -pub fn blake2s(input: [u8; N]) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L22-L24 - - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::blake2s(x); -} -``` - - - -## blake2s_slice - -A version of blake2s specialized to slices: - -```rust title="blake2s_slice" showLineNumbers -pub fn blake2s_slice(input: [u8]) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L28-L30 - - - - -## blake3 - -Given an array of bytes, returns an array with the Blake3 hash -See blake3_slice for a version that works directly on slices. - -```rust title="blake3" showLineNumbers -pub fn blake3(input: [u8; N]) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L34-L36 - - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::blake3(x); -} -``` - - - -## blake3_slice - -A version of blake3 specialized to slices: - -```rust title="blake3_slice" showLineNumbers -pub fn blake3_slice(input: [u8]) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L40-L42 - - - - -## pedersen_hash - -Given an array of Fields, returns the Pedersen hash. -See pedersen_hash_slice for a version that works directly on slices. - -```rust title="pedersen_hash" showLineNumbers -pub fn pedersen_hash(input: [Field; N]) -> Field -``` -> Source code: noir_stdlib/src/hash.nr#L78-L80 - - -example: - -```rust title="pedersen-hash" showLineNumbers -use dep::std; - -fn main(x: Field, y: Field, expected_hash: Field) { - let hash = std::hash::pedersen_hash([x, y]); - assert_eq(hash, expected_hash); -} -``` -> Source code: test_programs/execution_success/pedersen_hash/src/main.nr#L1-L8 - - - - -## pedersen_hash_slice - -Given a slice of Fields, returns the Pedersen hash. - -```rust title="pedersen_hash_slice" showLineNumbers -pub fn pedersen_hash_slice(input: [Field]) -> Field -``` -> Source code: noir_stdlib/src/hash.nr#L85-L87 - - - - -## pedersen_commitment - -Given an array of Fields, returns the Pedersen commitment. -See pedersen_commitment_slice for a version that works directly on slices. - -```rust title="pedersen_commitment" showLineNumbers -struct PedersenPoint { - x : Field, - y : Field, -} - -pub fn pedersen_commitment(input: [Field; N]) -> PedersenPoint { -``` -> Source code: noir_stdlib/src/hash.nr#L45-L52 - - -example: - -```rust title="pedersen-commitment" showLineNumbers -use dep::std; - -fn main(x: Field, y: Field, expected_commitment: std::hash::PedersenPoint) { - let commitment = std::hash::pedersen_commitment([x, y]); - assert_eq(commitment.x, expected_commitment.x); - assert_eq(commitment.y, expected_commitment.y); -} -``` -> Source code: test_programs/execution_success/pedersen_commitment/src/main.nr#L1-L9 - - - - -## pedersen_commitment_slice - -Given a slice of Fields, returns the Pedersen commitment. - -```rust title="pedersen_commitment_slice" showLineNumbers -pub fn pedersen_commitment_slice(input: [Field]) -> PedersenPoint { - pedersen_commitment_with_separator_slice(input, 0) -} -``` -> Source code: noir_stdlib/src/hash.nr#L56-L60 - - - - -## keccak256 - -Given an array of bytes (`u8`), returns the resulting keccak hash as an array of -32 bytes (`[u8; 32]`). Specify a message_size to hash only the first -`message_size` bytes of the input. See keccak256_slice for a version that works -directly on slices. - -```rust title="keccak256" showLineNumbers -pub fn keccak256(input: [u8; N], message_size: u32) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L113-L115 - - -example: - -```rust title="keccak256" showLineNumbers -use dep::std; - -fn main(x: Field, result: [u8; 32]) { - // We use the `as` keyword here to denote the fact that we want to take just the first byte from the x Field - // The padding is taken care of by the program - let digest = std::hash::keccak256([x as u8], 1); - assert(digest == result); - - //#1399: variable message size - let message_size = 4; - let hash_a = std::hash::keccak256([1, 2, 3, 4], message_size); - let hash_b = std::hash::keccak256([1, 2, 3, 4, 0, 0, 0, 0], message_size); - - assert(hash_a == hash_b); - - let message_size_big = 8; - let hash_c = std::hash::keccak256([1, 2, 3, 4, 0, 0, 0, 0], message_size_big); - - assert(hash_a != hash_c); -} -``` -> Source code: test_programs/execution_success/keccak256/src/main.nr#L1-L22 - - - - -## keccak256_slice - -Given a slice of bytes (`u8`), returns the resulting keccak hash as an array of -32 bytes (`[u8; 32]`). - -```rust title="keccak256_slice" showLineNumbers -pub fn keccak256_slice(input: [u8], message_size: u32) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L119-L121 - - - - -## poseidon - -Given an array of Fields, returns a new Field with the Poseidon Hash. Mind that you need to specify -how many inputs are there to your Poseidon function. - -```rust -// example for hash_1, hash_2 accepts an array of length 2, etc -fn hash_1(input: [Field; 1]) -> Field -``` - -example: - -```rust title="poseidon" showLineNumbers -use dep::std::hash::poseidon; -use dep::std::hash::poseidon2; - -fn main(x1: [Field; 2], y1: pub Field, x2: [Field; 4], y2: pub Field, x3: [Field; 4], y3: Field) { - let hash1 = poseidon::bn254::hash_2(x1); - assert(hash1 == y1); - - let hash2 = poseidon::bn254::hash_4(x2); - assert(hash2 == y2); - - let hash3 = poseidon2::Poseidon2::hash(x3, x3.len()); - assert(hash3 == y3); -} -``` -> Source code: test_programs/execution_success/poseidon_bn254_hash/src/main.nr#L1-L15 - - -## poseidon 2 - -Given an array of Fields, returns a new Field with the Poseidon2 Hash. Contrary to the Poseidon -function, there is only one hash and you can specify a message_size to hash only the first -`message_size` bytes of the input, - -```rust -// example for hashing the first three elements of the input -Poseidon2::hash(input, 3); -``` - -The above example for Poseidon also includes Poseidon2. - -## mimc_bn254 and mimc - -`mimc_bn254` is `mimc`, but with hardcoded parameters for the BN254 curve. You can use it by -providing an array of Fields, and it returns a Field with the hash. You can use the `mimc` method if -you're willing to input your own constants: - -```rust -fn mimc(x: Field, k: Field, constants: [Field; N], exp : Field) -> Field -``` - -otherwise, use the `mimc_bn254` method: - -```rust -fn mimc_bn254(array: [Field; N]) -> Field -``` - -example: - -```rust - -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::mimc::mimc_bn254(x); -} -``` - -## hash_to_field - -```rust -fn hash_to_field(_input : [Field]) -> Field {} -``` - -Calculates the `blake2s` hash of the inputs and returns the hash modulo the field modulus to return -a value which can be represented as a `Field`. - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/index.md deleted file mode 100644 index 650f30165d5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/index.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Cryptographic Primitives -description: - Learn about the cryptographic primitives ready to use for any Noir project -keywords: - [ - cryptographic primitives, - Noir project, - ] ---- - -The Noir team is progressively adding new cryptographic primitives to the standard library. Reach out for news or if you would be interested in adding more of these calculations in Noir. - -Some methods are available thanks to the Aztec backend, not being performed using Noir. When using other backends, these methods may or may not be supplied. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/scalar.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/scalar.mdx deleted file mode 100644 index df411ca5443..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/scalar.mdx +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Scalar multiplication -description: See how you can perform scalar multiplications over a fixed base in Noir -keywords: [cryptographic primitives, Noir project, scalar multiplication] -sidebar_position: 1 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## scalar_mul::fixed_base_embedded_curve - -Performs scalar multiplication over the embedded curve whose coordinates are defined by the -configured noir field. For the BN254 scalar field, this is BabyJubJub or Grumpkin. - -```rust title="fixed_base_embedded_curve" showLineNumbers -pub fn fixed_base_embedded_curve( - low: Field, - high: Field -) -> [Field; 2] -``` -> Source code: noir_stdlib/src/scalar_mul.nr#L27-L32 - - -example - -```rust -fn main(x : Field) { - let scal = std::scalar_mul::fixed_base_embedded_curve(x); - println(scal); -} -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/schnorr.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/schnorr.mdx deleted file mode 100644 index b59e69c8f07..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/schnorr.mdx +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: Schnorr Signatures -description: Learn how you can verify Schnorr signatures using Noir -keywords: [cryptographic primitives, Noir project, schnorr, signatures] -sidebar_position: 2 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## schnorr::verify_signature - -Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin). -See schnorr::verify_signature_slice for a version that works directly on slices. - -```rust title="schnorr_verify" showLineNumbers -pub fn verify_signature( - public_key_x: Field, - public_key_y: Field, - signature: [u8; 64], - message: [u8; N] -) -> bool -``` -> Source code: noir_stdlib/src/schnorr.nr#L2-L9 - - -where `_signature` can be generated like so using the npm package -[@noir-lang/barretenberg](https://www.npmjs.com/package/@noir-lang/barretenberg) - -```js -const { BarretenbergWasm } = require('@noir-lang/barretenberg/dest/wasm'); -const { Schnorr } = require('@noir-lang/barretenberg/dest/crypto/schnorr'); - -... - -const barretenberg = await BarretenbergWasm.new(); -const schnorr = new Schnorr(barretenberg); -const pubKey = schnorr.computePublicKey(privateKey); -const message = ... -const signature = Array.from( - schnorr.constructSignature(hash, privateKey).toBuffer() -); - -... -``` - - - -## schnorr::verify_signature_slice - -Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin) -where the message is a slice. - -```rust title="schnorr_verify_slice" showLineNumbers -pub fn verify_signature_slice( - public_key_x: Field, - public_key_y: Field, - signature: [u8; 64], - message: [u8] -) -> bool -``` -> Source code: noir_stdlib/src/schnorr.nr#L13-L20 - - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/logging.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/logging.md deleted file mode 100644 index db75ef9f86f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/logging.md +++ /dev/null @@ -1,78 +0,0 @@ ---- -title: Logging -description: - Learn how to use the println statement for debugging in Noir with this tutorial. Understand the - basics of logging in Noir and how to implement it in your code. -keywords: - [ - noir logging, - println statement, - print statement, - debugging in noir, - noir std library, - logging tutorial, - basic logging in noir, - noir logging implementation, - noir debugging techniques, - rust, - ] ---- - -The standard library provides two familiar statements you can use: `println` and `print`. Despite being a limited implementation of rust's `println!` and `print!` macros, these constructs can be useful for debugging. - -You can print the output of both statements in your Noir code by using the `nargo execute` command or the `--show-output` flag when using `nargo test` (provided there are print statements in your tests). - -It is recommended to use `nargo execute` if you want to debug failing constraints with `println` or `print` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). Neither `println`, nor `print` are callable for failed constraints caught at compile time. - -Both `print` and `println` are generic functions which can work on integers, fields, strings, and even structs or expressions. Note however, that slices are currently unsupported. For example: - -```rust -struct Person { - age: Field, - height: Field, -} - -fn main(age: Field, height: Field) { - let person = Person { - age: age, - height: height, - }; - println(person); - println(age + height); - println("Hello world!"); -} -``` - -You can print different types in the same statement (including strings) with a type called `fmtstr`. It can be specified in the same way as a normal string, just prepended with an "f" character: - -```rust - let fmt_str = f"i: {i}, j: {j}"; - println(fmt_str); - - let s = myStruct { y: x, x: y }; - println(s); - - println(f"i: {i}, s: {s}"); - - println(x); - println([x, y]); - - let foo = fooStruct { my_struct: s, foo: 15 }; - println(f"s: {s}, foo: {foo}"); - - println(15); // prints 0x0f, implicit Field - println(-1 as u8); // prints 255 - println(-1 as i8); // prints -1 -``` - -Examples shown above are interchangeable between the two `print` statements: - -```rust -let person = Person { age : age, height : height }; - -println(person); -print(person); - -println("Hello world!"); // Prints with a newline at the end of the input -print("Hello world!"); // Prints the input and keeps cursor on the same line -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/merkle_trees.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/merkle_trees.md deleted file mode 100644 index 6a9ebf72ada..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/merkle_trees.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: Merkle Trees -description: Learn about Merkle Trees in Noir with this tutorial. Explore the basics of computing a merkle root using a proof, with examples. -keywords: - [ - Merkle trees in Noir, - Noir programming language, - check membership, - computing root from leaf, - Noir Merkle tree implementation, - Merkle tree tutorial, - Merkle tree code examples, - Noir libraries, - pedersen hash., - ] ---- - -## compute_merkle_root - -Returns the root of the tree from the provided leaf and its hash path, using a [Pedersen hash](./cryptographic_primitives/hashes.mdx#pedersen_hash). - -```rust -fn compute_merkle_root(leaf : Field, index : Field, hash_path: [Field]) -> Field -``` - -example: - -```rust -/** - // these values are for this example only - index = "0" - priv_key = "0x000000000000000000000000000000000000000000000000000000616c696365" - secret = "0x1929ea3ab8d9106a899386883d9428f8256cfedb3c4f6b66bf4aa4d28a79988f" - note_hash_path = [ - "0x1e61bdae0f027b1b2159e1f9d3f8d00fa668a952dddd822fda80dc745d6f65cc", - "0x0e4223f3925f98934393c74975142bd73079ab0621f4ee133cee050a3c194f1a", - "0x2fd7bb412155bf8693a3bd2a3e7581a679c95c68a052f835dddca85fa1569a40" - ] - */ -fn main(index: Field, priv_key: Field, secret: Field, note_hash_path: [Field; 3]) { - - let pubkey = std::scalar_mul::fixed_base_embedded_curve(priv_key); - let pubkey_x = pubkey[0]; - let pubkey_y = pubkey[1]; - let note_commitment = std::hash::pedersen(&[pubkey_x, pubkey_y, secret]); - - let root = std::merkle::compute_merkle_root(note_commitment[0], index, note_hash_path.as_slice()); - println(root); -} -``` - -To check merkle tree membership: - -1. Include a merkle root as a program input. -2. Compute the merkle root of a given leaf, index and hash path. -3. Assert the merkle roots are equal. - -For more info about merkle trees, see the Wikipedia [page](https://en.wikipedia.org/wiki/Merkle_tree). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/options.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/options.md deleted file mode 100644 index a1bd4e1de5f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/options.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -title: Option Type ---- - -The `Option` type is a way to express that a value might be present (`Some(T))` or absent (`None`). It's a safer way to handle potential absence of values, compared to using nulls in many other languages. - -```rust -struct Option { - None, - Some(T), -} -``` - -The `Option` type, already imported into your Noir program, can be used directly: - -```rust -fn main() { - let none = Option::none(); - let some = Option::some(3); -} -``` - -See [this test](https://github.com/noir-lang/noir/blob/5cbfb9c4a06c8865c98ff2b594464b037d821a5c/crates/nargo_cli/tests/test_data/option/src/main.nr) for a more comprehensive set of examples of each of the methods described below. - -## Methods - -### none - -Constructs a none value. - -### some - -Constructs a some wrapper around a given value. - -### is_none - -Returns true if the Option is None. - -### is_some - -Returns true of the Option is Some. - -### unwrap - -Asserts `self.is_some()` and returns the wrapped value. - -### unwrap_unchecked - -Returns the inner value without asserting `self.is_some()`. This method can be useful within an if condition when we already know that `option.is_some()`. If the option is None, there is no guarantee what value will be returned, only that it will be of type T for an `Option`. - -### unwrap_or - -Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value. - -### unwrap_or_else - -Returns the wrapped value if `self.is_some()`. Otherwise, calls the given function to return a default value. - -### expect - -Asserts `self.is_some()` with a provided custom message and returns the contained `Some` value. The custom message is expected to be a format string. - -### map - -If self is `Some(x)`, this returns `Some(f(x))`. Otherwise, this returns `None`. - -### map_or - -If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns the given default value. - -### map_or_else - -If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns `default()`. - -### and - -Returns None if self is None. Otherwise, this returns `other`. - -### and_then - -If self is None, this returns None. Otherwise, this calls the given function with the Some value contained within self, and returns the result of that call. In some languages this function is called `flat_map` or `bind`. - -### or - -If self is Some, return self. Otherwise, return `other`. - -### or_else - -If self is Some, return self. Otherwise, return `default()`. - -### xor - -If only one of the two Options is Some, return that option. Otherwise, if both options are Some or both are None, None is returned. - -### filter - -Returns `Some(x)` if self is `Some(x)` and `predicate(x)` is true. Otherwise, this returns `None`. - -### flatten - -Flattens an `Option>` into a `Option`. This returns `None` if the outer Option is None. Otherwise, this returns the inner Option. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/recursion.md deleted file mode 100644 index f33c285cf4e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/recursion.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -title: Recursive Proofs -description: Learn about how to write recursive proofs in Noir. -keywords: [recursion, recursive proofs, verification_key, verify_proof] ---- - -Noir supports recursively verifying proofs, meaning you verify the proof of a Noir program in another Noir program. This enables creating proofs of arbitrary size by doing step-wise verification of smaller components of a large proof. - -Read [the explainer on recursion](../../explainers/explainer-recursion.md) to know more about this function and the [guide on how to use it.](../../how_to/how-to-recursion.md) - -## The `#[recursive]` Attribute - -In Noir, the `#[recursive]` attribute is used to indicate that a circuit is designed for recursive proof generation. When applied, it informs the compiler and the tooling that the circuit should be compiled in a way that makes its proofs suitable for recursive verification. This attribute eliminates the need for manual flagging of recursion at the tooling level, streamlining the proof generation process for recursive circuits. - -### Example usage with `#[recursive]` - -```rust -#[recursive] -fn main(x: Field, y: pub Field) { - assert(x == y, "x and y are not equal"); -} - -// This marks the circuit as recursion-friendly and indicates that proofs generated from this circuit -// are intended for recursive verification. -``` - -By incorporating this attribute directly in the circuit's definition, tooling like Nargo and NoirJS can automatically execute recursive-specific duties for Noir programs (e.g. recursive-friendly proof artifact generation) without additional flags or configurations. - -## Verifying Recursive Proofs - -```rust -#[foreign(recursive_aggregation)] -pub fn verify_proof(verification_key: [Field], proof: [Field], public_inputs: [Field], key_hash: Field) {} -``` - -:::info - -This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. - -::: - -## Example usage - -```rust -use dep::std; - -fn main( - verification_key : [Field; 114], - proof : [Field; 93], - public_inputs : [Field; 1], - key_hash : Field, - proof_b : [Field; 93], -) { - std::verify_proof( - verification_key.as_slice(), - proof.as_slice(), - public_inputs.as_slice(), - key_hash - ); - - std::verify_proof( - verification_key.as_slice(), - proof_b.as_slice(), - public_inputs.as_slice(), - key_hash - ); -} -``` - -You can see a full example of recursive proofs in [this example recursion demo repo](https://github.com/noir-lang/noir-examples/tree/master/recursion). - -## Parameters - -### `verification_key` - -The verification key for the zk program that is being verified. - -### `proof` - -The proof for the zk program that is being verified. - -### `public_inputs` - -These represent the public inputs of the proof we are verifying. - -### `key_hash` - -A key hash is used to check the validity of the verification key. The circuit implementing this opcode can use this hash to ensure that the key provided to the circuit matches the key produced by the circuit creator. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/traits.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/traits.md deleted file mode 100644 index 68a9dc3d54b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/traits.md +++ /dev/null @@ -1,408 +0,0 @@ ---- -title: Traits -description: Noir's stdlib provides a few commonly used traits. -keywords: [traits, trait, interface, protocol, default, add, eq] ---- - -## `std::default` - -### `std::default::Default` - -```rust title="default-trait" showLineNumbers -trait Default { - fn default() -> Self; -} -``` -> Source code: noir_stdlib/src/default.nr#L1-L5 - - -Constructs a default value of a type. - -Implementations: -```rust -impl Default for Field { .. } - -impl Default for i8 { .. } -impl Default for i16 { .. } -impl Default for i32 { .. } -impl Default for i64 { .. } - -impl Default for u8 { .. } -impl Default for u16 { .. } -impl Default for u32 { .. } -impl Default for u64 { .. } - -impl Default for () { .. } -impl Default for bool { .. } - -impl Default for [T; N] - where T: Default { .. } - -impl Default for [T] { .. } - -impl Default for (A, B) - where A: Default, B: Default { .. } - -impl Default for (A, B, C) - where A: Default, B: Default, C: Default { .. } - -impl Default for (A, B, C, D) - where A: Default, B: Default, C: Default, D: Default { .. } - -impl Default for (A, B, C, D, E) - where A: Default, B: Default, C: Default, D: Default, E: Default { .. } -``` - -For primitive integer types, the return value of `default` is `0`. Container -types such as arrays are filled with default values of their element type, -except slices whose length is unknown and thus defaulted to zero. - - -## `std::convert` - -### `std::convert::From` - -```rust title="from-trait" showLineNumbers -trait From { - fn from(input: T) -> Self; -} -``` -> Source code: noir_stdlib/src/convert.nr#L1-L5 - - -The `From` trait defines how to convert from a given type `T` to the type on which the trait is implemented. - -The Noir standard library provides a number of implementations of `From` between primitive types. -```rust title="from-impls" showLineNumbers -// Unsigned integers - -impl From for u32 { fn from(value: u8) -> u32 { value as u32 } } - -impl From for u64 { fn from(value: u8) -> u64 { value as u64 } } -impl From for u64 { fn from(value: u32) -> u64 { value as u64 } } - -impl From for Field { fn from(value: u8) -> Field { value as Field } } -impl From for Field { fn from(value: u32) -> Field { value as Field } } -impl From for Field { fn from(value: u64) -> Field { value as Field } } - -// Signed integers - -impl From for i32 { fn from(value: i8) -> i32 { value as i32 } } - -impl From for i64 { fn from(value: i8) -> i64 { value as i64 } } -impl From for i64 { fn from(value: i32) -> i64 { value as i64 } } - -// Booleans -impl From for u8 { fn from(value: bool) -> u8 { value as u8 } } -impl From for u32 { fn from(value: bool) -> u32 { value as u32 } } -impl From for u64 { fn from(value: bool) -> u64 { value as u64 } } -impl From for i8 { fn from(value: bool) -> i8 { value as i8 } } -impl From for i32 { fn from(value: bool) -> i32 { value as i32 } } -impl From for i64 { fn from(value: bool) -> i64 { value as i64 } } -impl From for Field { fn from(value: bool) -> Field { value as Field } } -``` -> Source code: noir_stdlib/src/convert.nr#L25-L52 - - -#### When to implement `From` - -As a general rule of thumb, `From` may be implemented in the [situations where it would be suitable in Rust](https://doc.rust-lang.org/std/convert/trait.From.html#when-to-implement-from): - -- The conversion is *infallible*: Noir does not provide an equivalent to Rust's `TryFrom`, if the conversion can fail then provide a named method instead. -- The conversion is *lossless*: semantically, it should not lose or discard information. For example, `u32: From` can losslessly convert any `u16` into a valid `u32` such that the original `u16` can be recovered. On the other hand, `u16: From` should not be implemented as `2**16` is a `u32` which cannot be losslessly converted into a `u16`. -- The conversion is *value-preserving*: the conceptual kind and meaning of the resulting value is the same, even though the Noir type and technical representation might be different. While it's possible to infallibly and losslessly convert a `u8` into a `str<2>` hex representation, `4u8` and `"04"` are too different for `str<2>: From` to be implemented. -- The conversion is *obvious*: it's the only reasonable conversion between the two types. If there's ambiguity on how to convert between them such that the same input could potentially map to two different values then a named method should be used. For instance rather than implementing `U128: From<[u8; 16]>`, the methods `U128::from_le_bytes` and `U128::from_be_bytes` are used as otherwise the endianness of the array would be ambiguous, resulting in two potential values of `U128` from the same byte array. - -One additional recommendation specific to Noir is: -- The conversion is *efficient*: it's relatively cheap to convert between the two types. Due to being a ZK DSL, it's more important to avoid unnecessary computation compared to Rust. If the implementation of `From` would encourage users to perform unnecessary conversion, resulting in additional proving time, then it may be preferable to expose functionality such that this conversion may be avoided. - -### `std::convert::Into` - -The `Into` trait is defined as the reciprocal of `From`. It should be easy to convince yourself that if we can convert to type `A` from type `B`, then it's possible to convert type `B` into type `A`. - -For this reason, implementing `From` on a type will automatically generate a matching `Into` implementation. One should always prefer implementing `From` over `Into` as implementing `Into` will not generate a matching `From` implementation. - -```rust title="into-trait" showLineNumbers -trait Into { - fn into(input: Self) -> T; -} - -impl Into for U where T: From { - fn into(input: U) -> T { - T::from(input) - } -} -``` -> Source code: noir_stdlib/src/convert.nr#L13-L23 - - -`Into` is most useful when passing function arguments where the types don't quite match up with what the function expects. In this case, the compiler has enough type information to perform the necessary conversion by just appending `.into()` onto the arguments in question. - - -## `std::cmp` - -### `std::cmp::Eq` - -```rust title="eq-trait" showLineNumbers -trait Eq { - fn eq(self, other: Self) -> bool; -} -``` -> Source code: noir_stdlib/src/cmp.nr#L1-L5 - - -Returns `true` if `self` is equal to `other`. Implementing this trait on a type -allows the type to be used with `==` and `!=`. - -Implementations: -```rust -impl Eq for Field { .. } - -impl Eq for i8 { .. } -impl Eq for i16 { .. } -impl Eq for i32 { .. } -impl Eq for i64 { .. } - -impl Eq for u8 { .. } -impl Eq for u16 { .. } -impl Eq for u32 { .. } -impl Eq for u64 { .. } - -impl Eq for () { .. } -impl Eq for bool { .. } - -impl Eq for [T; N] - where T: Eq { .. } - -impl Eq for [T] - where T: Eq { .. } - -impl Eq for (A, B) - where A: Eq, B: Eq { .. } - -impl Eq for (A, B, C) - where A: Eq, B: Eq, C: Eq { .. } - -impl Eq for (A, B, C, D) - where A: Eq, B: Eq, C: Eq, D: Eq { .. } - -impl Eq for (A, B, C, D, E) - where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq { .. } -``` - -### `std::cmp::Ord` - -```rust title="ord-trait" showLineNumbers -trait Ord { - fn cmp(self, other: Self) -> Ordering; -} -``` -> Source code: noir_stdlib/src/cmp.nr#L102-L106 - - -`a.cmp(b)` compares two values returning `Ordering::less()` if `a < b`, -`Ordering::equal()` if `a == b`, or `Ordering::greater()` if `a > b`. -Implementing this trait on a type allows `<`, `<=`, `>`, and `>=` to be -used on values of the type. - -Implementations: - -```rust -impl Ord for u8 { .. } -impl Ord for u16 { .. } -impl Ord for u32 { .. } -impl Ord for u64 { .. } - -impl Ord for i8 { .. } -impl Ord for i16 { .. } -impl Ord for i32 { .. } - -impl Ord for i64 { .. } - -impl Ord for () { .. } -impl Ord for bool { .. } - -impl Ord for [T; N] - where T: Ord { .. } - -impl Ord for [T] - where T: Ord { .. } - -impl Ord for (A, B) - where A: Ord, B: Ord { .. } - -impl Ord for (A, B, C) - where A: Ord, B: Ord, C: Ord { .. } - -impl Ord for (A, B, C, D) - where A: Ord, B: Ord, C: Ord, D: Ord { .. } - -impl Ord for (A, B, C, D, E) - where A: Ord, B: Ord, C: Ord, D: Ord, E: Ord { .. } -``` - -## `std::ops` - -### `std::ops::Add`, `std::ops::Sub`, `std::ops::Mul`, and `std::ops::Div` - -These traits abstract over addition, subtraction, multiplication, and division respectively. -Implementing these traits for a given type will also allow that type to be used with the corresponding operator -for that trait (`+` for Add, etc) in addition to the normal method names. - -```rust title="add-trait" showLineNumbers -trait Add { - fn add(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L1-L5 - -```rust title="sub-trait" showLineNumbers -trait Sub { - fn sub(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L17-L21 - -```rust title="mul-trait" showLineNumbers -trait Mul { - fn mul(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L33-L37 - -```rust title="div-trait" showLineNumbers -trait Div { - fn div(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L49-L53 - - -The implementations block below is given for the `Add` trait, but the same types that implement -`Add` also implement `Sub`, `Mul`, and `Div`. - -Implementations: -```rust -impl Add for Field { .. } - -impl Add for i8 { .. } -impl Add for i16 { .. } -impl Add for i32 { .. } -impl Add for i64 { .. } - -impl Add for u8 { .. } -impl Add for u16 { .. } -impl Add for u32 { .. } -impl Add for u64 { .. } -``` - -### `std::ops::Rem` - -```rust title="rem-trait" showLineNumbers -trait Rem{ - fn rem(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L65-L69 - - -`Rem::rem(a, b)` is the remainder function returning the result of what is -left after dividing `a` and `b`. Implementing `Rem` allows the `%` operator -to be used with the implementation type. - -Unlike other numeric traits, `Rem` is not implemented for `Field`. - -Implementations: -```rust -impl Rem for u8 { fn rem(self, other: u8) -> u8 { self % other } } -impl Rem for u16 { fn rem(self, other: u16) -> u16 { self % other } } -impl Rem for u32 { fn rem(self, other: u32) -> u32 { self % other } } -impl Rem for u64 { fn rem(self, other: u64) -> u64 { self % other } } - -impl Rem for i8 { fn rem(self, other: i8) -> i8 { self % other } } -impl Rem for i16 { fn rem(self, other: i16) -> i16 { self % other } } -impl Rem for i32 { fn rem(self, other: i32) -> i32 { self % other } } -impl Rem for i64 { fn rem(self, other: i64) -> i64 { self % other } } -``` - -### `std::ops::{ BitOr, BitAnd, BitXor }` - -```rust title="bitor-trait" showLineNumbers -trait BitOr { - fn bitor(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L79-L83 - -```rust title="bitand-trait" showLineNumbers -trait BitAnd { - fn bitand(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L95-L99 - -```rust title="bitxor-trait" showLineNumbers -trait BitXor { - fn bitxor(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L111-L115 - - -Traits for the bitwise operations `|`, `&`, and `^`. - -Implementing `BitOr`, `BitAnd` or `BitXor` for a type allows the `|`, `&`, or `^` operator respectively -to be used with the type. - -The implementations block below is given for the `BitOr` trait, but the same types that implement -`BitOr` also implement `BitAnd` and `BitXor`. - -Implementations: -```rust -impl BitOr for bool { fn bitor(self, other: bool) -> bool { self | other } } - -impl BitOr for u8 { fn bitor(self, other: u8) -> u8 { self | other } } -impl BitOr for u16 { fn bitor(self, other: u16) -> u16 { self | other } } -impl BitOr for u32 { fn bitor(self, other: u32) -> u32 { self | other } } -impl BitOr for u64 { fn bitor(self, other: u64) -> u64 { self | other } } - -impl BitOr for i8 { fn bitor(self, other: i8) -> i8 { self | other } } -impl BitOr for i16 { fn bitor(self, other: i16) -> i16 { self | other } } -impl BitOr for i32 { fn bitor(self, other: i32) -> i32 { self | other } } -impl BitOr for i64 { fn bitor(self, other: i64) -> i64 { self | other } } -``` - -### `std::ops::{ Shl, Shr }` - -```rust title="shl-trait" showLineNumbers -trait Shl { - fn shl(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L127-L131 - -```rust title="shr-trait" showLineNumbers -trait Shr { - fn shr(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L142-L146 - - -Traits for a bit shift left and bit shift right. - -Implementing `Shl` for a type allows the left shift operator (`<<`) to be used with the implementation type. -Similarly, implementing `Shr` allows the right shift operator (`>>`) to be used with the type. - -Note that bit shifting is not currently implemented for signed types. - -The implementations block below is given for the `Shl` trait, but the same types that implement -`Shl` also implement `Shr`. - -Implementations: -```rust -impl Shl for u8 { fn shl(self, other: u8) -> u8 { self << other } } -impl Shl for u16 { fn shl(self, other: u16) -> u16 { self << other } } -impl Shl for u32 { fn shl(self, other: u32) -> u32 { self << other } } -impl Shl for u64 { fn shl(self, other: u64) -> u64 { self << other } } -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/zeroed.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/zeroed.md deleted file mode 100644 index f450fecdd36..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/zeroed.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Zeroed Function -description: - The zeroed function returns a zeroed value of any type. -keywords: - [ - zeroed - ] ---- - -Implements `fn zeroed() -> T` to return a zeroed value of any type. This function is generally unsafe to use as the zeroed bit pattern is not guaranteed to be valid for all types. It can however, be useful in cases when the value is guaranteed not to be used such as in a BoundedVec library implementing a growable vector, up to a certain length, backed by an array. The array can be initialized with zeroed values which are guaranteed to be inaccessible until the vector is pushed to. Similarly, enumerations in noir can be implemented using this method by providing zeroed values for the unused variants. - -You can access the function at `std::unsafe::zeroed`. - -This function currently supports the following types: - -- Field -- Bool -- Uint -- Array -- Slice -- String -- Tuple -- Function - -Using it on other types could result in unexpected behavior. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/backend_barretenberg/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/backend_barretenberg/.nojekyll deleted file mode 100644 index e2ac6616add..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/backend_barretenberg/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md deleted file mode 100644 index b18c1926b93..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md +++ /dev/null @@ -1,119 +0,0 @@ -# BarretenbergBackend - -## Implements - -- [`Backend`](../index.md#backend) - -## Constructors - -### new BarretenbergBackend(acirCircuit, options) - -```ts -new BarretenbergBackend(acirCircuit, options): BarretenbergBackend -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `acirCircuit` | `CompiledCircuit` | -| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | - -#### Returns - -[`BarretenbergBackend`](BarretenbergBackend.md) - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -*** - -### generateProof() - -```ts -generateProof(compressedWitness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `compressedWitness` | `Uint8Array` | - -#### Returns - -`Promise`\<`ProofData`\> - -#### Description - -Generates a proof - -*** - -### generateRecursiveProofArtifacts() - -```ts -generateRecursiveProofArtifacts(proofData, numOfPublicInputs): Promise -``` - -Generates artifacts that will be passed to a circuit that will verify this proof. - -Instead of passing the proof and verification key as a byte array, we pass them -as fields which makes it cheaper to verify in a circuit. - -The proof that is passed here will have been created using a circuit -that has the #[recursive] attribute on its `main` method. - -The number of public inputs denotes how many public inputs are in the inner proof. - -#### Parameters - -| Parameter | Type | Default value | -| :------ | :------ | :------ | -| `proofData` | `ProofData` | `undefined` | -| `numOfPublicInputs` | `number` | `0` | - -#### Returns - -`Promise`\<`object`\> - -#### Example - -```typescript -const artifacts = await backend.generateRecursiveProofArtifacts(proof, numOfPublicInputs); -``` - -*** - -### verifyProof() - -```ts -verifyProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | `ProofData` | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Verifies a proof - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/backend_barretenberg/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/backend_barretenberg/index.md deleted file mode 100644 index c146316a915..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/backend_barretenberg/index.md +++ /dev/null @@ -1,58 +0,0 @@ -# backend_barretenberg - -## Exports - -### Classes - -| Class | Description | -| :------ | :------ | -| [BarretenbergBackend](classes/BarretenbergBackend.md) | - | - -### Type Aliases - -| Type alias | Description | -| :------ | :------ | -| [BackendOptions](type-aliases/BackendOptions.md) | - | - -## References - -### CompiledCircuit - -Renames and re-exports [Backend](index.md#backend) - -*** - -### ProofData - -Renames and re-exports [Backend](index.md#backend) - -## Variables - -### Backend - -```ts -Backend: any; -``` - -## Functions - -### publicInputsToWitnessMap() - -```ts -publicInputsToWitnessMap(publicInputs, abi): Backend -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `publicInputs` | `string`[] | -| `abi` | `Abi` | - -#### Returns - -[`Backend`](index.md#backend) - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md deleted file mode 100644 index b49a479f4f4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md +++ /dev/null @@ -1,21 +0,0 @@ -# BackendOptions - -```ts -type BackendOptions: object; -``` - -## Description - -An options object, currently only used to specify the number of threads to use. - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `memory` | `object` | - | -| `memory.maximum` | `number` | - | -| `threads` | `number` | **Description**

Number of threads | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs deleted file mode 100644 index 339353b9862..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend","label":"BarretenbergBackend"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions","label":"BackendOptions"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/.nojekyll deleted file mode 100644 index e2ac6616add..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/classes/Noir.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/classes/Noir.md deleted file mode 100644 index 45dd62ee57e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/classes/Noir.md +++ /dev/null @@ -1,132 +0,0 @@ -# Noir - -## Constructors - -### new Noir(circuit, backend) - -```ts -new Noir(circuit, backend?): Noir -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `circuit` | `CompiledCircuit` | -| `backend`? | `any` | - -#### Returns - -[`Noir`](Noir.md) - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Description - -Destroys the underlying backend instance. - -#### Example - -```typescript -await noir.destroy(); -``` - -*** - -### execute() - -```ts -execute(inputs, foreignCallHandler?): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `inputs` | `InputMap` | -| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | - -#### Returns - -`Promise`\<`object`\> - -#### Description - -Allows to execute a circuit to get its witness and return value. - -#### Example - -```typescript -async execute(inputs) -``` - -*** - -### generateProof() - -```ts -generateProof(inputs, foreignCallHandler?): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `inputs` | `InputMap` | -| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | - -#### Returns - -`Promise`\<`ProofData`\> - -#### Description - -Generates a witness and a proof given an object as input. - -#### Example - -```typescript -async generateProof(input) -``` - -*** - -### verifyProof() - -```ts -verifyProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | `ProofData` | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Instantiates the verification key and verifies a proof. - -#### Example - -```typescript -async verifyProof(proof) -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/and.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/and.md deleted file mode 100644 index c783283e396..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/and.md +++ /dev/null @@ -1,22 +0,0 @@ -# and() - -```ts -and(lhs, rhs): string -``` - -Performs a bitwise AND operation between `lhs` and `rhs` - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `lhs` | `string` | | -| `rhs` | `string` | | - -## Returns - -`string` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/blake2s256.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/blake2s256.md deleted file mode 100644 index 7882d0da8d5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/blake2s256.md +++ /dev/null @@ -1,21 +0,0 @@ -# blake2s256() - -```ts -blake2s256(inputs): Uint8Array -``` - -Calculates the Blake2s256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md deleted file mode 100644 index 5e3cd53e9d3..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md +++ /dev/null @@ -1,28 +0,0 @@ -# ecdsa\_secp256k1\_verify() - -```ts -ecdsa_secp256k1_verify( - hashed_msg, - public_key_x_bytes, - public_key_y_bytes, - signature): boolean -``` - -Verifies a ECDSA signature over the secp256k1 curve. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `hashed_msg` | `Uint8Array` | | -| `public_key_x_bytes` | `Uint8Array` | | -| `public_key_y_bytes` | `Uint8Array` | | -| `signature` | `Uint8Array` | | - -## Returns - -`boolean` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md deleted file mode 100644 index 0b20ff68957..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md +++ /dev/null @@ -1,28 +0,0 @@ -# ecdsa\_secp256r1\_verify() - -```ts -ecdsa_secp256r1_verify( - hashed_msg, - public_key_x_bytes, - public_key_y_bytes, - signature): boolean -``` - -Verifies a ECDSA signature over the secp256r1 curve. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `hashed_msg` | `Uint8Array` | | -| `public_key_x_bytes` | `Uint8Array` | | -| `public_key_y_bytes` | `Uint8Array` | | -| `signature` | `Uint8Array` | | - -## Returns - -`boolean` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/keccak256.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/keccak256.md deleted file mode 100644 index d10f155ce86..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/keccak256.md +++ /dev/null @@ -1,21 +0,0 @@ -# keccak256() - -```ts -keccak256(inputs): Uint8Array -``` - -Calculates the Keccak256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/sha256.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/sha256.md deleted file mode 100644 index 6ba4ecac022..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/sha256.md +++ /dev/null @@ -1,21 +0,0 @@ -# sha256() - -```ts -sha256(inputs): Uint8Array -``` - -Calculates the SHA256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/xor.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/xor.md deleted file mode 100644 index 8d762b895d3..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/xor.md +++ /dev/null @@ -1,22 +0,0 @@ -# xor() - -```ts -xor(lhs, rhs): string -``` - -Performs a bitwise XOR operation between `lhs` and `rhs` - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `lhs` | `string` | | -| `rhs` | `string` | | - -## Returns - -`string` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/index.md deleted file mode 100644 index cca6b3ace41..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/index.md +++ /dev/null @@ -1,54 +0,0 @@ -# noir_js - -## Exports - -### Classes - -| Class | Description | -| :------ | :------ | -| [Noir](classes/Noir.md) | - | - -### Type Aliases - -| Type alias | Description | -| :------ | :------ | -| [ForeignCallHandler](type-aliases/ForeignCallHandler.md) | A callback which performs an foreign call and returns the response. | -| [ForeignCallInput](type-aliases/ForeignCallInput.md) | - | -| [ForeignCallOutput](type-aliases/ForeignCallOutput.md) | - | -| [WitnessMap](type-aliases/WitnessMap.md) | - | - -### Functions - -| Function | Description | -| :------ | :------ | -| [and](functions/and.md) | Performs a bitwise AND operation between `lhs` and `rhs` | -| [blake2s256](functions/blake2s256.md) | Calculates the Blake2s256 hash of the input bytes | -| [ecdsa\_secp256k1\_verify](functions/ecdsa_secp256k1_verify.md) | Verifies a ECDSA signature over the secp256k1 curve. | -| [ecdsa\_secp256r1\_verify](functions/ecdsa_secp256r1_verify.md) | Verifies a ECDSA signature over the secp256r1 curve. | -| [keccak256](functions/keccak256.md) | Calculates the Keccak256 hash of the input bytes | -| [sha256](functions/sha256.md) | Calculates the SHA256 hash of the input bytes | -| [xor](functions/xor.md) | Performs a bitwise XOR operation between `lhs` and `rhs` | - -## References - -### CompiledCircuit - -Renames and re-exports [InputMap](index.md#inputmap) - -*** - -### ProofData - -Renames and re-exports [InputMap](index.md#inputmap) - -## Variables - -### InputMap - -```ts -InputMap: any; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md deleted file mode 100644 index 812b8b16481..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md +++ /dev/null @@ -1,24 +0,0 @@ -# ForeignCallHandler - -```ts -type ForeignCallHandler: (name, inputs) => Promise; -``` - -A callback which performs an foreign call and returns the response. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `name` | `string` | The identifier for the type of foreign call being performed. | -| `inputs` | [`ForeignCallInput`](ForeignCallInput.md)[] | An array of hex encoded inputs to the foreign call. | - -## Returns - -`Promise`\<[`ForeignCallOutput`](ForeignCallOutput.md)[]\> - -outputs - An array of hex encoded outputs containing the results of the foreign call. - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md deleted file mode 100644 index dd95809186a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md +++ /dev/null @@ -1,9 +0,0 @@ -# ForeignCallInput - -```ts -type ForeignCallInput: string[]; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md deleted file mode 100644 index b71fb78a946..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md +++ /dev/null @@ -1,9 +0,0 @@ -# ForeignCallOutput - -```ts -type ForeignCallOutput: string | string[]; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md deleted file mode 100644 index 258c46f9d0c..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md +++ /dev/null @@ -1,9 +0,0 @@ -# WitnessMap - -```ts -type WitnessMap: Map; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs deleted file mode 100644 index c6d8125eaad..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/noir_js/classes/Noir","label":"Noir"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallHandler","label":"ForeignCallHandler"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallInput","label":"ForeignCallInput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallOutput","label":"ForeignCallOutput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/WitnessMap","label":"WitnessMap"}]},{"type":"category","label":"Functions","items":[{"type":"doc","id":"reference/NoirJS/noir_js/functions/and","label":"and"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/blake2s256","label":"blake2s256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify","label":"ecdsa_secp256k1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify","label":"ecdsa_secp256r1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/keccak256","label":"keccak256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/sha256","label":"sha256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/xor","label":"xor"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/.nojekyll deleted file mode 100644 index e2ac6616add..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/functions/compile.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/functions/compile.md deleted file mode 100644 index 6faf763b37f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/functions/compile.md +++ /dev/null @@ -1,51 +0,0 @@ -# compile() - -```ts -compile( - fileManager, - projectPath?, - logFn?, -debugLogFn?): Promise -``` - -Compiles a Noir project - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `fileManager` | `FileManager` | The file manager to use | -| `projectPath`? | `string` | The path to the project inside the file manager. Defaults to the root of the file manager | -| `logFn`? | `LogFn` | A logging function. If not provided, console.log will be used | -| `debugLogFn`? | `LogFn` | A debug logging function. If not provided, logFn will be used | - -## Returns - -`Promise`\<[`ProgramCompilationArtifacts`](../index.md#programcompilationartifacts)\> - -## Example - -```typescript -// Node.js - -import { compile_program, createFileManager } from '@noir-lang/noir_wasm'; - -const fm = createFileManager(myProjectPath); -const myCompiledCode = await compile_program(fm); -``` - -```typescript -// Browser - -import { compile_program, createFileManager } from '@noir-lang/noir_wasm'; - -const fm = createFileManager('/'); -for (const path of files) { - await fm.writeFile(path, await getFileAsStream(path)); -} -const myCompiledCode = await compile_program(fm); -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/functions/compile_contract.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/functions/compile_contract.md deleted file mode 100644 index 7d0b39a43ef..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/functions/compile_contract.md +++ /dev/null @@ -1,51 +0,0 @@ -# compile\_contract() - -```ts -compile_contract( - fileManager, - projectPath?, - logFn?, -debugLogFn?): Promise -``` - -Compiles a Noir project - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `fileManager` | `FileManager` | The file manager to use | -| `projectPath`? | `string` | The path to the project inside the file manager. Defaults to the root of the file manager | -| `logFn`? | `LogFn` | A logging function. If not provided, console.log will be used | -| `debugLogFn`? | `LogFn` | A debug logging function. If not provided, logFn will be used | - -## Returns - -`Promise`\<[`ContractCompilationArtifacts`](../index.md#contractcompilationartifacts)\> - -## Example - -```typescript -// Node.js - -import { compile_contract, createFileManager } from '@noir-lang/noir_wasm'; - -const fm = createFileManager(myProjectPath); -const myCompiledCode = await compile_contract(fm); -``` - -```typescript -// Browser - -import { compile_contract, createFileManager } from '@noir-lang/noir_wasm'; - -const fm = createFileManager('/'); -for (const path of files) { - await fm.writeFile(path, await getFileAsStream(path)); -} -const myCompiledCode = await compile_contract(fm); -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/functions/createFileManager.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/functions/createFileManager.md deleted file mode 100644 index 7e65c1d69c7..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/functions/createFileManager.md +++ /dev/null @@ -1,21 +0,0 @@ -# createFileManager() - -```ts -createFileManager(dataDir): FileManager -``` - -Creates a new FileManager instance based on fs in node and memfs in the browser (via webpack alias) - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `dataDir` | `string` | root of the file system | - -## Returns - -`FileManager` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md deleted file mode 100644 index fcea9275341..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md +++ /dev/null @@ -1,21 +0,0 @@ -# inflateDebugSymbols() - -```ts -inflateDebugSymbols(debugSymbols): any -``` - -Decompresses and decodes the debug symbols - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `debugSymbols` | `string` | The base64 encoded debug symbols | - -## Returns - -`any` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/index.md deleted file mode 100644 index b6e0f9d1bc0..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/index.md +++ /dev/null @@ -1,49 +0,0 @@ -# noir_wasm - -## Exports - -### Functions - -| Function | Description | -| :------ | :------ | -| [compile](functions/compile.md) | Compiles a Noir project | -| [compile\_contract](functions/compile_contract.md) | Compiles a Noir project | -| [createFileManager](functions/createFileManager.md) | Creates a new FileManager instance based on fs in node and memfs in the browser (via webpack alias) | -| [inflateDebugSymbols](functions/inflateDebugSymbols.md) | Decompresses and decodes the debug symbols | - -## References - -### compile\_program - -Renames and re-exports [compile](functions/compile.md) - -## Interfaces - -### ContractCompilationArtifacts - -The compilation artifacts of a given contract. - -#### Properties - -| Property | Type | Description | -| :------ | :------ | :------ | -| `contract` | `ContractArtifact` | The compiled contract. | -| `warnings` | `unknown`[] | Compilation warnings. | - -*** - -### ProgramCompilationArtifacts - -The compilation artifacts of a given program. - -#### Properties - -| Property | Type | Description | -| :------ | :------ | :------ | -| `name` | `string` | not part of the compilation output, injected later | -| `program` | `ProgramArtifact` | The compiled contract. | -| `warnings` | `unknown`[] | Compilation warnings. | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs deleted file mode 100644 index e0870710349..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"doc","id":"reference/NoirJS/noir_wasm/index","label":"API"},{"type":"category","label":"Functions","items":[{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/compile","label":"compile"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/compile_contract","label":"compile_contract"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/createFileManager","label":"createFileManager"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/inflateDebugSymbols","label":"inflateDebugSymbols"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/_category_.json deleted file mode 100644 index 5b6a20a609a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 4, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/tutorials/noirjs_app.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/tutorials/noirjs_app.md deleted file mode 100644 index 0d75e2e8045..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/tutorials/noirjs_app.md +++ /dev/null @@ -1,279 +0,0 @@ ---- -title: Building a web app with NoirJS -description: Learn how to setup a new app that uses Noir to generate and verify zero-knowledge SNARK proofs in a typescript or javascript environment. -keywords: [how to, guide, javascript, typescript, noir, barretenberg, zero-knowledge, proofs, app] -sidebar_position: 0 -pagination_next: noir/concepts/data_types/index ---- - -NoirJS is a set of packages meant to work both in a browser and a server environment. In this tutorial, we will build a simple web app using them. From here, you should get an idea on how to proceed with your own Noir projects! - -You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). - -## Setup - -:::note - -Feel free to use whatever versions, just keep in mind that Nargo and the NoirJS packages are meant to be in sync. For example, Nargo 0.19.x matches `noir_js@0.19.x`, etc. - -In this guide, we will be pinned to 0.19.4. - -::: - -Before we start, we want to make sure we have Node and Nargo installed. - -We start by opening a terminal and executing `node --version`. If we don't get an output like `v20.10.0`, that means node is not installed. Let's do that by following the handy [nvm guide](https://github.com/nvm-sh/nvm?tab=readme-ov-file#install--update-script). - -As for `Nargo`, we can follow the [Nargo guide](../getting_started/installation/index.md) to install it. If you're lazy, just paste this on a terminal and run `noirup`: - -```sh -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -Easy enough. Onwards! - -## Our project - -ZK is a powerful technology. An app that doesn't reveal one of the inputs to *anyone* is almost unbelievable, yet Noir makes it as easy as a single line of code. - -In fact, it's so simple that it comes nicely packaged in `nargo`. Let's do that! - -### Nargo - -Run: - -```nargo new circuit``` - -And... That's about it. Your program is ready to be compiled and run. - -To compile, let's `cd` into the `circuit` folder to enter our project, and call: - -```nargo compile``` - -This compiles our circuit into `json` format and add it to a new `target` folder. - -:::info - -At this point in the tutorial, your folder structure should look like this: - -```tree -. -└── circuit <---- our working directory - ├── Nargo.toml - ├── src - │ └── main.nr - └── target - └── circuit.json -``` - -::: - -### Node and Vite - -If you want to explore Nargo, feel free to go on a side-quest now and follow the steps in the -[getting started](../getting_started/hello_noir/index.md) guide. However, we want our app to run on the browser, so we need Vite. - -Vite is a powerful tool to generate static websites. While it provides all kinds of features, let's just go barebones with some good old vanilla JS. - -To do this this, go back to the previous folder (`cd ..`) and create a new vite project by running `npm create vite` and choosing "Vanilla" and "Javascript". - -You should see `vite-project` appear in your root folder. This seems like a good time to `cd` into it and install our NoirJS packages: - -```bash -npm i @noir-lang/backend_barretenberg@0.19.4 @noir-lang/noir_js@0.19.4 -``` - -:::info - -At this point in the tutorial, your folder structure should look like this: - -```tree -. -└── circuit - └── ...etc... -└── vite-project <---- our working directory - └── ...etc... -``` - -::: - -#### Some cleanup - -`npx create vite` is amazing but it creates a bunch of files we don't really need for our simple example. Actually, let's just delete everything except for `index.html`, `main.js` and `package.json`. I feel lighter already. - -![my heart is ready for you, noir.js](@site/static/img/memes/titanic.jpeg) - -## HTML - -Our app won't run like this, of course. We need some working HTML, at least. Let's open our broken-hearted `index.html` and replace everything with this code snippet: - -```html - - - - - - -

Noir app

-
- - -
-
-

Logs

-

Proof

-
- - -``` - -It *could* be a beautiful UI... Depending on which universe you live in. - -## Some good old vanilla Javascript - -Our love for Noir needs undivided attention, so let's just open `main.js` and delete everything (this is where the romantic scenery becomes a bit creepy). - -Start by pasting in this boilerplate code: - -```js -const setup = async () => { - await Promise.all([ - import("@noir-lang/noirc_abi").then(module => - module.default(new URL("@noir-lang/noirc_abi/web/noirc_abi_wasm_bg.wasm", import.meta.url).toString()) - ), - import("@noir-lang/acvm_js").then(module => - module.default(new URL("@noir-lang/acvm_js/web/acvm_js_bg.wasm", import.meta.url).toString()) - ) - ]); -} - -function display(container, msg) { - const c = document.getElementById(container); - const p = document.createElement('p'); - p.textContent = msg; - c.appendChild(p); -} - -document.getElementById('submitGuess').addEventListener('click', async () => { - try { - // here's where love happens - } catch(err) { - display("logs", "Oh 💔 Wrong guess") - } -}); - -``` - -The display function doesn't do much. We're simply manipulating our website to see stuff happening. For example, if the proof fails, it will simply log a broken heart 😢 - -As for the `setup` function, it's just a sad reminder that dealing with `wasm` on the browser is not as easy as it should. Just copy, paste, and forget. - -:::info - -At this point in the tutorial, your folder structure should look like this: - -```tree -. -└── circuit - └── ...same as above -└── vite-project - ├── main.js - ├── package.json - └── index.html -``` - -You'll see other files and folders showing up (like `package-lock.json`, `node_modules`) but you shouldn't have to care about those. - -::: - -## Some NoirJS - -We're starting with the good stuff now. If you've compiled the circuit as described above, you should have a `json` file we want to import at the very top of our `main.js` file: - -```ts -import circuit from '../circuit/target/circuit.json'; -``` - -[Noir is backend-agnostic](../index.mdx#whats-new-about-noir). We write Noir, but we also need a proving backend. That's why we need to import and instantiate the two dependencies we installed above: `BarretenbergBackend` and `Noir`. Let's import them right below: - -```js -import { BarretenbergBackend } from '@noir-lang/backend_barretenberg'; -import { Noir } from '@noir-lang/noir_js'; -``` - -And instantiate them inside our try-catch block: - -```ts -// try { -const backend = new BarretenbergBackend(circuit); -const noir = new Noir(circuit, backend); -// } -``` - -:::note - -For the remainder of the tutorial, everything will be happening inside the `try` block - -::: - -## Our app - -Now for the app itself. We're capturing whatever is in the input when people press the submit button. Just add this: - -```js -const x = parseInt(document.getElementById('guessInput').value); -const input = { x, y: 2 }; -``` - -Now we're ready to prove stuff! Let's feed some inputs to our circuit and calculate the proof: - -```js -await setup(); // let's squeeze our wasm inits here - -display('logs', 'Generating proof... ⌛'); -const proof = await noir.generateProof(input); -display('logs', 'Generating proof... ✅'); -display('results', proof.proof); -``` - -You're probably eager to see stuff happening, so go and run your app now! - -From your terminal, run `npm run dev`. If it doesn't open a browser for you, just visit `localhost:5173`. You should now see the worst UI ever, with an ugly input. - -![Getting Started 0](@site/static/img/noir_getting_started_1.png) - -Now, our circuit says `fn main(x: Field, y: pub Field)`. This means only the `y` value is public, and it's hardcoded above: `input = { x, y: 2 }`. In other words, you won't need to send your secret`x` to the verifier! - -By inputting any number other than 2 in the input box and clicking "submit", you should get a valid proof. Otherwise the proof won't even generate correctly. By the way, if you're human, you shouldn't be able to understand anything on the "proof" box. That's OK. We like you, human ❤️. - -## Verifying - -Time to celebrate, yes! But we shouldn't trust machines so blindly. Let's add these lines to see our proof being verified: - -```js -display('logs', 'Verifying proof... ⌛'); -const verification = await noir.verifyProof(proof); -if (verification) display('logs', 'Verifying proof... ✅'); -``` - -You have successfully generated a client-side Noir web app! - -![coded app without math knowledge](@site/static/img/memes/flextape.jpeg) - -## Further Reading - -You can see how noirjs is used in a full stack Next.js hardhat application in the [noir-starter repo here](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat). The example shows how to calculate a proof in the browser and verify it with a deployed Solidity verifier contract from noirjs. - -You should also check out the more advanced examples in the [noir-examples repo](https://github.com/noir-lang/noir-examples), where you'll find reference usage for some cool apps. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/explainers/explainer-oracle.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/explainers/explainer-oracle.md deleted file mode 100644 index b84ca5dd986..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/explainers/explainer-oracle.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: Oracles -description: This guide provides an in-depth understanding of how Oracles work in Noir programming. Learn how to use outside calculations in your programs, constrain oracles, and understand their uses and limitations. -keywords: - - Noir Programming - - Oracles - - JSON-RPC - - Foreign Call Handlers - - Constrained Functions - - Blockchain Programming -sidebar_position: 1 ---- - -If you've seen "The Matrix" you may recall "The Oracle" as Gloria Foster smoking cigarettes and baking cookies. While she appears to "know things", she is actually providing a calculation of a pre-determined future. Noir Oracles are similar, in a way. They don't calculate the future (yet), but they allow you to use outside calculations in your programs. - -![matrix oracle prediction](@site/static/img/memes/matrix_oracle.jpeg) - -A Noir program is usually self-contained. You can pass certain inputs to it, and it will generate a deterministic output for those inputs. But what if you wanted to defer some calculation to an outside process or source? - -Oracles are functions that provide this feature. - -## Use cases - -An example usage for Oracles is proving something on-chain. For example, proving that the ETH-USDC quote was below a certain target at a certain block time. Or even making more complex proofs like proving the ownership of an NFT as an anonymous login method. - -Another interesting use case is to defer expensive calculations to be made outside of the Noir program, and then constraining the result; similar to the use of [unconstrained functions](../noir/concepts//unconstrained.md). - -In short, anything that can be constrained in a Noir program but needs to be fetched from an external source is a great candidate to be used in oracles. - -## Constraining oracles - -Just like in The Matrix, Oracles are powerful. But with great power, comes great responsibility. Just because you're using them in a Noir program doesn't mean they're true. Noir has no superpowers. If you want to prove that Portugal won the Euro Cup 2016, you're still relying on potentially untrusted information. - -To give a concrete example, Alice wants to login to the [NounsDAO](https://nouns.wtf/) forum with her username "noir_nouner" by proving she owns a noun without revealing her ethereum address. Her Noir program could have a oracle call like this: - -```rust -#[oracle(getNoun)] -unconstrained fn get_noun(address: Field) -> Field -``` - -This oracle could naively resolve with the number of Nouns she possesses. However, it is useless as a trusted source, as the oracle could resolve to anything Alice wants. In order to make this oracle call actually useful, Alice would need to constrain the response from the oracle, by proving her address and the noun count belongs to the state tree of the contract. - -In short, **Oracles don't prove anything. Your Noir program does.** - -:::danger - -If you don't constrain the return of your oracle, you could be clearly opening an attack vector on your Noir program. Make double-triple sure that the return of an oracle call is constrained! - -::: - -## How to use Oracles - -On CLI, Nargo resolves oracles by making JSON RPC calls, which means it would require an RPC node to be running. - -In JavaScript, NoirJS accepts and resolves arbitrary call handlers (that is, not limited to JSON) as long as they matches the expected types the developer defines. Refer to [Foreign Call Handler](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) to learn more about NoirJS's call handling. - -If you want to build using oracles, follow through to the [oracle guide](../how_to/how-to-oracles.md) for a simple example on how to do that. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/explainers/explainer-recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/explainers/explainer-recursion.md deleted file mode 100644 index 18846176ca7..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/explainers/explainer-recursion.md +++ /dev/null @@ -1,176 +0,0 @@ ---- -title: Recursive proofs -description: Explore the concept of recursive proofs in Zero-Knowledge programming. Understand how recursion works in Noir, a language for writing smart contracts on the EVM blockchain. Learn through practical examples like Alice and Bob's guessing game, Charlie's recursive merkle tree, and Daniel's reusable components. Discover how to use recursive proofs to optimize computational resources and improve efficiency. - -keywords: - [ - "Recursive Proofs", - "Zero-Knowledge Programming", - "Noir", - "EVM Blockchain", - "Smart Contracts", - "Recursion in Noir", - "Alice and Bob Guessing Game", - "Recursive Merkle Tree", - "Reusable Components", - "Optimizing Computational Resources", - "Improving Efficiency", - "Verification Key", - "Aggregation", - "Recursive zkSNARK schemes", - "PLONK", - "Proving and Verification Keys" - ] -sidebar_position: 1 -pagination_next: how_to/how-to-recursion ---- - -In programming, we tend to think of recursion as something calling itself. A classic example would be the calculation of the factorial of a number: - -```js -function factorial(n) { - if (n === 0 || n === 1) { - return 1; - } else { - return n * factorial(n - 1); - } -} -``` - -In this case, while `n` is not `1`, this function will keep calling itself until it hits the base case, bubbling up the result on the call stack: - -```md - Is `n` 1? <--------- - /\ / - / \ n = n -1 - / \ / - Yes No -------- -``` - -In Zero-Knowledge, recursion has some similarities. - -It is not a Noir function calling itself, but a proof being used as an input to another circuit. In short, you verify one proof *inside* another proof, returning the proof that both proofs are valid. - -This means that, given enough computational resources, you can prove the correctness of any arbitrary number of proofs in a single proof. This could be useful to design state channels (for which a common example would be [Bitcoin's Lightning Network](https://en.wikipedia.org/wiki/Lightning_Network)), to save on gas costs by settling one proof on-chain, or simply to make business logic less dependent on a consensus mechanism. - -## Examples - -Let us look at some of these examples - -### Alice and Bob - Guessing game - -Alice and Bob are friends, and they like guessing games. They want to play a guessing game online, but for that, they need a trusted third-party that knows both of their secrets and finishes the game once someone wins. - -So, they use zero-knowledge proofs. Alice tries to guess Bob's number, and Bob will generate a ZK proof stating whether she succeeded or failed. - -This ZK proof can go on a smart contract, revealing the winner and even giving prizes. However, this means every turn needs to be verified on-chain. This incurs some cost and waiting time that may simply make the game too expensive or time-consuming to be worth it. - -As a solution, Alice proposes the following: "what if Bob generates his proof, and instead of sending it on-chain, I verify it *within* my own proof before playing my own turn?". - -She can then generate a proof that she verified his proof, and so on. - -```md - Did you fail? <-------------------------- - / \ / - / \ n = n -1 - / \ / - Yes No / - | | / - | | / - | You win / - | / - | / -Generate proof of that / - + / - my own guess ---------------- -``` - -### Charlie - Recursive merkle tree - -Charlie is a concerned citizen, and wants to be sure his vote in an election is accounted for. He votes with a ZK proof, but he has no way of knowing that his ZK proof was included in the total vote count! - -If the vote collector puts all of the votes into a [Merkle tree](https://en.wikipedia.org/wiki/Merkle_tree), everyone can prove the verification of two proofs within one proof, as such: - -```md - abcd - __________|______________ - | | - ab cd - _____|_____ ______|______ - | | | | - alice bob charlie daniel -``` - -Doing this recursively allows us to arrive on a final proof `abcd` which if true, verifies the correctness of all the votes. - -### Daniel - Reusable components - -Daniel has a big circuit and a big headache. A part of his circuit is a setup phase that finishes with some assertions that need to be made. But that section alone takes most of the proving time, and is largely independent of the rest of the circuit. - -He might find it more efficient to generate a proof for that setup phase separately, and verify that proof recursively in the actual business logic section of his circuit. This will allow for parallelization of both proofs, which results in a considerable speedup. - -## What params do I need - -As you can see in the [recursion reference](noir/standard_library/recursion.md), a simple recursive proof requires: - -- The proof to verify -- The Verification Key of the circuit that generated the proof -- A hash of this verification key, as it's needed for some backends -- The public inputs for the proof - -:::info - -Recursive zkSNARK schemes do not necessarily "verify a proof" in the sense that you expect a true or false to be spit out by the verifier. Rather an aggregation object is built over the public inputs. - -So, taking the example of Alice and Bob and their guessing game: - -- Alice makes her guess. Her proof is *not* recursive: it doesn't verify any proof within it! It's just a standard `assert(x != y)` circuit -- Bob verifies Alice's proof and makes his own guess. In this circuit, he doesn't exactly *prove* the verification of Alice's proof. Instead, he *aggregates* his proof to Alice's proof. The actual verification is done when the full proof is verified, for example when using `nargo verify` or through the verifier smart contract. - -We can imagine recursive proofs a [relay race](https://en.wikipedia.org/wiki/Relay_race). The first runner doesn't have to receive the baton from anyone else, as he/she already starts with it. But when his/her turn is over, the next runner needs to receive it, run a bit more, and pass it along. Even though every runner could theoretically verify the baton mid-run (why not? 🏃🔍), only at the end of the race does the referee verify that the whole race is valid. - -::: - -## Some architecture - -As with everything in computer science, there's no one-size-fits all. But there are some patterns that could help understanding and implementing them. To give three examples: - -### Adding some logic to a proof verification - -This would be an approach for something like our guessing game, where proofs are sent back and forth and are verified by each opponent. This circuit would be divided in two sections: - -- A `recursive verification` section, which would be just the call to `std::verify_proof`, and that would be skipped on the first move (since there's no proof to verify) -- A `guessing` section, which is basically the logic part where the actual guessing happens - -In such a situation, and assuming Alice is first, she would skip the first part and try to guess Bob's number. Bob would then verify her proof on the first section of his run, and try to guess Alice's number on the second part, and so on. - -### Aggregating proofs - -In some one-way interaction situations, recursion would allow for aggregation of simple proofs that don't need to be immediately verified on-chain or elsewhere. - -To give a practical example, a barman wouldn't need to verify a "proof-of-age" on-chain every time he serves alcohol to a customer. Instead, the architecture would comprise two circuits: - -- A `main`, non-recursive circuit with some logic -- A `recursive` circuit meant to verify two proofs in one proof - -The customer's proofs would be intermediate, and made on their phones, and the barman could just verify them locally. He would then aggregate them into a final proof sent on-chain (or elsewhere) at the end of the day. - -### Recursively verifying different circuits - -Nothing prevents you from verifying different circuits in a recursive proof, for example: - -- A `circuit1` circuit -- A `circuit2` circuit -- A `recursive` circuit - -In this example, a regulator could verify that taxes were paid for a specific purchase by aggregating both a `payer` circuit (proving that a purchase was made and taxes were paid), and a `receipt` circuit (proving that the payment was received) - -## How fast is it - -At the time of writing, verifying recursive proofs is surprisingly fast. This is because most of the time is spent on generating the verification key that will be used to generate the next proof. So you are able to cache the verification key and reuse it later. - -Currently, Noir JS packages don't expose the functionality of loading proving and verification keys, but that feature exists in the underlying `bb.js` package. - -## How can I try it - -Learn more about using recursion in Nargo and NoirJS in the [how-to guide](../how_to/how-to-recursion.md) and see a full example in [noir-examples](https://github.com/noir-lang/noir-examples). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/getting_started/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/getting_started/_category_.json deleted file mode 100644 index 5d694210bbf..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/getting_started/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 0, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/getting_started/hello_noir/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/getting_started/hello_noir/_category_.json deleted file mode 100644 index 23b560f610b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/getting_started/hello_noir/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 1, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/getting_started/hello_noir/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/getting_started/hello_noir/index.md deleted file mode 100644 index 743c4d8d634..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/getting_started/hello_noir/index.md +++ /dev/null @@ -1,142 +0,0 @@ ---- -title: Creating a Project -description: - Learn how to create and verify your first Noir program using Nargo, a programming language for - zero-knowledge proofs. -keywords: - [ - Nargo, - Noir, - zero-knowledge proofs, - programming language, - create Noir program, - verify Noir program, - step-by-step guide, - ] -sidebar_position: 1 - ---- - -Now that we have installed Nargo, it is time to make our first hello world program! - -## Create a Project Directory - -Noir code can live anywhere on your computer. Let us create a _projects_ folder in the home -directory to house our Noir programs. - -For Linux, macOS, and Windows PowerShell, create the directory and change directory into it by -running: - -```sh -mkdir ~/projects -cd ~/projects -``` - -## Create Our First Nargo Project - -Now that we are in the projects directory, create a new Nargo project by running: - -```sh -nargo new hello_world -``` - -> **Note:** `hello_world` can be any arbitrary project name, we are simply using `hello_world` for -> demonstration. -> -> In production, the common practice is to name the project folder as `circuits` for better -> identifiability when sitting alongside other folders in the codebase (e.g. `contracts`, `scripts`, -> `test`). - -A `hello_world` folder would be created. Similar to Rust, the folder houses _src/main.nr_ and -_Nargo.toml_ which contain the source code and environmental options of your Noir program -respectively. - -### Intro to Noir Syntax - -Let us take a closer look at _main.nr_. The default _main.nr_ generated should look like this: - -```rust -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` - -The first line of the program specifies the program's inputs: - -```rust -x : Field, y : pub Field -``` - -Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the -keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](../../noir/concepts/data_types/index.md) section. - -The next line of the program specifies its body: - -```rust -assert(x != y); -``` - -The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. - -For more Noir syntax, check the [Language Concepts](../../noir/concepts/comments.md) chapter. - -## Build In/Output Files - -Change directory into _hello_world_ and build in/output files for your Noir program by running: - -```sh -cd hello_world -nargo check -``` - -Two additional files would be generated in your project directory: - -_Prover.toml_ houses input values, and _Verifier.toml_ houses public values. - -## Prove Our Noir Program - -Now that the project is set up, we can create a proof of correct execution of our Noir program. - -Fill in input values for execution in the _Prover.toml_ file. For example: - -```toml -x = "1" -y = "2" -``` - -Prove the valid execution of your Noir program: - -```sh -nargo prove -``` - -A new folder _proofs_ would then be generated in your project directory, containing the proof file -`.proof`, where the project name is defined in Nargo.toml. - -The _Verifier.toml_ file would also be updated with the public values computed from program -execution (in this case the value of `y`): - -```toml -y = "0x0000000000000000000000000000000000000000000000000000000000000002" -``` - -> **Note:** Values in _Verifier.toml_ are computed as 32-byte hex values. - -## Verify Our Noir Program - -Once a proof is generated, we can verify correct execution of our Noir program by verifying the -proof file. - -Verify your proof by running: - -```sh -nargo verify -``` - -The verification will complete in silence if it is successful. If it fails, it will log the -corresponding error instead. - -Congratulations, you have now created and verified a proof for your very first Noir program! - -In the [next section](./project_breakdown.md), we will go into more detail on each step performed. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/getting_started/hello_noir/project_breakdown.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/getting_started/hello_noir/project_breakdown.md deleted file mode 100644 index 6160a102c6c..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/getting_started/hello_noir/project_breakdown.md +++ /dev/null @@ -1,199 +0,0 @@ ---- -title: Project Breakdown -description: - Learn about the anatomy of a Nargo project, including the purpose of the Prover and Verifier TOML - files, and how to prove and verify your program. -keywords: - [Nargo, Nargo project, Prover.toml, Verifier.toml, proof verification, private asset transfer] -sidebar_position: 2 ---- - -This section breaks down our hello world program from the previous section. We elaborate on the project -structure and what the `prove` and `verify` commands did. - -## Anatomy of a Nargo Project - -Upon creating a new project with `nargo new` and building the in/output files with `nargo check` -commands, you would get a minimal Nargo project of the following structure: - - - src - - Prover.toml - - Verifier.toml - - Nargo.toml - -The source directory _src_ holds the source code for your Noir program. By default only a _main.nr_ -file will be generated within it. - -### Prover.toml - -_Prover.toml_ is used for specifying the input values for executing and proving the program. You can specify `toml` files with different names by using the `--prover-name` or `-p` flags, see the [Prover](#provertoml) section below. Optionally you may specify expected output values for prove-time checking as well. - -### Verifier.toml - -_Verifier.toml_ contains public in/output values computed when executing the Noir program. - -### Nargo.toml - -_Nargo.toml_ contains the environmental options of your project. It contains a "package" section and a "dependencies" section. - -Example Nargo.toml: - -```toml -[package] -name = "noir_starter" -type = "bin" -authors = ["Alice"] -compiler_version = "0.9.0" -description = "Getting started with Noir" -entry = "circuit/main.nr" -license = "MIT" - -[dependencies] -ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} -``` - -Nargo.toml for a [workspace](../../noir/modules_packages_crates/workspaces.md) will look a bit different. For example: - -```toml -[workspace] -members = ["crates/a", "crates/b"] -default-member = "crates/a" -``` - -#### Package section - -The package section defines a number of fields including: - -- `name` (**required**) - the name of the package -- `type` (**required**) - can be "bin", "lib", or "contract" to specify whether its a binary, library or Aztec contract -- `authors` (optional) - authors of the project -- `compiler_version` - specifies the version of the compiler to use. This is enforced by the compiler and follow's [Rust's versioning](https://doc.rust-lang.org/cargo/reference/manifest.html#the-version-field), so a `compiler_version = 0.18.0` will enforce Nargo version 0.18.0, `compiler_version = ^0.18.0` will enforce anything above 0.18.0 but below 0.19.0, etc. For more information, see how [Rust handles these operators](https://docs.rs/semver/latest/semver/enum.Op.html) -- `description` (optional) -- `entry` (optional) - a relative filepath to use as the entry point into your package (overrides the default of `src/lib.nr` or `src/main.nr`) -- `backend` (optional) -- `license` (optional) - -#### Dependencies section - -This is where you will specify any dependencies for your project. See the [Dependencies page](../../noir/modules_packages_crates/dependencies.md) for more info. - -`./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or -verifier contract respectively. - -### main.nr - -The _main.nr_ file contains a `main` method, this method is the entry point into your Noir program. - -In our sample program, _main.nr_ looks like this: - -```rust -fn main(x : Field, y : Field) { - assert(x != y); -} -``` - -The parameters `x` and `y` can be seen as the API for the program and must be supplied by the -prover. Since neither `x` nor `y` is marked as public, the verifier does not supply any inputs, when -verifying the proof. - -The prover supplies the values for `x` and `y` in the _Prover.toml_ file. - -As for the program body, `assert` ensures that the condition to be satisfied (e.g. `x != y`) is -constrained by the proof of the execution of said program (i.e. if the condition was not met, the -verifier would reject the proof as an invalid proof). - -### Prover.toml - -The _Prover.toml_ file is a file which the prover uses to supply his witness values(both private and -public). - -In our hello world program the _Prover.toml_ file looks like this: - -```toml -x = "1" -y = "2" -``` - -When the command `nargo prove` is executed, two processes happen: - -1. Noir creates a proof that `x`, which holds the value of `1`, and `y`, which holds the value of `2`, - is not equal. This inequality constraint is due to the line `assert(x != y)`. - -2. Noir creates and stores the proof of this statement in the _proofs_ directory in a file called your-project.proof. So if your project is named "private_voting" (defined in the project Nargo.toml), the proof will be saved at `./proofs/private_voting.proof`. Opening this file will display the proof in hex format. - -#### Arrays of Structs - -The following code shows how to pass an array of structs to a Noir program to generate a proof. - -```rust -// main.nr -struct Foo { - bar: Field, - baz: Field, -} - -fn main(foos: [Foo; 3]) -> pub Field { - foos[2].bar + foos[2].baz -} -``` - -Prover.toml: - -```toml -[[foos]] # foos[0] -bar = 0 -baz = 0 - -[[foos]] # foos[1] -bar = 0 -baz = 0 - -[[foos]] # foos[2] -bar = 1 -baz = 2 -``` - -#### Custom toml files - -You can specify a `toml` file with a different name to use for proving by using the `--prover-name` or `-p` flags. - -This command looks for proof inputs in the default **Prover.toml** and generates the proof and saves it at `./proofs/.proof`: - -```bash -nargo prove -``` - -This command looks for proof inputs in the custom **OtherProver.toml** and generates proof and saves it at `./proofs/.proof`: - -```bash -nargo prove -p OtherProver -``` - -## Verifying a Proof - -When the command `nargo verify` is executed, two processes happen: - -1. Noir checks in the _proofs_ directory for a proof file with the project name (eg. test_project.proof) - -2. If that file is found, the proof's validity is checked - -> **Note:** The validity of the proof is linked to the current Noir program; if the program is -> changed and the verifier verifies the proof, it will fail because the proof is not valid for the -> _modified_ Noir program. - -In production, the prover and the verifier are usually two separate entities. A prover would -retrieve the necessary inputs, execute the Noir program, generate a proof and pass it to the -verifier. The verifier would then retrieve the public inputs, usually from external sources, and -verify the validity of the proof against it. - -Take a private asset transfer as an example: - -A person using a browser as the prover would retrieve private inputs locally (e.g. the user's private key) and -public inputs (e.g. the user's encrypted balance on-chain), compute the transfer, generate a proof -and submit it to the verifier smart contract. - -The verifier contract would then draw the user's encrypted balance directly from the blockchain and -verify the proof submitted against it. If the verification passes, additional functions in the -verifier contract could trigger (e.g. approve the asset transfer). - -Now that you understand the concepts, you'll probably want some editor feedback while you are writing more complex code. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/getting_started/installation/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/getting_started/installation/_category_.json deleted file mode 100644 index 0c02fb5d4d7..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/getting_started/installation/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "position": 0, - "label": "Install Nargo", - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/getting_started/installation/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/getting_started/installation/index.md deleted file mode 100644 index 4ef86aa5914..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/getting_started/installation/index.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Nargo Installation -description: - nargo is a command line tool for interacting with Noir programs. This page is a quick guide on how to install Nargo through the most common and easy method, noirup -keywords: [ - Nargo - Noir - Rust - Cargo - Noirup - Installation - Terminal Commands - Version Check - Nightlies - Specific Versions - Branches - Noirup Repository -] -pagination_next: getting_started/hello_noir/index ---- - -`nargo` is the one-stop-shop for almost everything related with Noir. The name comes from our love for Rust and its package manager `cargo`. - -With `nargo`, you can start new projects, compile, execute, prove, verify, test, generate solidity contracts, and do pretty much all that is available in Noir. - -Similarly to `rustup`, we also maintain an easy installation method that covers most machines: `noirup`. - -## Installing Noirup - -Open a terminal on your machine, and write: - -```bash -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -Close the terminal, open another one, and run - -```bash -noirup -``` - -Done. That's it. You should have the latest version working. You can check with `nargo --version`. - -You can also install nightlies, specific versions -or branches. Check out the [noirup repository](https://github.com/noir-lang/noirup) for more -information. - -Now we're ready to start working on [our first Noir program!](../hello_noir/index.md) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/getting_started/installation/other_install_methods.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/getting_started/installation/other_install_methods.md deleted file mode 100644 index 3634723562b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/getting_started/installation/other_install_methods.md +++ /dev/null @@ -1,102 +0,0 @@ ---- -title: Alternative Installations -description: There are different ways to install Nargo, the one-stop shop and command-line tool for developing Noir programs. This guide explains how to specify which version to install when using noirup, and using WSL for windows. -keywords: [ - Installation - Nargo - Noirup - Binaries - Compiling from Source - WSL for Windows - macOS - Linux - Nix - Direnv - Uninstalling Nargo - ] -sidebar_position: 1 ---- - -## Encouraged Installation Method: Noirup - -Noirup is the endorsed method for installing Nargo, streamlining the process of fetching binaries or compiling from source. It supports a range of options to cater to your specific needs, from nightly builds and specific versions to compiling from various sources. - -### Installing Noirup - -First, ensure you have `noirup` installed: - -```sh -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -### Fetching Binaries - -With `noirup`, you can easily switch between different Nargo versions, including nightly builds: - -- **Nightly Version**: Install the latest nightly build. - - ```sh - noirup --version nightly - ``` - -- **Specific Version**: Install a specific version of Nargo. - ```sh - noirup --version - ``` - -### Compiling from Source - -`noirup` also enables compiling Nargo from various sources: - -- **From a Specific Branch**: Install from the latest commit on a branch. - - ```sh - noirup --branch - ``` - -- **From a Fork**: Install from the main branch of a fork. - - ```sh - noirup --repo - ``` - -- **From a Specific Branch in a Fork**: Install from a specific branch in a fork. - - ```sh - noirup --repo --branch - ``` - -- **From a Specific Pull Request**: Install from a specific PR. - - ```sh - noirup --pr - ``` - -- **From a Specific Commit**: Install from a specific commit. - - ```sh - noirup -C - ``` - -- **From Local Source**: Compile and install from a local directory. - ```sh - noirup --path ./path/to/local/source - ``` - -## Installation on Windows - -The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed natively. However, it is available by using Windows Subsystem for Linux (WSL). - -Step 1: Follow the instructions [here](https://learn.microsoft.com/en-us/windows/wsl/install) to install and run WSL. - -step 2: Follow the [Noirup instructions](#encouraged-installation-method-noirup). - -## Uninstalling Nargo - -If you installed Nargo with `noirup`, you can uninstall Nargo by removing the files in `~/.nargo`, `~/nargo`, and `~/noir_cache`. This ensures that all installed binaries, configurations, and cache related to Nargo are fully removed from your system. - -```bash -rm -r ~/.nargo -rm -r ~/nargo -rm -r ~/noir_cache -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/getting_started/tooling/noir_codegen.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/getting_started/tooling/noir_codegen.md deleted file mode 100644 index d65151da0ab..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/getting_started/tooling/noir_codegen.md +++ /dev/null @@ -1,113 +0,0 @@ ---- -title: Noir Codegen for TypeScript -description: Learn how to use Noir codegen to generate TypeScript bindings -keywords: [Nargo, Noir, compile, TypeScript] -sidebar_position: 2 ---- - -When using TypeScript, it is extra work to interpret Noir program outputs in a type-safe way. Third party libraries may exist for popular Noir programs, but they are either hard to find or unmaintained. - -Now you can generate TypeScript bindings for your Noir programs in two steps: -1. Exporting Noir functions using `nargo export` -2. Using the TypeScript module `noir_codegen` to generate TypeScript binding - -**Note:** you can only export functions from a Noir *library* (not binary or contract program types). - -## Installation - -### Your TypeScript project - -If you don't already have a TypeScript project you can add the module with `yarn` (or `npm`), then initialize it: - -```bash -yarn add typescript -D -npx tsc --init -``` - -### Add TypeScript module - `noir_codegen` - -The following command will add the module to your project's devDependencies: - -```bash -yarn add @noir-lang/noir_codegen -D -``` - -### Nargo library -Make sure you have Nargo, v0.25.0 or greater, installed. If you don't, follow the [installation guide](../installation/index.md). - -If you're in a new project, make a `circuits` folder and create a new Noir library: - -```bash -mkdir circuits && cd circuits -nargo new --lib myNoirLib -``` - -## Usage - -### Export ABI of specified functions - -First go to the `.nr` files in your Noir library, and add the `#[export]` macro to each function that you want to use in TypeScript. - -```rust -#[export] -fn your_function(... -``` - -From your Noir library (where `Nargo.toml` is), run the following command: - -```bash -nargo export -``` - -You will now have an `export` directory with a .json file per exported function. - -You can also specify the directory of Noir programs using `--program-dir`, for example: - -```bash -nargo export --program-dir=./circuits/myNoirLib -``` - -### Generate TypeScript bindings from exported functions - -To use the `noir-codegen` package we added to the TypeScript project: - -```bash -yarn noir-codegen ./export/your_function.json -``` - -This creates an `exports` directory with an `index.ts` file containing all exported functions. - -**Note:** adding `--out-dir` allows you to specify an output dir for your TypeScript bindings to go. Eg: - -```bash -yarn noir-codegen ./export/*.json --out-dir ./path/to/output/dir -``` - -## Example .nr function to .ts output - -Consider a Noir library with this function: - -```rust -#[export] -fn not_equal(x: Field, y: Field) -> bool { - x != y -} -``` - -After the export and codegen steps, you should have an `index.ts` like: - -```typescript -export type Field = string; - - -export const is_equal_circuit: CompiledCircuit = {"abi":{"parameters":[{"name":"x","type":{"kind":"field"},"visibility":"private"},{"name":"y","type":{"kind":"field"},"visibility":"private"}],"param_witnesses":{"x":[{"start":0,"end":1}],"y":[{"start":1,"end":2}]},"return_type":{"abi_type":{"kind":"boolean"},"visibility":"private"},"return_witnesses":[4]},"bytecode":"H4sIAAAAAAAA/7WUMQ7DIAxFQ0Krrr2JjSGYLVcpKrn/CaqqDQN12WK+hPBgmWd/wEyHbF1SS923uhOs3pfoChI+wKXMAXzIKyNj4PB0TFTYc0w5RUjoqeAeEu1wqK0F54RGkWvW44LPzExnlkbMEs4JNZmN8PxS42uHv82T8a3Jeyn2Ks+VLPcO558HmyLMCDOXAXXtpPt4R/Rt9T36ss6dS9HGPx/eG17nGegKBQAA"}; - -export async function is_equal(x: Field, y: Field, foreignCallHandler?: ForeignCallHandler): Promise { - const program = new Noir(is_equal_circuit); - const args: InputMap = { x, y }; - const { returnValue } = await program.execute(args, foreignCallHandler); - return returnValue as boolean; -} -``` - -Now the `is_equal()` function and relevant types are readily available for use in TypeScript. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/how_to/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/how_to/_category_.json deleted file mode 100644 index 23b560f610b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/how_to/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 1, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/how_to/how-to-oracles.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/how_to/how-to-oracles.md deleted file mode 100644 index 8cf8035a5c4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/how_to/how-to-oracles.md +++ /dev/null @@ -1,276 +0,0 @@ ---- -title: How to use Oracles -description: Learn how to use oracles in your Noir program with examples in both Nargo and NoirJS. This guide also covers writing a JSON RPC server and providing custom foreign call handlers for NoirJS. -keywords: - - Noir Programming - - Oracles - - Nargo - - NoirJS - - JSON RPC Server - - Foreign Call Handlers -sidebar_position: 1 ---- - -This guide shows you how to use oracles in your Noir program. For the sake of clarity, it assumes that: - -- You have read the [explainer on Oracles](../explainers/explainer-oracle.md) and are comfortable with the concept. -- You have a Noir program to add oracles to. You can create one using the [vite-hardhat starter](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat) as a boilerplate. -- You understand the concept of a JSON-RPC server. Visit the [JSON-RPC website](https://www.jsonrpc.org/) if you need a refresher. -- You are comfortable with server-side JavaScript (e.g. Node.js, managing packages, etc.). - -For reference, you can find the snippets used in this tutorial on the [Aztec DevRel Repository](https://github.com/AztecProtocol/dev-rel/tree/main/code-snippets/how-to-oracles). - -## Rundown - -This guide has 3 major steps: - -1. How to modify our Noir program to make use of oracle calls as unconstrained functions -2. How to write a JSON RPC Server to resolve these oracle calls with Nargo -3. How to use them in Nargo and how to provide a custom resolver in NoirJS - -## Step 1 - Modify your Noir program - -An oracle is defined in a Noir program by defining two methods: - -- An unconstrained method - This tells the compiler that it is executing an [unconstrained functions](../noir/concepts//unconstrained.md). -- A decorated oracle method - This tells the compiler that this method is an RPC call. - -An example of an oracle that returns a `Field` would be: - -```rust -#[oracle(getSqrt)] -unconstrained fn sqrt(number: Field) -> Field { } - -unconstrained fn get_sqrt(number: Field) -> Field { - sqrt(number) -} -``` - -In this example, we're wrapping our oracle function in a unconstrained method, and decorating it with `oracle(getSqrt)`. We can then call the unconstrained function as we would call any other function: - -```rust -fn main(input: Field) { - let sqrt = get_sqrt(input); -} -``` - -In the next section, we will make this `getSqrt` (defined on the `sqrt` decorator) be a method of the RPC server Noir will use. - -:::danger - -As explained in the [Oracle Explainer](../explainers/explainer-oracle.md), this `main` function is unsafe unless you constrain its return value. For example: - -```rust -fn main(input: Field) { - let sqrt = get_sqrt(input); - assert(sqrt.pow_32(2) as u64 == input as u64); // <---- constrain the return of an oracle! -} -``` - -::: - -:::info - -Currently, oracles only work with single params or array params. For example: - -```rust -#[oracle(getSqrt)] -unconstrained fn sqrt([Field; 2]) -> [Field; 2] { } -``` - -::: - -## Step 2 - Write an RPC server - -Brillig will call *one* RPC server. Most likely you will have to write your own, and you can do it in whatever language you prefer. In this guide, we will do it in Javascript. - -Let's use the above example of an oracle that consumes an array with two `Field` and returns their square roots: - -```rust -#[oracle(getSqrt)] -unconstrained fn sqrt(input: [Field; 2]) -> [Field; 2] { } - -unconstrained fn get_sqrt(input: [Field; 2]) -> [Field; 2] { - sqrt(input) -} - -fn main(input: [Field; 2]) { - let sqrt = get_sqrt(input); - assert(sqrt[0].pow_32(2) as u64 == input[0] as u64); - assert(sqrt[1].pow_32(2) as u64 == input[1] as u64); -} -``` - -:::info - -Why square root? - -In general, computing square roots is computationally more expensive than multiplications, which takes a toll when speaking about ZK applications. In this case, instead of calculating the square root in Noir, we are using our oracle to offload that computation to be made in plain. In our circuit we can simply multiply the two values. - -::: - -Now, we should write the correspondent RPC server, starting with the [default JSON-RPC 2.0 boilerplate](https://www.npmjs.com/package/json-rpc-2.0#example): - -```js -import { JSONRPCServer } from "json-rpc-2.0"; -import express from "express"; -import bodyParser from "body-parser"; - -const app = express(); -app.use(bodyParser.json()); - -const server = new JSONRPCServer(); -app.post("/", (req, res) => { - const jsonRPCRequest = req.body; - server.receive(jsonRPCRequest).then((jsonRPCResponse) => { - if (jsonRPCResponse) { - res.json(jsonRPCResponse); - } else { - res.sendStatus(204); - } - }); -}); - -app.listen(5555); -``` - -Now, we will add our `getSqrt` method, as expected by the `#[oracle(getSqrt)]` decorator in our Noir code. It maps through the params array and returns their square roots: - -```js -server.addMethod("getSqrt", async (params) => { - const values = params[0].Array.map((field) => { - return `${Math.sqrt(parseInt(field, 16))}`; - }); - return { values: [{ Array: values }] }; -}); -``` - -:::tip - -Brillig expects an object with an array of values. Each value is an object declaring to be `Single` or `Array` and returning a field element *as a string*. For example: - -```json -{ "values": [{ "Array": ["1", "2"] }]} -{ "values": [{ "Single": "1" }]} -{ "values": [{ "Single": "1" }, { "Array": ["1", "2"] }]} -``` - -If you're using Typescript, the following types may be helpful in understanding the expected return value and making sure they're easy to follow: - -```js -interface SingleForeignCallParam { - Single: string, -} - -interface ArrayForeignCallParam { - Array: string[], -} - -type ForeignCallParam = SingleForeignCallParam | ArrayForeignCallParam; - -interface ForeignCallResult { - values: ForeignCallParam[], -} -``` - -::: - -## Step 3 - Usage with Nargo - -Using the [`nargo` CLI tool](../getting_started/installation/index.md), you can use oracles in the `nargo test`, `nargo execute` and `nargo prove` commands by passing a value to `--oracle-resolver`. For example: - -```bash -nargo test --oracle-resolver http://localhost:5555 -``` - -This tells `nargo` to use your RPC Server URL whenever it finds an oracle decorator. - -## Step 4 - Usage with NoirJS - -In a JS environment, an RPC server is not strictly necessary, as you may want to resolve your oracles without needing any JSON call at all. NoirJS simply expects that you pass a callback function when you generate proofs, and that callback function can be anything. - -For example, if your Noir program expects the host machine to provide CPU pseudo-randomness, you could simply pass it as the `foreignCallHandler`. You don't strictly need to create an RPC server to serve pseudo-randomness, as you may as well get it directly in your app: - -```js -const foreignCallHandler = (name, inputs) => crypto.randomBytes(16) // etc - -await noir.generateProof(inputs, foreignCallHandler) -``` - -As one can see, in NoirJS, the [`foreignCallHandler`](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) function simply means "a callback function that returns a value of type [`ForeignCallOutput`](../reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md). It doesn't have to be an RPC call like in the case for Nargo. - -:::tip - -Does this mean you don't have to write an RPC server like in [Step #2](#step-2---write-an-rpc-server)? - -You don't technically have to, but then how would you run `nargo test` or `nargo prove`? To use both `Nargo` and `NoirJS` in your development flow, you will have to write a JSON RPC server. - -::: - -In this case, let's make `foreignCallHandler` call the JSON RPC Server we created in [Step #2](#step-2---write-an-rpc-server), by making it a JSON RPC Client. - -For example, using the same `getSqrt` program in [Step #1](#step-1---modify-your-noir-program) (comments in the code): - -```js -import { JSONRPCClient } from "json-rpc-2.0"; - -// declaring the JSONRPCClient -const client = new JSONRPCClient((jsonRPCRequest) => { -// hitting the same JSON RPC Server we coded above - return fetch("http://localhost:5555", { - method: "POST", - headers: { - "content-type": "application/json", - }, - body: JSON.stringify(jsonRPCRequest), - }).then((response) => { - if (response.status === 200) { - return response - .json() - .then((jsonRPCResponse) => client.receive(jsonRPCResponse)); - } else if (jsonRPCRequest.id !== undefined) { - return Promise.reject(new Error(response.statusText)); - } - }); -}); - -// declaring a function that takes the name of the foreign call (getSqrt) and the inputs -const foreignCallHandler = async (name, input) => { - // notice that the "inputs" parameter contains *all* the inputs - // in this case we to make the RPC request with the first parameter "numbers", which would be input[0] - const oracleReturn = await client.request(name, [ - { Array: input[0].map((i) => i.toString("hex")) }, - ]); - return [oracleReturn.values[0].Array]; -}; - -// the rest of your NoirJS code -const input = { input: [4, 16] }; -const { witness } = await noir.execute(numbers, foreignCallHandler); -``` - -:::tip - -If you're in a NoirJS environment running your RPC server together with a frontend app, you'll probably hit a familiar problem in full-stack development: requests being blocked by [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) policy. For development only, you can simply install and use the [`cors` npm package](https://www.npmjs.com/package/cors) to get around the problem: - -```bash -yarn add cors -``` - -and use it as a middleware: - -```js -import cors from "cors"; - -const app = express(); -app.use(cors()) -``` - -::: - -## Conclusion - -Hopefully by the end of this guide, you should be able to: - -- Write your own logic around Oracles and how to write a JSON RPC server to make them work with your Nargo commands. -- Provide custom foreign call handlers for NoirJS. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/how_to/how-to-recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/how_to/how-to-recursion.md deleted file mode 100644 index 4c45bb87ae2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/how_to/how-to-recursion.md +++ /dev/null @@ -1,179 +0,0 @@ ---- -title: How to use recursion on NoirJS -description: Learn how to implement recursion with NoirJS, a powerful tool for creating smart contracts on the EVM blockchain. This guide assumes familiarity with NoirJS, solidity verifiers, and the Barretenberg proving backend. Discover how to generate both final and intermediate proofs using `noir_js` and `backend_barretenberg`. -keywords: - [ - "NoirJS", - "EVM blockchain", - "smart contracts", - "recursion", - "solidity verifiers", - "Barretenberg backend", - "noir_js", - "backend_barretenberg", - "intermediate proofs", - "final proofs", - "nargo compile", - "json import", - "recursive circuit", - "recursive app" - ] -sidebar_position: 1 ---- - -This guide shows you how to use recursive proofs in your NoirJS app. For the sake of clarity, it is assumed that: - -- You already have a NoirJS app. If you don't, please visit the [NoirJS tutorial](../tutorials/noirjs_app.md) and the [reference](../reference/NoirJS/noir_js/index.md). -- You are familiar with what are recursive proofs and you have read the [recursion explainer](../explainers/explainer-recursion.md) -- You already built a recursive circuit following [the reference](../noir/standard_library/recursion.md), and understand how it works. - -It is also assumed that you're not using `noir_wasm` for compilation, and instead you've used [`nargo compile`](../reference/nargo_commands.md) to generate the `json` you're now importing into your project. However, the guide should work just the same if you're using `noir_wasm`. - -:::info - -As you've read in the [explainer](../explainers/explainer-recursion.md), a recursive proof is an intermediate proof. This means that it doesn't necessarily generate the final step that makes it verifiable in a smart contract. However, it is easy to verify within another circuit. - -While "standard" usage of NoirJS packages abstracts final proofs, it currently lacks the necessary interface to abstract away intermediate proofs. This means that these proofs need to be created by using the backend directly. - -In short: - -- `noir_js` generates *only* final proofs -- `backend_barretenberg` generates both types of proofs - -::: - -In a standard recursive app, you're also dealing with at least two circuits. For the purpose of this guide, we will assume the following: - -- `main`: a circuit of type `assert(x != y)`, where `main` is marked with a `#[recursive]` attribute. This attribute states that the backend should generate proofs that are friendly for verification within another circuit. -- `recursive`: a circuit that verifies `main` - -For a full example on how recursive proofs work, please refer to the [noir-examples](https://github.com/noir-lang/noir-examples) repository. We will *not* be using it as a reference for this guide. - -## Step 1: Setup - -In a common NoirJS app, you need to instantiate a backend with something like `const backend = new Backend(circuit)`. Then you feed it to the `noir_js` interface. - -For recursion, this doesn't happen, and the only need for `noir_js` is only to `execute` a circuit and get its witness and return value. Everything else is not interfaced, so it needs to happen on the `backend` object. - -It is also recommended that you instantiate the backend with as many threads as possible, to allow for maximum concurrency: - -```js -const backend = new Backend(circuit, { threads: 8 }) -``` - -:::tip -You can use the [`os.cpus()`](https://nodejs.org/api/os.html#oscpus) object in `nodejs` or [`navigator.hardwareConcurrency`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/hardwareConcurrency) on the browser to make the most out of those glorious cpu cores -::: - -## Step 2: Generating the witness and the proof for `main` - -After instantiating the backend, you should also instantiate `noir_js`. We will use it to execute the circuit and get the witness. - -```js -const noir = new Noir(circuit, backend) -const { witness } = noir.execute(input) -``` - -With this witness, you are now able to generate the intermediate proof for the main circuit: - -```js -const { proof, publicInputs } = await backend.generateProof(witness) -``` - -:::warning - -Always keep in mind what is actually happening on your development process, otherwise you'll quickly become confused about what circuit we are actually running and why! - -In this case, you can imagine that Alice (running the `main` circuit) is proving something to Bob (running the `recursive` circuit), and Bob is verifying her proof within his proof. - -With this in mind, it becomes clear that our intermediate proof is the one *meant to be verified within another circuit*, so it must be Alice's. Actually, the only final proof in this theoretical scenario would be the last one, sent on-chain. - -::: - -## Step 3 - Verification and proof artifacts - -Optionally, you are able to verify the intermediate proof: - -```js -const verified = await backend.verifyProof({ proof, publicInputs }) -``` - -This can be useful to make sure our intermediate proof was correctly generated. But the real goal is to do it within another circuit. For that, we need to generate recursive proof artifacts that will be passed to the circuit that is verifying the proof we just generated. Instead of passing the proof and verification key as a byte array, we pass them as fields which makes it cheaper to verify in a circuit: - -```js -const { proofAsFields, vkAsFields, vkHash } = await backend.generateRecursiveProofArtifacts( { publicInputs, proof }, publicInputsCount) -``` - -This call takes the public inputs and the proof, but also the public inputs count. While this is easily retrievable by simply counting the `publicInputs` length, the backend interface doesn't currently abstract it away. - -:::info - -The `proofAsFields` has a constant size `[Field; 93]` and verification keys in Barretenberg are always `[Field; 114]`. - -::: - -:::warning - -One common mistake is to forget *who* makes this call. - -In a situation where Alice is generating the `main` proof, if she generates the proof artifacts and sends them to Bob, which gladly takes them as true, this would mean Alice could prove anything! - -Instead, Bob needs to make sure *he* extracts the proof artifacts, using his own instance of the `main` circuit backend. This way, Alice has to provide a valid proof for the correct `main` circuit. - -::: - -## Step 4 - Recursive proof generation - -With the artifacts, generating a recursive proof is no different from a normal proof. You simply use the `backend` (with the recursive circuit) to generate it: - -```js -const recursiveInputs = { - verification_key: vkAsFields, // array of length 114 - proof: proofAsFields, // array of length 93 + size of public inputs - publicInputs: [mainInput.y], // using the example above, where `y` is the only public input - key_hash: vkHash, -} - -const { witness, returnValue } = noir.execute(recursiveInputs) // we're executing the recursive circuit now! -const { proof, publicInputs } = backend.generateProof(witness) -const verified = backend.verifyProof({ proof, publicInputs }) -``` - -You can obviously chain this proof into another proof. In fact, if you're using recursive proofs, you're probably interested of using them this way! - -:::tip - -Managing circuits and "who does what" can be confusing. To make sure your naming is consistent, you can keep them in an object. For example: - -```js -const circuits = { - main: mainJSON, - recursive: recursiveJSON -} -const backends = { - main: new BarretenbergBackend(circuits.main), - recursive: new BarretenbergBackend(circuits.recursive) -} -const noir_programs = { - main: new Noir(circuits.main, backends.main), - recursive: new Noir(circuits.recursive, backends.recursive) -} -``` - -This allows you to neatly call exactly the method you want without conflicting names: - -```js -// Alice runs this 👇 -const { witness: mainWitness } = await noir_programs.main.execute(input) -const proof = await backends.main.generateProof(mainWitness) - -// Bob runs this 👇 -const verified = await backends.main.verifyProof(proof) -const { proofAsFields, vkAsFields, vkHash } = await backends.main.generateRecursiveProofArtifacts( - proof, - numPublicInputs, -); -const recursiveProof = await noir_programs.recursive.generateProof(recursiveInputs) -``` - -::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/how_to/how-to-solidity-verifier.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/how_to/how-to-solidity-verifier.md deleted file mode 100644 index e3c7c1065da..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/how_to/how-to-solidity-verifier.md +++ /dev/null @@ -1,231 +0,0 @@ ---- -title: Generate a Solidity Verifier -description: - Learn how to run the verifier as a smart contract on the blockchain. Compile a Solidity verifier - contract for your Noir program and deploy it on any EVM blockchain acting as a verifier smart - contract. Read more to find out -keywords: - [ - solidity verifier, - smart contract, - blockchain, - compiler, - plonk_vk.sol, - EVM blockchain, - verifying Noir programs, - proving backend, - Barretenberg, - ] -sidebar_position: 0 -pagination_next: tutorials/noirjs_app ---- - -Noir has the ability to generate a verifier contract in Solidity, which can be deployed in many EVM-compatible blockchains such as Ethereum. - -This allows for a powerful feature set, as one can make use of the conciseness and the privacy provided by Noir in an immutable ledger. Applications can range from simple P2P guessing games, to complex private DeFi interactions. - -This guide shows you how to generate a Solidity Verifier and deploy it on the [Remix IDE](https://remix.ethereum.org/). It is assumed that: - -- You are comfortable with the Solidity programming language and understand how contracts are deployed on the Ethereum network -- You have Noir installed and you have a Noir program. If you don't, [get started](../getting_started/installation/index.md) with Nargo and the example Hello Noir circuit -- You are comfortable navigating RemixIDE. If you aren't or you need a refresher, you can find some video tutorials [here](https://www.youtube.com/channel/UCjTUPyFEr2xDGN6Cg8nKDaA) that could help you. - -## Rundown - -Generating a Solidity Verifier contract is actually a one-command process. However, compiling it and deploying it can have some caveats. Here's the rundown of this guide: - -1. How to generate a solidity smart contract -2. How to compile the smart contract in the RemixIDE -3. How to deploy it to a testnet - -## Step 1 - Generate a contract - -This is by far the most straight-forward step. Just run: - -```sh -nargo codegen-verifier -``` - -A new `contract` folder would then be generated in your project directory, containing the Solidity -file `plonk_vk.sol`. It can be deployed to any EVM blockchain acting as a verifier smart contract. - -:::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. - -Barretenberg, the default proving backend for Nargo, supports generation of verifier contracts, for the time being these are only in Solidity. -::: - -## Step 2 - Compiling - -We will mostly skip the details of RemixIDE, as the UI can change from version to version. For now, we can just open -Remix and create a blank workspace. - -![Create Workspace](@site/static/img/how-tos/solidity_verifier_1.png) - -We will create a new file to contain the contract Nargo generated, and copy-paste its content. - -:::warning - -You'll likely see a warning advising you to not trust pasted code. While it is an important warning, it is irrelevant in the context of this guide and can be ignored. We will not be deploying anywhere near a mainnet. - -::: - -To compile our the verifier, we can navigate to the compilation tab: - -![Compilation Tab](@site/static/img/how-tos/solidity_verifier_2.png) - -Remix should automatically match a suitable compiler version. However, hitting the "Compile" button will most likely generate a "Stack too deep" error: - -![Stack too deep](@site/static/img/how-tos/solidity_verifier_3.png) - -This is due to the verify function needing to put many variables on the stack, but enabling the optimizer resolves the issue. To do this, let's open the "Advanced Configurations" tab and enable optimization. The default 200 runs will suffice. - -:::info - -This time we will see a warning about an unused function parameter. This is expected, as the `verify` function doesn't use the `_proof` parameter inside a solidity block, it is loaded from calldata and used in assembly. - -::: - -![Compilation success](@site/static/img/how-tos/solidity_verifier_4.png) - -## Step 3 - Deploying - -At this point we should have a compiled contract read to deploy. If we navigate to the deploy section in Remix, we will see many different environments we can deploy to. The steps to deploy on each environment would be out-of-scope for this guide, so we will just use the default Remix VM. - -Looking closely, we will notice that our "Solidity Verifier" is actually three contracts working together: - -- An `UltraVerificationKey` library which simply stores the verification key for our circuit. -- An abstract contract `BaseUltraVerifier` containing most of the verifying logic. -- A main `UltraVerifier` contract that inherits from the Base and uses the Key contract. - -Remix will take care of the dependencies for us so we can simply deploy the UltraVerifier contract by selecting it and hitting "deploy": - -![Deploying UltraVerifier](@site/static/img/how-tos/solidity_verifier_5.png) - -A contract will show up in the "Deployed Contracts" section, where we can retrieve the Verification Key Hash. This is particularly useful for double-checking the deployer contract is the correct one. - -:::note - -Why "UltraVerifier"? - -To be precise, the Noir compiler (`nargo`) doesn't generate the verifier contract directly. It compiles the Noir code into an intermediate language (ACIR), which is then executed by the backend. So it is the backend that returns the verifier smart contract, not Noir. - -In this case, the Barretenberg Backend uses the UltraPlonk proving system, hence the "UltraVerifier" name. - -::: - -## Step 4 - Verifying - -To verify a proof using the Solidity verifier contract, we call the `verify` function in this extended contract: - -```solidity -function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) -``` - -When using the default example in the [Hello Noir](../getting_started/hello_noir/index.md) guide, the easiest way to confirm that the verifier contract is doing its job is by calling the `verify` function via remix with the required parameters. For `_proof`, run `nargo prove` and use the string in `proof/.proof` (adding the hex `0x` prefix). We can also copy the public input from `Verifier.toml`, as it will be properly formatted as 32-byte strings: - -``` -0x...... , [0x0000.....02] -``` - -A programmatic example of how the `verify` function is called can be seen in the example zk voting application [here](https://github.com/noir-lang/noir-examples/blob/33e598c257e2402ea3a6b68dd4c5ad492bce1b0a/foundry-voting/src/zkVote.sol#L35): - -```solidity -function castVote(bytes calldata proof, uint proposalId, uint vote, bytes32 nullifierHash) public returns (bool) { - // ... - bytes32[] memory publicInputs = new bytes32[](4); - publicInputs[0] = merkleRoot; - publicInputs[1] = bytes32(proposalId); - publicInputs[2] = bytes32(vote); - publicInputs[3] = nullifierHash; - require(verifier.verify(proof, publicInputs), "Invalid proof"); -``` - -:::info[Return Values] - -A circuit doesn't have the concept of a return value. Return values are just syntactic sugar in -Noir. - -Under the hood, the return value is passed as an input to the circuit and is checked at the end of -the circuit program. - -For example, if you have Noir program like this: - -```rust -fn main( - // Public inputs - pubkey_x: pub Field, - pubkey_y: pub Field, - // Private inputs - priv_key: Field, -) -> pub Field -``` - -the `verify` function will expect the public inputs array (second function parameter) to be of length 3, the two inputs and the return value. Like before, these values are populated in Verifier.toml after running `nargo prove`. - -Passing only two inputs will result in an error such as `PUBLIC_INPUT_COUNT_INVALID(3, 2)`. - -In this case, the inputs parameter to `verify` would be an array ordered as `[pubkey_x, pubkey_y, return]`. - -::: - -:::tip[Structs] - -You can pass structs to the verifier contract. They will be flattened so that the array of inputs is 1-dimensional array. - -For example, consider the following program: - -```rust -struct Type1 { - val1: Field, - val2: Field, -} - -struct Nested { - t1: Type1, - is_true: bool, -} - -fn main(x: pub Field, nested: pub Nested, y: pub Field) { - //... -} -``` - -The order of these inputs would be flattened to: `[x, nested.t1.val1, nested.t1.val2, nested.is_true, y]` - -::: - -The other function you can call is our entrypoint `verify` function, as defined above. - -:::tip - -It's worth noticing that the `verify` function is actually a `view` function. A `view` function does not alter the blockchain state, so it doesn't need to be distributed (i.e. it will run only on the executing node), and therefore doesn't cost any gas. - -This can be particularly useful in some situations. If Alice generated a proof and wants Bob to verify its correctness, Bob doesn't need to run Nargo, NoirJS, or any Noir specific infrastructure. He can simply make a call to the blockchain with the proof and verify it is correct without paying any gas. - -It would be incorrect to say that a Noir proof verification costs any gas at all. However, most of the time the result of `verify` is used to modify state (for example, to update a balance, a game state, etc). In that case the whole network needs to execute it, which does incur gas costs (calldata and execution, but not storage). - -::: - -## A Note on EVM chains - -ZK-SNARK verification depends on some precompiled cryptographic primitives such as Elliptic Curve Pairings (if you like complex math, you can read about EC Pairings [here](https://medium.com/@VitalikButerin/exploring-elliptic-curve-pairings-c73c1864e627)). Not all EVM chains support EC Pairings, notably some of the ZK-EVMs. This means that you won't be able to use the verifier contract in all of them. - -For example, chains like `zkSync ERA` and `Polygon zkEVM` do not currently support these precompiles, so proof verification via Solidity verifier contracts won't work. Here's a quick list of EVM chains that have been tested and are known to work: - -- Optimism -- Arbitrum -- Polygon PoS -- Scroll -- Celo - -If you test any other chains, please open a PR on this page to update the list. See [this doc](https://github.com/noir-lang/noir-starter/tree/main/with-foundry#testing-on-chain) for more info about testing verifier contracts on different EVM chains. - -## What's next - -Now that you know how to call a Noir Solidity Verifier on a smart contract using Remix, you should be comfortable with using it with some programmatic frameworks, such as [hardhat](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat) and [foundry](https://github.com/noir-lang/noir-starter/tree/main/with-foundry). - -You can find other tools, examples, boilerplates and libraries in the [awesome-noir](https://github.com/noir-lang/awesome-noir) repository. - -You should also be ready to write and deploy your first NoirJS app and start generating proofs on websites, phones, and NodeJS environments! Head on to the [NoirJS tutorial](../tutorials/noirjs_app.md) to learn how to do that. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/how_to/merkle-proof.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/how_to/merkle-proof.mdx deleted file mode 100644 index 16c425bed76..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/how_to/merkle-proof.mdx +++ /dev/null @@ -1,49 +0,0 @@ ---- -title: Prove Merkle Tree Membership -description: - Learn how to use merkle membership proof in Noir to prove that a given leaf is a member of a - merkle tree with a specified root, at a given index. -keywords: - [merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree] -sidebar_position: 4 ---- - -Let's walk through an example of a merkle membership proof in Noir that proves that a given leaf is -in a merkle tree. - -```rust -use dep::std; - -fn main(message : [Field; 62], index : Field, hashpath : [Field; 40], root : Field) { - let leaf = std::hash::hash_to_field(message.as_slice()); - let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); - assert(merkle_root == root); -} - -``` - -The message is hashed using `hash_to_field`. The specific hash function that is being used is chosen -by the backend. The only requirement is that this hash function can heuristically be used as a -random oracle. If only collision resistance is needed, then one can call `std::hash::pedersen_hash` -instead. - -```rust -let leaf = std::hash::hash_to_field(message.as_slice()); -``` - -The leaf is then passed to a compute_merkle_root function with the root, index and hashpath. The returned root can then be asserted to be the same as the provided root. - -```rust -let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); -assert (merkle_root == root); -``` - -> **Note:** It is possible to re-implement the merkle tree implementation without standard library. -> However, for most usecases, it is enough. In general, the standard library will always opt to be -> as conservative as possible, while striking a balance with efficiency. - -An example, the merkle membership proof, only requires a hash function that has collision -resistance, hence a hash function like Pedersen is allowed, which in most cases is more efficient -than the even more conservative sha256. - -[View an example on the starter repo](https://github.com/noir-lang/noir-examples/blob/3ea09545cabfa464124ec2f3ea8e60c608abe6df/stealthdrop/circuits/src/main.nr#L20) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/how_to/using-devcontainers.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/how_to/using-devcontainers.mdx deleted file mode 100644 index 727ec6ca667..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/how_to/using-devcontainers.mdx +++ /dev/null @@ -1,110 +0,0 @@ ---- -title: Developer Containers and Codespaces -description: "Learn how to set up a devcontainer in your GitHub repository for a seamless coding experience with Codespaces. Follow our easy 8-step guide to create your own Noir environment without installing Nargo locally." -keywords: ["Devcontainer", "Codespaces", "GitHub", "Noir Environment", "Docker Image", "Development Environment", "Remote Coding", "GitHub Codespaces", "Noir Programming", "Nargo", "VSCode Extensions", "Noirup"] -sidebar_position: 1 ---- - -Adding a developer container configuration file to your Noir project is one of the easiest way to unlock coding in browser. - -## What's a devcontainer after all? - -A [Developer Container](https://containers.dev/) (devcontainer for short) is a Docker image that comes preloaded with tools, extensions, and other tools you need to quickly get started or continue a project, without having to install Nargo locally. Think of it as a development environment in a box. - -There are many advantages to this: - -- It's platform and architecture agnostic -- You don't need to have an IDE installed, or Nargo, or use a terminal at all -- It's safer for using on a public machine or public network - -One of the best ways of using devcontainers is... not using your machine at all, for maximum control, performance, and ease of use. -Enter Codespaces. - -## Codespaces - -If a devcontainer is just a Docker image, then what stops you from provisioning a `p3dn.24xlarge` AWS EC2 instance with 92 vCPUs and 768 GiB RAM and using it to prove your 10-gate SNARK proof? - -Nothing! Except perhaps the 30-40$ per hour it will cost you. - -The problem is that provisioning takes time, and I bet you don't want to see the AWS console every time you want to code something real quick. - -Fortunately, there's an easy and free way to get a decent remote machine ready and loaded in less than 2 minutes: Codespaces. [Codespaces is a Github feature](https://github.com/features/codespaces) that allows you to code in a remote machine by using devcontainers, and it's pretty cool: - -- You can start coding Noir in less than a minute -- It uses the resources of a remote machine, so you can code on your grandma's phone if needed be -- It makes it easy to share work with your frens -- It's fully reusable, you can stop and restart whenever you need to - -:::info - -Don't take out your wallet just yet. Free GitHub accounts get about [15-60 hours of coding](https://github.com/features/codespaces) for free per month, depending on the size of your provisioned machine. - -::: - -## Tell me it's _actually_ easy - -It is! - -Github comes with a default codespace and you can use it to code your own devcontainer. That's exactly what we will be doing in this guide. - - - -8 simple steps: - -#### 1. Create a new repository on GitHub. - -#### 2. Click "Start coding with Codespaces". This will use the default image. - -#### 3. Create a folder called `.devcontainer` in the root of your repository. - -#### 4. Create a Dockerfile in that folder, and paste the following code: - -```docker -FROM --platform=linux/amd64 node:lts-bookworm-slim -SHELL ["/bin/bash", "-c"] -RUN apt update && apt install -y curl bash git tar gzip libc++-dev -RUN curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -ENV PATH="/root/.nargo/bin:$PATH" -RUN noirup -ENTRYPOINT ["nargo"] -``` -#### 5. Create a file called `devcontainer.json` in the same folder, and paste the following code: - -```json -{ - "name": "Noir on Codespaces", - "build": { - "context": ".", - "dockerfile": "Dockerfile" - }, - "customizations": { - "vscode": { - "extensions": ["noir-lang.vscode-noir"] - } - } -} -``` -#### 6. Commit and push your changes - -This will pull the new image and build it, so it could take a minute or so - -#### 8. Done! -Just wait for the build to finish, and there's your easy Noir environment. - - -Refer to [noir-starter](https://github.com/noir-lang/noir-starter/) as an example of how devcontainers can be used together with codespaces. - - - -## How do I use it? - -Using the codespace is obviously much easier than setting it up. -Just navigate to your repository and click "Code" -> "Open with Codespaces". It should take a few seconds to load, and you're ready to go. - -:::info - -If you really like the experience, you can add a badge to your readme, links to existing codespaces, and more. -Check out the [official docs](https://docs.github.com/en/codespaces/setting-up-your-project-for-codespaces/setting-up-your-repository/facilitating-quick-creation-and-resumption-of-codespaces) for more info. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/index.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/index.mdx deleted file mode 100644 index 75086ddcdde..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/index.mdx +++ /dev/null @@ -1,67 +0,0 @@ ---- -title: Noir Lang -hide_title: true -description: - Learn about the public alpha release of Noir, a domain specific language heavily influenced by Rust that compiles to - an intermediate language which can be compiled to an arithmetic circuit or a rank-1 constraint system. -keywords: - [Noir, - Domain Specific Language, - Rust, - Intermediate Language, - Arithmetic Circuit, - Rank-1 Constraint System, - Ethereum Developers, - Protocol Developers, - Blockchain Developers, - Proving System, - Smart Contract Language] -sidebar_position: 0 ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -Noir Logo - -Noir is a Domain-Specific Language for SNARK proving systems developed by [Aztec Labs](https://aztec.network/). It allows you to generate complex Zero-Knowledge Programs (ZKP) by using simple and flexible syntax, requiring no previous knowledge on the underlying mathematics or cryptography. - -ZK programs are programs that can generate short proofs of a certain statement without revealing some details about it. You can read more about ZKPs [here](https://dev.to/spalladino/a-beginners-intro-to-coding-zero-knowledge-proofs-c56). - -## What's new about Noir? - -Noir works differently from most ZK languages by taking a two-pronged path. First, it compiles the program to an adaptable intermediate language known as ACIR. From there, depending on a given project's needs, ACIR can be further compiled into an arithmetic circuit for integration with the proving backend. - -:::info - -Noir is backend agnostic, which means it makes no assumptions on which proving backend powers the ZK proof. Being the language that powers [Aztec Contracts](https://docs.aztec.network/developers/contracts/main), it defaults to Aztec's Barretenberg proving backend. - -However, the ACIR output can be transformed to be compatible with other PLONK-based backends, or into a [rank-1 constraint system](https://www.rareskills.io/post/rank-1-constraint-system) suitable for backends such as Arkwork's Marlin. - -::: - -## Who is Noir for? - -Noir can be used both in complex cloud-based backends and in user's smartphones, requiring no knowledge on the underlying math or cryptography. From authorization systems that keep a password in the user's device, to complex on-chain verification of recursive proofs, Noir is designed to abstract away complexity without any significant overhead. Here are some examples of situations where Noir can be used: - - - - Noir Logo - - Aztec Contracts leverage Noir to allow for the storage and execution of private information. Writing an Aztec Contract is as easy as writing Noir, and Aztec developers can easily interact with the network storage and execution through the [Aztec.nr](https://docs.aztec.network/developers/contracts/main) library. - - - Soliditry Verifier Example - Noir can auto-generate Solidity verifier contracts that verify Noir proofs. This allows for non-interactive verification of proofs containing private information in an immutable system. This feature powers a multitude of use-case scenarios, from P2P chess tournaments, to [Aztec Layer-2 Blockchain](https://docs.aztec.network/) - - - Aztec Labs developed NoirJS, an easy interface to generate and verify Noir proofs in a Javascript environment. This allows for Noir to be used in webpages, mobile apps, games, and any other environment supporting JS execution in a standalone manner. - - - - -## Libraries - -Noir is meant to be easy to extend by simply importing Noir libraries just like in Rust. -The [awesome-noir repo](https://github.com/noir-lang/awesome-noir#libraries) is a collection of libraries developed by the Noir community. -Writing a new library is easy and makes code be composable and easy to reuse. See the section on [dependencies](noir/modules_packages_crates/dependencies.md) for more information. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/migration_notes.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/migration_notes.md deleted file mode 100644 index 6bd740024e5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/migration_notes.md +++ /dev/null @@ -1,105 +0,0 @@ ---- -title: Migration notes -description: Read about migration notes from previous versions, which could solve problems while updating -keywords: [Noir, notes, migration, updating, upgrading] ---- - -Noir is in full-speed development. Things break fast, wild, and often. This page attempts to leave some notes on errors you might encounter when upgrading and how to resolve them until proper patches are built. - -### `backend encountered an error: libc++.so.1` - -Depending on your OS, you may encounter the following error when running `nargo prove` for the first time: - -```text -The backend encountered an error: "/home/codespace/.nargo/backends/acvm-backend-barretenberg/backend_binary: error while loading shared libraries: libc++.so.1: cannot open shared object file: No such file or directory\n" -``` - -Install the `libc++-dev` library with: - -```bash -sudo apt install libc++-dev -``` - -## ≥0.19 - -### Enforcing `compiler_version` - -From this version on, the compiler will check for the `compiler_version` field in `Nargo.toml`, and will error if it doesn't match the current Nargo version in use. - -To update, please make sure this field in `Nargo.toml` matches the output of `nargo --version`. - -## ≥0.14 - -The index of the [for loops](noir/concepts/control_flow.md#loops) is now of type `u64` instead of `Field`. An example refactor would be: - -```rust -for i in 0..10 { - let i = i as Field; -} -``` - -## ≥v0.11.0 and Nargo backend - -From this version onwards, Nargo starts managing backends through the `nargo backend` command. Upgrading to the versions per usual steps might lead to: - -### `backend encountered an error` - -This is likely due to the existing locally installed version of proving backend (e.g. barretenberg) is incompatible with the version of Nargo in use. - -To fix the issue: - -1. Uninstall the existing backend - -```bash -nargo backend uninstall acvm-backend-barretenberg -``` - -You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. - -2. Reinstall a compatible version of the proving backend. - -If you are using the default barretenberg backend, simply run: - -``` -nargo prove -``` - -with your Noir program. - -This will trigger the download and installation of the latest version of barretenberg compatible with your Nargo in use. - -### `backend encountered an error: illegal instruction` - -On certain Intel-based systems, an `illegal instruction` error may arise due to incompatibility of barretenberg with certain CPU instructions. - -To fix the issue: - -1. Uninstall the existing backend - -```bash -nargo backend uninstall acvm-backend-barretenberg -``` - -You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. - -2. Reinstall a compatible version of the proving backend. - -If you are using the default barretenberg backend, simply run: - -``` -nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/barretenberg-js-binary/raw/master/run-bb.tar.gz -``` - -This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. - -The gzipped file is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. - -Then run: - -``` -DESIRED_BINARY_VERSION=0.8.1 nargo info -``` - -This overrides the bb native binary with a bb.js node application instead, which should be compatible with most if not all hardware. This does come with the drawback of being generally slower than native binary. - -0.8.1 indicates bb.js version 0.8.1, so if you change that it will update to a different version or the default version in the script if none was supplied. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/_category_.json deleted file mode 100644 index 7da08f8a8c5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Concepts", - "position": 0, - "collapsible": true, - "collapsed": true -} \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/assert.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/assert.md deleted file mode 100644 index bcff613a695..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/assert.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Assert Function -description: - Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or - comparison expression that follows to be true, and what happens if the expression is false at - runtime. -keywords: [Noir programming language, assert statement, predicate expression, comparison expression] -sidebar_position: 4 ---- - -Noir includes a special `assert` function which will explicitly constrain the predicate/comparison -expression that follows to be true. If this expression is false at runtime, the program will fail to -be proven. Example: - -```rust -fn main(x : Field, y : Field) { - assert(x == y); -} -``` - -> Assertions only work for predicate operations, such as `==`. If there's any ambiguity on the operation, the program will fail to compile. For example, it is unclear if `assert(x + y)` would check for `x + y == 0` or simply would return `true`. - -You can optionally provide a message to be logged when the assertion fails: - -```rust -assert(x == y, "x and y are not equal"); -``` - -Aside string literals, the optional message can be a format string or any other type supported as input for Noir's [print](../standard_library/logging.md) functions. This feature lets you incorporate runtime variables into your failed assertion logs: - -```rust -assert(x == y, f"Expected x == y, but got {x} == {y}"); -``` - -Using a variable as an assertion message directly: - -```rust -struct myStruct { - myField: Field -} - -let s = myStruct { myField: y }; -assert(s.myField == x, s); -``` - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/comments.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/comments.md deleted file mode 100644 index b51a85f5c94..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/comments.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Comments -description: - Learn how to write comments in Noir programming language. A comment is a line of code that is - ignored by the compiler, but it can be read by programmers. Single-line and multi-line comments - are supported in Noir. -keywords: [Noir programming language, comments, single-line comments, multi-line comments] -sidebar_position: 10 ---- - -A comment is a line in your codebase which the compiler ignores, however it can be read by -programmers. - -Here is a single line comment: - -```rust -// This is a comment and is ignored -``` - -`//` is used to tell the compiler to ignore the rest of the line. - -Noir also supports multi-line block comments. Start a block comment with `/*` and end the block with `*/`. - -Noir does not natively support doc comments. You may be able to use [Rust doc comments](https://doc.rust-lang.org/reference/comments.html) in your code to leverage some Rust documentation build tools with Noir code. - -```rust -/* - This is a block comment describing a complex function. -*/ -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/control_flow.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/control_flow.md deleted file mode 100644 index 045d3c3a5f5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/control_flow.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -title: Control Flow -description: - Learn how to use loops and if expressions in the Noir programming language. Discover the syntax - and examples for for loops and if-else statements. -keywords: [Noir programming language, loops, for loop, if-else statements, Rust syntax] -sidebar_position: 2 ---- - -## If Expressions - -Noir supports `if-else` statements. The syntax is most similar to Rust's where it is not required -for the statement's conditional to be surrounded by parentheses. - -```rust -let a = 0; -let mut x: u32 = 0; - -if a == 0 { - if a != 0 { - x = 6; - } else { - x = 2; - } -} else { - x = 5; - assert(x == 5); -} -assert(x == 2); -``` - -## Loops - -Noir has one kind of loop: the `for` loop. `for` loops allow you to repeat a block of code multiple -times. - -The following block of code between the braces is run 10 times. - -```rust -for i in 0..10 { - // do something -} -``` - -The index for loops is of type `u64`. - -### Break and Continue - -In unconstrained code, `break` and `continue` are also allowed in `for` loops. These are only allowed -in unconstrained code since normal constrained code requires that Noir knows exactly how many iterations -a loop may have. `break` and `continue` can be used like so: - -```rust -for i in 0 .. 10 { - println("Iteration start") - - if i == 2 { - continue; - } - - if i == 5 { - break; - } - - println(i); -} -println("Loop end") -``` - -When used, `break` will end the current loop early and jump to the statement after the for loop. In the example -above, the `break` will stop the loop and jump to the `println("Loop end")`. - -`continue` will stop the current iteration of the loop, and jump to the start of the next iteration. In the example -above, `continue` will jump to `println("Iteration start")` when used. Note that the loop continues as normal after this. -The iteration variable `i` is still increased by one as normal when `continue` is used. - -`break` and `continue` cannot currently be used to jump out of more than a single loop at a time. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_bus.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_bus.md deleted file mode 100644 index e54fc861257..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_bus.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: Data Bus -sidebar_position: 13 ---- -**Disclaimer** this feature is experimental, do not use it! - -The data bus is an optimization that the backend can use to make recursion more efficient. -In order to use it, you must define some inputs of the program entry points (usually the `main()` -function) with the `call_data` modifier, and the return values with the `return_data` modifier. -These modifiers are incompatible with `pub` and `mut` modifiers. - -## Example - -```rust -fn main(mut x: u32, y: call_data u32, z: call_data [u32;4] ) -> return_data u32 { - let a = z[x]; - a+y -} -``` - -As a result, both call_data and return_data will be treated as private inputs and encapsulated into a read-only array each, for the backend to process. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/_category_.json deleted file mode 100644 index 5d694210bbf..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 0, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/arrays.md deleted file mode 100644 index 9b02d52e8a8..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/arrays.md +++ /dev/null @@ -1,253 +0,0 @@ ---- -title: Arrays -description: - Dive into the Array data type in Noir. Grasp its methods, practical examples, and best practices for efficiently using Arrays in your Noir code. -keywords: - [ - noir, - array type, - methods, - examples, - indexing, - ] -sidebar_position: 4 ---- - -An array is one way of grouping together values into one compound type. Array types can be inferred -or explicitly specified via the syntax `[; ]`: - -```rust -fn main(x : Field, y : Field) { - let my_arr = [x, y]; - let your_arr: [Field; 2] = [x, y]; -} -``` - -Here, both `my_arr` and `your_arr` are instantiated as an array containing two `Field` elements. - -Array elements can be accessed using indexing: - -```rust -fn main() { - let a = [1, 2, 3, 4, 5]; - - let first = a[0]; - let second = a[1]; -} -``` - -All elements in an array must be of the same type (i.e. homogeneous). That is, an array cannot group -a `Field` value and a `u8` value together for example. - -You can write mutable arrays, like: - -```rust -fn main() { - let mut arr = [1, 2, 3, 4, 5]; - assert(arr[0] == 1); - - arr[0] = 42; - assert(arr[0] == 42); -} -``` - -You can instantiate a new array of a fixed size with the same value repeated for each element. The following example instantiates an array of length 32 where each element is of type Field and has the value 0. - -```rust -let array: [Field; 32] = [0; 32]; -``` - -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: - -```rust -let array: [Field; 32] = [0; 32]; -let sl = array.as_slice() -``` - -You can define multidimensional arrays: - -```rust -let array : [[Field; 2]; 2]; -let element = array[0][0]; -``` - -However, multidimensional slices are not supported. For example, the following code will error at compile time: - -```rust -let slice : [[Field]] = &[]; -``` - -## Types - -You can create arrays of primitive types or structs. There is not yet support for nested arrays -(arrays of arrays) or arrays of structs that contain arrays. - -## Methods - -For convenience, the STD provides some ready-to-use, common methods for arrays. -Each of these functions are located within the generic impl `impl [T; N] {`. -So anywhere `self` appears, it refers to the variable `self: [T; N]`. - -### len - -Returns the length of an array - -```rust -fn len(self) -> Field -``` - -example - -```rust -fn main() { - let array = [42, 42]; - assert(array.len() == 2); -} -``` - -### sort - -Returns a new sorted array. The original array remains untouched. Notice that this function will -only work for arrays of fields or integers, not for any arbitrary type. This is because the sorting -logic it uses internally is optimized specifically for these values. If you need a sort function to -sort any type, you should use the function `sort_via` described below. - -```rust -fn sort(self) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32]; - let sorted = arr.sort(); - assert(sorted == [32, 42]); -} -``` - -### sort_via - -Sorts the array with a custom comparison function - -```rust -fn sort_via(self, ordering: fn(T, T) -> bool) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32] - let sorted_ascending = arr.sort_via(|a, b| a <= b); - assert(sorted_ascending == [32, 42]); // verifies - - let sorted_descending = arr.sort_via(|a, b| a >= b); - assert(sorted_descending == [32, 42]); // does not verify -} -``` - -### map - -Applies a function to each element of the array, returning a new array containing the mapped elements. - -```rust -fn map(self, f: fn(T) -> U) -> [U; N] -``` - -example - -```rust -let a = [1, 2, 3]; -let b = a.map(|a| a * 2); // b is now [2, 4, 6] -``` - -### fold - -Applies a function to each element of the array, returning the final accumulated value. The first -parameter is the initial value. - -```rust -fn fold(self, mut accumulator: U, f: fn(U, T) -> U) -> U -``` - -This is a left fold, so the given function will be applied to the accumulator and first element of -the array, then the second, and so on. For a given call the expected result would be equivalent to: - -```rust -let a1 = [1]; -let a2 = [1, 2]; -let a3 = [1, 2, 3]; - -let f = |a, b| a - b; -a1.fold(10, f) //=> f(10, 1) -a2.fold(10, f) //=> f(f(10, 1), 2) -a3.fold(10, f) //=> f(f(f(10, 1), 2), 3) -``` - -example: - -```rust - -fn main() { - let arr = [2, 2, 2, 2, 2]; - let folded = arr.fold(0, |a, b| a + b); - assert(folded == 10); -} - -``` - -### reduce - -Same as fold, but uses the first element as starting element. - -```rust -fn reduce(self, f: fn(T, T) -> T) -> T -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let reduced = arr.reduce(|a, b| a + b); - assert(reduced == 10); -} -``` - -### all - -Returns true if all the elements satisfy the given predicate - -```rust -fn all(self, predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let all = arr.all(|a| a == 2); - assert(all); -} -``` - -### any - -Returns true if any of the elements satisfy the given predicate - -```rust -fn any(self, predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 5]; - let any = arr.any(|a| a == 5); - assert(any); -} - -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/booleans.md deleted file mode 100644 index 7211716f63e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/booleans.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Booleans -description: - Delve into the Boolean data type in Noir. Understand its methods, practical examples, and best practices for using Booleans in your Noir programs. -keywords: - [ - noir, - boolean type, - methods, - examples, - logical operations, - ] -sidebar_position: 2 ---- - - -The `bool` type in Noir has two possible values: `true` and `false`: - -```rust -fn main() { - let t = true; - let f: bool = false; -} -``` - -> **Note:** When returning a boolean value, it will show up as a value of 1 for `true` and 0 for -> `false` in _Verifier.toml_. - -The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and -[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/fields.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/fields.md deleted file mode 100644 index a10a4810788..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/fields.md +++ /dev/null @@ -1,192 +0,0 @@ ---- -title: Fields -description: - Dive deep into the Field data type in Noir. Understand its methods, practical examples, and best practices to effectively use Fields in your Noir programs. -keywords: - [ - noir, - field type, - methods, - examples, - best practices, - ] -sidebar_position: 0 ---- - -The field type corresponds to the native field type of the proving backend. - -The size of a Noir field depends on the elliptic curve's finite field for the proving backend -adopted. For example, a field would be a 254-bit integer when paired with the default backend that -spans the Grumpkin curve. - -Fields support integer arithmetic and are often used as the default numeric type in Noir: - -```rust -fn main(x : Field, y : Field) { - let z = x + y; -} -``` - -`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new -private value `z` constrained to be equal to `x + y`. - -If proving efficiency is of priority, fields should be used as a default for solving problems. -Smaller integer types (e.g. `u64`) incur extra range constraints. - -## Methods - -After declaring a Field, you can use these common methods on it: - -### to_le_bits - -Transforms the field into an array of bits, Little Endian. - -```rust -fn to_le_bits(_x : Field, _bit_size: u32) -> [u1] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_le_bits(32); -} -``` - -### to_be_bits - -Transforms the field into an array of bits, Big Endian. - -```rust -fn to_be_bits(_x : Field, _bit_size: u32) -> [u1] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_be_bits(32); -} -``` - -### to_le_bytes - -Transforms into an array of bytes, Little Endian - -```rust -fn to_le_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_le_bytes(4); -} -``` - -### to_be_bytes - -Transforms into an array of bytes, Big Endian - -```rust -fn to_be_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_be_bytes(4); -} -``` - -### to_le_radix - -Decomposes into a vector over the specified base, Little Endian - -```rust -fn to_le_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_le_radix(256, 4); -} -``` - -### to_be_radix - -Decomposes into a vector over the specified base, Big Endian - -```rust -fn to_be_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_be_radix(256, 4); -} -``` - -### pow_32 - -Returns the value to the power of the specified exponent - -```rust -fn pow_32(self, exponent: Field) -> Field -``` - -example: - -```rust -fn main() { - let field = 2 - let pow = field.pow_32(4); - assert(pow == 16); -} -``` - -### assert_max_bit_size - -Adds a constraint to specify that the field can be represented with `bit_size` number of bits - -```rust -fn assert_max_bit_size(self, bit_size: u32) -``` - -example: - -```rust -fn main() { - let field = 2 - field.assert_max_bit_size(32); -} -``` - -### sgn0 - -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. - -```rust -fn sgn0(self) -> u1 -``` - - -### lt - -Returns true if the field is less than the other field - -```rust -pub fn lt(self, another: Field) -> bool -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/function_types.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/function_types.md deleted file mode 100644 index f6121af17e2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/function_types.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Function types -sidebar_position: 10 ---- - -Noir supports higher-order functions. The syntax for a function type is as follows: - -```rust -fn(arg1_type, arg2_type, ...) -> return_type -``` - -Example: - -```rust -fn assert_returns_100(f: fn() -> Field) { // f takes no args and returns a Field - assert(f() == 100); -} - -fn main() { - assert_returns_100(|| 100); // ok - assert_returns_100(|| 150); // fails -} -``` - -A function type also has an optional capture environment - this is necessary to support closures. -See [Lambdas](../lambdas.md) for more details. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/index.md deleted file mode 100644 index 357813c147a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/index.md +++ /dev/null @@ -1,110 +0,0 @@ ---- -title: Data Types -description: - Get a clear understanding of the two categories of Noir data types - primitive types and compound - types. Learn about their characteristics, differences, and how to use them in your Noir - programming. -keywords: - [ - noir, - data types, - primitive types, - compound types, - private types, - public types, - ] ---- - -Every value in Noir has a type, which determines which operations are valid for it. - -All values in Noir are fundamentally composed of `Field` elements. For a more approachable -developing experience, abstractions are added on top to introduce different data types in Noir. - -Noir has two category of data types: primitive types (e.g. `Field`, integers, `bool`) and compound -types that group primitive types (e.g. arrays, tuples, structs). Each value can either be private or -public. - -## Private & Public Types - -A **private value** is known only to the Prover, while a **public value** is known by both the -Prover and Verifier. Mark values as `private` when the value should only be known to the prover. All -primitive types (including individual fields of compound types) in Noir are private by default, and -can be marked public when certain values are intended to be revealed to the Verifier. - -> **Note:** For public values defined in Noir programs paired with smart contract verifiers, once -> the proofs are verified on-chain the values can be considered known to everyone that has access to -> that blockchain. - -Public data types are treated no differently to private types apart from the fact that their values -will be revealed in proofs generated. Simply changing the value of a public type will not change the -circuit (where the same goes for changing values of private types as well). - -_Private values_ are also referred to as _witnesses_ sometimes. - -> **Note:** The terms private and public when applied to a type (e.g. `pub Field`) have a different -> meaning than when applied to a function (e.g. `pub fn foo() {}`). -> -> The former is a visibility modifier for the Prover to interpret if a value should be made known to -> the Verifier, while the latter is a visibility modifier for the compiler to interpret if a -> function should be made accessible to external Noir programs like in other languages. - -### pub Modifier - -All data types in Noir are private by default. Types are explicitly declared as public using the -`pub` modifier: - -```rust -fn main(x : Field, y : pub Field) -> pub Field { - x + y -} -``` - -In this example, `x` is **private** while `y` and `x + y` (the return value) are **public**. Note -that visibility is handled **per variable**, so it is perfectly valid to have one input that is -private and another that is public. - -> **Note:** Public types can only be declared through parameters on `main`. - -## Type Aliases - -A type alias is a new name for an existing type. Type aliases are declared with the keyword `type`: - -```rust -type Id = u8; - -fn main() { - let id: Id = 1; - let zero: u8 = 0; - assert(zero + 1 == id); -} -``` - -Type aliases can also be used with [generics](../generics.md): - -```rust -type Id = Size; - -fn main() { - let id: Id = 1; - let zero: u32 = 0; - assert(zero + 1 == id); -} -``` - -Type aliases can even refer to other aliases. An error will be issued if they form a cycle: - -```rust -// Ok! -type A = B; -type B = Field; - -type Bad1 = Bad2; - -// error: Dependency cycle found -type Bad2 = Bad1; -// ^^^^^^^^^^^ 'Bad2' recursively depends on itself: Bad2 -> Bad1 -> Bad2 -``` - -### BigInt - -You can achieve BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/integers.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/integers.md deleted file mode 100644 index 1c6b375db49..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/integers.md +++ /dev/null @@ -1,155 +0,0 @@ ---- -title: Integers -description: Explore the Integer data type in Noir. Learn about its methods, see real-world examples, and grasp how to efficiently use Integers in your Noir code. -keywords: [noir, integer types, methods, examples, arithmetic] -sidebar_position: 1 ---- - -An integer type is a range constrained field type. The Noir frontend supports both unsigned and signed integer types. The allowed sizes are 1, 8, 32 and 64 bits. - -:::info - -When an integer is defined in Noir without a specific type, it will default to `Field`. - -The one exception is for loop indices which default to `u64` since comparisons on `Field`s are not possible. - -::: - -## Unsigned Integers - -An unsigned integer type is specified first with the letter `u` (indicating its unsigned nature) followed by its bit size (e.g. `8`): - -```rust -fn main() { - let x: u8 = 1; - let y: u8 = 1; - let z = x + y; - assert (z == 2); -} -``` - -The bit size determines the maximum value the integer type can store. For example, a `u8` variable can store a value in the range of 0 to 255 (i.e. $\\2^{8}-1\\$). - -## Signed Integers - -A signed integer type is specified first with the letter `i` (which stands for integer) followed by its bit size (e.g. `8`): - -```rust -fn main() { - let x: i8 = -1; - let y: i8 = -1; - let z = x + y; - assert (z == -2); -} -``` - -The bit size determines the maximum and minimum range of value the integer type can store. For example, an `i8` variable can store a value in the range of -128 to 127 (i.e. $\\-2^{7}\\$ to $\\2^{7}-1\\$). - -## 128 bits Unsigned Integers - -The built-in structure `U128` allows you to use 128-bit unsigned integers almost like a native integer type. However, there are some differences to keep in mind: -- You cannot cast between a native integer and `U128` -- There is a higher performance cost when using `U128`, compared to a native type. - -Conversion between unsigned integer types and U128 are done through the use of `from_integer` and `to_integer` functions. `from_integer` also accepts the `Field` type as input. - -```rust -fn main() { - let x = U128::from_integer(23); - let y = U128::from_hex("0x7"); - let z = x + y; - assert(z.to_integer() == 30); -} -``` - -`U128` is implemented with two 64 bits limbs, representing the low and high bits, which explains the performance cost. You should expect `U128` to be twice more costly for addition and four times more costly for multiplication. -You can construct a U128 from its limbs: -```rust -fn main(x: u64, y: u64) { - let x = U128::from_u64s_be(x,y); - assert(z.hi == x as Field); - assert(z.lo == y as Field); -} -``` - -Note that the limbs are stored as Field elements in order to avoid unnecessary conversions. -Apart from this, most operations will work as usual: - -```rust -fn main(x: U128, y: U128) { - // multiplication - let c = x * y; - // addition and subtraction - let c = c - x + y; - // division - let c = x / y; - // bit operation; - let c = x & y | y; - // bit shift - let c = x << y; - // comparisons; - let c = x < y; - let c = x == y; -} -``` - -## Overflows - -Computations that exceed the type boundaries will result in overflow errors. This happens with both signed and unsigned integers. For example, attempting to prove: - -```rust -fn main(x: u8, y: u8) { - let z = x + y; -} -``` - -With: - -```toml -x = "255" -y = "1" -``` - -Would result in: - -``` -$ nargo prove -error: Assertion failed: 'attempt to add with overflow' -┌─ ~/src/main.nr:9:13 -│ -│ let z = x + y; -│ ----- -│ -= Call stack: - ... -``` - -A similar error would happen with signed integers: - -```rust -fn main() { - let x: i8 = -118; - let y: i8 = -11; - let z = x + y; -} -``` - -### Wrapping methods - -Although integer overflow is expected to error, some use-cases rely on wrapping. For these use-cases, the standard library provides `wrapping` variants of certain common operations: - -```rust -fn wrapping_add(x: T, y: T) -> T; -fn wrapping_sub(x: T, y: T) -> T; -fn wrapping_mul(x: T, y: T) -> T; -``` - -Example of how it is used: - -```rust -use dep::std; - -fn main(x: u8, y: u8) -> pub u8 { - std::wrapping_add(x, y) -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/references.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/references.md deleted file mode 100644 index a5293d11cfb..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/references.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: References -sidebar_position: 9 ---- - -Noir supports first-class references. References are a bit like pointers: they point to a specific address that can be followed to access the data stored at that address. You can use Rust-like syntax to use pointers in Noir: the `&` operator references the variable, the `*` operator dereferences it. - -Example: - -```rust -fn main() { - let mut x = 2; - - // you can reference x as &mut and pass it to multiplyBy2 - multiplyBy2(&mut x); -} - -// you can access &mut here -fn multiplyBy2(x: &mut Field) { - // and dereference it with * - *x = *x * 2; -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/slices.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/slices.mdx deleted file mode 100644 index 4eccc677b80..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/slices.mdx +++ /dev/null @@ -1,195 +0,0 @@ ---- -title: Slices -description: Explore the Slice data type in Noir. Understand its methods, see real-world examples, and learn how to effectively use Slices in your Noir programs. -keywords: [noir, slice type, methods, examples, subarrays] -sidebar_position: 5 ---- - -import Experimental from '@site/src/components/Notes/_experimental.mdx'; - - - -A slice is a dynamically-sized view into a sequence of elements. They can be resized at runtime, but because they don't own the data, they cannot be returned from a circuit. You can treat slices as arrays without a constrained size. - -```rust -use dep::std::slice; - -fn main() -> pub Field { - let mut slice: [Field] = &[0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -To write a slice literal, use a preceeding ampersand as in: `&[0; 2]` or -`&[1, 2, 3]`. - -It is important to note that slices are not references to arrays. In Noir, -`&[..]` is more similar to an immutable, growable vector. - -View the corresponding test file [here][test-file]. - -[test-file]: https://github.com/noir-lang/noir/blob/f387ec1475129732f72ba294877efdf6857135ac/crates/nargo_cli/tests/test_data_ssa_refactor/slices/src/main.nr - -## Methods - -For convenience, the STD provides some ready-to-use, common methods for slices: - -### push_back - -Pushes a new element to the end of the slice, returning a new slice with a length one greater than the original unmodified slice. - -```rust -fn push_back(_self: [T], _elem: T) -> [T] -``` - -example: - -```rust -fn main() -> pub Field { - let mut slice: [Field] = &[0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -View the corresponding test file [here][test-file]. - -### push_front - -Returns a new array with the specified element inserted at index 0. The existing elements indexes are incremented by 1. - -```rust -fn push_front(_self: Self, _elem: T) -> Self -``` - -Example: - -```rust -let mut new_slice: [Field] = &[]; -new_slice = new_slice.push_front(20); -assert(new_slice[0] == 20); // returns true -``` - -View the corresponding test file [here][test-file]. - -### pop_front - -Returns a tuple of two items, the first element of the array and the rest of the array. - -```rust -fn pop_front(_self: Self) -> (T, Self) -``` - -Example: - -```rust -let (first_elem, rest_of_slice) = slice.pop_front(); -``` - -View the corresponding test file [here][test-file]. - -### pop_back - -Returns a tuple of two items, the beginning of the array with the last element omitted and the last element. - -```rust -fn pop_back(_self: Self) -> (Self, T) -``` - -Example: - -```rust -let (popped_slice, last_elem) = slice.pop_back(); -``` - -View the corresponding test file [here][test-file]. - -### append - -Loops over a slice and adds it to the end of another. - -```rust -fn append(mut self, other: Self) -> Self -``` - -Example: - -```rust -let append = &[1, 2].append(&[3, 4, 5]); -``` - -### insert - -Inserts an element at a specified index and shifts all following elements by 1. - -```rust -fn insert(_self: Self, _index: Field, _elem: T) -> Self -``` - -Example: - -```rust -new_slice = rest_of_slice.insert(2, 100); -assert(new_slice[2] == 100); -``` - -View the corresponding test file [here][test-file]. - -### remove - -Remove an element at a specified index, shifting all elements after it to the left, returning the altered slice and the removed element. - -```rust -fn remove(_self: Self, _index: Field) -> (Self, T) -``` - -Example: - -```rust -let (remove_slice, removed_elem) = slice.remove(3); -``` - -### len - -Returns the length of a slice - -```rust -fn len(self) -> Field -``` - -Example: - -```rust -fn main() { - let slice = &[42, 42]; - assert(slice.len() == 2); -} -``` - -### as_array - -Converts this slice into an array. - -Make sure to specify the size of the resulting array. -Panics if the resulting array length is different than the slice's length. - -```rust -fn as_array(self) -> [T; N] -``` - -Example: - -```rust -fn main() { - let slice = &[5, 6]; - - // Always specify the length of the resulting array! - let array: [Field; 2] = slice.as_array(); - - assert(array[0] == slice[0]); - assert(array[1] == slice[1]); -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/strings.md deleted file mode 100644 index 8ab5825a4c4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/strings.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: Strings -description: - Discover the String data type in Noir. Learn about its methods, see real-world examples, and understand how to effectively manipulate and use Strings in Noir. -keywords: - [ - noir, - string type, - methods, - examples, - concatenation, - ] -sidebar_position: 3 ---- - - -The string type is a fixed length value defined with `str`. - -You can use strings in `assert()` functions or print them with -`println()`. See more about [Logging](../../standard_library/logging.md). - -```rust -use dep::std; - -fn main(message : pub str<11>, hex_as_string : str<4>) { - println(message); - assert(message == "hello world"); - assert(hex_as_string == "0x41"); -} -``` - -You can convert a `str` to a byte array by calling `as_bytes()` -or a vector by calling `as_bytes_vec()`. - -```rust -fn main() { - let message = "hello world"; - let message_bytes = message.as_bytes(); - let mut message_vec = message.as_bytes_vec(); - assert(message_bytes.len() == 11); - assert(message_bytes[0] == 104); - assert(message_bytes[0] == message_vec.get(0)); -} -``` - -## Escape characters - -You can use escape characters for your strings: - -| Escape Sequence | Description | -|-----------------|-----------------| -| `\r` | Carriage Return | -| `\n` | Newline | -| `\t` | Tab | -| `\0` | Null Character | -| `\"` | Double Quote | -| `\\` | Backslash | - -Example: - -```rust -let s = "Hello \"world" // prints "Hello "world" -let s = "hey \tyou"; // prints "hey you" -``` - -## Raw strings - -A raw string begins with the letter `r` and is optionally delimited by a number of hashes `#`. - -Escape characters are *not* processed within raw strings. All contents are interpreted literally. - -Example: - -```rust -let s = r"Hello world"; -let s = r#"Simon says "hello world""#; - -// Any number of hashes may be used (>= 1) as long as the string also terminates with the same number of hashes -let s = r#####"One "#, Two "##, Three "###, Four "####, Five will end the string."#####; -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/structs.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/structs.md deleted file mode 100644 index dbf68c99813..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/structs.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -title: Structs -description: - Explore the Struct data type in Noir. Learn about its methods, see real-world examples, and grasp how to effectively define and use Structs in your Noir programs. -keywords: - [ - noir, - struct type, - methods, - examples, - data structures, - ] -sidebar_position: 8 ---- - -A struct also allows for grouping multiple values of different types. Unlike tuples, we can also -name each field. - -> **Note:** The usage of _field_ here refers to each element of the struct and is unrelated to the -> field type of Noir. - -Defining a struct requires giving it a name and listing each field within as `: ` pairs: - -```rust -struct Animal { - hands: Field, - legs: Field, - eyes: u8, -} -``` - -An instance of a struct can then be created with actual values in `: ` pairs in any -order. Struct fields are accessible using their given names: - -```rust -fn main() { - let legs = 4; - - let dog = Animal { - eyes: 2, - hands: 0, - legs, - }; - - let zero = dog.hands; -} -``` - -Structs can also be destructured in a pattern, binding each field to a new variable: - -```rust -fn main() { - let Animal { hands, legs: feet, eyes } = get_octopus(); - - let ten = hands + feet + eyes as u8; -} - -fn get_octopus() -> Animal { - let octopus = Animal { - hands: 0, - legs: 8, - eyes: 2, - }; - - octopus -} -``` - -The new variables can be bound with names different from the original struct field names, as -showcased in the `legs --> feet` binding in the example above. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/tuples.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/tuples.md deleted file mode 100644 index 2ec5c9c4113..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/tuples.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Tuples -description: - Dive into the Tuple data type in Noir. Understand its methods, practical examples, and best practices for efficiently using Tuples in your Noir code. -keywords: - [ - noir, - tuple type, - methods, - examples, - multi-value containers, - ] -sidebar_position: 7 ---- - -A tuple collects multiple values like an array, but with the added ability to collect values of -different types: - -```rust -fn main() { - let tup: (u8, u64, Field) = (255, 500, 1000); -} -``` - -One way to access tuple elements is via destructuring using pattern matching: - -```rust -fn main() { - let tup = (1, 2); - - let (one, two) = tup; - - let three = one + two; -} -``` - -Another way to access tuple elements is via direct member access, using a period (`.`) followed by -the index of the element we want to access. Index `0` corresponds to the first tuple element, `1` to -the second and so on: - -```rust -fn main() { - let tup = (5, 6, 7, 8); - - let five = tup.0; - let eight = tup.3; -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/distinct.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/distinct.md deleted file mode 100644 index 6c993b8b5e0..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/distinct.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: Distinct Witnesses -sidebar_position: 11 ---- - -The `distinct` keyword prevents repetitions of witness indices in the program's ABI. This ensures -that the witnesses being returned as public inputs are all unique. - -The `distinct` keyword is only used for return values on program entry points (usually the `main()` -function). - -When using `distinct` and `pub` simultaneously, `distinct` comes first. See the example below. - -You can read more about the problem this solves -[here](https://github.com/noir-lang/noir/issues/1183). - -## Example - -Without the `distinct` keyword, the following program - -```rust -fn main(x : pub Field, y : pub Field) -> pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - "return_witnesses": [3, 2, 4, 4] - } -} -``` - -Whereas (with the `distinct` keyword) - -```rust -fn main(x : pub Field, y : pub Field) -> distinct pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - //... - "return_witnesses": [3, 4, 5, 6] - } -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/generics.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/generics.md deleted file mode 100644 index 0c1c27a2221..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/generics.md +++ /dev/null @@ -1,106 +0,0 @@ ---- -title: Generics -description: Learn how to use Generics in Noir -keywords: [Noir, Rust, generics, functions, structs] -sidebar_position: 7 ---- - -Generics allow you to use the same functions with multiple different concrete data types. You can -read more about the concept of generics in the Rust documentation -[here](https://doc.rust-lang.org/book/ch10-01-syntax.html). - -Here is a trivial example showing the identity function that supports any type. In Rust, it is -common to refer to the most general type as `T`. We follow the same convention in Noir. - -```rust -fn id(x: T) -> T { - x -} -``` - -## In Structs - -Generics are useful for specifying types in structs. For example, we can specify that a field in a -struct will be of a certain generic type. In this case `value` is of type `T`. - -```rust -struct RepeatedValue { - value: T, - count: Field, -} - -impl RepeatedValue { - fn print(self) { - for _i in 0 .. self.count { - println(self.value); - } - } -} - -fn main() { - let repeated = RepeatedValue { value: "Hello!", count: 2 }; - repeated.print(); -} -``` - -The `print` function will print `Hello!` an arbitrary number of times, twice in this case. - -If we want to be generic over array lengths (which are type-level integers), we can use numeric -generics. Using these looks just like using regular generics, but these generics can resolve to -integers at compile-time, rather than resolving to types. Here's an example of a struct that is -generic over the size of the array it contains internally: - -```rust -struct BigInt { - limbs: [u32; N], -} - -impl BigInt { - // `N` is in scope of all methods in the impl - fn first(first: BigInt, second: BigInt) -> Self { - assert(first.limbs != second.limbs); - first - - fn second(first: BigInt, second: Self) -> Self { - assert(first.limbs != second.limbs); - second - } -} -``` - -## Calling functions on generic parameters - -Since a generic type `T` can represent any type, how can we call functions on the underlying type? -In other words, how can we go from "any type `T`" to "any type `T` that has certain methods available?" - -This is what [traits](../concepts/traits.md) are for in Noir. Here's an example of a function generic over -any type `T` that implements the `Eq` trait for equality: - -```rust -fn first_element_is_equal(array1: [T; N], array2: [T; N]) -> bool - where T: Eq -{ - if (array1.len() == 0) | (array2.len() == 0) { - true - } else { - array1[0] == array2[0] - } -} - -fn main() { - assert(first_element_is_equal([1, 2, 3], [1, 5, 6])); - - // We can use first_element_is_equal for arrays of any type - // as long as we have an Eq impl for the types we pass in - let array = [MyStruct::new(), MyStruct::new()]; - assert(array_eq(array, array, MyStruct::eq)); -} - -impl Eq for MyStruct { - fn eq(self, other: MyStruct) -> bool { - self.foo == other.foo - } -} -``` - -You can find more details on traits and trait implementations on the [traits page](../concepts/traits.md). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/globals.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/globals.md deleted file mode 100644 index 063a3d89248..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/globals.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -title: Global Variables -description: - Learn about global variables in Noir. Discover how - to declare, modify, and use them in your programs. -keywords: [noir programming language, globals, global variables, constants] -sidebar_position: 8 ---- - -## Globals - - -Noir supports global variables. The global's type can be inferred by the compiler entirely: - -```rust -global N = 5; // Same as `global N: Field = 5` - -global TUPLE = (3, 2); - -fn main() { - assert(N == 5); - assert(N == TUPLE.0 + TUPLE.1); -} -``` - -:::info - -Globals can be defined as any expression, so long as they don't depend on themselves - otherwise there would be a dependency cycle! For example: - -```rust -global T = foo(T); // dependency error -``` - -::: - - -If they are initialized to a literal integer, globals can be used to specify an array's length: - -```rust -global N: Field = 2; - -fn main(y : [Field; N]) { - assert(y[0] == y[1]) -} -``` - -A global from another module can be imported or referenced externally like any other name: - -```rust -global N = 20; - -fn main() { - assert(my_submodule::N != N); -} - -mod my_submodule { - global N: Field = 10; -} -``` - -When a global is used, Noir replaces the name with its definition on each occurrence. -This means globals defined using function calls will repeat the call each time they're used: - -```rust -global RESULT = foo(); - -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. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/lambdas.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/lambdas.md deleted file mode 100644 index be3c7e0b5ca..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/lambdas.md +++ /dev/null @@ -1,81 +0,0 @@ ---- -title: Lambdas -description: Learn how to use anonymous functions in Noir programming language. -keywords: [Noir programming language, lambda, closure, function, anonymous function] -sidebar_position: 9 ---- - -## Introduction - -Lambdas are anonymous functions. The syntax is `|arg1, arg2, ..., argN| return_expression`. - -```rust -let add_50 = |val| val + 50; -assert(add_50(100) == 150); -``` - -A block can be used as the body of a lambda, allowing you to declare local variables inside it: - -```rust -let cool = || { - let x = 100; - let y = 100; - x + y -} - -assert(cool() == 200); -``` - -## Closures - -Inside the body of a lambda, you can use variables defined in the enclosing function. Such lambdas are called **closures**. In this example `x` is defined inside `main` and is accessed from within the lambda: - -```rust -fn main() { - let x = 100; - let closure = || x + 150; - assert(closure() == 250); -} -``` - -## Passing closures to higher-order functions - -It may catch you by surprise that the following code fails to compile: - -```rust -fn foo(f: fn () -> Field) -> Field { - f() -} - -fn main() { - let (x, y) = (50, 50); - assert(foo(|| x + y) == 100); // error :( -} -``` - -The reason is that the closure's capture environment affects its type - we have a closure that captures two Fields and `foo` -expects a regular function as an argument - those are incompatible. -:::note - -Variables contained within the `||` are the closure's parameters, and the expression that follows it is the closure's body. The capture environment is comprised of any variables used in the closure's body that are not parameters. - -E.g. in |x| x + y, y would be a captured variable, but x would not be, since it is a parameter of the closure. - -::: -The syntax for the type of a closure is `fn[env](args) -> ret_type`, where `env` is the capture environment of the closure - -in this example that's `(Field, Field)`. - -The best solution in our case is to make `foo` generic over the environment type of its parameter, so that it can be called -with closures with any environment, as well as with regular functions: - -```rust -fn foo(f: fn[Env]() -> Field) -> Field { - f() -} - -fn main() { - let (x, y) = (50, 50); - assert(foo(|| x + y) == 100); // compiles fine - assert(foo(|| 60) == 60); // compiles fine -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/mutability.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/mutability.md deleted file mode 100644 index fdeef6a87c5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/mutability.md +++ /dev/null @@ -1,121 +0,0 @@ ---- -title: Mutability -description: - Learn about mutable variables in Noir. Discover how - to declare, modify, and use them in your programs. -keywords: [noir programming language, mutability in noir, mutable variables] -sidebar_position: 8 ---- - -Variables in noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned -to via an assignment expression. - -```rust -let x = 2; -x = 3; // error: x must be mutable to be assigned to - -let mut y = 3; -let y = 4; // OK -``` - -The `mut` modifier can also apply to patterns: - -```rust -let (a, mut b) = (1, 2); -a = 11; // error: a must be mutable to be assigned to -b = 12; // OK - -let mut (c, d) = (3, 4); -c = 13; // OK -d = 14; // OK - -// etc. -let MyStruct { x: mut y } = MyStruct { x: a }; -// y is now in scope -``` - -Note that mutability in noir is local and everything is passed by value, so if a called function -mutates its parameters then the parent function will keep the old value of the parameters. - -```rust -fn main() -> pub Field { - let x = 3; - helper(x); - x // x is still 3 -} - -fn helper(mut x: i32) { - x = 4; -} -``` - -## Non-local mutability - -Non-local mutability can be achieved through the mutable reference type `&mut T`: - -```rust -fn set_to_zero(x: &mut Field) { - *x = 0; -} - -fn main() { - let mut y = 42; - set_to_zero(&mut y); - assert(*y == 0); -} -``` - -When creating a mutable reference, the original variable being referred to (`y` in this -example) must also be mutable. Since mutable references are a reference type, they must -be explicitly dereferenced via `*` to retrieve the underlying value. Note that this yields -a copy of the value, so mutating this copy will not change the original value behind the -reference: - -```rust -fn main() { - let mut x = 1; - let x_ref = &mut x; - - let mut y = *x_ref; - let y_ref = &mut y; - - x = 2; - *x_ref = 3; - - y = 4; - *y_ref = 5; - - assert(x == 3); - assert(*x_ref == 3); - assert(y == 5); - assert(*y_ref == 5); -} -``` - -Note that types in Noir are actually deeply immutable so the copy that occurs when -dereferencing is only a conceptual copy - no additional constraints will occur. - -Mutable references can also be stored within structs. Note that there is also -no lifetime parameter on these unlike rust. This is because the allocated memory -always lasts the entire program - as if it were an array of one element. - -```rust -struct Foo { - x: &mut Field -} - -impl Foo { - fn incr(mut self) { - *self.x += 1; - } -} - -fn main() { - let foo = Foo { x: &mut 0 }; - foo.incr(); - assert(*foo.x == 1); -} -``` - -In general, you should avoid non-local & shared mutability unless it is needed. Sticking -to only local mutability will improve readability and potentially improve compiler optimizations as well. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/ops.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/ops.md deleted file mode 100644 index 60425cb8994..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/ops.md +++ /dev/null @@ -1,98 +0,0 @@ ---- -title: Logical Operations -description: - Learn about the supported arithmetic and logical operations in the Noir programming language. - Discover how to perform operations on private input types, integers, and booleans. -keywords: - [ - Noir programming language, - supported operations, - arithmetic operations, - logical operations, - predicate operators, - bitwise operations, - short-circuiting, - backend, - ] -sidebar_position: 3 ---- - -# Operations - -## Table of Supported Operations - -| Operation | Description | Requirements | -| :-------- | :------------------------------------------------------------: | -------------------------------------: | -| + | Adds two private input types together | Types must be private input | -| - | Subtracts two private input types together | Types must be private input | -| \* | Multiplies two private input types together | Types must be private input | -| / | Divides two private input types together | Types must be private input | -| ^ | XOR two private input types together | Types must be integer | -| & | AND two private input types together | Types must be integer | -| \| | OR two private input types together | Types must be integer | -| \<\< | Left shift an integer by another integer amount | Types must be integer | -| >> | Right shift an integer by another integer amount | Types must be integer | -| ! | Bitwise not of a value | Type must be integer or boolean | -| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | -| > | returns a bool if one value is more than the other | Upper bound must have a known bit size | -| >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | -| == | returns a bool if one value is equal to the other | Both types must not be constants | -| != | returns a bool if one value is not equal to the other | Both types must not be constants | - -### Predicate Operators - -`<,<=, !=, == , >, >=` are known as predicate/comparison operations because they compare two values. -This differs from the operations such as `+` where the operands are used in _computation_. - -### Bitwise Operations Example - -```rust -fn main(x : Field) { - let y = x as u32; - let z = y & y; -} -``` - -`z` is implicitly constrained to be the result of `y & y`. The `&` operand is used to denote bitwise -`&`. - -> `x & x` would not compile as `x` is a `Field` and not an integer type. - -### Logical Operators - -Noir has no support for the logical operators `||` and `&&`. This is because encoding the -short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can -use the bitwise operators `|` and `&` which operate identically for booleans, just without the -short-circuiting. - -```rust -let my_val = 5; - -let mut flag = 1; -if (my_val > 6) | (my_val == 0) { - flag = 0; -} -assert(flag == 1); - -if (my_val != 10) & (my_val < 50) { - flag = 0; -} -assert(flag == 0); -``` - -### Shorthand operators - -Noir shorthand operators for most of the above operators, namely `+=, -=, *=, /=, %=, &=, |=, ^=, <<=`, and `>>=`. These allow for more concise syntax. For example: - -```rust -let mut i = 0; -i = i + 1; -``` - -could be written as: - -```rust -let mut i = 0; -i += 1; -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/shadowing.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/shadowing.md deleted file mode 100644 index 5ce6130d201..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/shadowing.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Shadowing -sidebar_position: 12 ---- - -Noir allows for inheriting variables' values and re-declaring them with the same name similar to Rust, known as shadowing. - -For example, the following function is valid in Noir: - -```rust -fn main() { - let x = 5; - - { - let x = x * 2; - assert (x == 10); - } - - assert (x == 5); -} -``` - -In this example, a variable x is first defined with the value 5. - -The local scope that follows shadows the original x, i.e. creates a local mutable x based on the value of the original x. It is given a value of 2 times the original x. - -When we return to the main scope, x once again refers to just the original x, which stays at the value of 5. - -## Temporal mutability - -One way that shadowing is useful, in addition to ergonomics across scopes, is for temporarily mutating variables. - -```rust -fn main() { - let age = 30; - // age = age + 5; // Would error as `age` is immutable by default. - - let mut age = age + 5; // Temporarily mutates `age` with a new value. - - let age = age; // Locks `age`'s mutability again. - - assert (age == 35); -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/traits.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/traits.md deleted file mode 100644 index ef1445a5907..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/traits.md +++ /dev/null @@ -1,389 +0,0 @@ ---- -title: Traits -description: - Traits in Noir can be used to abstract out a common interface for functions across - several data types. -keywords: [noir programming language, traits, interfaces, generic, protocol] -sidebar_position: 14 ---- - -## Overview - -Traits in Noir are a useful abstraction similar to interfaces or protocols in other languages. Each trait defines -the interface of several methods contained within the trait. Types can then implement this trait by providing -implementations for these methods. For example in the program: - -```rust -struct Rectangle { - width: Field, - height: Field, -} - -impl Rectangle { - fn area(self) -> Field { - self.width * self.height - } -} - -fn log_area(r: Rectangle) { - println(r.area()); -} -``` - -We have a function `log_area` to log the area of a `Rectangle`. Now how should we change the program if we want this -function to work on `Triangle`s as well?: - -```rust -struct Triangle { - width: Field, - height: Field, -} - -impl Triangle { - fn area(self) -> Field { - self.width * self.height / 2 - } -} -``` - -Making `log_area` generic over all types `T` would be invalid since not all types have an `area` method. Instead, we can -introduce a new `Area` trait and make `log_area` generic over all types `T` that implement `Area`: - -```rust -trait Area { - fn area(self) -> Field; -} - -fn log_area(shape: T) where T: Area { - println(shape.area()); -} -``` - -We also need to explicitly implement `Area` for `Rectangle` and `Triangle`. We can do that by changing their existing -impls slightly. Note that the parameter types and return type of each of our `area` methods must match those defined -by the `Area` trait. - -```rust -impl Area for Rectangle { - fn area(self) -> Field { - self.width * self.height - } -} - -impl Area for Triangle { - fn area(self) -> Field { - self.width * self.height / 2 - } -} -``` - -Now we have a working program that is generic over any type of Shape that is used! Others can even use this program -as a library with their own types - such as `Circle` - as long as they also implement `Area` for these types. - -## Where Clauses - -As seen in `log_area` above, when we want to create a function or method that is generic over any type that implements -a trait, we can add a where clause to the generic function. - -```rust -fn log_area(shape: T) where T: Area { - println(shape.area()); -} -``` - -It is also possible to apply multiple trait constraints on the same variable at once by combining traits with the `+` -operator. Similarly, we can have multiple trait constraints by separating each with a comma: - -```rust -fn foo(elements: [T], thing: U) where - T: Default + Add + Eq, - U: Bar, -{ - let mut sum = T::default(); - - for element in elements { - sum += element; - } - - if sum == T::default() { - thing.bar(); - } -} -``` - -## Generic Implementations - -You can add generics to a trait implementation by adding the generic list after the `impl` keyword: - -```rust -trait Second { - fn second(self) -> Field; -} - -impl Second for (T, Field) { - fn second(self) -> Field { - self.1 - } -} -``` - -You can also implement a trait for every type this way: - -```rust -trait Debug { - fn debug(self); -} - -impl Debug for T { - fn debug(self) { - println(self); - } -} - -fn main() { - 1.debug(); -} -``` - -### Generic Trait Implementations With Where Clauses - -Where clauses can also be placed on trait implementations themselves to restrict generics in a similar way. -For example, while `impl Foo for T` implements the trait `Foo` for every type, `impl Foo for T where T: Bar` -will implement `Foo` only for types that also implement `Bar`. This is often used for implementing generic types. -For example, here is the implementation for array equality: - -```rust -impl Eq for [T; N] where T: Eq { - // Test if two arrays have the same elements. - // Because both arrays must have length N, we know their lengths already match. - fn eq(self, other: Self) -> bool { - let mut result = true; - - for i in 0 .. self.len() { - // The T: Eq constraint is needed to call == on the array elements here - result &= self[i] == other[i]; - } - - result - } -} -``` - -## Generic Traits - -Traits themselves can also be generic by placing the generic arguments after the trait name. These generics are in -scope of every item within the trait. - -```rust -trait Into { - // Convert `self` to type `T` - fn into(self) -> T; -} -``` - -When implementing generic traits the generic arguments of the trait must be specified. This is also true anytime -when referencing a generic trait (e.g. in a `where` clause). - -```rust -struct MyStruct { - array: [Field; 2], -} - -impl Into<[Field; 2]> for MyStruct { - fn into(self) -> [Field; 2] { - self.array - } -} - -fn as_array(x: T) -> [Field; 2] - where T: Into<[Field; 2]> -{ - x.into() -} - -fn main() { - let array = [1, 2]; - let my_struct = MyStruct { array }; - - assert_eq(as_array(my_struct), array); -} -``` - -## Trait Methods With No `self` - -A trait can contain any number of methods, each of which have access to the `Self` type which represents each type -that eventually implements the trait. Similarly, the `self` variable is available as well but is not required to be used. -For example, we can define a trait to create a default value for a type. This trait will need to return the `Self` type -but doesn't need to take any parameters: - -```rust -trait Default { - fn default() -> Self; -} -``` - -Implementing this trait can be done similarly to any other trait: - -```rust -impl Default for Field { - fn default() -> Field { - 0 - } -} - -struct MyType {} - -impl Default for MyType { - fn default() -> Field { - MyType {} - } -} -``` - -However, since there is no `self` parameter, we cannot call it via the method call syntax `object.method()`. -Instead, we'll need to refer to the function directly. This can be done either by referring to the -specific impl `MyType::default()` or referring to the trait itself `Default::default()`. In the later -case, type inference determines the impl that is selected. - -```rust -let my_struct = MyStruct::default(); - -let x: Field = Default::default(); -let result = x + Default::default(); -``` - -:::warning - -```rust -let _ = Default::default(); -``` - -If type inference cannot select which impl to use because of an ambiguous `Self` type, an impl will be -arbitrarily selected. This occurs most often when the result of a trait function call with no parameters -is unused. To avoid this, when calling a trait function with no `self` or `Self` parameters or return type, -always refer to it via the implementation type's namespace - e.g. `MyType::default()`. -This is set to change to an error in future Noir versions. - -::: - -## Default Method Implementations - -A trait can also have default implementations of its methods by giving a body to the desired functions. -Note that this body must be valid for all types that may implement the trait. As a result, the only -valid operations on `self` will be operations valid for any type or other operations on the trait itself. - -```rust -trait Numeric { - fn add(self, other: Self) -> Self; - - // Default implementation of double is (self + self) - fn double(self) -> Self { - self.add(self) - } -} -``` - -When implementing a trait with default functions, a type may choose to implement only the required functions: - -```rust -impl Numeric for Field { - fn add(self, other: Field) -> Field { - self + other - } -} -``` - -Or it may implement the optional methods as well: - -```rust -impl Numeric for u32 { - fn add(self, other: u32) -> u32 { - self + other - } - - fn double(self) -> u32 { - self * 2 - } -} -``` - -## Impl Specialization - -When implementing traits for a generic type it is possible to implement the trait for only a certain combination -of generics. This can be either as an optimization or because those specific generics are required to implement the trait. - -```rust -trait Sub { - fn sub(self, other: Self) -> Self; -} - -struct NonZero { - value: T, -} - -impl Sub for NonZero { - fn sub(self, other: Self) -> Self { - let value = self.value - other.value; - assert(value != 0); - NonZero { value } - } -} -``` - -## Overlapping Implementations - -Overlapping implementations are disallowed by Noir to ensure Noir's decision on which impl to select is never ambiguous. -This means if a trait `Foo` is already implemented -by a type `Bar` for all `T`, then we cannot also have a separate impl for `Bar` (or any other -type argument). Similarly, if there is an impl for all `T` such as `impl Debug for T`, we cannot create -any more impls to `Debug` for other types since it would be ambiguous which impl to choose for any given -method call. - -```rust -trait Trait {} - -// Previous impl defined here -impl Trait for (A, B) {} - -// error: Impl for type `(Field, Field)` overlaps with existing impl -impl Trait for (Field, Field) {} -``` - -## Trait Coherence - -Another restriction on trait implementations is coherence. This restriction ensures other crates cannot create -impls that may overlap with other impls, even if several unrelated crates are used as dependencies in the same -program. - -The coherence restriction is: to implement a trait, either the trait itself or the object type must be declared -in the crate the impl is in. - -In practice this often comes up when using types provided by libraries. If a library provides a type `Foo` that does -not implement a trait in the standard library such as `Default`, you may not `impl Default for Foo` in your own crate. -While restrictive, this prevents later issues or silent changes in the program if the `Foo` library later added its -own impl for `Default`. If you are a user of the `Foo` library in this scenario and need a trait not implemented by the -library your choices are to either submit a patch to the library or use the newtype pattern. - -### The Newtype Pattern - -The newtype pattern gets around the coherence restriction by creating a new wrapper type around the library type -that we cannot create `impl`s for. Since the new wrapper type is defined in our current crate, we can create -impls for any trait we need on it. - -```rust -struct Wrapper { - foo: dep::some_library::Foo, -} - -impl Default for Wrapper { - fn default() -> Wrapper { - Wrapper { - foo: dep::some_library::Foo::new(), - } - } -} -``` - -Since we have an impl for our own type, the behavior of this code will not change even if `some_library` is updated -to provide its own `impl Default for Foo`. The downside of this pattern is that it requires extra wrapping and -unwrapping of values when converting to and from the `Wrapper` and `Foo` types. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/unconstrained.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/unconstrained.md deleted file mode 100644 index 96f824c5e42..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/unconstrained.md +++ /dev/null @@ -1,99 +0,0 @@ ---- -title: Unconstrained Functions -description: "Learn about what unconstrained functions in Noir are, how to use them and when you'd want to." - -keywords: [Noir programming language, unconstrained, open] -sidebar_position: 5 ---- - -Unconstrained functions are functions which do not constrain any of the included computation and allow for non-deterministic computation. - -## Why? - -Zero-knowledge (ZK) domain-specific languages (DSL) enable developers to generate ZK proofs from their programs by compiling code down to the constraints of an NP complete language (such as R1CS or PLONKish languages). However, the hard bounds of a constraint system can be very limiting to the functionality of a ZK DSL. - -Enabling a circuit language to perform unconstrained execution is a powerful tool. Said another way, unconstrained execution lets developers generate witnesses from code that does not generate any constraints. Being able to execute logic outside of a circuit is critical for both circuit performance and constructing proofs on information that is external to a circuit. - -Fetching information from somewhere external to a circuit can also be used to enable developers to improve circuit efficiency. - -A ZK DSL does not just prove computation, but proves that some computation was handled correctly. Thus, it is necessary that when we switch from performing some operation directly inside of a circuit to inside of an unconstrained environment that the appropriate constraints are still laid down elsewhere in the circuit. - -## Example - -An in depth example might help drive the point home. This example comes from the excellent [post](https://discord.com/channels/1113924620781883405/1124022445054111926/1128747641853972590) by Tom in the Noir Discord. - -Let's look at how we can optimize a function to turn a `u72` into an array of `u8`s. - -```rust -fn main(num: u72) -> pub [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8)) as u72 & 0xff) as u8; - } - - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 91 -Backend circuit size: 3619 -``` - -A lot of the operations in this function are optimized away by the compiler (all the bit-shifts turn into divisions by constants). However we can save a bunch of gates by casting to u8 a bit earlier. This automatically truncates the bit-shifted value to fit in a u8 which allows us to remove the AND against 0xff. This saves us ~480 gates in total. - -```rust -fn main(num: u72) -> pub [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8)) as u8; - } - - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 75 -Backend circuit size: 3143 -``` - -Those are some nice savings already but we can do better. This code is all constrained so we're proving every step of calculating out using num, but we don't actually care about how we calculate this, just that it's correct. This is where brillig comes in. - -It turns out that truncating a u72 into a u8 is hard to do inside a snark, each time we do as u8 we lay down 4 ACIR opcodes which get converted into multiple gates. It's actually much easier to calculate num from out than the other way around. All we need to do is multiply each element of out by a constant and add them all together, both relatively easy operations inside a snark. - -We can then run u72_to_u8 as unconstrained brillig code in order to calculate out, then use that result in our constrained function and assert that if we were to do the reverse calculation we'd get back num. This looks a little like the below: - -```rust -fn main(num: u72) -> pub [u8; 8] { - let out = u72_to_u8(num); - - let mut reconstructed_num: u72 = 0; - for i in 0..8 { - reconstructed_num += (out[i] as u72 << (56 - (8 * i))); - } - assert(num == reconstructed_num); - out -} - -unconstrained fn u72_to_u8(num: u72) -> [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8))) as u8; - } - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 78 -Backend circuit size: 2902 -``` - -This ends up taking off another ~250 gates from our circuit! We've ended up with more ACIR opcodes than before but they're easier for the backend to prove (resulting in fewer gates). - -Generally we want to use brillig whenever there's something that's easy to verify but hard to compute within the circuit. For example, if you wanted to calculate a square root of a number it'll be a much better idea to calculate this in brillig and then assert that if you square the result you get back your number. - -## Break and Continue - -In addition to loops over runtime bounds, `break` and `continue` are also available in unconstrained code. See [break and continue](../concepts/control_flow.md#break-and-continue) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/_category_.json deleted file mode 100644 index 1debcfe7675..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Modules, Packages and Crates", - "position": 2, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/crates_and_packages.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/crates_and_packages.md deleted file mode 100644 index 95ee9f52ab2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/crates_and_packages.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Crates and Packages -description: Learn how to use Crates and Packages in your Noir project -keywords: [Nargo, dependencies, package management, crates, package] -sidebar_position: 0 ---- - -## Crates - -A crate is the smallest amount of code that the Noir compiler considers at a time. -Crates can contain modules, and the modules may be defined in other files that get compiled with the crate, as we’ll see in the coming sections. - -### Crate Types - -A Noir crate can come in several forms: binaries, libraries or contracts. - -#### Binaries - -_Binary crates_ are programs which you can compile to an ACIR circuit which you can then create proofs against. Each must have a function called `main` that defines the ACIR circuit which is to be proved. - -#### Libraries - -_Library crates_ don't have a `main` function and they don't compile down to ACIR. Instead they define functionality intended to be shared with multiple projects, and eventually included in a binary crate. - -#### Contracts - -Contract crates are similar to binary crates in that they compile to ACIR which you can create proofs against. They are different in that they do not have a single `main` function, but are a collection of functions to be deployed to the [Aztec network](https://aztec.network). You can learn more about the technical details of Aztec in the [monorepo](https://github.com/AztecProtocol/aztec-packages) or contract [examples](https://github.com/AztecProtocol/aztec-packages/tree/master/noir-projects/noir-contracts/contracts). - -### Crate Root - -Every crate has a root, which is the source file that the compiler starts, this is also known as the root module. The Noir compiler does not enforce any conditions on the name of the file which is the crate root, however if you are compiling via Nargo the crate root must be called `lib.nr` or `main.nr` for library or binary crates respectively. - -## Packages - -A Nargo _package_ is a collection of one of more crates that provides a set of functionality. A package must include a Nargo.toml file. - -A package _must_ contain either a library or a binary crate, but not both. - -### Differences from Cargo Packages - -One notable difference between Rust's Cargo and Noir's Nargo is that while Cargo allows a package to contain an unlimited number of binary crates and a single library crate, Nargo currently only allows a package to contain a single crate. - -In future this restriction may be lifted to allow a Nargo package to contain both a binary and library crate or multiple binary crates. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/dependencies.md deleted file mode 100644 index 2c028d85853..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/dependencies.md +++ /dev/null @@ -1,124 +0,0 @@ ---- -title: Dependencies -description: - Learn how to specify and manage dependencies in Nargo, allowing you to upload packages to GitHub - and use them easily in your project. -keywords: [Nargo, dependencies, GitHub, package management, versioning] -sidebar_position: 1 ---- - -Nargo allows you to upload packages to GitHub and use them as dependencies. - -## Specifying a dependency - -Specifying a dependency requires a tag to a specific commit and the git url to the url containing -the package. - -Currently, there are no requirements on the tag contents. If requirements are added, it would follow -semver 2.0 guidelines. - -> Note: Without a `tag` , there would be no versioning and dependencies would change each time you -> compile your project. - -For example, to add the [ecrecover-noir library](https://github.com/colinnielsen/ecrecover-noir) to your project, add it to `Nargo.toml`: - -```toml -# Nargo.toml - -[dependencies] -ecrecover = {tag = "v0.8.0", git = "https://github.com/colinnielsen/ecrecover-noir"} -``` - -If the module is in a subdirectory, you can define a subdirectory in your git repository, for example: - -```toml -# Nargo.toml - -[dependencies] -easy_private_token_contract = {tag ="v0.1.0-alpha62", git = "https://github.com/AztecProtocol/aztec-packages", directory = "noir-contracts/contracts/easy_private_token_contract"} -``` - -## Specifying a local dependency - -You can also specify dependencies that are local to your machine. - -For example, this file structure has a library and binary crate - -```tree -├── binary_crate -│   ├── Nargo.toml -│   └── src -│   └── main.nr -└── lib_a - ├── Nargo.toml - └── src - └── lib.nr -``` - -Inside of the binary crate, you can specify: - -```toml -# Nargo.toml - -[dependencies] -lib_a = { path = "../lib_a" } -``` - -## Importing dependencies - -You can import a dependency to a Noir file using the following syntax. For example, to import the -ecrecover-noir library and local lib_a referenced above: - -```rust -use dep::ecrecover; -use dep::lib_a; -``` - -You can also import only the specific parts of dependency that you want to use, like so: - -```rust -use dep::std::hash::sha256; -use dep::std::scalar_mul::fixed_base_embedded_curve; -``` - -Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you -can import multiple items in the same line by enclosing them in curly braces: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; -``` - -We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. - -Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. - -## Dependencies of Dependencies - -Note that when you import a dependency, you also get access to all of the dependencies of that package. - -For example, the [phy_vector](https://github.com/resurgencelabs/phy_vector) library imports an [fraction](https://github.com/resurgencelabs/fraction) library. If you're importing the phy_vector library, then you can access the functions in fractions library like so: - -```rust -use dep::phy_vector; - -fn main(x : Field, y : pub Field) { - //... - let f = phy_vector::fraction::toFraction(true, 2, 1); - //... -} -``` - -## Available Libraries - -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). - -Some libraries that are available today include: - -- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library -- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) -- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers -- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address -- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees -- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir -- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/modules.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/modules.md deleted file mode 100644 index ae822a1cff4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/modules.md +++ /dev/null @@ -1,105 +0,0 @@ ---- -title: Modules -description: - Learn how to organize your files using modules in Noir, following the same convention as Rust's - module system. Examples included. -keywords: [Noir, Rust, modules, organizing files, sub-modules] -sidebar_position: 2 ---- - -Noir's module system follows the same convention as the _newer_ version of Rust's module system. - -## Purpose of Modules - -Modules are used to organize files. Without modules all of your code would need to live in a single -file. In Noir, the compiler does not automatically scan all of your files to detect modules. This -must be done explicitly by the developer. - -## Examples - -### Importing a module in the crate root - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::hello_world(); -} -``` - -Filename : `src/foo.nr` - -```rust -fn from_foo() {} -``` - -In the above snippet, the crate root is the `src/main.nr` file. The compiler sees the module -declaration `mod foo` which prompts it to look for a foo.nr file. - -Visually this module hierarchy looks like the following : - -``` -crate - ├── main - │ - └── foo - └── from_foo - -``` - -### Importing a module throughout the tree - -All modules are accessible from the `crate::` namespace. - -``` -crate - ├── bar - ├── foo - └── main - -``` - -In the above snippet, if `bar` would like to use functions in `foo`, it can do so by `use crate::foo::function_name`. - -### Sub-modules - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::from_foo(); -} -``` - -Filename : `src/foo.nr` - -```rust -mod bar; -fn from_foo() {} -``` - -Filename : `src/foo/bar.nr` - -```rust -fn from_bar() {} -``` - -In the above snippet, we have added an extra module to the module tree; `bar`. `bar` is a submodule -of `foo` hence we declare bar in `foo.nr` with `mod bar`. Since `foo` is not the crate root, the -compiler looks for the file associated with the `bar` module in `src/foo/bar.nr` - -Visually the module hierarchy looks as follows: - -``` -crate - ├── main - │ - └── foo - ├── from_foo - └── bar - └── from_bar -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/workspaces.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/workspaces.md deleted file mode 100644 index 513497f12bf..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/workspaces.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Workspaces -sidebar_position: 3 ---- - -Workspaces are a feature of nargo that allow you to manage multiple related Noir packages in a single repository. A workspace is essentially a group of related projects that share common build output directories and configurations. - -Each Noir project (with it's own Nargo.toml file) can be thought of as a package. Each package is expected to contain exactly one "named circuit", being the "name" defined in Nargo.toml with the program logic defined in `./src/main.nr`. - -For a project with the following structure: - -```tree -├── crates -│ ├── a -│ │ ├── Nargo.toml -│ │ └── Prover.toml -│ │ └── src -│ │ └── main.nr -│ └── b -│ ├── Nargo.toml -│ └── Prover.toml -│ └── src -│ └── main.nr -│ -└── Nargo.toml -``` - -You can define a workspace in Nargo.toml like so: - -```toml -[workspace] -members = ["crates/a", "crates/b"] -default-member = "crates/a" -``` - -`members` indicates which packages are included in the workspace. As such, all member packages of a workspace will be processed when the `--workspace` flag is used with various commands or if a `default-member` is not specified. - -`default-member` indicates which package various commands process by default. - -Libraries can be defined in a workspace. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. - -Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/_category_.json deleted file mode 100644 index af04c0933fd..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Standard Library", - "position": 1, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/bigint.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/bigint.md deleted file mode 100644 index 2bfdeec6631..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/bigint.md +++ /dev/null @@ -1,122 +0,0 @@ ---- -title: Big Integers -description: How to use big integers from Noir standard library -keywords: - [ - Big Integer, - Noir programming language, - Noir libraries, - ] ---- - -The BigInt module in the standard library exposes some class of integers which do not fit (well) into a Noir native field. It implements modulo arithmetic, modulo a 'big' prime number. - -:::note - -The module can currently be considered as `Field`s with fixed modulo sizes used by a set of elliptic curves, in addition to just the native curve. [More work](https://github.com/noir-lang/noir/issues/510) is needed to achieve arbitrarily sized big integers. - -::: - -Currently 6 classes of integers (i.e 'big' prime numbers) are available in the module, namely: - -- BN254 Fq: Bn254Fq -- BN254 Fr: Bn254Fr -- Secp256k1 Fq: Secpk1Fq -- Secp256k1 Fr: Secpk1Fr -- Secp256r1 Fr: Secpr1Fr -- Secp256r1 Fq: Secpr1Fq - -Where XXX Fq and XXX Fr denote respectively the order of the base and scalar field of the (usual) elliptic curve XXX. -For instance the big integer 'Secpk1Fq' in the standard library refers to integers modulo $2^{256}-2^{32}-977$. - -Feel free to explore the source code for the other primes: - -```rust title="big_int_definition" showLineNumbers -struct BigInt { - pointer: u32, - modulus: u32, -} -``` -> Source code: noir_stdlib/src/bigint.nr#L14-L19 - - -## Example usage - -A common use-case is when constructing a big integer from its bytes representation, and performing arithmetic operations on it: - -```rust title="big_int_example" showLineNumbers -fn big_int_example(x: u8, y: u8) { - let a = Secpk1Fq::from_le_bytes(&[x, y, 0, 45, 2]); - let b = Secpk1Fq::from_le_bytes(&[y, x, 9]); - let c = (a + b) * b / a; - let d = c.to_le_bytes(); - println(d[0]); -} -``` -> Source code: test_programs/execution_success/bigint/src/main.nr#L70-L78 - - -## Methods - -The available operations for each big integer are: - -### from_le_bytes - -Construct a big integer from its little-endian bytes representation. Example: - -```rust - // Construct a big integer from a slice of bytes - let a = Secpk1Fq::from_le_bytes(&[x, y, 0, 45, 2]); - // Construct a big integer from an array of 32 bytes - let a = Secpk1Fq::from_le_bytes_32([1;32]); - ``` - -Sure, here's the formatted version of the remaining methods: - -### to_le_bytes - -Return the little-endian bytes representation of a big integer. Example: - -```rust -let bytes = a.to_le_bytes(); -``` - -### add - -Add two big integers. Example: - -```rust -let sum = a + b; -``` - -### sub - -Subtract two big integers. Example: - -```rust -let difference = a - b; -``` - -### mul - -Multiply two big integers. Example: - -```rust -let product = a * b; -``` - -### div - -Divide two big integers. Note that division is field division and not euclidean division. Example: - -```rust -let quotient = a / b; -``` - -### eq - -Compare two big integers. Example: - -```rust -let are_equal = a == b; -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/black_box_fns.md deleted file mode 100644 index e8b62f21d4e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/black_box_fns.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Black Box Functions -description: Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. -keywords: [noir, black box functions] ---- - -Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. This makes certain zk-snark unfriendly computations cheaper than if they were implemented in Noir. - -The ACVM spec defines a set of blackbox functions which backends will be expected to implement. This allows backends to use optimized implementations of these constraints if they have them, however they may also fallback to less efficient naive implementations if not. - -## Function list - -Here is a list of the current black box functions: - -- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) -- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) -- [Blake3](./cryptographic_primitives/hashes.mdx#blake3) -- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash) -- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx) -- AND -- XOR -- RANGE -- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion.md) - -Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. - -You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/noir/blob/master/acvm-repo/acir/src/circuit/black_box_functions.rs). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/bn254.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/bn254.md deleted file mode 100644 index 3294f005dbb..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/bn254.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: Bn254 Field Library ---- - -Noir provides a module in standard library with some optimized functions for bn254 Fr in `std::field::bn254`. - -## decompose - -```rust -fn decompose(x: Field) -> (Field, Field) {} -``` - -Decomposes a single field into two fields, low and high. The low field contains the lower 16 bytes of the input field and the high field contains the upper 16 bytes of the input field. Both field results are range checked to 128 bits. - - -## assert_gt - -```rust -fn assert_gt(a: Field, b: Field) {} -``` - -Asserts that a > b. This will generate less constraints than using `assert(gt(a, b))`. - -## assert_lt - -```rust -fn assert_lt(a: Field, b: Field) {} -``` - -Asserts that a < b. This will generate less constraints than using `assert(lt(a, b))`. - -## gt - -```rust -fn gt(a: Field, b: Field) -> bool {} -``` - -Returns true if a > b. - -## lt - -```rust -fn lt(a: Field, b: Field) -> bool {} -``` - -Returns true if a < b. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/containers/boundedvec.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/containers/boundedvec.md deleted file mode 100644 index ce4529f6e57..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/containers/boundedvec.md +++ /dev/null @@ -1,326 +0,0 @@ ---- -title: Bounded Vectors -keywords: [noir, vector, bounded vector, slice] -sidebar_position: 1 ---- - -A `BoundedVec` is a growable storage similar to a `Vec` except that it -is bounded with a maximum possible length. Unlike `Vec`, `BoundedVec` is not implemented -via slices and thus is not subject to the same restrictions slices are (notably, nested -slices - and thus nested vectors as well - are disallowed). - -Since a BoundedVec is backed by a normal array under the hood, growing the BoundedVec by -pushing an additional element is also more efficient - the length only needs to be increased -by one. - -For these reasons `BoundedVec` should generally be preferred over `Vec` when there -is a reasonable maximum bound that can be placed on the vector. - -Example: - -```rust -let mut vector: BoundedVec = BoundedVec::new(); -for i in 0..5 { - vector.push(i); -} -assert(vector.len() == 5); -assert(vector.max_len() == 10); -``` - -## Methods - -### new - -```rust -pub fn new() -> Self -``` - -Creates a new, empty vector of length zero. - -Since this container is backed by an array internally, it still needs an initial value -to give each element. To resolve this, each element is zeroed internally. This value -is guaranteed to be inaccessible unless `get_unchecked` is used. - -Example: - -```rust -let empty_vector: BoundedVec = BoundedVec::new(); -assert(empty_vector.len() == 0); -``` - -Note that whenever calling `new` the maximum length of the vector should always be specified -via a type signature: - -```rust title="new_example" showLineNumbers -fn foo() -> BoundedVec { - // Ok! MaxLen is specified with a type annotation - let v1: BoundedVec = BoundedVec::new(); - let v2 = BoundedVec::new(); - - // Ok! MaxLen is known from the type of foo's return value - v2 -} - -fn bad() { - let mut v3 = BoundedVec::new(); - - // Not Ok! We don't know if v3's MaxLen is at least 1, and the compiler often infers 0 by default. - v3.push(5); -} -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L11-L27 - - -This defaulting of `MaxLen` (and numeric generics in general) to zero may change in future noir versions -but for now make sure to use type annotations when using bounded vectors. Otherwise, you will receive a constraint failure at runtime when the vec is pushed to. - -### get - -```rust -pub fn get(mut self: Self, index: u64) -> T { -``` - -Retrieves an element from the vector at the given index, starting from zero. - -If the given index is equal to or greater than the length of the vector, this -will issue a constraint failure. - -Example: - -```rust -fn foo(v: BoundedVec) { - let first = v.get(0); - let last = v.get(v.len() - 1); - assert(first != last); -} -``` - -### get_unchecked - -```rust -pub fn get_unchecked(mut self: Self, index: u64) -> T { -``` - -Retrieves an element from the vector at the given index, starting from zero, without -performing a bounds check. - -Since this function does not perform a bounds check on length before accessing the element, -it is unsafe! Use at your own risk! - -Example: - -```rust title="get_unchecked_example" showLineNumbers -fn sum_of_first_three(v: BoundedVec) -> u32 { - // Always ensure the length is larger than the largest - // index passed to get_unchecked - assert(v.len() > 2); - let first = v.get_unchecked(0); - let second = v.get_unchecked(1); - let third = v.get_unchecked(2); - first + second + third -} -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L54-L64 - - - -### push - -```rust -pub fn push(&mut self, elem: T) { -``` - -Pushes an element to the end of the vector. This increases the length -of the vector by one. - -Panics if the new length of the vector will be greater than the max length. - -Example: - -```rust title="bounded-vec-push-example" showLineNumbers -let mut v: BoundedVec = BoundedVec::new(); - - v.push(1); - v.push(2); - - // Panics with failed assertion "push out of bounds" - v.push(3); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L68-L76 - - -### pop - -```rust -pub fn pop(&mut self) -> T -``` - -Pops the element at the end of the vector. This will decrease the length -of the vector by one. - -Panics if the vector is empty. - -Example: - -```rust title="bounded-vec-pop-example" showLineNumbers -let mut v: BoundedVec = BoundedVec::new(); - v.push(1); - v.push(2); - - let two = v.pop(); - let one = v.pop(); - - assert(two == 2); - assert(one == 1); - // error: cannot pop from an empty vector - // let _ = v.pop(); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L81-L93 - - -### len - -```rust -pub fn len(self) -> u64 { -``` - -Returns the current length of this vector - -Example: - -```rust title="bounded-vec-len-example" showLineNumbers -let mut v: BoundedVec = BoundedVec::new(); - assert(v.len() == 0); - - v.push(100); - assert(v.len() == 1); - - v.push(200); - v.push(300); - v.push(400); - assert(v.len() == 4); - - let _ = v.pop(); - let _ = v.pop(); - assert(v.len() == 2); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L98-L113 - - -### max_len - -```rust -pub fn max_len(_self: BoundedVec) -> u64 { -``` - -Returns the maximum length of this vector. This is always -equal to the `MaxLen` parameter this vector was initialized with. - -Example: - -```rust title="bounded-vec-max-len-example" showLineNumbers -let mut v: BoundedVec = BoundedVec::new(); - - assert(v.max_len() == 5); - v.push(10); - assert(v.max_len() == 5); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L118-L124 - - -### storage - -```rust -pub fn storage(self) -> [T; MaxLen] { -``` - -Returns the internal array within this vector. -Since arrays in Noir are immutable, mutating the returned storage array will not mutate -the storage held internally by this vector. - -Note that uninitialized elements may be zeroed out! - -Example: - -```rust title="bounded-vec-storage-example" showLineNumbers -let mut v: BoundedVec = BoundedVec::new(); - - assert(v.storage() == [0, 0, 0, 0, 0]); - - v.push(57); - assert(v.storage() == [57, 0, 0, 0, 0]); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L129-L136 - - -### extend_from_array - -```rust -pub fn extend_from_array(&mut self, array: [T; Len]) -``` - -Pushes each element from the given array to this vector. - -Panics if pushing each element would cause the length of this vector -to exceed the maximum length. - -Example: - -```rust title="bounded-vec-extend-from-array-example" showLineNumbers -let mut vec: BoundedVec = BoundedVec::new(); - vec.extend_from_array([2, 4]); - - assert(vec.len == 2); - assert(vec.get(0) == 2); - assert(vec.get(1) == 4); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L141-L148 - - -### extend_from_bounded_vec - -```rust -pub fn extend_from_bounded_vec(&mut self, vec: BoundedVec) -``` - -Pushes each element from the other vector to this vector. The length of -the other vector is left unchanged. - -Panics if pushing each element would cause the length of this vector -to exceed the maximum length. - -Example: - -```rust title="bounded-vec-extend-from-bounded-vec-example" showLineNumbers -let mut v1: BoundedVec = BoundedVec::new(); - let mut v2: BoundedVec = BoundedVec::new(); - - v2.extend_from_array([1, 2, 3]); - v1.extend_from_bounded_vec(v2); - - assert(v1.storage() == [1, 2, 3, 0, 0]); - assert(v2.storage() == [1, 2, 3, 0, 0, 0, 0]); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L153-L162 - - -### any - -```rust -pub fn any(self, predicate: fn[Env](T) -> bool) -> bool -``` - -Returns true if the given predicate returns true for any element -in this vector. - -Example: - -```rust title="bounded-vec-any-example" showLineNumbers -let mut v: BoundedVec = BoundedVec::new(); - v.extend_from_array([2, 4, 6]); - - let all_even = !v.any(|elem: u32| elem % 2 != 0); - assert(all_even); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L229-L235 - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/containers/hashmap.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/containers/hashmap.md deleted file mode 100644 index 47faa99aba6..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/containers/hashmap.md +++ /dev/null @@ -1,570 +0,0 @@ ---- -title: HashMap -keywords: [noir, map, hash, hashmap] -sidebar_position: 1 ---- - -`HashMap` is used to efficiently store and look up key-value pairs. - -`HashMap` is a bounded type which can store anywhere from zero to `MaxLen` total elements. -Note that due to hash collisions, the actual maximum number of elements stored by any particular -hashmap is likely lower than `MaxLen`. This is true even with cryptographic hash functions since -every hash value will be performed modulo `MaxLen`. - -When creating `HashMap`s, the `MaxLen` generic should always be specified if it is not already -known. Otherwise, the compiler may infer a different value for `MaxLen` (such as zero), which -will likely change the result of the program. This behavior is set to become an error in future -versions instead. - -Example: - -```rust -// Create a mapping from Fields to u32s with a maximum length of 12 -// using a poseidon2 hasher -use dep::std::hash::poseidon2::Poseidon2Hasher; -let mut map: HashMap> = HashMap::default(); - -map.insert(1, 2); -map.insert(3, 4); - -let two = map.get(1).unwrap(); -``` - -## Methods - -### default - -```rust title="default" showLineNumbers -impl Default for HashMap -where - B: BuildHasher + Default, - H: Hasher + Default -{ - fn default() -> Self { -``` -> Source code: noir_stdlib/src/collections/map.nr#L462-L469 - - -Creates a fresh, empty HashMap. - -When using this function, always make sure to specify the maximum size of the hash map. - -This is the same `default` from the `Default` implementation given further below. It is -repeated here for convenience since it is the recommended way to create a hashmap. - -Example: - -```rust title="default_example" showLineNumbers -let hashmap: HashMap> = HashMap::default(); - assert(hashmap.is_empty()); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L202-L205 - - -Because `HashMap` has so many generic arguments that are likely to be the same throughout -your program, it may be helpful to create a type alias: - -```rust title="type_alias" showLineNumbers -type MyMap = HashMap>; -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L196-L198 - - -### with_hasher - -```rust title="with_hasher" showLineNumbers -pub fn with_hasher(_build_hasher: B) -> Self - where - B: BuildHasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L82-L86 - - -Creates a hashmap with an existing `BuildHasher`. This can be used to ensure multiple -hashmaps are created with the same hasher instance. - -Example: - -```rust title="with_hasher_example" showLineNumbers -let my_hasher: BuildHasherDefault = Default::default(); - let hashmap: HashMap> = HashMap::with_hasher(my_hasher); - assert(hashmap.is_empty()); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L207-L211 - - -### get - -```rust title="get" showLineNumbers -pub fn get( - self, - key: K - ) -> Option - where - K: Eq + Hash, - B: BuildHasher, - H: Hasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L278-L287 - - -Retrieves a value from the hashmap, returning `Option::none()` if it was not found. - -Example: - -```rust title="get_example" showLineNumbers -fn get_example(map: HashMap>) { - let x = map.get(12); - - if x.is_some() { - assert(x.unwrap() == 42); - } -} -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L299-L307 - - -### insert - -```rust title="insert" showLineNumbers -pub fn insert( - &mut self, - key: K, - value: V - ) - where - K: Eq + Hash, - B: BuildHasher, - H: Hasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L313-L323 - - -Inserts a new key-value pair into the map. If the key was already in the map, its -previous value will be overridden with the newly provided one. - -Example: - -```rust title="insert_example" showLineNumbers -let mut map: HashMap> = HashMap::default(); - map.insert(12, 42); - assert(map.len() == 1); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L213-L217 - - -### remove - -```rust title="remove" showLineNumbers -pub fn remove( - &mut self, - key: K - ) - where - K: Eq + Hash, - B: BuildHasher, - H: Hasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L356-L365 - - -Removes the given key-value pair from the map. If the key was not already present -in the map, this does nothing. - -Example: - -```rust title="remove_example" showLineNumbers -map.remove(12); - assert(map.is_empty()); - - // If a key was not present in the map, remove does nothing - map.remove(12); - assert(map.is_empty()); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L221-L228 - - -### is_empty - -```rust title="is_empty" showLineNumbers -pub fn is_empty(self) -> bool { -``` -> Source code: noir_stdlib/src/collections/map.nr#L115-L117 - - -True if the length of the hash map is empty. - -Example: - -```rust title="is_empty_example" showLineNumbers -assert(map.is_empty()); - - map.insert(1, 2); - assert(!map.is_empty()); - - map.remove(1); - assert(map.is_empty()); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L230-L238 - - -### len - -```rust title="len" showLineNumbers -pub fn len(self) -> u64 { -``` -> Source code: noir_stdlib/src/collections/map.nr#L264-L266 - - -Returns the current length of this hash map. - -Example: - -```rust title="len_example" showLineNumbers -// This is equivalent to checking map.is_empty() - assert(map.len() == 0); - - map.insert(1, 2); - map.insert(3, 4); - map.insert(5, 6); - assert(map.len() == 3); - - // 3 was already present as a key in the hash map, so the length is unchanged - map.insert(3, 7); - assert(map.len() == 3); - - map.remove(1); - assert(map.len() == 2); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L240-L255 - - -### capacity - -```rust title="capacity" showLineNumbers -pub fn capacity(_self: Self) -> u64 { -``` -> Source code: noir_stdlib/src/collections/map.nr#L271-L273 - - -Returns the maximum capacity of this hashmap. This is always equal to the capacity -specified in the hashmap's type. - -Unlike hashmaps in general purpose programming languages, hashmaps in Noir have a -static capacity that does not increase as the map grows larger. Thus, this capacity -is also the maximum possible element count that can be inserted into the hashmap. -Due to hash collisions (modulo the hashmap length), it is likely the actual maximum -element count will be lower than the full capacity. - -Example: - -```rust title="capacity_example" showLineNumbers -let empty_map: HashMap> = HashMap::default(); - assert(empty_map.len() == 0); - assert(empty_map.capacity() == 42); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L257-L261 - - -### clear - -```rust title="clear" showLineNumbers -pub fn clear(&mut self) { -``` -> Source code: noir_stdlib/src/collections/map.nr#L93-L95 - - -Clears the hashmap, removing all key-value pairs from it. - -Example: - -```rust title="clear_example" showLineNumbers -assert(!map.is_empty()); - map.clear(); - assert(map.is_empty()); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L263-L267 - - -### contains_key - -```rust title="contains_key" showLineNumbers -pub fn contains_key( - self, - key: K - ) -> bool - where - K: Hash + Eq, - B: BuildHasher, - H: Hasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L101-L110 - - -True if the hashmap contains the given key. Unlike `get`, this will not also return -the value associated with the key. - -Example: - -```rust title="contains_key_example" showLineNumbers -if map.contains_key(7) { - let value = map.get(7); - assert(value.is_some()); - } else { - println("No value for key 7!"); - } -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L269-L276 - - -### entries - -```rust title="entries" showLineNumbers -pub fn entries(self) -> BoundedVec<(K, V), N> { -``` -> Source code: noir_stdlib/src/collections/map.nr#L123-L125 - - -Returns a vector of each key-value pair present in the hashmap. - -The length of the returned vector is always equal to the length of the hashmap. - -Example: - -```rust title="entries_example" showLineNumbers -let entries = map.entries(); - - // The length of a hashmap may not be compile-time known, so we - // need to loop over its capacity instead - for i in 0..map.capacity() { - if i < entries.len() { - let (key, value) = entries.get(i); - println(f"{key} -> {value}"); - } - } -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L310-L321 - - -### keys - -```rust title="keys" showLineNumbers -pub fn keys(self) -> BoundedVec { -``` -> Source code: noir_stdlib/src/collections/map.nr#L144-L146 - - -Returns a vector of each key present in the hashmap. - -The length of the returned vector is always equal to the length of the hashmap. - -Example: - -```rust title="keys_example" showLineNumbers -let keys = map.keys(); - - for i in 0..keys.max_len() { - if i < keys.len() { - let key = keys.get_unchecked(i); - let value = map.get(key).unwrap_unchecked(); - println(f"{key} -> {value}"); - } - } -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L323-L333 - - -### values - -```rust title="values" showLineNumbers -pub fn values(self) -> BoundedVec { -``` -> Source code: noir_stdlib/src/collections/map.nr#L164-L166 - - -Returns a vector of each value present in the hashmap. - -The length of the returned vector is always equal to the length of the hashmap. - -Example: - -```rust title="values_example" showLineNumbers -let values = map.values(); - - for i in 0..values.max_len() { - if i < values.len() { - let value = values.get_unchecked(i); - println(f"Found value {value}"); - } - } -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L335-L344 - - -### iter_mut - -```rust title="iter_mut" showLineNumbers -pub fn iter_mut( - &mut self, - f: fn(K, V) -> (K, V) - ) - where - K: Eq + Hash, - B: BuildHasher, - H: Hasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L183-L192 - - -Iterates through each key-value pair of the HashMap, setting each key-value pair to the -result returned from the given function. - -Note that since keys can be mutated, the HashMap needs to be rebuilt as it is iterated -through. If this is not desired, use `iter_values_mut` if only values need to be mutated, -or `entries` if neither keys nor values need to be mutated. - -The iteration order is left unspecified. As a result, if two keys are mutated to become -equal, which of the two values that will be present for the key in the resulting map is also unspecified. - -Example: - -```rust title="iter_mut_example" showLineNumbers -// Add 1 to each key in the map, and double the value associated with that key. - map.iter_mut(|k, v| (k + 1, v * 2)); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L348-L351 - - -### iter_keys_mut - -```rust title="iter_keys_mut" showLineNumbers -pub fn iter_keys_mut( - &mut self, - f: fn(K) -> K - ) - where - K: Eq + Hash, - B: BuildHasher, - H: Hasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L208-L217 - - -Iterates through the HashMap, mutating each key to the result returned from -the given function. - -Note that since keys can be mutated, the HashMap needs to be rebuilt as it is iterated -through. If only iteration is desired and the keys are not intended to be mutated, -prefer using `entries` instead. - -The iteration order is left unspecified. As a result, if two keys are mutated to become -equal, which of the two values that will be present for the key in the resulting map is also unspecified. - -Example: - -```rust title="iter_keys_mut_example" showLineNumbers -// Double each key, leaving the value associated with that key untouched - map.iter_keys_mut(|k| k * 2); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L353-L356 - - -### iter_values_mut - -```rust title="iter_values_mut" showLineNumbers -pub fn iter_values_mut(&mut self, f: fn(V) -> V) { -``` -> Source code: noir_stdlib/src/collections/map.nr#L233-L235 - - -Iterates through the HashMap, applying the given function to each value and mutating the -value to equal the result. This function is more efficient than `iter_mut` and `iter_keys_mut` -because the keys are untouched and the underlying hashmap thus does not need to be reordered. - -Example: - -```rust title="iter_values_mut_example" showLineNumbers -// Halve each value - map.iter_values_mut(|v| v / 2); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L358-L361 - - -### retain - -```rust title="retain" showLineNumbers -pub fn retain(&mut self, f: fn(K, V) -> bool) { -``` -> Source code: noir_stdlib/src/collections/map.nr#L247-L249 - - -Retains only the key-value pairs for which the given function returns true. -Any key-value pairs for which the function returns false will be removed from the map. - -Example: - -```rust title="retain_example" showLineNumbers -map.retain(|k, v| (k != 0) & (v != 0)); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L281-L283 - - -## Trait Implementations - -### default - -```rust title="default" showLineNumbers -impl Default for HashMap -where - B: BuildHasher + Default, - H: Hasher + Default -{ - fn default() -> Self { -``` -> Source code: noir_stdlib/src/collections/map.nr#L462-L469 - - -Constructs an empty HashMap. - -Example: - -```rust title="default_example" showLineNumbers -let hashmap: HashMap> = HashMap::default(); - assert(hashmap.is_empty()); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L202-L205 - - -### eq - -```rust title="eq" showLineNumbers -impl Eq for HashMap -where - K: Eq + Hash, - V: Eq, - B: BuildHasher, - H: Hasher -{ - fn eq(self, other: HashMap) -> bool { -``` -> Source code: noir_stdlib/src/collections/map.nr#L426-L435 - - -Checks if two HashMaps are equal. - -Example: - -```rust title="eq_example" showLineNumbers -let mut map1: HashMap> = HashMap::default(); - let mut map2: HashMap> = HashMap::default(); - - map1.insert(1, 2); - map1.insert(3, 4); - - map2.insert(3, 4); - map2.insert(1, 2); - - assert(map1 == map2); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L285-L296 - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/containers/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/containers/index.md deleted file mode 100644 index ea84c6d5c21..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/containers/index.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Containers -description: Container types provided by Noir's standard library for storing and retrieving data -keywords: [containers, data types, vec, hashmap] ---- diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/containers/vec.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/containers/vec.mdx deleted file mode 100644 index fcfd7e07aa0..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/containers/vec.mdx +++ /dev/null @@ -1,151 +0,0 @@ ---- -title: Vectors -description: Delve into the Vec data type in Noir. Learn about its methods, practical examples, and best practices for using Vectors in your Noir code. -keywords: [noir, vector type, methods, examples, dynamic arrays] -sidebar_position: 6 ---- - -import Experimental from '@site/src/components/Notes/_experimental.mdx'; - - - -A vector is a collection type similar to Rust's `Vec` type. In Noir, it is a convenient way to use slices as mutable arrays. - -Example: - -```rust -let mut vector: Vec = Vec::new(); -for i in 0..5 { - vector.push(i); -} -assert(vector.len() == 5); -``` - -## Methods - -### new - -Creates a new, empty vector. - -```rust -pub fn new() -> Self -``` - -Example: - -```rust -let empty_vector: Vec = Vec::new(); -assert(empty_vector.len() == 0); -``` - -### from_slice - -Creates a vector containing each element from a given slice. Mutations to the resulting vector will not affect the original slice. - -```rust -pub fn from_slice(slice: [T]) -> Self -``` - -Example: - -```rust -let slice: [Field] = &[1, 2, 3]; -let vector_from_slice = Vec::from_slice(slice); -assert(vector_from_slice.len() == 3); -``` - -### len - -Returns the number of elements in the vector. - -```rust -pub fn len(self) -> Field -``` - -Example: - -```rust -let empty_vector: Vec = Vec::new(); -assert(empty_vector.len() == 0); -``` - -### get - -Retrieves an element from the vector at a given index. Panics if the index points beyond the vector's end. - -```rust -pub fn get(self, index: Field) -> T -``` - -Example: - -```rust -let vector: Vec = Vec::from_slice(&[10, 20, 30]); -assert(vector.get(1) == 20); -``` - -### push - -Adds a new element to the vector's end, returning a new vector with a length one greater than the original unmodified vector. - -```rust -pub fn push(&mut self, elem: T) -``` - -Example: - -```rust -let mut vector: Vec = Vec::new(); -vector.push(10); -assert(vector.len() == 1); -``` - -### pop - -Removes an element from the vector's end, returning a new vector with a length one less than the original vector, along with the removed element. Panics if the vector's length is zero. - -```rust -pub fn pop(&mut self) -> T -``` - -Example: - -```rust -let mut vector = Vec::from_slice(&[10, 20]); -let popped_elem = vector.pop(); -assert(popped_elem == 20); -assert(vector.len() == 1); -``` - -### insert - -Inserts an element at a specified index, shifting subsequent elements to the right. - -```rust -pub fn insert(&mut self, index: Field, elem: T) -``` - -Example: - -```rust -let mut vector = Vec::from_slice(&[10, 30]); -vector.insert(1, 20); -assert(vector.get(1) == 20); -``` - -### remove - -Removes an element at a specified index, shifting subsequent elements to the left, and returns the removed element. - -```rust -pub fn remove(&mut self, index: Field) -> T -``` - -Example: - -```rust -let mut vector = Vec::from_slice(&[10, 20, 30]); -let removed_elem = vector.remove(1); -assert(removed_elem == 20); -assert(vector.len() == 2); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/_category_.json deleted file mode 100644 index 5d694210bbf..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 0, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/ec_primitives.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/ec_primitives.md deleted file mode 100644 index 9c6987b693e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/ec_primitives.md +++ /dev/null @@ -1,102 +0,0 @@ ---- -title: Elliptic Curve Primitives -keywords: [cryptographic primitives, Noir project] -sidebar_position: 4 ---- - -Data structures and methods on them that allow you to carry out computations involving elliptic -curves over the (mathematical) field corresponding to `Field`. For the field currently at our -disposal, applications would involve a curve embedded in BN254, e.g. the -[Baby Jubjub curve](https://eips.ethereum.org/EIPS/eip-2494). - -## Data structures - -### Elliptic curve configurations - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Curve`), i.e. the specific elliptic -curve you want to use, which would be specified using any one of the methods -`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::new` which take the coefficients in the -defining equation together with a generator point as parameters. You can find more detail in the -comments in -[`noir_stdlib/src/ec.nr`](https://github.com/noir-lang/noir/blob/v0.28.0/noir_stdlib/src/ec.nr), but -the gist of it is that the elliptic curves of interest are usually expressed in one of the standard -forms implemented here (Twisted Edwards, Montgomery and Short Weierstraß), and in addition to that, -you could choose to use `affine` coordinates (Cartesian coordinates - the usual (x,y) - possibly -together with a point at infinity) or `curvegroup` coordinates (some form of projective coordinates -requiring more coordinates but allowing for more efficient implementations of elliptic curve -operations). Conversions between all of these forms are provided, and under the hood these -conversions are done whenever an operation is more efficient in a different representation (or a -mixed coordinate representation is employed). - -### Points - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Point`), i.e. points lying on the -elliptic curve. For a curve configuration `c` and a point `p`, it may be checked that `p` -does indeed lie on `c` by calling `c.contains(p1)`. - -## Methods - -(given a choice of curve representation, e.g. use `std::ec::tecurve::affine::Curve` and use -`std::ec::tecurve::affine::Point`) - -- The **zero element** is given by `Point::zero()`, and we can verify whether a point `p: Point` is - zero by calling `p.is_zero()`. -- **Equality**: Points `p1: Point` and `p2: Point` may be checked for equality by calling - `p1.eq(p2)`. -- **Addition**: For `c: Curve` and points `p1: Point` and `p2: Point` on the curve, adding these two - points is accomplished by calling `c.add(p1,p2)`. -- **Negation**: For a point `p: Point`, `p.negate()` is its negation. -- **Subtraction**: For `c` and `p1`, `p2` as above, subtracting `p2` from `p1` is accomplished by - calling `c.subtract(p1,p2)`. -- **Scalar multiplication**: For `c` as above, `p: Point` a point on the curve and `n: Field`, - scalar multiplication is given by `c.mul(n,p)`. If instead `n :: [u1; N]`, i.e. `n` is a bit - array, the `bit_mul` method may be used instead: `c.bit_mul(n,p)` -- **Multi-scalar multiplication**: For `c` as above and arrays `n: [Field; N]` and `p: [Point; N]`, - multi-scalar multiplication is given by `c.msm(n,p)`. -- **Coordinate representation conversions**: The `into_group` method converts a point or curve - configuration in the affine representation to one in the CurveGroup representation, and - `into_affine` goes in the other direction. -- **Curve representation conversions**: `tecurve` and `montcurve` curves and points are equivalent - and may be converted between one another by calling `into_montcurve` or `into_tecurve` on their - configurations or points. `swcurve` is more general and a curve c of one of the other two types - may be converted to this representation by calling `c.into_swcurve()`, whereas a point `p` lying - on the curve given by `c` may be mapped to its corresponding `swcurve` point by calling - `c.map_into_swcurve(p)`. -- **Map-to-curve methods**: The Elligator 2 method of mapping a field element `n: Field` into a - `tecurve` or `montcurve` with configuration `c` may be called as `c.elligator2_map(n)`. For all of - the curve configurations, the SWU map-to-curve method may be called as `c.swu_map(z,n)`, where - `z: Field` depends on `Field` and `c` and must be chosen by the user (the conditions it needs to - satisfy are specified in the comments - [here](https://github.com/noir-lang/noir/blob/v0.28.0/noir_stdlib/src/ec.nr). - -## Examples - -The -[ec_baby_jubjub test](https://github.com/noir-lang/noir/blob/master/test_programs/compile_success_empty/ec_baby_jubjub/src/main.nr) -illustrates all of the above primitives on various forms of the Baby Jubjub curve. A couple of more -interesting examples in Noir would be: - -Public-key cryptography: Given an elliptic curve and a 'base point' on it, determine the public key -from the private key. This is a matter of using scalar multiplication. In the case of Baby Jubjub, -for example, this code would do: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; - -fn bjj_pub_key(priv_key: Field) -> Point -{ - - let bjj = Curve::new(168700, 168696, G::new(995203441582195749578291179787384436505546430278305826713579947235728471134,5472060717959818805561601436314318772137091100104008585924551046643952123905)); - - let base_pt = Point::new(5299619240641551281634865583518297030282874472190772894086521144482721001553, 16950150798460657717958625567821834550301663161624707787222815936182638968203); - - bjj.mul(priv_key,base_pt) -} -``` - -This would come in handy in a Merkle proof. - -- EdDSA signature verification: This is a matter of combining these primitives with a suitable hash - function. See - [feat(stdlib): EdDSA sig verification noir#1136](https://github.com/noir-lang/noir/pull/1136) for - the case of Baby Jubjub and the Poseidon hash function. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx deleted file mode 100644 index 4394b48f907..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx +++ /dev/null @@ -1,98 +0,0 @@ ---- -title: ECDSA Signature Verification -description: Learn about the cryptographic primitives regarding ECDSA over the secp256k1 and secp256r1 curves -keywords: [cryptographic primitives, Noir project, ecdsa, secp256k1, secp256r1, signatures] -sidebar_position: 3 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -Noir supports ECDSA signatures verification over the secp256k1 and secp256r1 curves. - -## ecdsa_secp256k1::verify_signature - -Verifier for ECDSA Secp256k1 signatures. -See ecdsa_secp256k1::verify_signature_slice for a version that accepts slices directly. - -```rust title="ecdsa_secp256k1" showLineNumbers -pub fn verify_signature( - public_key_x: [u8; 32], - public_key_y: [u8; 32], - signature: [u8; 64], - message_hash: [u8; N] -) -> bool -``` -> Source code: noir_stdlib/src/ecdsa_secp256k1.nr#L2-L9 - - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - - - -## ecdsa_secp256k1::verify_signature_slice - -Verifier for ECDSA Secp256k1 signatures where the message is a slice. - -```rust title="ecdsa_secp256k1_slice" showLineNumbers -pub fn verify_signature_slice( - public_key_x: [u8; 32], - public_key_y: [u8; 32], - signature: [u8; 64], - message_hash: [u8] -) -> bool -``` -> Source code: noir_stdlib/src/ecdsa_secp256k1.nr#L13-L20 - - - - -## ecdsa_secp256r1::verify_signature - -Verifier for ECDSA Secp256r1 signatures. -See ecdsa_secp256r1::verify_signature_slice for a version that accepts slices directly. - -```rust title="ecdsa_secp256r1" showLineNumbers -pub fn verify_signature( - public_key_x: [u8; 32], - public_key_y: [u8; 32], - signature: [u8; 64], - message_hash: [u8; N] -) -> bool -``` -> Source code: noir_stdlib/src/ecdsa_secp256r1.nr#L2-L9 - - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - - - -## ecdsa_secp256r1::verify_signature - -Verifier for ECDSA Secp256r1 signatures where the message is a slice. - -```rust title="ecdsa_secp256r1_slice" showLineNumbers -pub fn verify_signature_slice( - public_key_x: [u8; 32], - public_key_y: [u8; 32], - signature: [u8; 64], - message_hash: [u8] -) -> bool -``` -> Source code: noir_stdlib/src/ecdsa_secp256r1.nr#L13-L20 - - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/eddsa.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/eddsa.mdx deleted file mode 100644 index c2c0624dfad..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/eddsa.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: EdDSA Verification -description: Learn about the cryptographic primitives regarding EdDSA -keywords: [cryptographic primitives, Noir project, eddsa, signatures] -sidebar_position: 5 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## eddsa::eddsa_poseidon_verify - -Verifier for EdDSA signatures - -```rust -fn eddsa_poseidon_verify(public_key_x : Field, public_key_y : Field, signature_s: Field, signature_r8_x: Field, signature_r8_y: Field, message: Field) -> bool -``` - -It is also possible to specify the hash algorithm used for the signature by using the `eddsa_verify_with_hasher` function with a parameter implementing the Hasher trait. For instance, if you want to use Poseidon2 instead, you can do the following: -```rust -use dep::std::hash::poseidon2::Poseidon2Hasher; - -let mut hasher = Poseidon2Hasher::default(); -eddsa_verify_with_hasher(pub_key_a.x, pub_key_a.y, s_a, r8_a.x, r8_a.y, msg, &mut hasher); -``` - - - -## eddsa::eddsa_to_pub - -Private to public key conversion. - -Returns `(pub_key_x, pub_key_y)` - -```rust -fn eddsa_to_pub(secret : Field) -> (Field, Field) -``` - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/hashes.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/hashes.mdx deleted file mode 100644 index 87e113b96cd..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/hashes.mdx +++ /dev/null @@ -1,250 +0,0 @@ ---- -title: Hash methods -description: - Learn about the cryptographic primitives ready to use for any Noir project, including sha256, - blake2s, pedersen, mimc_bn254 and mimc -keywords: - [cryptographic primitives, Noir project, sha256, blake2s, pedersen, mimc_bn254, mimc, hash] -sidebar_position: 0 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## sha256 - -Given an array of bytes, returns the resulting sha256 hash. - -```rust title="sha256" showLineNumbers -pub fn sha256(input: [u8; N]) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L9-L11 - - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::sha256(x); -} -``` - - - -## blake2s - -Given an array of bytes, returns an array with the Blake2 hash - -```rust title="blake2s" showLineNumbers -pub fn blake2s(input: [u8; N]) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L15-L17 - - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::blake2s(x); -} -``` - - - -## blake3 - -Given an array of bytes, returns an array with the Blake3 hash - -```rust title="blake3" showLineNumbers -pub fn blake3(input: [u8; N]) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L21-L23 - - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::blake3(x); -} -``` - - - -## pedersen_hash - -Given an array of Fields, returns the Pedersen hash. - -```rust title="pedersen_hash" showLineNumbers -pub fn pedersen_hash(input: [Field; N]) -> Field -``` -> Source code: noir_stdlib/src/hash.nr#L45-L47 - - -example: - -```rust title="pedersen-hash" showLineNumbers -use dep::std; - -fn main(x: Field, y: Field, expected_hash: Field) { - let hash = std::hash::pedersen_hash([x, y]); - assert_eq(hash, expected_hash); -} -``` -> Source code: test_programs/execution_success/pedersen_hash/src/main.nr#L1-L8 - - - - -## pedersen_commitment - -Given an array of Fields, returns the Pedersen commitment. - -```rust title="pedersen_commitment" showLineNumbers -struct PedersenPoint { - x : Field, - y : Field, -} - -pub fn pedersen_commitment(input: [Field; N]) -> PedersenPoint { -``` -> Source code: noir_stdlib/src/hash.nr#L26-L33 - - -example: - -```rust title="pedersen-commitment" showLineNumbers -use dep::std; - -fn main(x: Field, y: Field, expected_commitment: std::hash::PedersenPoint) { - let commitment = std::hash::pedersen_commitment([x, y]); - assert_eq(commitment.x, expected_commitment.x); - assert_eq(commitment.y, expected_commitment.y); -} -``` -> Source code: test_programs/execution_success/pedersen_commitment/src/main.nr#L1-L9 - - - - -## keccak256 - -Given an array of bytes (`u8`), returns the resulting keccak hash as an array of -32 bytes (`[u8; 32]`). Specify a message_size to hash only the first -`message_size` bytes of the input. - -```rust title="keccak256" showLineNumbers -pub fn keccak256(input: [u8; N], message_size: u32) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L67-L69 - - -example: - -```rust title="keccak256" showLineNumbers -use dep::std; - -fn main(x: Field, result: [u8; 32]) { - // We use the `as` keyword here to denote the fact that we want to take just the first byte from the x Field - // The padding is taken care of by the program - let digest = std::hash::keccak256([x as u8], 1); - assert(digest == result); - - //#1399: variable message size - let message_size = 4; - let hash_a = std::hash::keccak256([1, 2, 3, 4], message_size); - let hash_b = std::hash::keccak256([1, 2, 3, 4, 0, 0, 0, 0], message_size); - - assert(hash_a == hash_b); - - let message_size_big = 8; - let hash_c = std::hash::keccak256([1, 2, 3, 4, 0, 0, 0, 0], message_size_big); - - assert(hash_a != hash_c); -} -``` -> Source code: test_programs/execution_success/keccak256/src/main.nr#L1-L22 - - - - -## poseidon - -Given an array of Fields, returns a new Field with the Poseidon Hash. Mind that you need to specify -how many inputs are there to your Poseidon function. - -```rust -// example for hash_1, hash_2 accepts an array of length 2, etc -fn hash_1(input: [Field; 1]) -> Field -``` - -example: - -```rust title="poseidon" showLineNumbers -use dep::std::hash::poseidon; -use dep::std::hash::poseidon2; - -fn main(x1: [Field; 2], y1: pub Field, x2: [Field; 4], y2: pub Field, x3: [Field; 4], y3: Field) { - let hash1 = poseidon::bn254::hash_2(x1); - assert(hash1 == y1); - - let hash2 = poseidon::bn254::hash_4(x2); - assert(hash2 == y2); - - let hash3 = poseidon2::Poseidon2::hash(x3, x3.len()); - assert(hash3 == y3); -} -``` -> Source code: test_programs/execution_success/poseidon_bn254_hash/src/main.nr#L1-L15 - - -## poseidon 2 - -Given an array of Fields, returns a new Field with the Poseidon2 Hash. Contrary to the Poseidon -function, there is only one hash and you can specify a message_size to hash only the first -`message_size` bytes of the input, - -```rust -// example for hashing the first three elements of the input -Poseidon2::hash(input, 3); -``` - -The above example for Poseidon also includes Poseidon2. - -## mimc_bn254 and mimc - -`mimc_bn254` is `mimc`, but with hardcoded parameters for the BN254 curve. You can use it by -providing an array of Fields, and it returns a Field with the hash. You can use the `mimc` method if -you're willing to input your own constants: - -```rust -fn mimc(x: Field, k: Field, constants: [Field; N], exp : Field) -> Field -``` - -otherwise, use the `mimc_bn254` method: - -```rust -fn mimc_bn254(array: [Field; N]) -> Field -``` - -example: - -```rust - -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::mimc::mimc_bn254(x); -} -``` - -## hash_to_field - -```rust -fn hash_to_field(_input : [Field]) -> Field {} -``` - -Calculates the `blake2s` hash of the inputs and returns the hash modulo the field modulus to return -a value which can be represented as a `Field`. - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/index.md deleted file mode 100644 index 650f30165d5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/index.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Cryptographic Primitives -description: - Learn about the cryptographic primitives ready to use for any Noir project -keywords: - [ - cryptographic primitives, - Noir project, - ] ---- - -The Noir team is progressively adding new cryptographic primitives to the standard library. Reach out for news or if you would be interested in adding more of these calculations in Noir. - -Some methods are available thanks to the Aztec backend, not being performed using Noir. When using other backends, these methods may or may not be supplied. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/scalar.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/scalar.mdx deleted file mode 100644 index df411ca5443..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/scalar.mdx +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Scalar multiplication -description: See how you can perform scalar multiplications over a fixed base in Noir -keywords: [cryptographic primitives, Noir project, scalar multiplication] -sidebar_position: 1 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## scalar_mul::fixed_base_embedded_curve - -Performs scalar multiplication over the embedded curve whose coordinates are defined by the -configured noir field. For the BN254 scalar field, this is BabyJubJub or Grumpkin. - -```rust title="fixed_base_embedded_curve" showLineNumbers -pub fn fixed_base_embedded_curve( - low: Field, - high: Field -) -> [Field; 2] -``` -> Source code: noir_stdlib/src/scalar_mul.nr#L27-L32 - - -example - -```rust -fn main(x : Field) { - let scal = std::scalar_mul::fixed_base_embedded_curve(x); - println(scal); -} -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/schnorr.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/schnorr.mdx deleted file mode 100644 index b59e69c8f07..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/schnorr.mdx +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: Schnorr Signatures -description: Learn how you can verify Schnorr signatures using Noir -keywords: [cryptographic primitives, Noir project, schnorr, signatures] -sidebar_position: 2 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## schnorr::verify_signature - -Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin). -See schnorr::verify_signature_slice for a version that works directly on slices. - -```rust title="schnorr_verify" showLineNumbers -pub fn verify_signature( - public_key_x: Field, - public_key_y: Field, - signature: [u8; 64], - message: [u8; N] -) -> bool -``` -> Source code: noir_stdlib/src/schnorr.nr#L2-L9 - - -where `_signature` can be generated like so using the npm package -[@noir-lang/barretenberg](https://www.npmjs.com/package/@noir-lang/barretenberg) - -```js -const { BarretenbergWasm } = require('@noir-lang/barretenberg/dest/wasm'); -const { Schnorr } = require('@noir-lang/barretenberg/dest/crypto/schnorr'); - -... - -const barretenberg = await BarretenbergWasm.new(); -const schnorr = new Schnorr(barretenberg); -const pubKey = schnorr.computePublicKey(privateKey); -const message = ... -const signature = Array.from( - schnorr.constructSignature(hash, privateKey).toBuffer() -); - -... -``` - - - -## schnorr::verify_signature_slice - -Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin) -where the message is a slice. - -```rust title="schnorr_verify_slice" showLineNumbers -pub fn verify_signature_slice( - public_key_x: Field, - public_key_y: Field, - signature: [u8; 64], - message: [u8] -) -> bool -``` -> Source code: noir_stdlib/src/schnorr.nr#L13-L20 - - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/logging.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/logging.md deleted file mode 100644 index db75ef9f86f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/logging.md +++ /dev/null @@ -1,78 +0,0 @@ ---- -title: Logging -description: - Learn how to use the println statement for debugging in Noir with this tutorial. Understand the - basics of logging in Noir and how to implement it in your code. -keywords: - [ - noir logging, - println statement, - print statement, - debugging in noir, - noir std library, - logging tutorial, - basic logging in noir, - noir logging implementation, - noir debugging techniques, - rust, - ] ---- - -The standard library provides two familiar statements you can use: `println` and `print`. Despite being a limited implementation of rust's `println!` and `print!` macros, these constructs can be useful for debugging. - -You can print the output of both statements in your Noir code by using the `nargo execute` command or the `--show-output` flag when using `nargo test` (provided there are print statements in your tests). - -It is recommended to use `nargo execute` if you want to debug failing constraints with `println` or `print` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). Neither `println`, nor `print` are callable for failed constraints caught at compile time. - -Both `print` and `println` are generic functions which can work on integers, fields, strings, and even structs or expressions. Note however, that slices are currently unsupported. For example: - -```rust -struct Person { - age: Field, - height: Field, -} - -fn main(age: Field, height: Field) { - let person = Person { - age: age, - height: height, - }; - println(person); - println(age + height); - println("Hello world!"); -} -``` - -You can print different types in the same statement (including strings) with a type called `fmtstr`. It can be specified in the same way as a normal string, just prepended with an "f" character: - -```rust - let fmt_str = f"i: {i}, j: {j}"; - println(fmt_str); - - let s = myStruct { y: x, x: y }; - println(s); - - println(f"i: {i}, s: {s}"); - - println(x); - println([x, y]); - - let foo = fooStruct { my_struct: s, foo: 15 }; - println(f"s: {s}, foo: {foo}"); - - println(15); // prints 0x0f, implicit Field - println(-1 as u8); // prints 255 - println(-1 as i8); // prints -1 -``` - -Examples shown above are interchangeable between the two `print` statements: - -```rust -let person = Person { age : age, height : height }; - -println(person); -print(person); - -println("Hello world!"); // Prints with a newline at the end of the input -print("Hello world!"); // Prints the input and keeps cursor on the same line -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/merkle_trees.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/merkle_trees.md deleted file mode 100644 index 6a9ebf72ada..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/merkle_trees.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: Merkle Trees -description: Learn about Merkle Trees in Noir with this tutorial. Explore the basics of computing a merkle root using a proof, with examples. -keywords: - [ - Merkle trees in Noir, - Noir programming language, - check membership, - computing root from leaf, - Noir Merkle tree implementation, - Merkle tree tutorial, - Merkle tree code examples, - Noir libraries, - pedersen hash., - ] ---- - -## compute_merkle_root - -Returns the root of the tree from the provided leaf and its hash path, using a [Pedersen hash](./cryptographic_primitives/hashes.mdx#pedersen_hash). - -```rust -fn compute_merkle_root(leaf : Field, index : Field, hash_path: [Field]) -> Field -``` - -example: - -```rust -/** - // these values are for this example only - index = "0" - priv_key = "0x000000000000000000000000000000000000000000000000000000616c696365" - secret = "0x1929ea3ab8d9106a899386883d9428f8256cfedb3c4f6b66bf4aa4d28a79988f" - note_hash_path = [ - "0x1e61bdae0f027b1b2159e1f9d3f8d00fa668a952dddd822fda80dc745d6f65cc", - "0x0e4223f3925f98934393c74975142bd73079ab0621f4ee133cee050a3c194f1a", - "0x2fd7bb412155bf8693a3bd2a3e7581a679c95c68a052f835dddca85fa1569a40" - ] - */ -fn main(index: Field, priv_key: Field, secret: Field, note_hash_path: [Field; 3]) { - - let pubkey = std::scalar_mul::fixed_base_embedded_curve(priv_key); - let pubkey_x = pubkey[0]; - let pubkey_y = pubkey[1]; - let note_commitment = std::hash::pedersen(&[pubkey_x, pubkey_y, secret]); - - let root = std::merkle::compute_merkle_root(note_commitment[0], index, note_hash_path.as_slice()); - println(root); -} -``` - -To check merkle tree membership: - -1. Include a merkle root as a program input. -2. Compute the merkle root of a given leaf, index and hash path. -3. Assert the merkle roots are equal. - -For more info about merkle trees, see the Wikipedia [page](https://en.wikipedia.org/wiki/Merkle_tree). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/options.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/options.md deleted file mode 100644 index a1bd4e1de5f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/options.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -title: Option Type ---- - -The `Option` type is a way to express that a value might be present (`Some(T))` or absent (`None`). It's a safer way to handle potential absence of values, compared to using nulls in many other languages. - -```rust -struct Option { - None, - Some(T), -} -``` - -The `Option` type, already imported into your Noir program, can be used directly: - -```rust -fn main() { - let none = Option::none(); - let some = Option::some(3); -} -``` - -See [this test](https://github.com/noir-lang/noir/blob/5cbfb9c4a06c8865c98ff2b594464b037d821a5c/crates/nargo_cli/tests/test_data/option/src/main.nr) for a more comprehensive set of examples of each of the methods described below. - -## Methods - -### none - -Constructs a none value. - -### some - -Constructs a some wrapper around a given value. - -### is_none - -Returns true if the Option is None. - -### is_some - -Returns true of the Option is Some. - -### unwrap - -Asserts `self.is_some()` and returns the wrapped value. - -### unwrap_unchecked - -Returns the inner value without asserting `self.is_some()`. This method can be useful within an if condition when we already know that `option.is_some()`. If the option is None, there is no guarantee what value will be returned, only that it will be of type T for an `Option`. - -### unwrap_or - -Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value. - -### unwrap_or_else - -Returns the wrapped value if `self.is_some()`. Otherwise, calls the given function to return a default value. - -### expect - -Asserts `self.is_some()` with a provided custom message and returns the contained `Some` value. The custom message is expected to be a format string. - -### map - -If self is `Some(x)`, this returns `Some(f(x))`. Otherwise, this returns `None`. - -### map_or - -If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns the given default value. - -### map_or_else - -If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns `default()`. - -### and - -Returns None if self is None. Otherwise, this returns `other`. - -### and_then - -If self is None, this returns None. Otherwise, this calls the given function with the Some value contained within self, and returns the result of that call. In some languages this function is called `flat_map` or `bind`. - -### or - -If self is Some, return self. Otherwise, return `other`. - -### or_else - -If self is Some, return self. Otherwise, return `default()`. - -### xor - -If only one of the two Options is Some, return that option. Otherwise, if both options are Some or both are None, None is returned. - -### filter - -Returns `Some(x)` if self is `Some(x)` and `predicate(x)` is true. Otherwise, this returns `None`. - -### flatten - -Flattens an `Option>` into a `Option`. This returns `None` if the outer Option is None. Otherwise, this returns the inner Option. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/recursion.md deleted file mode 100644 index f33c285cf4e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/recursion.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -title: Recursive Proofs -description: Learn about how to write recursive proofs in Noir. -keywords: [recursion, recursive proofs, verification_key, verify_proof] ---- - -Noir supports recursively verifying proofs, meaning you verify the proof of a Noir program in another Noir program. This enables creating proofs of arbitrary size by doing step-wise verification of smaller components of a large proof. - -Read [the explainer on recursion](../../explainers/explainer-recursion.md) to know more about this function and the [guide on how to use it.](../../how_to/how-to-recursion.md) - -## The `#[recursive]` Attribute - -In Noir, the `#[recursive]` attribute is used to indicate that a circuit is designed for recursive proof generation. When applied, it informs the compiler and the tooling that the circuit should be compiled in a way that makes its proofs suitable for recursive verification. This attribute eliminates the need for manual flagging of recursion at the tooling level, streamlining the proof generation process for recursive circuits. - -### Example usage with `#[recursive]` - -```rust -#[recursive] -fn main(x: Field, y: pub Field) { - assert(x == y, "x and y are not equal"); -} - -// This marks the circuit as recursion-friendly and indicates that proofs generated from this circuit -// are intended for recursive verification. -``` - -By incorporating this attribute directly in the circuit's definition, tooling like Nargo and NoirJS can automatically execute recursive-specific duties for Noir programs (e.g. recursive-friendly proof artifact generation) without additional flags or configurations. - -## Verifying Recursive Proofs - -```rust -#[foreign(recursive_aggregation)] -pub fn verify_proof(verification_key: [Field], proof: [Field], public_inputs: [Field], key_hash: Field) {} -``` - -:::info - -This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. - -::: - -## Example usage - -```rust -use dep::std; - -fn main( - verification_key : [Field; 114], - proof : [Field; 93], - public_inputs : [Field; 1], - key_hash : Field, - proof_b : [Field; 93], -) { - std::verify_proof( - verification_key.as_slice(), - proof.as_slice(), - public_inputs.as_slice(), - key_hash - ); - - std::verify_proof( - verification_key.as_slice(), - proof_b.as_slice(), - public_inputs.as_slice(), - key_hash - ); -} -``` - -You can see a full example of recursive proofs in [this example recursion demo repo](https://github.com/noir-lang/noir-examples/tree/master/recursion). - -## Parameters - -### `verification_key` - -The verification key for the zk program that is being verified. - -### `proof` - -The proof for the zk program that is being verified. - -### `public_inputs` - -These represent the public inputs of the proof we are verifying. - -### `key_hash` - -A key hash is used to check the validity of the verification key. The circuit implementing this opcode can use this hash to ensure that the key provided to the circuit matches the key produced by the circuit creator. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/traits.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/traits.md deleted file mode 100644 index 94337e77a3e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/traits.md +++ /dev/null @@ -1,410 +0,0 @@ ---- -title: Traits -description: Noir's stdlib provides a few commonly used traits. -keywords: [traits, trait, interface, protocol, default, add, eq] ---- - -## `std::default` - -### `std::default::Default` - -```rust title="default-trait" showLineNumbers -trait Default { - fn default() -> Self; -} -``` -> Source code: noir_stdlib/src/default.nr#L1-L5 - - -Constructs a default value of a type. - -Implementations: -```rust -impl Default for Field { .. } - -impl Default for i8 { .. } -impl Default for i16 { .. } -impl Default for i32 { .. } -impl Default for i64 { .. } - -impl Default for u8 { .. } -impl Default for u16 { .. } -impl Default for u32 { .. } -impl Default for u64 { .. } - -impl Default for () { .. } -impl Default for bool { .. } - -impl Default for [T; N] - where T: Default { .. } - -impl Default for [T] { .. } - -impl Default for (A, B) - where A: Default, B: Default { .. } - -impl Default for (A, B, C) - where A: Default, B: Default, C: Default { .. } - -impl Default for (A, B, C, D) - where A: Default, B: Default, C: Default, D: Default { .. } - -impl Default for (A, B, C, D, E) - where A: Default, B: Default, C: Default, D: Default, E: Default { .. } -``` - -For primitive integer types, the return value of `default` is `0`. Container -types such as arrays are filled with default values of their element type, -except slices whose length is unknown and thus defaulted to zero. - - -## `std::convert` - -### `std::convert::From` - -```rust title="from-trait" showLineNumbers -trait From { - fn from(input: T) -> Self; -} -``` -> Source code: noir_stdlib/src/convert.nr#L1-L5 - - -The `From` trait defines how to convert from a given type `T` to the type on which the trait is implemented. - -The Noir standard library provides a number of implementations of `From` between primitive types. -```rust title="from-impls" showLineNumbers -// Unsigned integers - -impl From for u32 { fn from(value: u8) -> u32 { value as u32 } } - -impl From for u64 { fn from(value: u8) -> u64 { value as u64 } } -impl From for u64 { fn from(value: u32) -> u64 { value as u64 } } - -impl From for Field { fn from(value: u8) -> Field { value as Field } } -impl From for Field { fn from(value: u32) -> Field { value as Field } } -impl From for Field { fn from(value: u64) -> Field { value as Field } } - -// Signed integers - -impl From for i32 { fn from(value: i8) -> i32 { value as i32 } } - -impl From for i64 { fn from(value: i8) -> i64 { value as i64 } } -impl From for i64 { fn from(value: i32) -> i64 { value as i64 } } - -// Booleans -impl From for u8 { fn from(value: bool) -> u8 { value as u8 } } -impl From for u32 { fn from(value: bool) -> u32 { value as u32 } } -impl From for u64 { fn from(value: bool) -> u64 { value as u64 } } -impl From for i8 { fn from(value: bool) -> i8 { value as i8 } } -impl From for i32 { fn from(value: bool) -> i32 { value as i32 } } -impl From for i64 { fn from(value: bool) -> i64 { value as i64 } } -impl From for Field { fn from(value: bool) -> Field { value as Field } } -``` -> Source code: noir_stdlib/src/convert.nr#L25-L52 - - -#### When to implement `From` - -As a general rule of thumb, `From` may be implemented in the [situations where it would be suitable in Rust](https://doc.rust-lang.org/std/convert/trait.From.html#when-to-implement-from): - -- The conversion is *infallible*: Noir does not provide an equivalent to Rust's `TryFrom`, if the conversion can fail then provide a named method instead. -- The conversion is *lossless*: semantically, it should not lose or discard information. For example, `u32: From` can losslessly convert any `u16` into a valid `u32` such that the original `u16` can be recovered. On the other hand, `u16: From` should not be implemented as `2**16` is a `u32` which cannot be losslessly converted into a `u16`. -- The conversion is *value-preserving*: the conceptual kind and meaning of the resulting value is the same, even though the Noir type and technical representation might be different. While it's possible to infallibly and losslessly convert a `u8` into a `str<2>` hex representation, `4u8` and `"04"` are too different for `str<2>: From` to be implemented. -- The conversion is *obvious*: it's the only reasonable conversion between the two types. If there's ambiguity on how to convert between them such that the same input could potentially map to two different values then a named method should be used. For instance rather than implementing `U128: From<[u8; 16]>`, the methods `U128::from_le_bytes` and `U128::from_be_bytes` are used as otherwise the endianness of the array would be ambiguous, resulting in two potential values of `U128` from the same byte array. - -One additional recommendation specific to Noir is: -- The conversion is *efficient*: it's relatively cheap to convert between the two types. Due to being a ZK DSL, it's more important to avoid unnecessary computation compared to Rust. If the implementation of `From` would encourage users to perform unnecessary conversion, resulting in additional proving time, then it may be preferable to expose functionality such that this conversion may be avoided. - -### `std::convert::Into` - -The `Into` trait is defined as the reciprocal of `From`. It should be easy to convince yourself that if we can convert to type `A` from type `B`, then it's possible to convert type `B` into type `A`. - -For this reason, implementing `From` on a type will automatically generate a matching `Into` implementation. One should always prefer implementing `From` over `Into` as implementing `Into` will not generate a matching `From` implementation. - -```rust title="into-trait" showLineNumbers -trait Into { - fn into(self) -> T; -} - -impl Into for U where T: From { - fn into(self) -> T { - T::from(self) - } -} -``` -> Source code: noir_stdlib/src/convert.nr#L13-L23 - - -`Into` is most useful when passing function arguments where the types don't quite match up with what the function expects. In this case, the compiler has enough type information to perform the necessary conversion by just appending `.into()` onto the arguments in question. - - -## `std::cmp` - -### `std::cmp::Eq` - -```rust title="eq-trait" showLineNumbers -trait Eq { - fn eq(self, other: Self) -> bool; -} -``` -> Source code: noir_stdlib/src/cmp.nr#L1-L5 - - -Returns `true` if `self` is equal to `other`. Implementing this trait on a type -allows the type to be used with `==` and `!=`. - -Implementations: -```rust -impl Eq for Field { .. } - -impl Eq for i8 { .. } -impl Eq for i16 { .. } -impl Eq for i32 { .. } -impl Eq for i64 { .. } - -impl Eq for u8 { .. } -impl Eq for u16 { .. } -impl Eq for u32 { .. } -impl Eq for u64 { .. } - -impl Eq for () { .. } -impl Eq for bool { .. } - -impl Eq for [T; N] - where T: Eq { .. } - -impl Eq for [T] - where T: Eq { .. } - -impl Eq for (A, B) - where A: Eq, B: Eq { .. } - -impl Eq for (A, B, C) - where A: Eq, B: Eq, C: Eq { .. } - -impl Eq for (A, B, C, D) - where A: Eq, B: Eq, C: Eq, D: Eq { .. } - -impl Eq for (A, B, C, D, E) - where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq { .. } -``` - -### `std::cmp::Ord` - -```rust title="ord-trait" showLineNumbers -trait Ord { - fn cmp(self, other: Self) -> Ordering; -} -``` -> Source code: noir_stdlib/src/cmp.nr#L102-L106 - - -`a.cmp(b)` compares two values returning `Ordering::less()` if `a < b`, -`Ordering::equal()` if `a == b`, or `Ordering::greater()` if `a > b`. -Implementing this trait on a type allows `<`, `<=`, `>`, and `>=` to be -used on values of the type. - -`std::cmp` also provides `max` and `min` functions for any type which implements the `Ord` trait. - -Implementations: - -```rust -impl Ord for u8 { .. } -impl Ord for u16 { .. } -impl Ord for u32 { .. } -impl Ord for u64 { .. } - -impl Ord for i8 { .. } -impl Ord for i16 { .. } -impl Ord for i32 { .. } - -impl Ord for i64 { .. } - -impl Ord for () { .. } -impl Ord for bool { .. } - -impl Ord for [T; N] - where T: Ord { .. } - -impl Ord for [T] - where T: Ord { .. } - -impl Ord for (A, B) - where A: Ord, B: Ord { .. } - -impl Ord for (A, B, C) - where A: Ord, B: Ord, C: Ord { .. } - -impl Ord for (A, B, C, D) - where A: Ord, B: Ord, C: Ord, D: Ord { .. } - -impl Ord for (A, B, C, D, E) - where A: Ord, B: Ord, C: Ord, D: Ord, E: Ord { .. } -``` - -## `std::ops` - -### `std::ops::Add`, `std::ops::Sub`, `std::ops::Mul`, and `std::ops::Div` - -These traits abstract over addition, subtraction, multiplication, and division respectively. -Implementing these traits for a given type will also allow that type to be used with the corresponding operator -for that trait (`+` for Add, etc) in addition to the normal method names. - -```rust title="add-trait" showLineNumbers -trait Add { - fn add(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L1-L5 - -```rust title="sub-trait" showLineNumbers -trait Sub { - fn sub(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L17-L21 - -```rust title="mul-trait" showLineNumbers -trait Mul { - fn mul(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L33-L37 - -```rust title="div-trait" showLineNumbers -trait Div { - fn div(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L49-L53 - - -The implementations block below is given for the `Add` trait, but the same types that implement -`Add` also implement `Sub`, `Mul`, and `Div`. - -Implementations: -```rust -impl Add for Field { .. } - -impl Add for i8 { .. } -impl Add for i16 { .. } -impl Add for i32 { .. } -impl Add for i64 { .. } - -impl Add for u8 { .. } -impl Add for u16 { .. } -impl Add for u32 { .. } -impl Add for u64 { .. } -``` - -### `std::ops::Rem` - -```rust title="rem-trait" showLineNumbers -trait Rem{ - fn rem(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L65-L69 - - -`Rem::rem(a, b)` is the remainder function returning the result of what is -left after dividing `a` and `b`. Implementing `Rem` allows the `%` operator -to be used with the implementation type. - -Unlike other numeric traits, `Rem` is not implemented for `Field`. - -Implementations: -```rust -impl Rem for u8 { fn rem(self, other: u8) -> u8 { self % other } } -impl Rem for u16 { fn rem(self, other: u16) -> u16 { self % other } } -impl Rem for u32 { fn rem(self, other: u32) -> u32 { self % other } } -impl Rem for u64 { fn rem(self, other: u64) -> u64 { self % other } } - -impl Rem for i8 { fn rem(self, other: i8) -> i8 { self % other } } -impl Rem for i16 { fn rem(self, other: i16) -> i16 { self % other } } -impl Rem for i32 { fn rem(self, other: i32) -> i32 { self % other } } -impl Rem for i64 { fn rem(self, other: i64) -> i64 { self % other } } -``` - -### `std::ops::{ BitOr, BitAnd, BitXor }` - -```rust title="bitor-trait" showLineNumbers -trait BitOr { - fn bitor(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L79-L83 - -```rust title="bitand-trait" showLineNumbers -trait BitAnd { - fn bitand(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L95-L99 - -```rust title="bitxor-trait" showLineNumbers -trait BitXor { - fn bitxor(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L111-L115 - - -Traits for the bitwise operations `|`, `&`, and `^`. - -Implementing `BitOr`, `BitAnd` or `BitXor` for a type allows the `|`, `&`, or `^` operator respectively -to be used with the type. - -The implementations block below is given for the `BitOr` trait, but the same types that implement -`BitOr` also implement `BitAnd` and `BitXor`. - -Implementations: -```rust -impl BitOr for bool { fn bitor(self, other: bool) -> bool { self | other } } - -impl BitOr for u8 { fn bitor(self, other: u8) -> u8 { self | other } } -impl BitOr for u16 { fn bitor(self, other: u16) -> u16 { self | other } } -impl BitOr for u32 { fn bitor(self, other: u32) -> u32 { self | other } } -impl BitOr for u64 { fn bitor(self, other: u64) -> u64 { self | other } } - -impl BitOr for i8 { fn bitor(self, other: i8) -> i8 { self | other } } -impl BitOr for i16 { fn bitor(self, other: i16) -> i16 { self | other } } -impl BitOr for i32 { fn bitor(self, other: i32) -> i32 { self | other } } -impl BitOr for i64 { fn bitor(self, other: i64) -> i64 { self | other } } -``` - -### `std::ops::{ Shl, Shr }` - -```rust title="shl-trait" showLineNumbers -trait Shl { - fn shl(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L127-L131 - -```rust title="shr-trait" showLineNumbers -trait Shr { - fn shr(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L142-L146 - - -Traits for a bit shift left and bit shift right. - -Implementing `Shl` for a type allows the left shift operator (`<<`) to be used with the implementation type. -Similarly, implementing `Shr` allows the right shift operator (`>>`) to be used with the type. - -Note that bit shifting is not currently implemented for signed types. - -The implementations block below is given for the `Shl` trait, but the same types that implement -`Shl` also implement `Shr`. - -Implementations: -```rust -impl Shl for u8 { fn shl(self, other: u8) -> u8 { self << other } } -impl Shl for u16 { fn shl(self, other: u16) -> u16 { self << other } } -impl Shl for u32 { fn shl(self, other: u32) -> u32 { self << other } } -impl Shl for u64 { fn shl(self, other: u64) -> u64 { self << other } } -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/zeroed.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/zeroed.md deleted file mode 100644 index f450fecdd36..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/zeroed.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Zeroed Function -description: - The zeroed function returns a zeroed value of any type. -keywords: - [ - zeroed - ] ---- - -Implements `fn zeroed() -> T` to return a zeroed value of any type. This function is generally unsafe to use as the zeroed bit pattern is not guaranteed to be valid for all types. It can however, be useful in cases when the value is guaranteed not to be used such as in a BoundedVec library implementing a growable vector, up to a certain length, backed by an array. The array can be initialized with zeroed values which are guaranteed to be inaccessible until the vector is pushed to. Similarly, enumerations in noir can be implemented using this method by providing zeroed values for the unused variants. - -You can access the function at `std::unsafe::zeroed`. - -This function currently supports the following types: - -- Field -- Bool -- Uint -- Array -- Slice -- String -- Tuple -- Function - -Using it on other types could result in unexpected behavior. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/backend_barretenberg/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/backend_barretenberg/.nojekyll deleted file mode 100644 index e2ac6616add..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/backend_barretenberg/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md deleted file mode 100644 index d7249d24330..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md +++ /dev/null @@ -1,160 +0,0 @@ -# BarretenbergBackend - -## Extends - -- `BarretenbergVerifierBackend` - -## Implements - -- [`Backend`](../index.md#backend) - -## Constructors - -### new BarretenbergBackend(acirCircuit, options) - -```ts -new BarretenbergBackend(acirCircuit, options): BarretenbergBackend -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `acirCircuit` | `CompiledCircuit` | -| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | - -#### Returns - -[`BarretenbergBackend`](BarretenbergBackend.md) - -#### Inherited from - -BarretenbergVerifierBackend.constructor - -## Properties - -| Property | Type | Description | Inheritance | -| :------ | :------ | :------ | :------ | -| `acirComposer` | `any` | - | BarretenbergVerifierBackend.acirComposer | -| `acirUncompressedBytecode` | `Uint8Array` | - | BarretenbergVerifierBackend.acirUncompressedBytecode | -| `api` | `Barretenberg` | - | BarretenbergVerifierBackend.api | -| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | - | BarretenbergVerifierBackend.options | - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Inherited from - -BarretenbergVerifierBackend.destroy - -*** - -### generateProof() - -```ts -generateProof(compressedWitness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `compressedWitness` | `Uint8Array` | - -#### Returns - -`Promise`\<`ProofData`\> - -#### Description - -Generates a proof - -*** - -### generateRecursiveProofArtifacts() - -```ts -generateRecursiveProofArtifacts(proofData, numOfPublicInputs): Promise -``` - -Generates artifacts that will be passed to a circuit that will verify this proof. - -Instead of passing the proof and verification key as a byte array, we pass them -as fields which makes it cheaper to verify in a circuit. - -The proof that is passed here will have been created using a circuit -that has the #[recursive] attribute on its `main` method. - -The number of public inputs denotes how many public inputs are in the inner proof. - -#### Parameters - -| Parameter | Type | Default value | -| :------ | :------ | :------ | -| `proofData` | `ProofData` | `undefined` | -| `numOfPublicInputs` | `number` | `0` | - -#### Returns - -`Promise`\<`object`\> - -#### Example - -```typescript -const artifacts = await backend.generateRecursiveProofArtifacts(proof, numOfPublicInputs); -``` - -*** - -### getVerificationKey() - -```ts -getVerificationKey(): Promise -``` - -#### Returns - -`Promise`\<`Uint8Array`\> - -#### Inherited from - -BarretenbergVerifierBackend.getVerificationKey - -*** - -### verifyProof() - -```ts -verifyProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | `ProofData` | - -#### Returns - -`Promise`\<`boolean`\> - -#### Inherited from - -BarretenbergVerifierBackend.verifyProof - -#### Description - -Verifies a proof - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/backend_barretenberg/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/backend_barretenberg/index.md deleted file mode 100644 index 64971973196..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/backend_barretenberg/index.md +++ /dev/null @@ -1,59 +0,0 @@ -# backend_barretenberg - -## Exports - -### Classes - -| Class | Description | -| :------ | :------ | -| [BarretenbergBackend](classes/BarretenbergBackend.md) | - | -| [BarretenbergVerifier](classes/BarretenbergVerifier.md) | - | - -### Type Aliases - -| Type alias | Description | -| :------ | :------ | -| [BackendOptions](type-aliases/BackendOptions.md) | - | - -## References - -### CompiledCircuit - -Renames and re-exports [Backend](index.md#backend) - -*** - -### ProofData - -Renames and re-exports [Backend](index.md#backend) - -## Variables - -### Backend - -```ts -Backend: any; -``` - -## Functions - -### publicInputsToWitnessMap() - -```ts -publicInputsToWitnessMap(publicInputs, abi): Backend -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `publicInputs` | `string`[] | -| `abi` | `Abi` | - -#### Returns - -[`Backend`](index.md#backend) - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md deleted file mode 100644 index b49a479f4f4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md +++ /dev/null @@ -1,21 +0,0 @@ -# BackendOptions - -```ts -type BackendOptions: object; -``` - -## Description - -An options object, currently only used to specify the number of threads to use. - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `memory` | `object` | - | -| `memory.maximum` | `number` | - | -| `threads` | `number` | **Description**

Number of threads | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs deleted file mode 100644 index d7d5128f9e3..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend","label":"BarretenbergBackend"},{"type":"doc","id":"reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier","label":"BarretenbergVerifier"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions","label":"BackendOptions"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/.nojekyll deleted file mode 100644 index e2ac6616add..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/classes/Noir.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/classes/Noir.md deleted file mode 100644 index 45dd62ee57e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/classes/Noir.md +++ /dev/null @@ -1,132 +0,0 @@ -# Noir - -## Constructors - -### new Noir(circuit, backend) - -```ts -new Noir(circuit, backend?): Noir -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `circuit` | `CompiledCircuit` | -| `backend`? | `any` | - -#### Returns - -[`Noir`](Noir.md) - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Description - -Destroys the underlying backend instance. - -#### Example - -```typescript -await noir.destroy(); -``` - -*** - -### execute() - -```ts -execute(inputs, foreignCallHandler?): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `inputs` | `InputMap` | -| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | - -#### Returns - -`Promise`\<`object`\> - -#### Description - -Allows to execute a circuit to get its witness and return value. - -#### Example - -```typescript -async execute(inputs) -``` - -*** - -### generateProof() - -```ts -generateProof(inputs, foreignCallHandler?): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `inputs` | `InputMap` | -| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | - -#### Returns - -`Promise`\<`ProofData`\> - -#### Description - -Generates a witness and a proof given an object as input. - -#### Example - -```typescript -async generateProof(input) -``` - -*** - -### verifyProof() - -```ts -verifyProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | `ProofData` | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Instantiates the verification key and verifies a proof. - -#### Example - -```typescript -async verifyProof(proof) -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/and.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/and.md deleted file mode 100644 index c783283e396..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/and.md +++ /dev/null @@ -1,22 +0,0 @@ -# and() - -```ts -and(lhs, rhs): string -``` - -Performs a bitwise AND operation between `lhs` and `rhs` - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `lhs` | `string` | | -| `rhs` | `string` | | - -## Returns - -`string` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/blake2s256.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/blake2s256.md deleted file mode 100644 index 7882d0da8d5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/blake2s256.md +++ /dev/null @@ -1,21 +0,0 @@ -# blake2s256() - -```ts -blake2s256(inputs): Uint8Array -``` - -Calculates the Blake2s256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md deleted file mode 100644 index 5e3cd53e9d3..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md +++ /dev/null @@ -1,28 +0,0 @@ -# ecdsa\_secp256k1\_verify() - -```ts -ecdsa_secp256k1_verify( - hashed_msg, - public_key_x_bytes, - public_key_y_bytes, - signature): boolean -``` - -Verifies a ECDSA signature over the secp256k1 curve. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `hashed_msg` | `Uint8Array` | | -| `public_key_x_bytes` | `Uint8Array` | | -| `public_key_y_bytes` | `Uint8Array` | | -| `signature` | `Uint8Array` | | - -## Returns - -`boolean` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md deleted file mode 100644 index 0b20ff68957..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md +++ /dev/null @@ -1,28 +0,0 @@ -# ecdsa\_secp256r1\_verify() - -```ts -ecdsa_secp256r1_verify( - hashed_msg, - public_key_x_bytes, - public_key_y_bytes, - signature): boolean -``` - -Verifies a ECDSA signature over the secp256r1 curve. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `hashed_msg` | `Uint8Array` | | -| `public_key_x_bytes` | `Uint8Array` | | -| `public_key_y_bytes` | `Uint8Array` | | -| `signature` | `Uint8Array` | | - -## Returns - -`boolean` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/keccak256.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/keccak256.md deleted file mode 100644 index d10f155ce86..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/keccak256.md +++ /dev/null @@ -1,21 +0,0 @@ -# keccak256() - -```ts -keccak256(inputs): Uint8Array -``` - -Calculates the Keccak256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/sha256.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/sha256.md deleted file mode 100644 index 6ba4ecac022..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/sha256.md +++ /dev/null @@ -1,21 +0,0 @@ -# sha256() - -```ts -sha256(inputs): Uint8Array -``` - -Calculates the SHA256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/xor.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/xor.md deleted file mode 100644 index 8d762b895d3..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/xor.md +++ /dev/null @@ -1,22 +0,0 @@ -# xor() - -```ts -xor(lhs, rhs): string -``` - -Performs a bitwise XOR operation between `lhs` and `rhs` - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `lhs` | `string` | | -| `rhs` | `string` | | - -## Returns - -`string` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/index.md deleted file mode 100644 index cca6b3ace41..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/index.md +++ /dev/null @@ -1,54 +0,0 @@ -# noir_js - -## Exports - -### Classes - -| Class | Description | -| :------ | :------ | -| [Noir](classes/Noir.md) | - | - -### Type Aliases - -| Type alias | Description | -| :------ | :------ | -| [ForeignCallHandler](type-aliases/ForeignCallHandler.md) | A callback which performs an foreign call and returns the response. | -| [ForeignCallInput](type-aliases/ForeignCallInput.md) | - | -| [ForeignCallOutput](type-aliases/ForeignCallOutput.md) | - | -| [WitnessMap](type-aliases/WitnessMap.md) | - | - -### Functions - -| Function | Description | -| :------ | :------ | -| [and](functions/and.md) | Performs a bitwise AND operation between `lhs` and `rhs` | -| [blake2s256](functions/blake2s256.md) | Calculates the Blake2s256 hash of the input bytes | -| [ecdsa\_secp256k1\_verify](functions/ecdsa_secp256k1_verify.md) | Verifies a ECDSA signature over the secp256k1 curve. | -| [ecdsa\_secp256r1\_verify](functions/ecdsa_secp256r1_verify.md) | Verifies a ECDSA signature over the secp256r1 curve. | -| [keccak256](functions/keccak256.md) | Calculates the Keccak256 hash of the input bytes | -| [sha256](functions/sha256.md) | Calculates the SHA256 hash of the input bytes | -| [xor](functions/xor.md) | Performs a bitwise XOR operation between `lhs` and `rhs` | - -## References - -### CompiledCircuit - -Renames and re-exports [InputMap](index.md#inputmap) - -*** - -### ProofData - -Renames and re-exports [InputMap](index.md#inputmap) - -## Variables - -### InputMap - -```ts -InputMap: any; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md deleted file mode 100644 index 812b8b16481..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md +++ /dev/null @@ -1,24 +0,0 @@ -# ForeignCallHandler - -```ts -type ForeignCallHandler: (name, inputs) => Promise; -``` - -A callback which performs an foreign call and returns the response. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `name` | `string` | The identifier for the type of foreign call being performed. | -| `inputs` | [`ForeignCallInput`](ForeignCallInput.md)[] | An array of hex encoded inputs to the foreign call. | - -## Returns - -`Promise`\<[`ForeignCallOutput`](ForeignCallOutput.md)[]\> - -outputs - An array of hex encoded outputs containing the results of the foreign call. - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md deleted file mode 100644 index dd95809186a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md +++ /dev/null @@ -1,9 +0,0 @@ -# ForeignCallInput - -```ts -type ForeignCallInput: string[]; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md deleted file mode 100644 index b71fb78a946..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md +++ /dev/null @@ -1,9 +0,0 @@ -# ForeignCallOutput - -```ts -type ForeignCallOutput: string | string[]; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md deleted file mode 100644 index 258c46f9d0c..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md +++ /dev/null @@ -1,9 +0,0 @@ -# WitnessMap - -```ts -type WitnessMap: Map; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs deleted file mode 100644 index c6d8125eaad..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/noir_js/classes/Noir","label":"Noir"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallHandler","label":"ForeignCallHandler"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallInput","label":"ForeignCallInput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallOutput","label":"ForeignCallOutput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/WitnessMap","label":"WitnessMap"}]},{"type":"category","label":"Functions","items":[{"type":"doc","id":"reference/NoirJS/noir_js/functions/and","label":"and"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/blake2s256","label":"blake2s256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify","label":"ecdsa_secp256k1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify","label":"ecdsa_secp256r1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/keccak256","label":"keccak256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/sha256","label":"sha256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/xor","label":"xor"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/.nojekyll deleted file mode 100644 index e2ac6616add..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/functions/compile.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/functions/compile.md deleted file mode 100644 index 6faf763b37f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/functions/compile.md +++ /dev/null @@ -1,51 +0,0 @@ -# compile() - -```ts -compile( - fileManager, - projectPath?, - logFn?, -debugLogFn?): Promise -``` - -Compiles a Noir project - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `fileManager` | `FileManager` | The file manager to use | -| `projectPath`? | `string` | The path to the project inside the file manager. Defaults to the root of the file manager | -| `logFn`? | `LogFn` | A logging function. If not provided, console.log will be used | -| `debugLogFn`? | `LogFn` | A debug logging function. If not provided, logFn will be used | - -## Returns - -`Promise`\<[`ProgramCompilationArtifacts`](../index.md#programcompilationartifacts)\> - -## Example - -```typescript -// Node.js - -import { compile_program, createFileManager } from '@noir-lang/noir_wasm'; - -const fm = createFileManager(myProjectPath); -const myCompiledCode = await compile_program(fm); -``` - -```typescript -// Browser - -import { compile_program, createFileManager } from '@noir-lang/noir_wasm'; - -const fm = createFileManager('/'); -for (const path of files) { - await fm.writeFile(path, await getFileAsStream(path)); -} -const myCompiledCode = await compile_program(fm); -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/functions/compile_contract.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/functions/compile_contract.md deleted file mode 100644 index 7d0b39a43ef..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/functions/compile_contract.md +++ /dev/null @@ -1,51 +0,0 @@ -# compile\_contract() - -```ts -compile_contract( - fileManager, - projectPath?, - logFn?, -debugLogFn?): Promise -``` - -Compiles a Noir project - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `fileManager` | `FileManager` | The file manager to use | -| `projectPath`? | `string` | The path to the project inside the file manager. Defaults to the root of the file manager | -| `logFn`? | `LogFn` | A logging function. If not provided, console.log will be used | -| `debugLogFn`? | `LogFn` | A debug logging function. If not provided, logFn will be used | - -## Returns - -`Promise`\<[`ContractCompilationArtifacts`](../index.md#contractcompilationartifacts)\> - -## Example - -```typescript -// Node.js - -import { compile_contract, createFileManager } from '@noir-lang/noir_wasm'; - -const fm = createFileManager(myProjectPath); -const myCompiledCode = await compile_contract(fm); -``` - -```typescript -// Browser - -import { compile_contract, createFileManager } from '@noir-lang/noir_wasm'; - -const fm = createFileManager('/'); -for (const path of files) { - await fm.writeFile(path, await getFileAsStream(path)); -} -const myCompiledCode = await compile_contract(fm); -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/functions/createFileManager.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/functions/createFileManager.md deleted file mode 100644 index 7e65c1d69c7..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/functions/createFileManager.md +++ /dev/null @@ -1,21 +0,0 @@ -# createFileManager() - -```ts -createFileManager(dataDir): FileManager -``` - -Creates a new FileManager instance based on fs in node and memfs in the browser (via webpack alias) - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `dataDir` | `string` | root of the file system | - -## Returns - -`FileManager` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md deleted file mode 100644 index fcea9275341..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md +++ /dev/null @@ -1,21 +0,0 @@ -# inflateDebugSymbols() - -```ts -inflateDebugSymbols(debugSymbols): any -``` - -Decompresses and decodes the debug symbols - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `debugSymbols` | `string` | The base64 encoded debug symbols | - -## Returns - -`any` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/index.md deleted file mode 100644 index b6e0f9d1bc0..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/index.md +++ /dev/null @@ -1,49 +0,0 @@ -# noir_wasm - -## Exports - -### Functions - -| Function | Description | -| :------ | :------ | -| [compile](functions/compile.md) | Compiles a Noir project | -| [compile\_contract](functions/compile_contract.md) | Compiles a Noir project | -| [createFileManager](functions/createFileManager.md) | Creates a new FileManager instance based on fs in node and memfs in the browser (via webpack alias) | -| [inflateDebugSymbols](functions/inflateDebugSymbols.md) | Decompresses and decodes the debug symbols | - -## References - -### compile\_program - -Renames and re-exports [compile](functions/compile.md) - -## Interfaces - -### ContractCompilationArtifacts - -The compilation artifacts of a given contract. - -#### Properties - -| Property | Type | Description | -| :------ | :------ | :------ | -| `contract` | `ContractArtifact` | The compiled contract. | -| `warnings` | `unknown`[] | Compilation warnings. | - -*** - -### ProgramCompilationArtifacts - -The compilation artifacts of a given program. - -#### Properties - -| Property | Type | Description | -| :------ | :------ | :------ | -| `name` | `string` | not part of the compilation output, injected later | -| `program` | `ProgramArtifact` | The compiled contract. | -| `warnings` | `unknown`[] | Compilation warnings. | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs deleted file mode 100644 index e0870710349..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"doc","id":"reference/NoirJS/noir_wasm/index","label":"API"},{"type":"category","label":"Functions","items":[{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/compile","label":"compile"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/compile_contract","label":"compile_contract"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/createFileManager","label":"createFileManager"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/inflateDebugSymbols","label":"inflateDebugSymbols"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/_category_.json deleted file mode 100644 index 5b6a20a609a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 4, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/nargo_commands.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/nargo_commands.md deleted file mode 100644 index 218fcfb0c8c..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/nargo_commands.md +++ /dev/null @@ -1,381 +0,0 @@ ---- -title: Nargo -description: - Noir CLI Commands for Noir Prover and Verifier to create, execute, prove and verify programs, - generate Solidity verifier smart contract and compile into JSON file containing ACIR - representation and ABI of circuit. -keywords: - [ - Nargo, - Noir CLI, - Noir Prover, - Noir Verifier, - generate Solidity verifier, - compile JSON file, - ACIR representation, - ABI of circuit, - TypeScript, - ] -sidebar_position: 0 ---- - -# Command-Line Help for `nargo` - -This document contains the help content for the `nargo` command-line program. - -**Command Overview:** - -* [`nargo`↴](#nargo) -* [`nargo backend`↴](#nargo-backend) -* [`nargo backend current`↴](#nargo-backend-current) -* [`nargo backend ls`↴](#nargo-backend-ls) -* [`nargo backend use`↴](#nargo-backend-use) -* [`nargo backend install`↴](#nargo-backend-install) -* [`nargo backend uninstall`↴](#nargo-backend-uninstall) -* [`nargo check`↴](#nargo-check) -* [`nargo fmt`↴](#nargo-fmt) -* [`nargo codegen-verifier`↴](#nargo-codegen-verifier) -* [`nargo compile`↴](#nargo-compile) -* [`nargo new`↴](#nargo-new) -* [`nargo init`↴](#nargo-init) -* [`nargo execute`↴](#nargo-execute) -* [`nargo prove`↴](#nargo-prove) -* [`nargo verify`↴](#nargo-verify) -* [`nargo test`↴](#nargo-test) -* [`nargo info`↴](#nargo-info) -* [`nargo lsp`↴](#nargo-lsp) - -## `nargo` - -Noir's package manager - -**Usage:** `nargo ` - -###### **Subcommands:** - -* `backend` — Install and select custom backends used to generate and verify proofs -* `check` — Checks the constraint system for errors -* `fmt` — Format the Noir files in a workspace -* `codegen-verifier` — Generates a Solidity verifier smart contract for the program -* `compile` — Compile the program and its secret execution trace into ACIR format -* `new` — Create a Noir project in a new directory -* `init` — Create a Noir project in the current directory -* `execute` — Executes a circuit to calculate its return value -* `prove` — Create proof for this program. The proof is returned as a hex encoded string -* `verify` — Given a proof and a program, verify whether the proof is valid -* `test` — Run the tests for this program -* `info` — Provides detailed information on each of a program's function (represented by a single circuit) -* `lsp` — Starts the Noir LSP server - -###### **Options:** - - - - -## `nargo backend` - -Install and select custom backends used to generate and verify proofs - -**Usage:** `nargo backend ` - -###### **Subcommands:** - -* `current` — Prints the name of the currently active backend -* `ls` — Prints the list of currently installed backends -* `use` — Select the backend to use -* `install` — Install a new backend from a URL -* `uninstall` — Uninstalls a backend - - - -## `nargo backend current` - -Prints the name of the currently active backend - -**Usage:** `nargo backend current` - - - -## `nargo backend ls` - -Prints the list of currently installed backends - -**Usage:** `nargo backend ls` - - - -## `nargo backend use` - -Select the backend to use - -**Usage:** `nargo backend use ` - -###### **Arguments:** - -* `` - - - -## `nargo backend install` - -Install a new backend from a URL - -**Usage:** `nargo backend install ` - -###### **Arguments:** - -* `` — The name of the backend to install -* `` — The URL from which to download the backend - - - -## `nargo backend uninstall` - -Uninstalls a backend - -**Usage:** `nargo backend uninstall ` - -###### **Arguments:** - -* `` — The name of the backend to uninstall - - - -## `nargo check` - -Checks the constraint system for errors - -**Usage:** `nargo check [OPTIONS]` - -###### **Options:** - -* `--package ` — The name of the package to check -* `--workspace` — Check all packages in the workspace -* `--overwrite` — Force overwrite of existing files -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings - - - -## `nargo fmt` - -Format the Noir files in a workspace - -**Usage:** `nargo fmt [OPTIONS]` - -###### **Options:** - -* `--check` — Run noirfmt in check mode - - - -## `nargo codegen-verifier` - -Generates a Solidity verifier smart contract for the program - -**Usage:** `nargo codegen-verifier [OPTIONS]` - -###### **Options:** - -* `--package ` — The name of the package to codegen -* `--workspace` — Codegen all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings - - - -## `nargo compile` - -Compile the program and its secret execution trace into ACIR format - -**Usage:** `nargo compile [OPTIONS]` - -###### **Options:** - -* `--package ` — The name of the package to compile -* `--workspace` — Compile all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings - - - -## `nargo new` - -Create a Noir project in a new directory - -**Usage:** `nargo new [OPTIONS] ` - -###### **Arguments:** - -* `` — The path to save the new project - -###### **Options:** - -* `--name ` — Name of the package [default: package directory name] -* `--lib` — Use a library template -* `--bin` — Use a binary template [default] -* `--contract` — Use a contract template - - - -## `nargo init` - -Create a Noir project in the current directory - -**Usage:** `nargo init [OPTIONS]` - -###### **Options:** - -* `--name ` — Name of the package [default: current directory name] -* `--lib` — Use a library template -* `--bin` — Use a binary template [default] -* `--contract` — Use a contract template - - - -## `nargo execute` - -Executes a circuit to calculate its return value - -**Usage:** `nargo execute [OPTIONS] [WITNESS_NAME]` - -###### **Arguments:** - -* `` — Write the execution witness to named file - -###### **Options:** - -* `-p`, `--prover-name ` — The name of the toml file which contains the inputs for the prover - - Default value: `Prover` -* `--package ` — The name of the package to execute -* `--workspace` — Execute all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings -* `--oracle-resolver ` — JSON RPC url to solve oracle calls - - - -## `nargo prove` - -Create proof for this program. The proof is returned as a hex encoded string - -**Usage:** `nargo prove [OPTIONS]` - -###### **Options:** - -* `-p`, `--prover-name ` — The name of the toml file which contains the inputs for the prover - - Default value: `Prover` -* `-v`, `--verifier-name ` — The name of the toml file which contains the inputs for the verifier - - Default value: `Verifier` -* `--verify` — Verify proof after proving -* `--package ` — The name of the package to prove -* `--workspace` — Prove all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings -* `--oracle-resolver ` — JSON RPC url to solve oracle calls - - - -## `nargo verify` - -Given a proof and a program, verify whether the proof is valid - -**Usage:** `nargo verify [OPTIONS]` - -###### **Options:** - -* `-v`, `--verifier-name ` — The name of the toml file which contains the inputs for the verifier - - Default value: `Verifier` -* `--package ` — The name of the package verify -* `--workspace` — Verify all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings - - - -## `nargo test` - -Run the tests for this program - -**Usage:** `nargo test [OPTIONS] [TEST_NAME]` - -###### **Arguments:** - -* `` — If given, only tests with names containing this string will be run - -###### **Options:** - -* `--show-output` — Display output of `println` statements -* `--exact` — Only run tests that match exactly -* `--package ` — The name of the package to test -* `--workspace` — Test all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings -* `--oracle-resolver ` — JSON RPC url to solve oracle calls - - - -## `nargo info` - -Provides detailed information on each of a program's function (represented by a single circuit) - -Current information provided per circuit: 1. The number of ACIR opcodes 2. Counts the final number gates in the circuit used by a backend - -**Usage:** `nargo info [OPTIONS]` - -###### **Options:** - -* `--package ` — The name of the package to detail -* `--workspace` — Detail all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings - - - -## `nargo lsp` - -Starts the Noir LSP server - -Starts an LSP server which allows IDEs such as VS Code to display diagnostics in Noir source. - -VS Code Noir Language Support: https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir - -**Usage:** `nargo lsp` - - - -
- - - This document was generated automatically by - clap-markdown. - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/tooling/language_server.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/tooling/language_server.md deleted file mode 100644 index 81e0356ef8a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/tooling/language_server.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Language Server -description: Learn about the Noir Language Server, how to install the components, and configuration that may be required. -keywords: [Nargo, Language Server, LSP, VSCode, Visual Studio Code] -sidebar_position: 0 ---- - -This section helps you install and configure the Noir Language Server. - -The Language Server Protocol (LSP) has two components, the [Server](#language-server) and the [Client](#language-client). Below we describe each in the context of Noir. - -## Language Server - -The Server component is provided by the Nargo command line tool that you installed at the beginning of this guide. -As long as Nargo is installed and you've used it to run other commands in this guide, it should be good to go! - -If you'd like to verify that the `nargo lsp` command is available, you can run `nargo --help` and look for `lsp` in the list of commands. If you see it, you're using a version of Noir with LSP support. - -## Language Client - -The Client component is usually an editor plugin that launches the Server. It communicates LSP messages between the editor and the Server. For example, when you save a file, the Client will alert the Server, so it can try to compile the project and report any errors. - -Currently, Noir provides a Language Client for Visual Studio Code via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). - -> **Note:** Noir's Language Server Protocol support currently assumes users' VSCode workspace root to be the same as users' Noir project root (i.e. where Nargo.toml lies). -> -> If LSP features seem to be missing / malfunctioning, make sure you are opening your Noir project directly (instead of as a sub-folder) in your VSCode instance. - -When your language server is running correctly and the VSCode plugin is installed, you should see handy codelens buttons for compilation, measuring circuit size, execution, and tests: - -![Compile and Execute](@site/static/img/codelens_compile_execute.png) -![Run test](@site/static/img/codelens_run_test.png) - -You should also see your tests in the `testing` panel: - -![Testing panel](@site/static/img/codelens_testing_panel.png) - -### Configuration - -- **Noir: Enable LSP** - If checked, the extension will launch the Language Server via `nargo lsp` and communicate with it. -- **Noir: Nargo Flags** - Additional flags may be specified if you require them to be added when the extension calls `nargo lsp`. -- **Noir: Nargo Path** - An absolute path to a Nargo binary with the `lsp` command. This may be useful if Nargo is not within the `PATH` of your editor. -- **Noir > Trace: Server** - Setting this to `"messages"` or `"verbose"` will log LSP messages between the Client and Server. Useful for debugging. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/tooling/testing.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/tooling/testing.md deleted file mode 100644 index d3e0c522473..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/tooling/testing.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -title: Testing in Noir -description: Learn how to use Nargo to test your Noir program in a quick and easy way -keywords: [Nargo, testing, Noir, compile, test] -sidebar_position: 1 ---- - -You can test your Noir programs using Noir circuits. - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. - -For example if you have a program like: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test] -fn test_add() { - assert(add(2,2) == 4); - assert(add(0,1) == 1); - assert(add(1,0) == 1); -} -``` - -Running `nargo test` will test that the `test_add` function can be executed while satisfying all -the constraints which allows you to test that add returns the expected values. Test functions can't -have any arguments currently. - -### Test fail - -You can write tests that are expected to fail by using the decorator `#[test(should_fail)]`. For example: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test(should_fail)] -fn test_add() { - assert(add(2,2) == 5); -} -``` - -You can be more specific and make it fail with a specific reason by using `should_fail_with = "`: - -```rust -fn main(african_swallow_avg_speed : Field) { - assert(african_swallow_avg_speed == 65, "What is the airspeed velocity of an unladen swallow"); -} - -#[test] -fn test_king_arthur() { - main(65); -} - -#[test(should_fail_with = "What is the airspeed velocity of an unladen swallow")] -fn test_bridgekeeper() { - main(32); -} - -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/tutorials/noirjs_app.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/tutorials/noirjs_app.md deleted file mode 100644 index 3dd9fe7d2b0..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/tutorials/noirjs_app.md +++ /dev/null @@ -1,326 +0,0 @@ ---- -title: Building a web app with NoirJS -description: Learn how to setup a new app that uses Noir to generate and verify zero-knowledge SNARK proofs in a typescript or javascript environment. -keywords: [how to, guide, javascript, typescript, noir, barretenberg, zero-knowledge, proofs, app] -sidebar_position: 0 -pagination_next: noir/concepts/data_types/index ---- - -NoirJS is a set of packages meant to work both in a browser and a server environment. In this tutorial, we will build a simple web app using them. From here, you should get an idea on how to proceed with your own Noir projects! - -You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). - -## Setup - -:::note - -Feel free to use whatever versions, just keep in mind that Nargo and the NoirJS packages are meant to be in sync. For example, Nargo 0.27.x matches `noir_js@0.27.x`, etc. - -In this guide, we will be pinned to 0.27.0. - -::: - -Before we start, we want to make sure we have Node and Nargo installed. - -We start by opening a terminal and executing `node --version`. If we don't get an output like `v20.10.0`, that means node is not installed. Let's do that by following the handy [nvm guide](https://github.com/nvm-sh/nvm?tab=readme-ov-file#install--update-script). - -As for `Nargo`, we can follow the [Nargo guide](../getting_started/installation/index.md) to install it. If you're lazy, just paste this on a terminal and run `noirup`: - -```sh -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -Easy enough. Onwards! - -## Our project - -ZK is a powerful technology. An app that doesn't reveal one of the inputs to _anyone_ is almost unbelievable, yet Noir makes it as easy as a single line of code. - -In fact, it's so simple that it comes nicely packaged in `nargo`. Let's do that! - -### Nargo - -Run: - -`nargo new circuit` - -And... That's about it. Your program is ready to be compiled and run. - -To compile, let's `cd` into the `circuit` folder to enter our project, and call: - -`nargo compile` - -This compiles our circuit into `json` format and add it to a new `target` folder. - -:::info - -At this point in the tutorial, your folder structure should look like this: - -```tree -. -└── circuit <---- our working directory - ├── Nargo.toml - ├── src - │ └── main.nr - └── target - └── circuit.json -``` - -::: - -### Node and Vite - -If you want to explore Nargo, feel free to go on a side-quest now and follow the steps in the -[getting started](../getting_started/hello_noir/index.md) guide. However, we want our app to run on the browser, so we need Vite. - -Vite is a powerful tool to generate static websites. While it provides all kinds of features, let's just go barebones with some good old vanilla JS. - -To do this this, go back to the previous folder (`cd ..`) and create a new vite project by running `npm create vite` and choosing "Vanilla" and "Javascript". - -A wild `vite-project` directory should now appear in your root folder! Let's not waste any time and dive right in: - -```bash -cd vite-project -``` - -### Setting Up Vite and Configuring the Project - -Before we proceed with any coding, let's get our environment tailored for Noir. We'll start by laying down the foundations with a `vite.config.js` file. This little piece of configuration is our secret sauce for making sure everything meshes well with the NoirJS libraries and other special setups we might need, like handling WebAssembly modules. Here’s how you get that going: - -#### Creating the vite.config.js - -In your freshly minted `vite-project` folder, create a new file named `vite.config.js` and open it in your code editor. Paste the following to set the stage: - -```javascript -import { defineConfig } from "vite"; -import copy from "rollup-plugin-copy"; - -export default defineConfig({ - esbuild: { - target: "esnext", - }, - optimizeDeps: { - esbuildOptions: { - target: "esnext", - }, - }, - plugins: [ - copy({ - targets: [ - { src: "node_modules/**/*.wasm", dest: "node_modules/.vite/dist" }, - ], - copySync: true, - hook: "buildStart", - }), - ], - server: { - port: 3000, - }, -}); -``` - -#### Install Dependencies - -Now that our stage is set, install the necessary NoirJS packages along with our other dependencies: - -```bash -npm install && npm install @noir-lang/backend_barretenberg@0.27.0 @noir-lang/noir_js@0.27.0 -npm install rollup-plugin-copy --save-dev -``` - -:::info - -At this point in the tutorial, your folder structure should look like this: - -```tree -. -└── circuit - └── ...etc... -└── vite-project <---- our working directory - └── ...etc... -``` - -::: - -#### Some cleanup - -`npx create vite` is amazing but it creates a bunch of files we don't really need for our simple example. Actually, let's just delete everything except for `vite.config.js`, `index.html`, `main.js` and `package.json`. I feel lighter already. - -![my heart is ready for you, noir.js](@site/static/img/memes/titanic.jpeg) - -## HTML - -Our app won't run like this, of course. We need some working HTML, at least. Let's open our broken-hearted `index.html` and replace everything with this code snippet: - -```html - - - - - - -

Noir app

-
- - -
-
-

Logs

-

Proof

-
- - -``` - -It _could_ be a beautiful UI... Depending on which universe you live in. - -## Some good old vanilla Javascript - -Our love for Noir needs undivided attention, so let's just open `main.js` and delete everything (this is where the romantic scenery becomes a bit creepy). - -Start by pasting in this boilerplate code: - -```js -const setup = async () => { - await Promise.all([ - import('@noir-lang/noirc_abi').then((module) => - module.default(new URL('@noir-lang/noirc_abi/web/noirc_abi_wasm_bg.wasm', import.meta.url).toString()), - ), - import('@noir-lang/acvm_js').then((module) => - module.default(new URL('@noir-lang/acvm_js/web/acvm_js_bg.wasm', import.meta.url).toString()), - ), - ]); -}; - -function display(container, msg) { - const c = document.getElementById(container); - const p = document.createElement('p'); - p.textContent = msg; - c.appendChild(p); -} - -document.getElementById('submitGuess').addEventListener('click', async () => { - try { - // here's where love happens - } catch (err) { - display('logs', 'Oh 💔 Wrong guess'); - } -}); -``` - -The display function doesn't do much. We're simply manipulating our website to see stuff happening. For example, if the proof fails, it will simply log a broken heart 😢 - -As for the `setup` function, it's just a sad reminder that dealing with `wasm` on the browser is not as easy as it should. Just copy, paste, and forget. - -:::info - -At this point in the tutorial, your folder structure should look like this: - -```tree -. -└── circuit - └── ...same as above -└── vite-project - ├── vite.config.js - ├── main.js - ├── package.json - └── index.html -``` - -You'll see other files and folders showing up (like `package-lock.json`, `node_modules`) but you shouldn't have to care about those. - -::: - -## Some NoirJS - -We're starting with the good stuff now. If you've compiled the circuit as described above, you should have a `json` file we want to import at the very top of our `main.js` file: - -```ts -import circuit from '../circuit/target/circuit.json'; -``` - -[Noir is backend-agnostic](../index.mdx#whats-new-about-noir). We write Noir, but we also need a proving backend. That's why we need to import and instantiate the two dependencies we installed above: `BarretenbergBackend` and `Noir`. Let's import them right below: - -```js -import { BarretenbergBackend, BarretenbergVerifier as Verifier } from '@noir-lang/backend_barretenberg'; -import { Noir } from '@noir-lang/noir_js'; -``` - -And instantiate them inside our try-catch block: - -```ts -// try { -const backend = new BarretenbergBackend(circuit); -const noir = new Noir(circuit, backend); -// } -``` - -:::note - -For the remainder of the tutorial, everything will be happening inside the `try` block - -::: - -## Our app - -Now for the app itself. We're capturing whatever is in the input when people press the submit button. Just add this: - -```js -const x = parseInt(document.getElementById('guessInput').value); -const input = { x, y: 2 }; -``` - -Now we're ready to prove stuff! Let's feed some inputs to our circuit and calculate the proof: - -```js -await setup(); // let's squeeze our wasm inits here - -display('logs', 'Generating proof... ⌛'); -const proof = await noir.generateProof(input); -display('logs', 'Generating proof... ✅'); -display('results', proof.proof); -``` - -You're probably eager to see stuff happening, so go and run your app now! - -From your terminal, run `npm run dev`. If it doesn't open a browser for you, just visit `localhost:5173`. You should now see the worst UI ever, with an ugly input. - -![Getting Started 0](@site/static/img/noir_getting_started_1.png) - -Now, our circuit says `fn main(x: Field, y: pub Field)`. This means only the `y` value is public, and it's hardcoded above: `input = { x, y: 2 }`. In other words, you won't need to send your secret`x` to the verifier! - -By inputting any number other than 2 in the input box and clicking "submit", you should get a valid proof. Otherwise the proof won't even generate correctly. By the way, if you're human, you shouldn't be able to understand anything on the "proof" box. That's OK. We like you, human ❤️. - -## Verifying - -Time to celebrate, yes! But we shouldn't trust machines so blindly. Let's add these lines to see our proof being verified: - -```js -display('logs', 'Verifying proof... ⌛'); -const verificationKey = await backend.getVerificationKey(); -const verifier = new Verifier(); -const isValid = await verifier.verifyProof(proof, verificationKey); -if (isValid) display('logs', 'Verifying proof... ✅'); -``` - -You have successfully generated a client-side Noir web app! - -![coded app without math knowledge](@site/static/img/memes/flextape.jpeg) - -## Further Reading - -You can see how noirjs is used in a full stack Next.js hardhat application in the [noir-starter repo here](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat). The example shows how to calculate a proof in the browser and verify it with a deployed Solidity verifier contract from noirjs. - -You should also check out the more advanced examples in the [noir-examples repo](https://github.com/noir-lang/noir-examples), where you'll find reference usage for some cool apps. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/explainers/explainer-oracle.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/explainers/explainer-oracle.md deleted file mode 100644 index b84ca5dd986..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/explainers/explainer-oracle.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: Oracles -description: This guide provides an in-depth understanding of how Oracles work in Noir programming. Learn how to use outside calculations in your programs, constrain oracles, and understand their uses and limitations. -keywords: - - Noir Programming - - Oracles - - JSON-RPC - - Foreign Call Handlers - - Constrained Functions - - Blockchain Programming -sidebar_position: 1 ---- - -If you've seen "The Matrix" you may recall "The Oracle" as Gloria Foster smoking cigarettes and baking cookies. While she appears to "know things", she is actually providing a calculation of a pre-determined future. Noir Oracles are similar, in a way. They don't calculate the future (yet), but they allow you to use outside calculations in your programs. - -![matrix oracle prediction](@site/static/img/memes/matrix_oracle.jpeg) - -A Noir program is usually self-contained. You can pass certain inputs to it, and it will generate a deterministic output for those inputs. But what if you wanted to defer some calculation to an outside process or source? - -Oracles are functions that provide this feature. - -## Use cases - -An example usage for Oracles is proving something on-chain. For example, proving that the ETH-USDC quote was below a certain target at a certain block time. Or even making more complex proofs like proving the ownership of an NFT as an anonymous login method. - -Another interesting use case is to defer expensive calculations to be made outside of the Noir program, and then constraining the result; similar to the use of [unconstrained functions](../noir/concepts//unconstrained.md). - -In short, anything that can be constrained in a Noir program but needs to be fetched from an external source is a great candidate to be used in oracles. - -## Constraining oracles - -Just like in The Matrix, Oracles are powerful. But with great power, comes great responsibility. Just because you're using them in a Noir program doesn't mean they're true. Noir has no superpowers. If you want to prove that Portugal won the Euro Cup 2016, you're still relying on potentially untrusted information. - -To give a concrete example, Alice wants to login to the [NounsDAO](https://nouns.wtf/) forum with her username "noir_nouner" by proving she owns a noun without revealing her ethereum address. Her Noir program could have a oracle call like this: - -```rust -#[oracle(getNoun)] -unconstrained fn get_noun(address: Field) -> Field -``` - -This oracle could naively resolve with the number of Nouns she possesses. However, it is useless as a trusted source, as the oracle could resolve to anything Alice wants. In order to make this oracle call actually useful, Alice would need to constrain the response from the oracle, by proving her address and the noun count belongs to the state tree of the contract. - -In short, **Oracles don't prove anything. Your Noir program does.** - -:::danger - -If you don't constrain the return of your oracle, you could be clearly opening an attack vector on your Noir program. Make double-triple sure that the return of an oracle call is constrained! - -::: - -## How to use Oracles - -On CLI, Nargo resolves oracles by making JSON RPC calls, which means it would require an RPC node to be running. - -In JavaScript, NoirJS accepts and resolves arbitrary call handlers (that is, not limited to JSON) as long as they matches the expected types the developer defines. Refer to [Foreign Call Handler](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) to learn more about NoirJS's call handling. - -If you want to build using oracles, follow through to the [oracle guide](../how_to/how-to-oracles.md) for a simple example on how to do that. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/explainers/explainer-recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/explainers/explainer-recursion.md deleted file mode 100644 index 18846176ca7..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/explainers/explainer-recursion.md +++ /dev/null @@ -1,176 +0,0 @@ ---- -title: Recursive proofs -description: Explore the concept of recursive proofs in Zero-Knowledge programming. Understand how recursion works in Noir, a language for writing smart contracts on the EVM blockchain. Learn through practical examples like Alice and Bob's guessing game, Charlie's recursive merkle tree, and Daniel's reusable components. Discover how to use recursive proofs to optimize computational resources and improve efficiency. - -keywords: - [ - "Recursive Proofs", - "Zero-Knowledge Programming", - "Noir", - "EVM Blockchain", - "Smart Contracts", - "Recursion in Noir", - "Alice and Bob Guessing Game", - "Recursive Merkle Tree", - "Reusable Components", - "Optimizing Computational Resources", - "Improving Efficiency", - "Verification Key", - "Aggregation", - "Recursive zkSNARK schemes", - "PLONK", - "Proving and Verification Keys" - ] -sidebar_position: 1 -pagination_next: how_to/how-to-recursion ---- - -In programming, we tend to think of recursion as something calling itself. A classic example would be the calculation of the factorial of a number: - -```js -function factorial(n) { - if (n === 0 || n === 1) { - return 1; - } else { - return n * factorial(n - 1); - } -} -``` - -In this case, while `n` is not `1`, this function will keep calling itself until it hits the base case, bubbling up the result on the call stack: - -```md - Is `n` 1? <--------- - /\ / - / \ n = n -1 - / \ / - Yes No -------- -``` - -In Zero-Knowledge, recursion has some similarities. - -It is not a Noir function calling itself, but a proof being used as an input to another circuit. In short, you verify one proof *inside* another proof, returning the proof that both proofs are valid. - -This means that, given enough computational resources, you can prove the correctness of any arbitrary number of proofs in a single proof. This could be useful to design state channels (for which a common example would be [Bitcoin's Lightning Network](https://en.wikipedia.org/wiki/Lightning_Network)), to save on gas costs by settling one proof on-chain, or simply to make business logic less dependent on a consensus mechanism. - -## Examples - -Let us look at some of these examples - -### Alice and Bob - Guessing game - -Alice and Bob are friends, and they like guessing games. They want to play a guessing game online, but for that, they need a trusted third-party that knows both of their secrets and finishes the game once someone wins. - -So, they use zero-knowledge proofs. Alice tries to guess Bob's number, and Bob will generate a ZK proof stating whether she succeeded or failed. - -This ZK proof can go on a smart contract, revealing the winner and even giving prizes. However, this means every turn needs to be verified on-chain. This incurs some cost and waiting time that may simply make the game too expensive or time-consuming to be worth it. - -As a solution, Alice proposes the following: "what if Bob generates his proof, and instead of sending it on-chain, I verify it *within* my own proof before playing my own turn?". - -She can then generate a proof that she verified his proof, and so on. - -```md - Did you fail? <-------------------------- - / \ / - / \ n = n -1 - / \ / - Yes No / - | | / - | | / - | You win / - | / - | / -Generate proof of that / - + / - my own guess ---------------- -``` - -### Charlie - Recursive merkle tree - -Charlie is a concerned citizen, and wants to be sure his vote in an election is accounted for. He votes with a ZK proof, but he has no way of knowing that his ZK proof was included in the total vote count! - -If the vote collector puts all of the votes into a [Merkle tree](https://en.wikipedia.org/wiki/Merkle_tree), everyone can prove the verification of two proofs within one proof, as such: - -```md - abcd - __________|______________ - | | - ab cd - _____|_____ ______|______ - | | | | - alice bob charlie daniel -``` - -Doing this recursively allows us to arrive on a final proof `abcd` which if true, verifies the correctness of all the votes. - -### Daniel - Reusable components - -Daniel has a big circuit and a big headache. A part of his circuit is a setup phase that finishes with some assertions that need to be made. But that section alone takes most of the proving time, and is largely independent of the rest of the circuit. - -He might find it more efficient to generate a proof for that setup phase separately, and verify that proof recursively in the actual business logic section of his circuit. This will allow for parallelization of both proofs, which results in a considerable speedup. - -## What params do I need - -As you can see in the [recursion reference](noir/standard_library/recursion.md), a simple recursive proof requires: - -- The proof to verify -- The Verification Key of the circuit that generated the proof -- A hash of this verification key, as it's needed for some backends -- The public inputs for the proof - -:::info - -Recursive zkSNARK schemes do not necessarily "verify a proof" in the sense that you expect a true or false to be spit out by the verifier. Rather an aggregation object is built over the public inputs. - -So, taking the example of Alice and Bob and their guessing game: - -- Alice makes her guess. Her proof is *not* recursive: it doesn't verify any proof within it! It's just a standard `assert(x != y)` circuit -- Bob verifies Alice's proof and makes his own guess. In this circuit, he doesn't exactly *prove* the verification of Alice's proof. Instead, he *aggregates* his proof to Alice's proof. The actual verification is done when the full proof is verified, for example when using `nargo verify` or through the verifier smart contract. - -We can imagine recursive proofs a [relay race](https://en.wikipedia.org/wiki/Relay_race). The first runner doesn't have to receive the baton from anyone else, as he/she already starts with it. But when his/her turn is over, the next runner needs to receive it, run a bit more, and pass it along. Even though every runner could theoretically verify the baton mid-run (why not? 🏃🔍), only at the end of the race does the referee verify that the whole race is valid. - -::: - -## Some architecture - -As with everything in computer science, there's no one-size-fits all. But there are some patterns that could help understanding and implementing them. To give three examples: - -### Adding some logic to a proof verification - -This would be an approach for something like our guessing game, where proofs are sent back and forth and are verified by each opponent. This circuit would be divided in two sections: - -- A `recursive verification` section, which would be just the call to `std::verify_proof`, and that would be skipped on the first move (since there's no proof to verify) -- A `guessing` section, which is basically the logic part where the actual guessing happens - -In such a situation, and assuming Alice is first, she would skip the first part and try to guess Bob's number. Bob would then verify her proof on the first section of his run, and try to guess Alice's number on the second part, and so on. - -### Aggregating proofs - -In some one-way interaction situations, recursion would allow for aggregation of simple proofs that don't need to be immediately verified on-chain or elsewhere. - -To give a practical example, a barman wouldn't need to verify a "proof-of-age" on-chain every time he serves alcohol to a customer. Instead, the architecture would comprise two circuits: - -- A `main`, non-recursive circuit with some logic -- A `recursive` circuit meant to verify two proofs in one proof - -The customer's proofs would be intermediate, and made on their phones, and the barman could just verify them locally. He would then aggregate them into a final proof sent on-chain (or elsewhere) at the end of the day. - -### Recursively verifying different circuits - -Nothing prevents you from verifying different circuits in a recursive proof, for example: - -- A `circuit1` circuit -- A `circuit2` circuit -- A `recursive` circuit - -In this example, a regulator could verify that taxes were paid for a specific purchase by aggregating both a `payer` circuit (proving that a purchase was made and taxes were paid), and a `receipt` circuit (proving that the payment was received) - -## How fast is it - -At the time of writing, verifying recursive proofs is surprisingly fast. This is because most of the time is spent on generating the verification key that will be used to generate the next proof. So you are able to cache the verification key and reuse it later. - -Currently, Noir JS packages don't expose the functionality of loading proving and verification keys, but that feature exists in the underlying `bb.js` package. - -## How can I try it - -Learn more about using recursion in Nargo and NoirJS in the [how-to guide](../how_to/how-to-recursion.md) and see a full example in [noir-examples](https://github.com/noir-lang/noir-examples). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/getting_started/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/getting_started/_category_.json deleted file mode 100644 index 5d694210bbf..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/getting_started/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 0, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/getting_started/hello_noir/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/getting_started/hello_noir/_category_.json deleted file mode 100644 index 23b560f610b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/getting_started/hello_noir/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 1, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/getting_started/hello_noir/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/getting_started/hello_noir/index.md deleted file mode 100644 index 743c4d8d634..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/getting_started/hello_noir/index.md +++ /dev/null @@ -1,142 +0,0 @@ ---- -title: Creating a Project -description: - Learn how to create and verify your first Noir program using Nargo, a programming language for - zero-knowledge proofs. -keywords: - [ - Nargo, - Noir, - zero-knowledge proofs, - programming language, - create Noir program, - verify Noir program, - step-by-step guide, - ] -sidebar_position: 1 - ---- - -Now that we have installed Nargo, it is time to make our first hello world program! - -## Create a Project Directory - -Noir code can live anywhere on your computer. Let us create a _projects_ folder in the home -directory to house our Noir programs. - -For Linux, macOS, and Windows PowerShell, create the directory and change directory into it by -running: - -```sh -mkdir ~/projects -cd ~/projects -``` - -## Create Our First Nargo Project - -Now that we are in the projects directory, create a new Nargo project by running: - -```sh -nargo new hello_world -``` - -> **Note:** `hello_world` can be any arbitrary project name, we are simply using `hello_world` for -> demonstration. -> -> In production, the common practice is to name the project folder as `circuits` for better -> identifiability when sitting alongside other folders in the codebase (e.g. `contracts`, `scripts`, -> `test`). - -A `hello_world` folder would be created. Similar to Rust, the folder houses _src/main.nr_ and -_Nargo.toml_ which contain the source code and environmental options of your Noir program -respectively. - -### Intro to Noir Syntax - -Let us take a closer look at _main.nr_. The default _main.nr_ generated should look like this: - -```rust -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` - -The first line of the program specifies the program's inputs: - -```rust -x : Field, y : pub Field -``` - -Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the -keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](../../noir/concepts/data_types/index.md) section. - -The next line of the program specifies its body: - -```rust -assert(x != y); -``` - -The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. - -For more Noir syntax, check the [Language Concepts](../../noir/concepts/comments.md) chapter. - -## Build In/Output Files - -Change directory into _hello_world_ and build in/output files for your Noir program by running: - -```sh -cd hello_world -nargo check -``` - -Two additional files would be generated in your project directory: - -_Prover.toml_ houses input values, and _Verifier.toml_ houses public values. - -## Prove Our Noir Program - -Now that the project is set up, we can create a proof of correct execution of our Noir program. - -Fill in input values for execution in the _Prover.toml_ file. For example: - -```toml -x = "1" -y = "2" -``` - -Prove the valid execution of your Noir program: - -```sh -nargo prove -``` - -A new folder _proofs_ would then be generated in your project directory, containing the proof file -`.proof`, where the project name is defined in Nargo.toml. - -The _Verifier.toml_ file would also be updated with the public values computed from program -execution (in this case the value of `y`): - -```toml -y = "0x0000000000000000000000000000000000000000000000000000000000000002" -``` - -> **Note:** Values in _Verifier.toml_ are computed as 32-byte hex values. - -## Verify Our Noir Program - -Once a proof is generated, we can verify correct execution of our Noir program by verifying the -proof file. - -Verify your proof by running: - -```sh -nargo verify -``` - -The verification will complete in silence if it is successful. If it fails, it will log the -corresponding error instead. - -Congratulations, you have now created and verified a proof for your very first Noir program! - -In the [next section](./project_breakdown.md), we will go into more detail on each step performed. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/getting_started/hello_noir/project_breakdown.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/getting_started/hello_noir/project_breakdown.md deleted file mode 100644 index 6160a102c6c..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/getting_started/hello_noir/project_breakdown.md +++ /dev/null @@ -1,199 +0,0 @@ ---- -title: Project Breakdown -description: - Learn about the anatomy of a Nargo project, including the purpose of the Prover and Verifier TOML - files, and how to prove and verify your program. -keywords: - [Nargo, Nargo project, Prover.toml, Verifier.toml, proof verification, private asset transfer] -sidebar_position: 2 ---- - -This section breaks down our hello world program from the previous section. We elaborate on the project -structure and what the `prove` and `verify` commands did. - -## Anatomy of a Nargo Project - -Upon creating a new project with `nargo new` and building the in/output files with `nargo check` -commands, you would get a minimal Nargo project of the following structure: - - - src - - Prover.toml - - Verifier.toml - - Nargo.toml - -The source directory _src_ holds the source code for your Noir program. By default only a _main.nr_ -file will be generated within it. - -### Prover.toml - -_Prover.toml_ is used for specifying the input values for executing and proving the program. You can specify `toml` files with different names by using the `--prover-name` or `-p` flags, see the [Prover](#provertoml) section below. Optionally you may specify expected output values for prove-time checking as well. - -### Verifier.toml - -_Verifier.toml_ contains public in/output values computed when executing the Noir program. - -### Nargo.toml - -_Nargo.toml_ contains the environmental options of your project. It contains a "package" section and a "dependencies" section. - -Example Nargo.toml: - -```toml -[package] -name = "noir_starter" -type = "bin" -authors = ["Alice"] -compiler_version = "0.9.0" -description = "Getting started with Noir" -entry = "circuit/main.nr" -license = "MIT" - -[dependencies] -ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} -``` - -Nargo.toml for a [workspace](../../noir/modules_packages_crates/workspaces.md) will look a bit different. For example: - -```toml -[workspace] -members = ["crates/a", "crates/b"] -default-member = "crates/a" -``` - -#### Package section - -The package section defines a number of fields including: - -- `name` (**required**) - the name of the package -- `type` (**required**) - can be "bin", "lib", or "contract" to specify whether its a binary, library or Aztec contract -- `authors` (optional) - authors of the project -- `compiler_version` - specifies the version of the compiler to use. This is enforced by the compiler and follow's [Rust's versioning](https://doc.rust-lang.org/cargo/reference/manifest.html#the-version-field), so a `compiler_version = 0.18.0` will enforce Nargo version 0.18.0, `compiler_version = ^0.18.0` will enforce anything above 0.18.0 but below 0.19.0, etc. For more information, see how [Rust handles these operators](https://docs.rs/semver/latest/semver/enum.Op.html) -- `description` (optional) -- `entry` (optional) - a relative filepath to use as the entry point into your package (overrides the default of `src/lib.nr` or `src/main.nr`) -- `backend` (optional) -- `license` (optional) - -#### Dependencies section - -This is where you will specify any dependencies for your project. See the [Dependencies page](../../noir/modules_packages_crates/dependencies.md) for more info. - -`./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or -verifier contract respectively. - -### main.nr - -The _main.nr_ file contains a `main` method, this method is the entry point into your Noir program. - -In our sample program, _main.nr_ looks like this: - -```rust -fn main(x : Field, y : Field) { - assert(x != y); -} -``` - -The parameters `x` and `y` can be seen as the API for the program and must be supplied by the -prover. Since neither `x` nor `y` is marked as public, the verifier does not supply any inputs, when -verifying the proof. - -The prover supplies the values for `x` and `y` in the _Prover.toml_ file. - -As for the program body, `assert` ensures that the condition to be satisfied (e.g. `x != y`) is -constrained by the proof of the execution of said program (i.e. if the condition was not met, the -verifier would reject the proof as an invalid proof). - -### Prover.toml - -The _Prover.toml_ file is a file which the prover uses to supply his witness values(both private and -public). - -In our hello world program the _Prover.toml_ file looks like this: - -```toml -x = "1" -y = "2" -``` - -When the command `nargo prove` is executed, two processes happen: - -1. Noir creates a proof that `x`, which holds the value of `1`, and `y`, which holds the value of `2`, - is not equal. This inequality constraint is due to the line `assert(x != y)`. - -2. Noir creates and stores the proof of this statement in the _proofs_ directory in a file called your-project.proof. So if your project is named "private_voting" (defined in the project Nargo.toml), the proof will be saved at `./proofs/private_voting.proof`. Opening this file will display the proof in hex format. - -#### Arrays of Structs - -The following code shows how to pass an array of structs to a Noir program to generate a proof. - -```rust -// main.nr -struct Foo { - bar: Field, - baz: Field, -} - -fn main(foos: [Foo; 3]) -> pub Field { - foos[2].bar + foos[2].baz -} -``` - -Prover.toml: - -```toml -[[foos]] # foos[0] -bar = 0 -baz = 0 - -[[foos]] # foos[1] -bar = 0 -baz = 0 - -[[foos]] # foos[2] -bar = 1 -baz = 2 -``` - -#### Custom toml files - -You can specify a `toml` file with a different name to use for proving by using the `--prover-name` or `-p` flags. - -This command looks for proof inputs in the default **Prover.toml** and generates the proof and saves it at `./proofs/.proof`: - -```bash -nargo prove -``` - -This command looks for proof inputs in the custom **OtherProver.toml** and generates proof and saves it at `./proofs/.proof`: - -```bash -nargo prove -p OtherProver -``` - -## Verifying a Proof - -When the command `nargo verify` is executed, two processes happen: - -1. Noir checks in the _proofs_ directory for a proof file with the project name (eg. test_project.proof) - -2. If that file is found, the proof's validity is checked - -> **Note:** The validity of the proof is linked to the current Noir program; if the program is -> changed and the verifier verifies the proof, it will fail because the proof is not valid for the -> _modified_ Noir program. - -In production, the prover and the verifier are usually two separate entities. A prover would -retrieve the necessary inputs, execute the Noir program, generate a proof and pass it to the -verifier. The verifier would then retrieve the public inputs, usually from external sources, and -verify the validity of the proof against it. - -Take a private asset transfer as an example: - -A person using a browser as the prover would retrieve private inputs locally (e.g. the user's private key) and -public inputs (e.g. the user's encrypted balance on-chain), compute the transfer, generate a proof -and submit it to the verifier smart contract. - -The verifier contract would then draw the user's encrypted balance directly from the blockchain and -verify the proof submitted against it. If the verification passes, additional functions in the -verifier contract could trigger (e.g. approve the asset transfer). - -Now that you understand the concepts, you'll probably want some editor feedback while you are writing more complex code. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/getting_started/installation/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/getting_started/installation/_category_.json deleted file mode 100644 index 0c02fb5d4d7..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/getting_started/installation/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "position": 0, - "label": "Install Nargo", - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/getting_started/installation/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/getting_started/installation/index.md deleted file mode 100644 index 4ef86aa5914..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/getting_started/installation/index.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Nargo Installation -description: - nargo is a command line tool for interacting with Noir programs. This page is a quick guide on how to install Nargo through the most common and easy method, noirup -keywords: [ - Nargo - Noir - Rust - Cargo - Noirup - Installation - Terminal Commands - Version Check - Nightlies - Specific Versions - Branches - Noirup Repository -] -pagination_next: getting_started/hello_noir/index ---- - -`nargo` is the one-stop-shop for almost everything related with Noir. The name comes from our love for Rust and its package manager `cargo`. - -With `nargo`, you can start new projects, compile, execute, prove, verify, test, generate solidity contracts, and do pretty much all that is available in Noir. - -Similarly to `rustup`, we also maintain an easy installation method that covers most machines: `noirup`. - -## Installing Noirup - -Open a terminal on your machine, and write: - -```bash -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -Close the terminal, open another one, and run - -```bash -noirup -``` - -Done. That's it. You should have the latest version working. You can check with `nargo --version`. - -You can also install nightlies, specific versions -or branches. Check out the [noirup repository](https://github.com/noir-lang/noirup) for more -information. - -Now we're ready to start working on [our first Noir program!](../hello_noir/index.md) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/getting_started/installation/other_install_methods.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/getting_started/installation/other_install_methods.md deleted file mode 100644 index 3634723562b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/getting_started/installation/other_install_methods.md +++ /dev/null @@ -1,102 +0,0 @@ ---- -title: Alternative Installations -description: There are different ways to install Nargo, the one-stop shop and command-line tool for developing Noir programs. This guide explains how to specify which version to install when using noirup, and using WSL for windows. -keywords: [ - Installation - Nargo - Noirup - Binaries - Compiling from Source - WSL for Windows - macOS - Linux - Nix - Direnv - Uninstalling Nargo - ] -sidebar_position: 1 ---- - -## Encouraged Installation Method: Noirup - -Noirup is the endorsed method for installing Nargo, streamlining the process of fetching binaries or compiling from source. It supports a range of options to cater to your specific needs, from nightly builds and specific versions to compiling from various sources. - -### Installing Noirup - -First, ensure you have `noirup` installed: - -```sh -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -### Fetching Binaries - -With `noirup`, you can easily switch between different Nargo versions, including nightly builds: - -- **Nightly Version**: Install the latest nightly build. - - ```sh - noirup --version nightly - ``` - -- **Specific Version**: Install a specific version of Nargo. - ```sh - noirup --version - ``` - -### Compiling from Source - -`noirup` also enables compiling Nargo from various sources: - -- **From a Specific Branch**: Install from the latest commit on a branch. - - ```sh - noirup --branch - ``` - -- **From a Fork**: Install from the main branch of a fork. - - ```sh - noirup --repo - ``` - -- **From a Specific Branch in a Fork**: Install from a specific branch in a fork. - - ```sh - noirup --repo --branch - ``` - -- **From a Specific Pull Request**: Install from a specific PR. - - ```sh - noirup --pr - ``` - -- **From a Specific Commit**: Install from a specific commit. - - ```sh - noirup -C - ``` - -- **From Local Source**: Compile and install from a local directory. - ```sh - noirup --path ./path/to/local/source - ``` - -## Installation on Windows - -The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed natively. However, it is available by using Windows Subsystem for Linux (WSL). - -Step 1: Follow the instructions [here](https://learn.microsoft.com/en-us/windows/wsl/install) to install and run WSL. - -step 2: Follow the [Noirup instructions](#encouraged-installation-method-noirup). - -## Uninstalling Nargo - -If you installed Nargo with `noirup`, you can uninstall Nargo by removing the files in `~/.nargo`, `~/nargo`, and `~/noir_cache`. This ensures that all installed binaries, configurations, and cache related to Nargo are fully removed from your system. - -```bash -rm -r ~/.nargo -rm -r ~/nargo -rm -r ~/noir_cache -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/getting_started/tooling/noir_codegen.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/getting_started/tooling/noir_codegen.md deleted file mode 100644 index d65151da0ab..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/getting_started/tooling/noir_codegen.md +++ /dev/null @@ -1,113 +0,0 @@ ---- -title: Noir Codegen for TypeScript -description: Learn how to use Noir codegen to generate TypeScript bindings -keywords: [Nargo, Noir, compile, TypeScript] -sidebar_position: 2 ---- - -When using TypeScript, it is extra work to interpret Noir program outputs in a type-safe way. Third party libraries may exist for popular Noir programs, but they are either hard to find or unmaintained. - -Now you can generate TypeScript bindings for your Noir programs in two steps: -1. Exporting Noir functions using `nargo export` -2. Using the TypeScript module `noir_codegen` to generate TypeScript binding - -**Note:** you can only export functions from a Noir *library* (not binary or contract program types). - -## Installation - -### Your TypeScript project - -If you don't already have a TypeScript project you can add the module with `yarn` (or `npm`), then initialize it: - -```bash -yarn add typescript -D -npx tsc --init -``` - -### Add TypeScript module - `noir_codegen` - -The following command will add the module to your project's devDependencies: - -```bash -yarn add @noir-lang/noir_codegen -D -``` - -### Nargo library -Make sure you have Nargo, v0.25.0 or greater, installed. If you don't, follow the [installation guide](../installation/index.md). - -If you're in a new project, make a `circuits` folder and create a new Noir library: - -```bash -mkdir circuits && cd circuits -nargo new --lib myNoirLib -``` - -## Usage - -### Export ABI of specified functions - -First go to the `.nr` files in your Noir library, and add the `#[export]` macro to each function that you want to use in TypeScript. - -```rust -#[export] -fn your_function(... -``` - -From your Noir library (where `Nargo.toml` is), run the following command: - -```bash -nargo export -``` - -You will now have an `export` directory with a .json file per exported function. - -You can also specify the directory of Noir programs using `--program-dir`, for example: - -```bash -nargo export --program-dir=./circuits/myNoirLib -``` - -### Generate TypeScript bindings from exported functions - -To use the `noir-codegen` package we added to the TypeScript project: - -```bash -yarn noir-codegen ./export/your_function.json -``` - -This creates an `exports` directory with an `index.ts` file containing all exported functions. - -**Note:** adding `--out-dir` allows you to specify an output dir for your TypeScript bindings to go. Eg: - -```bash -yarn noir-codegen ./export/*.json --out-dir ./path/to/output/dir -``` - -## Example .nr function to .ts output - -Consider a Noir library with this function: - -```rust -#[export] -fn not_equal(x: Field, y: Field) -> bool { - x != y -} -``` - -After the export and codegen steps, you should have an `index.ts` like: - -```typescript -export type Field = string; - - -export const is_equal_circuit: CompiledCircuit = {"abi":{"parameters":[{"name":"x","type":{"kind":"field"},"visibility":"private"},{"name":"y","type":{"kind":"field"},"visibility":"private"}],"param_witnesses":{"x":[{"start":0,"end":1}],"y":[{"start":1,"end":2}]},"return_type":{"abi_type":{"kind":"boolean"},"visibility":"private"},"return_witnesses":[4]},"bytecode":"H4sIAAAAAAAA/7WUMQ7DIAxFQ0Krrr2JjSGYLVcpKrn/CaqqDQN12WK+hPBgmWd/wEyHbF1SS923uhOs3pfoChI+wKXMAXzIKyNj4PB0TFTYc0w5RUjoqeAeEu1wqK0F54RGkWvW44LPzExnlkbMEs4JNZmN8PxS42uHv82T8a3Jeyn2Ks+VLPcO558HmyLMCDOXAXXtpPt4R/Rt9T36ss6dS9HGPx/eG17nGegKBQAA"}; - -export async function is_equal(x: Field, y: Field, foreignCallHandler?: ForeignCallHandler): Promise { - const program = new Noir(is_equal_circuit); - const args: InputMap = { x, y }; - const { returnValue } = await program.execute(args, foreignCallHandler); - return returnValue as boolean; -} -``` - -Now the `is_equal()` function and relevant types are readily available for use in TypeScript. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/how_to/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/how_to/_category_.json deleted file mode 100644 index 23b560f610b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/how_to/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 1, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/how_to/debugger/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/how_to/debugger/_category_.json deleted file mode 100644 index cc2cbb1c253..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/how_to/debugger/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Debugging", - "position": 5, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/how_to/debugger/debugging_with_the_repl.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/how_to/debugger/debugging_with_the_repl.md deleted file mode 100644 index 09e5bae68ad..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/how_to/debugger/debugging_with_the_repl.md +++ /dev/null @@ -1,164 +0,0 @@ ---- -title: Using the REPL Debugger -description: - Step by step guide on how to debug your Noir circuits with the REPL Debugger. -keywords: - [ - Nargo, - Noir CLI, - Noir Debugger, - REPL, - ] -sidebar_position: 1 ---- - -#### Pre-requisites - -In order to use the REPL debugger, first you need to install recent enough versions of Nargo and vscode-noir. - -## Debugging a simple circuit - -Let's debug a simple circuit: - -```rust -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` - -To start the REPL debugger, using a terminal, go to a Noir circuit's home directory. Then: - -`$ nargo debug` - -You should be seeing this in your terminal: - -``` -[main] Starting debugger -At ~/noir-examples/recursion/circuits/main/src/main.nr:1:9 - 1 -> fn main(x : Field, y : pub Field) { - 2 assert(x != y); - 3 } -> -``` - -The debugger displays the current Noir code location, and it is now waiting for us to drive it. - -Let's first take a look at the available commands. For that we'll use the `help` command. - -``` -> help -Available commands: - - opcodes display ACIR opcodes - into step into to the next opcode - next step until a new source location is reached - out step until a new source location is reached - and the current stack frame is finished - break LOCATION:OpcodeLocation add a breakpoint at an opcode location - over step until a new source location is reached - without diving into function calls - restart restart the debugging session - delete LOCATION:OpcodeLocation delete breakpoint at an opcode location - witness show witness map - witness index:u32 display a single witness from the witness map - witness index:u32 value:String update a witness with the given value - memset index:usize value:String update a memory cell with the given - value - continue continue execution until the end of the - program - vars show variable values available at this point - in execution - stacktrace display the current stack trace - memory show memory (valid when executing unconstrained code) - step step to the next ACIR opcode - -Other commands: - - help Show this help message - quit Quit repl - -``` - -Some commands operate only for unconstrained functions, such as `memory` and `memset`. If you try to use them while execution is paused at an ACIR opcode, the debugger will simply inform you that you are not executing unconstrained code: - -``` -> memory -Unconstrained VM memory not available -> -``` - -Before continuing, we can take a look at the initial witness map: - -``` -> witness -_0 = 1 -_1 = 2 -> -``` - -Cool, since `x==1`, `y==2`, and we want to check that `x != y`, our circuit should succeed. At this point we could intervene and use the witness setter command to change one of the witnesses. Let's set `y=3`, then back to 2, so we don't affect the expected result: - -``` -> witness -_0 = 1 -_1 = 2 -> witness 1 3 -_1 = 3 -> witness -_0 = 1 -_1 = 3 -> witness 1 2 -_1 = 2 -> witness -_0 = 1 -_1 = 2 -> -``` - -Now we can inspect the current state of local variables. For that we use the `vars` command. - -``` -> vars -> -``` - -We currently have no vars in context, since we are at the entry point of the program. Let's use `next` to execute until the next point in the program. - -``` -> vars -> next -At ~/noir-examples/recursion/circuits/main/src/main.nr:1:20 - 1 -> fn main(x : Field, y : pub Field) { - 2 assert(x != y); - 3 } -> vars -x:Field = 0x01 -``` - -As a result of stepping, the variable `x`, whose initial value comes from the witness map, is now in context and returned by `vars`. - -``` -> next - 1 fn main(x : Field, y : pub Field) { - 2 -> assert(x != y); - 3 } -> vars -y:Field = 0x02 -x:Field = 0x01 -``` - -Stepping again we can finally see both variables and their values. And now we can see that the next assertion should succeed. - -Let's continue to the end: - -``` -> continue -(Continuing execution...) -Finished execution -> q -[main] Circuit witness successfully solved -``` - -Upon quitting the debugger after a solved circuit, the resulting circuit witness gets saved, equivalent to what would happen if we had run the same circuit with `nargo execute`. - -We just went through the basics of debugging using Noir REPL debugger. For a comprehensive reference, check out [the reference page](../../reference/debugger/debugger_repl.md). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/how_to/debugger/debugging_with_vs_code.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/how_to/debugger/debugging_with_vs_code.md deleted file mode 100644 index a5858c1a5eb..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/how_to/debugger/debugging_with_vs_code.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -title: Using the VS Code Debugger -description: - Step by step guide on how to debug your Noir circuits with the VS Code Debugger configuration and features. -keywords: - [ - Nargo, - Noir CLI, - Noir Debugger, - VS Code, - IDE, - ] -sidebar_position: 0 ---- - -This guide will show you how to use VS Code with the vscode-noir extension to debug a Noir project. - -#### Pre-requisites - -- Nargo -- vscode-noir -- A Noir project with a `Nargo.toml`, `Prover.toml` and at least one Noir (`.nr`) containing an entry point function (typically `main`). - -## Running the debugger - -The easiest way to start debugging is to open the file you want to debug, and press `F5`. This will cause the debugger to launch, using your `Prover.toml` file as input. - -You should see something like this: - -![Debugger launched](@site/static/img/debugger/1-started.png) - -Let's inspect the state of the program. For that, we open VS Code's _Debug pane_. Look for this icon: - -![Debug pane icon](@site/static/img/debugger/2-icon.png) - -You will now see two categories of variables: Locals and Witness Map. - -![Debug pane expanded](@site/static/img/debugger/3-debug-pane.png) - -1. **Locals**: variables of your program. At this point in execution this section is empty, but as we step through the code it will get populated by `x`, `result`, `digest`, etc. - -2. **Witness map**: these are initially populated from your project's `Prover.toml` file. In this example, they will be used to populate `x` and `result` at the beginning of the `main` function. - -Most of the time you will probably be focusing mostly on locals, as they represent the high level state of your program. - -You might be interested in inspecting the witness map in case you are trying to solve a really low level issue in the compiler or runtime itself, so this concerns mostly advanced or niche users. - -Let's step through the program, by using the debugger buttons or their corresponding keyboard shortcuts. - -![Debugger buttons](@site/static/img/debugger/4-debugger-buttons.png) - -Now we can see in the variables pane that there's values for `digest`, `result` and `x`. - -![Inspecting locals](@site/static/img/debugger/5-assert.png) - -We can also inspect the values of variables by directly hovering on them on the code. - -![Hover locals](@site/static/img/debugger/6-hover.png) - -Let's set a break point at the `keccak256` function, so we can continue execution up to the point when it's first invoked without having to go one step at a time. - -We just need to click the to the right of the line number 18. Once the breakpoint appears, we can click the `continue` button or use its corresponding keyboard shortcut (`F5` by default). - -![Breakpoint](@site/static/img/debugger/7-break.png) - -Now we are debugging the `keccak256` function, notice the _Call Stack pane_ at the lower right. This lets us inspect the current call stack of our process. - -That covers most of the current debugger functionalities. Check out [the reference](../../reference/debugger/debugger_vscode.md) for more details on how to configure the debugger. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/how_to/how-to-oracles.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/how_to/how-to-oracles.md deleted file mode 100644 index 8cf8035a5c4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/how_to/how-to-oracles.md +++ /dev/null @@ -1,276 +0,0 @@ ---- -title: How to use Oracles -description: Learn how to use oracles in your Noir program with examples in both Nargo and NoirJS. This guide also covers writing a JSON RPC server and providing custom foreign call handlers for NoirJS. -keywords: - - Noir Programming - - Oracles - - Nargo - - NoirJS - - JSON RPC Server - - Foreign Call Handlers -sidebar_position: 1 ---- - -This guide shows you how to use oracles in your Noir program. For the sake of clarity, it assumes that: - -- You have read the [explainer on Oracles](../explainers/explainer-oracle.md) and are comfortable with the concept. -- You have a Noir program to add oracles to. You can create one using the [vite-hardhat starter](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat) as a boilerplate. -- You understand the concept of a JSON-RPC server. Visit the [JSON-RPC website](https://www.jsonrpc.org/) if you need a refresher. -- You are comfortable with server-side JavaScript (e.g. Node.js, managing packages, etc.). - -For reference, you can find the snippets used in this tutorial on the [Aztec DevRel Repository](https://github.com/AztecProtocol/dev-rel/tree/main/code-snippets/how-to-oracles). - -## Rundown - -This guide has 3 major steps: - -1. How to modify our Noir program to make use of oracle calls as unconstrained functions -2. How to write a JSON RPC Server to resolve these oracle calls with Nargo -3. How to use them in Nargo and how to provide a custom resolver in NoirJS - -## Step 1 - Modify your Noir program - -An oracle is defined in a Noir program by defining two methods: - -- An unconstrained method - This tells the compiler that it is executing an [unconstrained functions](../noir/concepts//unconstrained.md). -- A decorated oracle method - This tells the compiler that this method is an RPC call. - -An example of an oracle that returns a `Field` would be: - -```rust -#[oracle(getSqrt)] -unconstrained fn sqrt(number: Field) -> Field { } - -unconstrained fn get_sqrt(number: Field) -> Field { - sqrt(number) -} -``` - -In this example, we're wrapping our oracle function in a unconstrained method, and decorating it with `oracle(getSqrt)`. We can then call the unconstrained function as we would call any other function: - -```rust -fn main(input: Field) { - let sqrt = get_sqrt(input); -} -``` - -In the next section, we will make this `getSqrt` (defined on the `sqrt` decorator) be a method of the RPC server Noir will use. - -:::danger - -As explained in the [Oracle Explainer](../explainers/explainer-oracle.md), this `main` function is unsafe unless you constrain its return value. For example: - -```rust -fn main(input: Field) { - let sqrt = get_sqrt(input); - assert(sqrt.pow_32(2) as u64 == input as u64); // <---- constrain the return of an oracle! -} -``` - -::: - -:::info - -Currently, oracles only work with single params or array params. For example: - -```rust -#[oracle(getSqrt)] -unconstrained fn sqrt([Field; 2]) -> [Field; 2] { } -``` - -::: - -## Step 2 - Write an RPC server - -Brillig will call *one* RPC server. Most likely you will have to write your own, and you can do it in whatever language you prefer. In this guide, we will do it in Javascript. - -Let's use the above example of an oracle that consumes an array with two `Field` and returns their square roots: - -```rust -#[oracle(getSqrt)] -unconstrained fn sqrt(input: [Field; 2]) -> [Field; 2] { } - -unconstrained fn get_sqrt(input: [Field; 2]) -> [Field; 2] { - sqrt(input) -} - -fn main(input: [Field; 2]) { - let sqrt = get_sqrt(input); - assert(sqrt[0].pow_32(2) as u64 == input[0] as u64); - assert(sqrt[1].pow_32(2) as u64 == input[1] as u64); -} -``` - -:::info - -Why square root? - -In general, computing square roots is computationally more expensive than multiplications, which takes a toll when speaking about ZK applications. In this case, instead of calculating the square root in Noir, we are using our oracle to offload that computation to be made in plain. In our circuit we can simply multiply the two values. - -::: - -Now, we should write the correspondent RPC server, starting with the [default JSON-RPC 2.0 boilerplate](https://www.npmjs.com/package/json-rpc-2.0#example): - -```js -import { JSONRPCServer } from "json-rpc-2.0"; -import express from "express"; -import bodyParser from "body-parser"; - -const app = express(); -app.use(bodyParser.json()); - -const server = new JSONRPCServer(); -app.post("/", (req, res) => { - const jsonRPCRequest = req.body; - server.receive(jsonRPCRequest).then((jsonRPCResponse) => { - if (jsonRPCResponse) { - res.json(jsonRPCResponse); - } else { - res.sendStatus(204); - } - }); -}); - -app.listen(5555); -``` - -Now, we will add our `getSqrt` method, as expected by the `#[oracle(getSqrt)]` decorator in our Noir code. It maps through the params array and returns their square roots: - -```js -server.addMethod("getSqrt", async (params) => { - const values = params[0].Array.map((field) => { - return `${Math.sqrt(parseInt(field, 16))}`; - }); - return { values: [{ Array: values }] }; -}); -``` - -:::tip - -Brillig expects an object with an array of values. Each value is an object declaring to be `Single` or `Array` and returning a field element *as a string*. For example: - -```json -{ "values": [{ "Array": ["1", "2"] }]} -{ "values": [{ "Single": "1" }]} -{ "values": [{ "Single": "1" }, { "Array": ["1", "2"] }]} -``` - -If you're using Typescript, the following types may be helpful in understanding the expected return value and making sure they're easy to follow: - -```js -interface SingleForeignCallParam { - Single: string, -} - -interface ArrayForeignCallParam { - Array: string[], -} - -type ForeignCallParam = SingleForeignCallParam | ArrayForeignCallParam; - -interface ForeignCallResult { - values: ForeignCallParam[], -} -``` - -::: - -## Step 3 - Usage with Nargo - -Using the [`nargo` CLI tool](../getting_started/installation/index.md), you can use oracles in the `nargo test`, `nargo execute` and `nargo prove` commands by passing a value to `--oracle-resolver`. For example: - -```bash -nargo test --oracle-resolver http://localhost:5555 -``` - -This tells `nargo` to use your RPC Server URL whenever it finds an oracle decorator. - -## Step 4 - Usage with NoirJS - -In a JS environment, an RPC server is not strictly necessary, as you may want to resolve your oracles without needing any JSON call at all. NoirJS simply expects that you pass a callback function when you generate proofs, and that callback function can be anything. - -For example, if your Noir program expects the host machine to provide CPU pseudo-randomness, you could simply pass it as the `foreignCallHandler`. You don't strictly need to create an RPC server to serve pseudo-randomness, as you may as well get it directly in your app: - -```js -const foreignCallHandler = (name, inputs) => crypto.randomBytes(16) // etc - -await noir.generateProof(inputs, foreignCallHandler) -``` - -As one can see, in NoirJS, the [`foreignCallHandler`](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) function simply means "a callback function that returns a value of type [`ForeignCallOutput`](../reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md). It doesn't have to be an RPC call like in the case for Nargo. - -:::tip - -Does this mean you don't have to write an RPC server like in [Step #2](#step-2---write-an-rpc-server)? - -You don't technically have to, but then how would you run `nargo test` or `nargo prove`? To use both `Nargo` and `NoirJS` in your development flow, you will have to write a JSON RPC server. - -::: - -In this case, let's make `foreignCallHandler` call the JSON RPC Server we created in [Step #2](#step-2---write-an-rpc-server), by making it a JSON RPC Client. - -For example, using the same `getSqrt` program in [Step #1](#step-1---modify-your-noir-program) (comments in the code): - -```js -import { JSONRPCClient } from "json-rpc-2.0"; - -// declaring the JSONRPCClient -const client = new JSONRPCClient((jsonRPCRequest) => { -// hitting the same JSON RPC Server we coded above - return fetch("http://localhost:5555", { - method: "POST", - headers: { - "content-type": "application/json", - }, - body: JSON.stringify(jsonRPCRequest), - }).then((response) => { - if (response.status === 200) { - return response - .json() - .then((jsonRPCResponse) => client.receive(jsonRPCResponse)); - } else if (jsonRPCRequest.id !== undefined) { - return Promise.reject(new Error(response.statusText)); - } - }); -}); - -// declaring a function that takes the name of the foreign call (getSqrt) and the inputs -const foreignCallHandler = async (name, input) => { - // notice that the "inputs" parameter contains *all* the inputs - // in this case we to make the RPC request with the first parameter "numbers", which would be input[0] - const oracleReturn = await client.request(name, [ - { Array: input[0].map((i) => i.toString("hex")) }, - ]); - return [oracleReturn.values[0].Array]; -}; - -// the rest of your NoirJS code -const input = { input: [4, 16] }; -const { witness } = await noir.execute(numbers, foreignCallHandler); -``` - -:::tip - -If you're in a NoirJS environment running your RPC server together with a frontend app, you'll probably hit a familiar problem in full-stack development: requests being blocked by [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) policy. For development only, you can simply install and use the [`cors` npm package](https://www.npmjs.com/package/cors) to get around the problem: - -```bash -yarn add cors -``` - -and use it as a middleware: - -```js -import cors from "cors"; - -const app = express(); -app.use(cors()) -``` - -::: - -## Conclusion - -Hopefully by the end of this guide, you should be able to: - -- Write your own logic around Oracles and how to write a JSON RPC server to make them work with your Nargo commands. -- Provide custom foreign call handlers for NoirJS. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/how_to/how-to-recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/how_to/how-to-recursion.md deleted file mode 100644 index 4c45bb87ae2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/how_to/how-to-recursion.md +++ /dev/null @@ -1,179 +0,0 @@ ---- -title: How to use recursion on NoirJS -description: Learn how to implement recursion with NoirJS, a powerful tool for creating smart contracts on the EVM blockchain. This guide assumes familiarity with NoirJS, solidity verifiers, and the Barretenberg proving backend. Discover how to generate both final and intermediate proofs using `noir_js` and `backend_barretenberg`. -keywords: - [ - "NoirJS", - "EVM blockchain", - "smart contracts", - "recursion", - "solidity verifiers", - "Barretenberg backend", - "noir_js", - "backend_barretenberg", - "intermediate proofs", - "final proofs", - "nargo compile", - "json import", - "recursive circuit", - "recursive app" - ] -sidebar_position: 1 ---- - -This guide shows you how to use recursive proofs in your NoirJS app. For the sake of clarity, it is assumed that: - -- You already have a NoirJS app. If you don't, please visit the [NoirJS tutorial](../tutorials/noirjs_app.md) and the [reference](../reference/NoirJS/noir_js/index.md). -- You are familiar with what are recursive proofs and you have read the [recursion explainer](../explainers/explainer-recursion.md) -- You already built a recursive circuit following [the reference](../noir/standard_library/recursion.md), and understand how it works. - -It is also assumed that you're not using `noir_wasm` for compilation, and instead you've used [`nargo compile`](../reference/nargo_commands.md) to generate the `json` you're now importing into your project. However, the guide should work just the same if you're using `noir_wasm`. - -:::info - -As you've read in the [explainer](../explainers/explainer-recursion.md), a recursive proof is an intermediate proof. This means that it doesn't necessarily generate the final step that makes it verifiable in a smart contract. However, it is easy to verify within another circuit. - -While "standard" usage of NoirJS packages abstracts final proofs, it currently lacks the necessary interface to abstract away intermediate proofs. This means that these proofs need to be created by using the backend directly. - -In short: - -- `noir_js` generates *only* final proofs -- `backend_barretenberg` generates both types of proofs - -::: - -In a standard recursive app, you're also dealing with at least two circuits. For the purpose of this guide, we will assume the following: - -- `main`: a circuit of type `assert(x != y)`, where `main` is marked with a `#[recursive]` attribute. This attribute states that the backend should generate proofs that are friendly for verification within another circuit. -- `recursive`: a circuit that verifies `main` - -For a full example on how recursive proofs work, please refer to the [noir-examples](https://github.com/noir-lang/noir-examples) repository. We will *not* be using it as a reference for this guide. - -## Step 1: Setup - -In a common NoirJS app, you need to instantiate a backend with something like `const backend = new Backend(circuit)`. Then you feed it to the `noir_js` interface. - -For recursion, this doesn't happen, and the only need for `noir_js` is only to `execute` a circuit and get its witness and return value. Everything else is not interfaced, so it needs to happen on the `backend` object. - -It is also recommended that you instantiate the backend with as many threads as possible, to allow for maximum concurrency: - -```js -const backend = new Backend(circuit, { threads: 8 }) -``` - -:::tip -You can use the [`os.cpus()`](https://nodejs.org/api/os.html#oscpus) object in `nodejs` or [`navigator.hardwareConcurrency`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/hardwareConcurrency) on the browser to make the most out of those glorious cpu cores -::: - -## Step 2: Generating the witness and the proof for `main` - -After instantiating the backend, you should also instantiate `noir_js`. We will use it to execute the circuit and get the witness. - -```js -const noir = new Noir(circuit, backend) -const { witness } = noir.execute(input) -``` - -With this witness, you are now able to generate the intermediate proof for the main circuit: - -```js -const { proof, publicInputs } = await backend.generateProof(witness) -``` - -:::warning - -Always keep in mind what is actually happening on your development process, otherwise you'll quickly become confused about what circuit we are actually running and why! - -In this case, you can imagine that Alice (running the `main` circuit) is proving something to Bob (running the `recursive` circuit), and Bob is verifying her proof within his proof. - -With this in mind, it becomes clear that our intermediate proof is the one *meant to be verified within another circuit*, so it must be Alice's. Actually, the only final proof in this theoretical scenario would be the last one, sent on-chain. - -::: - -## Step 3 - Verification and proof artifacts - -Optionally, you are able to verify the intermediate proof: - -```js -const verified = await backend.verifyProof({ proof, publicInputs }) -``` - -This can be useful to make sure our intermediate proof was correctly generated. But the real goal is to do it within another circuit. For that, we need to generate recursive proof artifacts that will be passed to the circuit that is verifying the proof we just generated. Instead of passing the proof and verification key as a byte array, we pass them as fields which makes it cheaper to verify in a circuit: - -```js -const { proofAsFields, vkAsFields, vkHash } = await backend.generateRecursiveProofArtifacts( { publicInputs, proof }, publicInputsCount) -``` - -This call takes the public inputs and the proof, but also the public inputs count. While this is easily retrievable by simply counting the `publicInputs` length, the backend interface doesn't currently abstract it away. - -:::info - -The `proofAsFields` has a constant size `[Field; 93]` and verification keys in Barretenberg are always `[Field; 114]`. - -::: - -:::warning - -One common mistake is to forget *who* makes this call. - -In a situation where Alice is generating the `main` proof, if she generates the proof artifacts and sends them to Bob, which gladly takes them as true, this would mean Alice could prove anything! - -Instead, Bob needs to make sure *he* extracts the proof artifacts, using his own instance of the `main` circuit backend. This way, Alice has to provide a valid proof for the correct `main` circuit. - -::: - -## Step 4 - Recursive proof generation - -With the artifacts, generating a recursive proof is no different from a normal proof. You simply use the `backend` (with the recursive circuit) to generate it: - -```js -const recursiveInputs = { - verification_key: vkAsFields, // array of length 114 - proof: proofAsFields, // array of length 93 + size of public inputs - publicInputs: [mainInput.y], // using the example above, where `y` is the only public input - key_hash: vkHash, -} - -const { witness, returnValue } = noir.execute(recursiveInputs) // we're executing the recursive circuit now! -const { proof, publicInputs } = backend.generateProof(witness) -const verified = backend.verifyProof({ proof, publicInputs }) -``` - -You can obviously chain this proof into another proof. In fact, if you're using recursive proofs, you're probably interested of using them this way! - -:::tip - -Managing circuits and "who does what" can be confusing. To make sure your naming is consistent, you can keep them in an object. For example: - -```js -const circuits = { - main: mainJSON, - recursive: recursiveJSON -} -const backends = { - main: new BarretenbergBackend(circuits.main), - recursive: new BarretenbergBackend(circuits.recursive) -} -const noir_programs = { - main: new Noir(circuits.main, backends.main), - recursive: new Noir(circuits.recursive, backends.recursive) -} -``` - -This allows you to neatly call exactly the method you want without conflicting names: - -```js -// Alice runs this 👇 -const { witness: mainWitness } = await noir_programs.main.execute(input) -const proof = await backends.main.generateProof(mainWitness) - -// Bob runs this 👇 -const verified = await backends.main.verifyProof(proof) -const { proofAsFields, vkAsFields, vkHash } = await backends.main.generateRecursiveProofArtifacts( - proof, - numPublicInputs, -); -const recursiveProof = await noir_programs.recursive.generateProof(recursiveInputs) -``` - -::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/how_to/how-to-solidity-verifier.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/how_to/how-to-solidity-verifier.md deleted file mode 100644 index e5ce3b7bc22..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/how_to/how-to-solidity-verifier.md +++ /dev/null @@ -1,232 +0,0 @@ ---- -title: Generate a Solidity Verifier -description: - Learn how to run the verifier as a smart contract on the blockchain. Compile a Solidity verifier - contract for your Noir program and deploy it on any EVM blockchain acting as a verifier smart - contract. Read more to find out -keywords: - [ - solidity verifier, - smart contract, - blockchain, - compiler, - plonk_vk.sol, - EVM blockchain, - verifying Noir programs, - proving backend, - Barretenberg, - ] -sidebar_position: 0 -pagination_next: tutorials/noirjs_app ---- - -Noir has the ability to generate a verifier contract in Solidity, which can be deployed in many EVM-compatible blockchains such as Ethereum. - -This allows for a powerful feature set, as one can make use of the conciseness and the privacy provided by Noir in an immutable ledger. Applications can range from simple P2P guessing games, to complex private DeFi interactions. - -This guide shows you how to generate a Solidity Verifier and deploy it on the [Remix IDE](https://remix.ethereum.org/). It is assumed that: - -- You are comfortable with the Solidity programming language and understand how contracts are deployed on the Ethereum network -- You have Noir installed and you have a Noir program. If you don't, [get started](../getting_started/installation/index.md) with Nargo and the example Hello Noir circuit -- You are comfortable navigating RemixIDE. If you aren't or you need a refresher, you can find some video tutorials [here](https://www.youtube.com/channel/UCjTUPyFEr2xDGN6Cg8nKDaA) that could help you. - -## Rundown - -Generating a Solidity Verifier contract is actually a one-command process. However, compiling it and deploying it can have some caveats. Here's the rundown of this guide: - -1. How to generate a solidity smart contract -2. How to compile the smart contract in the RemixIDE -3. How to deploy it to a testnet - -## Step 1 - Generate a contract - -This is by far the most straight-forward step. Just run: - -```sh -nargo codegen-verifier -``` - -A new `contract` folder would then be generated in your project directory, containing the Solidity -file `plonk_vk.sol`. It can be deployed to any EVM blockchain acting as a verifier smart contract. - -:::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. - -Barretenberg, the default proving backend for Nargo, supports generation of verifier contracts, for the time being these are only in Solidity. -::: - -## Step 2 - Compiling - -We will mostly skip the details of RemixIDE, as the UI can change from version to version. For now, we can just open -Remix and create a blank workspace. - -![Create Workspace](@site/static/img/how-tos/solidity_verifier_1.png) - -We will create a new file to contain the contract Nargo generated, and copy-paste its content. - -:::warning - -You'll likely see a warning advising you to not trust pasted code. While it is an important warning, it is irrelevant in the context of this guide and can be ignored. We will not be deploying anywhere near a mainnet. - -::: - -To compile our the verifier, we can navigate to the compilation tab: - -![Compilation Tab](@site/static/img/how-tos/solidity_verifier_2.png) - -Remix should automatically match a suitable compiler version. However, hitting the "Compile" button will most likely generate a "Stack too deep" error: - -![Stack too deep](@site/static/img/how-tos/solidity_verifier_3.png) - -This is due to the verify function needing to put many variables on the stack, but enabling the optimizer resolves the issue. To do this, let's open the "Advanced Configurations" tab and enable optimization. The default 200 runs will suffice. - -:::info - -This time we will see a warning about an unused function parameter. This is expected, as the `verify` function doesn't use the `_proof` parameter inside a solidity block, it is loaded from calldata and used in assembly. - -::: - -![Compilation success](@site/static/img/how-tos/solidity_verifier_4.png) - -## Step 3 - Deploying - -At this point we should have a compiled contract read to deploy. If we navigate to the deploy section in Remix, we will see many different environments we can deploy to. The steps to deploy on each environment would be out-of-scope for this guide, so we will just use the default Remix VM. - -Looking closely, we will notice that our "Solidity Verifier" is actually three contracts working together: - -- An `UltraVerificationKey` library which simply stores the verification key for our circuit. -- An abstract contract `BaseUltraVerifier` containing most of the verifying logic. -- A main `UltraVerifier` contract that inherits from the Base and uses the Key contract. - -Remix will take care of the dependencies for us so we can simply deploy the UltraVerifier contract by selecting it and hitting "deploy": - -![Deploying UltraVerifier](@site/static/img/how-tos/solidity_verifier_5.png) - -A contract will show up in the "Deployed Contracts" section, where we can retrieve the Verification Key Hash. This is particularly useful for double-checking the deployer contract is the correct one. - -:::note - -Why "UltraVerifier"? - -To be precise, the Noir compiler (`nargo`) doesn't generate the verifier contract directly. It compiles the Noir code into an intermediate language (ACIR), which is then executed by the backend. So it is the backend that returns the verifier smart contract, not Noir. - -In this case, the Barretenberg Backend uses the UltraPlonk proving system, hence the "UltraVerifier" name. - -::: - -## Step 4 - Verifying - -To verify a proof using the Solidity verifier contract, we call the `verify` function in this extended contract: - -```solidity -function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) -``` - -When using the default example in the [Hello Noir](../getting_started/hello_noir/index.md) guide, the easiest way to confirm that the verifier contract is doing its job is by calling the `verify` function via remix with the required parameters. For `_proof`, run `nargo prove` and use the string in `proof/.proof` (adding the hex `0x` prefix). We can also copy the public input from `Verifier.toml`, as it will be properly formatted as 32-byte strings: - -``` -0x...... , [0x0000.....02] -``` - -A programmatic example of how the `verify` function is called can be seen in the example zk voting application [here](https://github.com/noir-lang/noir-examples/blob/33e598c257e2402ea3a6b68dd4c5ad492bce1b0a/foundry-voting/src/zkVote.sol#L35): - -```solidity -function castVote(bytes calldata proof, uint proposalId, uint vote, bytes32 nullifierHash) public returns (bool) { - // ... - bytes32[] memory publicInputs = new bytes32[](4); - publicInputs[0] = merkleRoot; - publicInputs[1] = bytes32(proposalId); - publicInputs[2] = bytes32(vote); - publicInputs[3] = nullifierHash; - require(verifier.verify(proof, publicInputs), "Invalid proof"); -``` - -:::info[Return Values] - -A circuit doesn't have the concept of a return value. Return values are just syntactic sugar in -Noir. - -Under the hood, the return value is passed as an input to the circuit and is checked at the end of -the circuit program. - -For example, if you have Noir program like this: - -```rust -fn main( - // Public inputs - pubkey_x: pub Field, - pubkey_y: pub Field, - // Private inputs - priv_key: Field, -) -> pub Field -``` - -the `verify` function will expect the public inputs array (second function parameter) to be of length 3, the two inputs and the return value. Like before, these values are populated in Verifier.toml after running `nargo prove`. - -Passing only two inputs will result in an error such as `PUBLIC_INPUT_COUNT_INVALID(3, 2)`. - -In this case, the inputs parameter to `verify` would be an array ordered as `[pubkey_x, pubkey_y, return]`. - -::: - -:::tip[Structs] - -You can pass structs to the verifier contract. They will be flattened so that the array of inputs is 1-dimensional array. - -For example, consider the following program: - -```rust -struct Type1 { - val1: Field, - val2: Field, -} - -struct Nested { - t1: Type1, - is_true: bool, -} - -fn main(x: pub Field, nested: pub Nested, y: pub Field) { - //... -} -``` - -The order of these inputs would be flattened to: `[x, nested.t1.val1, nested.t1.val2, nested.is_true, y]` - -::: - -The other function you can call is our entrypoint `verify` function, as defined above. - -:::tip - -It's worth noticing that the `verify` function is actually a `view` function. A `view` function does not alter the blockchain state, so it doesn't need to be distributed (i.e. it will run only on the executing node), and therefore doesn't cost any gas. - -This can be particularly useful in some situations. If Alice generated a proof and wants Bob to verify its correctness, Bob doesn't need to run Nargo, NoirJS, or any Noir specific infrastructure. He can simply make a call to the blockchain with the proof and verify it is correct without paying any gas. - -It would be incorrect to say that a Noir proof verification costs any gas at all. However, most of the time the result of `verify` is used to modify state (for example, to update a balance, a game state, etc). In that case the whole network needs to execute it, which does incur gas costs (calldata and execution, but not storage). - -::: - -## A Note on EVM chains - -ZK-SNARK verification depends on some precompiled cryptographic primitives such as Elliptic Curve Pairings (if you like complex math, you can read about EC Pairings [here](https://medium.com/@VitalikButerin/exploring-elliptic-curve-pairings-c73c1864e627)). Not all EVM chains support EC Pairings, notably some of the ZK-EVMs. This means that you won't be able to use the verifier contract in all of them. - -For example, `Polygon zkEVM` does not currently support these precompiles, so proof verification via Solidity verifier contracts won't work. Here's a quick list of EVM chains that have been tested and are known to work: - -- Optimism -- Arbitrum -- Polygon PoS -- Scroll -- Celo -- zkSync - -If you test any other chains, please open a PR on this page to update the list. See [this doc](https://github.com/noir-lang/noir-starter/tree/main/with-foundry#testing-on-chain) for more info about testing verifier contracts on different EVM chains. - -## What's next - -Now that you know how to call a Noir Solidity Verifier on a smart contract using Remix, you should be comfortable with using it with some programmatic frameworks, such as [hardhat](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat) and [foundry](https://github.com/noir-lang/noir-starter/tree/main/with-foundry). - -You can find other tools, examples, boilerplates and libraries in the [awesome-noir](https://github.com/noir-lang/awesome-noir) repository. - -You should also be ready to write and deploy your first NoirJS app and start generating proofs on websites, phones, and NodeJS environments! Head on to the [NoirJS tutorial](../tutorials/noirjs_app.md) to learn how to do that. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/how_to/merkle-proof.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/how_to/merkle-proof.mdx deleted file mode 100644 index 16c425bed76..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/how_to/merkle-proof.mdx +++ /dev/null @@ -1,49 +0,0 @@ ---- -title: Prove Merkle Tree Membership -description: - Learn how to use merkle membership proof in Noir to prove that a given leaf is a member of a - merkle tree with a specified root, at a given index. -keywords: - [merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree] -sidebar_position: 4 ---- - -Let's walk through an example of a merkle membership proof in Noir that proves that a given leaf is -in a merkle tree. - -```rust -use dep::std; - -fn main(message : [Field; 62], index : Field, hashpath : [Field; 40], root : Field) { - let leaf = std::hash::hash_to_field(message.as_slice()); - let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); - assert(merkle_root == root); -} - -``` - -The message is hashed using `hash_to_field`. The specific hash function that is being used is chosen -by the backend. The only requirement is that this hash function can heuristically be used as a -random oracle. If only collision resistance is needed, then one can call `std::hash::pedersen_hash` -instead. - -```rust -let leaf = std::hash::hash_to_field(message.as_slice()); -``` - -The leaf is then passed to a compute_merkle_root function with the root, index and hashpath. The returned root can then be asserted to be the same as the provided root. - -```rust -let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); -assert (merkle_root == root); -``` - -> **Note:** It is possible to re-implement the merkle tree implementation without standard library. -> However, for most usecases, it is enough. In general, the standard library will always opt to be -> as conservative as possible, while striking a balance with efficiency. - -An example, the merkle membership proof, only requires a hash function that has collision -resistance, hence a hash function like Pedersen is allowed, which in most cases is more efficient -than the even more conservative sha256. - -[View an example on the starter repo](https://github.com/noir-lang/noir-examples/blob/3ea09545cabfa464124ec2f3ea8e60c608abe6df/stealthdrop/circuits/src/main.nr#L20) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/how_to/using-devcontainers.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/how_to/using-devcontainers.mdx deleted file mode 100644 index 727ec6ca667..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/how_to/using-devcontainers.mdx +++ /dev/null @@ -1,110 +0,0 @@ ---- -title: Developer Containers and Codespaces -description: "Learn how to set up a devcontainer in your GitHub repository for a seamless coding experience with Codespaces. Follow our easy 8-step guide to create your own Noir environment without installing Nargo locally." -keywords: ["Devcontainer", "Codespaces", "GitHub", "Noir Environment", "Docker Image", "Development Environment", "Remote Coding", "GitHub Codespaces", "Noir Programming", "Nargo", "VSCode Extensions", "Noirup"] -sidebar_position: 1 ---- - -Adding a developer container configuration file to your Noir project is one of the easiest way to unlock coding in browser. - -## What's a devcontainer after all? - -A [Developer Container](https://containers.dev/) (devcontainer for short) is a Docker image that comes preloaded with tools, extensions, and other tools you need to quickly get started or continue a project, without having to install Nargo locally. Think of it as a development environment in a box. - -There are many advantages to this: - -- It's platform and architecture agnostic -- You don't need to have an IDE installed, or Nargo, or use a terminal at all -- It's safer for using on a public machine or public network - -One of the best ways of using devcontainers is... not using your machine at all, for maximum control, performance, and ease of use. -Enter Codespaces. - -## Codespaces - -If a devcontainer is just a Docker image, then what stops you from provisioning a `p3dn.24xlarge` AWS EC2 instance with 92 vCPUs and 768 GiB RAM and using it to prove your 10-gate SNARK proof? - -Nothing! Except perhaps the 30-40$ per hour it will cost you. - -The problem is that provisioning takes time, and I bet you don't want to see the AWS console every time you want to code something real quick. - -Fortunately, there's an easy and free way to get a decent remote machine ready and loaded in less than 2 minutes: Codespaces. [Codespaces is a Github feature](https://github.com/features/codespaces) that allows you to code in a remote machine by using devcontainers, and it's pretty cool: - -- You can start coding Noir in less than a minute -- It uses the resources of a remote machine, so you can code on your grandma's phone if needed be -- It makes it easy to share work with your frens -- It's fully reusable, you can stop and restart whenever you need to - -:::info - -Don't take out your wallet just yet. Free GitHub accounts get about [15-60 hours of coding](https://github.com/features/codespaces) for free per month, depending on the size of your provisioned machine. - -::: - -## Tell me it's _actually_ easy - -It is! - -Github comes with a default codespace and you can use it to code your own devcontainer. That's exactly what we will be doing in this guide. - - - -8 simple steps: - -#### 1. Create a new repository on GitHub. - -#### 2. Click "Start coding with Codespaces". This will use the default image. - -#### 3. Create a folder called `.devcontainer` in the root of your repository. - -#### 4. Create a Dockerfile in that folder, and paste the following code: - -```docker -FROM --platform=linux/amd64 node:lts-bookworm-slim -SHELL ["/bin/bash", "-c"] -RUN apt update && apt install -y curl bash git tar gzip libc++-dev -RUN curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -ENV PATH="/root/.nargo/bin:$PATH" -RUN noirup -ENTRYPOINT ["nargo"] -``` -#### 5. Create a file called `devcontainer.json` in the same folder, and paste the following code: - -```json -{ - "name": "Noir on Codespaces", - "build": { - "context": ".", - "dockerfile": "Dockerfile" - }, - "customizations": { - "vscode": { - "extensions": ["noir-lang.vscode-noir"] - } - } -} -``` -#### 6. Commit and push your changes - -This will pull the new image and build it, so it could take a minute or so - -#### 8. Done! -Just wait for the build to finish, and there's your easy Noir environment. - - -Refer to [noir-starter](https://github.com/noir-lang/noir-starter/) as an example of how devcontainers can be used together with codespaces. - - - -## How do I use it? - -Using the codespace is obviously much easier than setting it up. -Just navigate to your repository and click "Code" -> "Open with Codespaces". It should take a few seconds to load, and you're ready to go. - -:::info - -If you really like the experience, you can add a badge to your readme, links to existing codespaces, and more. -Check out the [official docs](https://docs.github.com/en/codespaces/setting-up-your-project-for-codespaces/setting-up-your-repository/facilitating-quick-creation-and-resumption-of-codespaces) for more info. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/index.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/index.mdx deleted file mode 100644 index 75086ddcdde..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/index.mdx +++ /dev/null @@ -1,67 +0,0 @@ ---- -title: Noir Lang -hide_title: true -description: - Learn about the public alpha release of Noir, a domain specific language heavily influenced by Rust that compiles to - an intermediate language which can be compiled to an arithmetic circuit or a rank-1 constraint system. -keywords: - [Noir, - Domain Specific Language, - Rust, - Intermediate Language, - Arithmetic Circuit, - Rank-1 Constraint System, - Ethereum Developers, - Protocol Developers, - Blockchain Developers, - Proving System, - Smart Contract Language] -sidebar_position: 0 ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -Noir Logo - -Noir is a Domain-Specific Language for SNARK proving systems developed by [Aztec Labs](https://aztec.network/). It allows you to generate complex Zero-Knowledge Programs (ZKP) by using simple and flexible syntax, requiring no previous knowledge on the underlying mathematics or cryptography. - -ZK programs are programs that can generate short proofs of a certain statement without revealing some details about it. You can read more about ZKPs [here](https://dev.to/spalladino/a-beginners-intro-to-coding-zero-knowledge-proofs-c56). - -## What's new about Noir? - -Noir works differently from most ZK languages by taking a two-pronged path. First, it compiles the program to an adaptable intermediate language known as ACIR. From there, depending on a given project's needs, ACIR can be further compiled into an arithmetic circuit for integration with the proving backend. - -:::info - -Noir is backend agnostic, which means it makes no assumptions on which proving backend powers the ZK proof. Being the language that powers [Aztec Contracts](https://docs.aztec.network/developers/contracts/main), it defaults to Aztec's Barretenberg proving backend. - -However, the ACIR output can be transformed to be compatible with other PLONK-based backends, or into a [rank-1 constraint system](https://www.rareskills.io/post/rank-1-constraint-system) suitable for backends such as Arkwork's Marlin. - -::: - -## Who is Noir for? - -Noir can be used both in complex cloud-based backends and in user's smartphones, requiring no knowledge on the underlying math or cryptography. From authorization systems that keep a password in the user's device, to complex on-chain verification of recursive proofs, Noir is designed to abstract away complexity without any significant overhead. Here are some examples of situations where Noir can be used: - - - - Noir Logo - - Aztec Contracts leverage Noir to allow for the storage and execution of private information. Writing an Aztec Contract is as easy as writing Noir, and Aztec developers can easily interact with the network storage and execution through the [Aztec.nr](https://docs.aztec.network/developers/contracts/main) library. - - - Soliditry Verifier Example - Noir can auto-generate Solidity verifier contracts that verify Noir proofs. This allows for non-interactive verification of proofs containing private information in an immutable system. This feature powers a multitude of use-case scenarios, from P2P chess tournaments, to [Aztec Layer-2 Blockchain](https://docs.aztec.network/) - - - Aztec Labs developed NoirJS, an easy interface to generate and verify Noir proofs in a Javascript environment. This allows for Noir to be used in webpages, mobile apps, games, and any other environment supporting JS execution in a standalone manner. - - - - -## Libraries - -Noir is meant to be easy to extend by simply importing Noir libraries just like in Rust. -The [awesome-noir repo](https://github.com/noir-lang/awesome-noir#libraries) is a collection of libraries developed by the Noir community. -Writing a new library is easy and makes code be composable and easy to reuse. See the section on [dependencies](noir/modules_packages_crates/dependencies.md) for more information. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/migration_notes.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/migration_notes.md deleted file mode 100644 index 6bd740024e5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/migration_notes.md +++ /dev/null @@ -1,105 +0,0 @@ ---- -title: Migration notes -description: Read about migration notes from previous versions, which could solve problems while updating -keywords: [Noir, notes, migration, updating, upgrading] ---- - -Noir is in full-speed development. Things break fast, wild, and often. This page attempts to leave some notes on errors you might encounter when upgrading and how to resolve them until proper patches are built. - -### `backend encountered an error: libc++.so.1` - -Depending on your OS, you may encounter the following error when running `nargo prove` for the first time: - -```text -The backend encountered an error: "/home/codespace/.nargo/backends/acvm-backend-barretenberg/backend_binary: error while loading shared libraries: libc++.so.1: cannot open shared object file: No such file or directory\n" -``` - -Install the `libc++-dev` library with: - -```bash -sudo apt install libc++-dev -``` - -## ≥0.19 - -### Enforcing `compiler_version` - -From this version on, the compiler will check for the `compiler_version` field in `Nargo.toml`, and will error if it doesn't match the current Nargo version in use. - -To update, please make sure this field in `Nargo.toml` matches the output of `nargo --version`. - -## ≥0.14 - -The index of the [for loops](noir/concepts/control_flow.md#loops) is now of type `u64` instead of `Field`. An example refactor would be: - -```rust -for i in 0..10 { - let i = i as Field; -} -``` - -## ≥v0.11.0 and Nargo backend - -From this version onwards, Nargo starts managing backends through the `nargo backend` command. Upgrading to the versions per usual steps might lead to: - -### `backend encountered an error` - -This is likely due to the existing locally installed version of proving backend (e.g. barretenberg) is incompatible with the version of Nargo in use. - -To fix the issue: - -1. Uninstall the existing backend - -```bash -nargo backend uninstall acvm-backend-barretenberg -``` - -You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. - -2. Reinstall a compatible version of the proving backend. - -If you are using the default barretenberg backend, simply run: - -``` -nargo prove -``` - -with your Noir program. - -This will trigger the download and installation of the latest version of barretenberg compatible with your Nargo in use. - -### `backend encountered an error: illegal instruction` - -On certain Intel-based systems, an `illegal instruction` error may arise due to incompatibility of barretenberg with certain CPU instructions. - -To fix the issue: - -1. Uninstall the existing backend - -```bash -nargo backend uninstall acvm-backend-barretenberg -``` - -You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. - -2. Reinstall a compatible version of the proving backend. - -If you are using the default barretenberg backend, simply run: - -``` -nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/barretenberg-js-binary/raw/master/run-bb.tar.gz -``` - -This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. - -The gzipped file is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. - -Then run: - -``` -DESIRED_BINARY_VERSION=0.8.1 nargo info -``` - -This overrides the bb native binary with a bb.js node application instead, which should be compatible with most if not all hardware. This does come with the drawback of being generally slower than native binary. - -0.8.1 indicates bb.js version 0.8.1, so if you change that it will update to a different version or the default version in the script if none was supplied. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/_category_.json deleted file mode 100644 index 7da08f8a8c5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Concepts", - "position": 0, - "collapsible": true, - "collapsed": true -} \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/assert.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/assert.md deleted file mode 100644 index bcff613a695..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/assert.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Assert Function -description: - Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or - comparison expression that follows to be true, and what happens if the expression is false at - runtime. -keywords: [Noir programming language, assert statement, predicate expression, comparison expression] -sidebar_position: 4 ---- - -Noir includes a special `assert` function which will explicitly constrain the predicate/comparison -expression that follows to be true. If this expression is false at runtime, the program will fail to -be proven. Example: - -```rust -fn main(x : Field, y : Field) { - assert(x == y); -} -``` - -> Assertions only work for predicate operations, such as `==`. If there's any ambiguity on the operation, the program will fail to compile. For example, it is unclear if `assert(x + y)` would check for `x + y == 0` or simply would return `true`. - -You can optionally provide a message to be logged when the assertion fails: - -```rust -assert(x == y, "x and y are not equal"); -``` - -Aside string literals, the optional message can be a format string or any other type supported as input for Noir's [print](../standard_library/logging.md) functions. This feature lets you incorporate runtime variables into your failed assertion logs: - -```rust -assert(x == y, f"Expected x == y, but got {x} == {y}"); -``` - -Using a variable as an assertion message directly: - -```rust -struct myStruct { - myField: Field -} - -let s = myStruct { myField: y }; -assert(s.myField == x, s); -``` - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/comments.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/comments.md deleted file mode 100644 index b51a85f5c94..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/comments.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Comments -description: - Learn how to write comments in Noir programming language. A comment is a line of code that is - ignored by the compiler, but it can be read by programmers. Single-line and multi-line comments - are supported in Noir. -keywords: [Noir programming language, comments, single-line comments, multi-line comments] -sidebar_position: 10 ---- - -A comment is a line in your codebase which the compiler ignores, however it can be read by -programmers. - -Here is a single line comment: - -```rust -// This is a comment and is ignored -``` - -`//` is used to tell the compiler to ignore the rest of the line. - -Noir also supports multi-line block comments. Start a block comment with `/*` and end the block with `*/`. - -Noir does not natively support doc comments. You may be able to use [Rust doc comments](https://doc.rust-lang.org/reference/comments.html) in your code to leverage some Rust documentation build tools with Noir code. - -```rust -/* - This is a block comment describing a complex function. -*/ -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/control_flow.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/control_flow.md deleted file mode 100644 index 045d3c3a5f5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/control_flow.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -title: Control Flow -description: - Learn how to use loops and if expressions in the Noir programming language. Discover the syntax - and examples for for loops and if-else statements. -keywords: [Noir programming language, loops, for loop, if-else statements, Rust syntax] -sidebar_position: 2 ---- - -## If Expressions - -Noir supports `if-else` statements. The syntax is most similar to Rust's where it is not required -for the statement's conditional to be surrounded by parentheses. - -```rust -let a = 0; -let mut x: u32 = 0; - -if a == 0 { - if a != 0 { - x = 6; - } else { - x = 2; - } -} else { - x = 5; - assert(x == 5); -} -assert(x == 2); -``` - -## Loops - -Noir has one kind of loop: the `for` loop. `for` loops allow you to repeat a block of code multiple -times. - -The following block of code between the braces is run 10 times. - -```rust -for i in 0..10 { - // do something -} -``` - -The index for loops is of type `u64`. - -### Break and Continue - -In unconstrained code, `break` and `continue` are also allowed in `for` loops. These are only allowed -in unconstrained code since normal constrained code requires that Noir knows exactly how many iterations -a loop may have. `break` and `continue` can be used like so: - -```rust -for i in 0 .. 10 { - println("Iteration start") - - if i == 2 { - continue; - } - - if i == 5 { - break; - } - - println(i); -} -println("Loop end") -``` - -When used, `break` will end the current loop early and jump to the statement after the for loop. In the example -above, the `break` will stop the loop and jump to the `println("Loop end")`. - -`continue` will stop the current iteration of the loop, and jump to the start of the next iteration. In the example -above, `continue` will jump to `println("Iteration start")` when used. Note that the loop continues as normal after this. -The iteration variable `i` is still increased by one as normal when `continue` is used. - -`break` and `continue` cannot currently be used to jump out of more than a single loop at a time. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_bus.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_bus.md deleted file mode 100644 index e54fc861257..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_bus.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: Data Bus -sidebar_position: 13 ---- -**Disclaimer** this feature is experimental, do not use it! - -The data bus is an optimization that the backend can use to make recursion more efficient. -In order to use it, you must define some inputs of the program entry points (usually the `main()` -function) with the `call_data` modifier, and the return values with the `return_data` modifier. -These modifiers are incompatible with `pub` and `mut` modifiers. - -## Example - -```rust -fn main(mut x: u32, y: call_data u32, z: call_data [u32;4] ) -> return_data u32 { - let a = z[x]; - a+y -} -``` - -As a result, both call_data and return_data will be treated as private inputs and encapsulated into a read-only array each, for the backend to process. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/_category_.json deleted file mode 100644 index 5d694210bbf..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 0, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/arrays.md deleted file mode 100644 index 9b02d52e8a8..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/arrays.md +++ /dev/null @@ -1,253 +0,0 @@ ---- -title: Arrays -description: - Dive into the Array data type in Noir. Grasp its methods, practical examples, and best practices for efficiently using Arrays in your Noir code. -keywords: - [ - noir, - array type, - methods, - examples, - indexing, - ] -sidebar_position: 4 ---- - -An array is one way of grouping together values into one compound type. Array types can be inferred -or explicitly specified via the syntax `[; ]`: - -```rust -fn main(x : Field, y : Field) { - let my_arr = [x, y]; - let your_arr: [Field; 2] = [x, y]; -} -``` - -Here, both `my_arr` and `your_arr` are instantiated as an array containing two `Field` elements. - -Array elements can be accessed using indexing: - -```rust -fn main() { - let a = [1, 2, 3, 4, 5]; - - let first = a[0]; - let second = a[1]; -} -``` - -All elements in an array must be of the same type (i.e. homogeneous). That is, an array cannot group -a `Field` value and a `u8` value together for example. - -You can write mutable arrays, like: - -```rust -fn main() { - let mut arr = [1, 2, 3, 4, 5]; - assert(arr[0] == 1); - - arr[0] = 42; - assert(arr[0] == 42); -} -``` - -You can instantiate a new array of a fixed size with the same value repeated for each element. The following example instantiates an array of length 32 where each element is of type Field and has the value 0. - -```rust -let array: [Field; 32] = [0; 32]; -``` - -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: - -```rust -let array: [Field; 32] = [0; 32]; -let sl = array.as_slice() -``` - -You can define multidimensional arrays: - -```rust -let array : [[Field; 2]; 2]; -let element = array[0][0]; -``` - -However, multidimensional slices are not supported. For example, the following code will error at compile time: - -```rust -let slice : [[Field]] = &[]; -``` - -## Types - -You can create arrays of primitive types or structs. There is not yet support for nested arrays -(arrays of arrays) or arrays of structs that contain arrays. - -## Methods - -For convenience, the STD provides some ready-to-use, common methods for arrays. -Each of these functions are located within the generic impl `impl [T; N] {`. -So anywhere `self` appears, it refers to the variable `self: [T; N]`. - -### len - -Returns the length of an array - -```rust -fn len(self) -> Field -``` - -example - -```rust -fn main() { - let array = [42, 42]; - assert(array.len() == 2); -} -``` - -### sort - -Returns a new sorted array. The original array remains untouched. Notice that this function will -only work for arrays of fields or integers, not for any arbitrary type. This is because the sorting -logic it uses internally is optimized specifically for these values. If you need a sort function to -sort any type, you should use the function `sort_via` described below. - -```rust -fn sort(self) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32]; - let sorted = arr.sort(); - assert(sorted == [32, 42]); -} -``` - -### sort_via - -Sorts the array with a custom comparison function - -```rust -fn sort_via(self, ordering: fn(T, T) -> bool) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32] - let sorted_ascending = arr.sort_via(|a, b| a <= b); - assert(sorted_ascending == [32, 42]); // verifies - - let sorted_descending = arr.sort_via(|a, b| a >= b); - assert(sorted_descending == [32, 42]); // does not verify -} -``` - -### map - -Applies a function to each element of the array, returning a new array containing the mapped elements. - -```rust -fn map(self, f: fn(T) -> U) -> [U; N] -``` - -example - -```rust -let a = [1, 2, 3]; -let b = a.map(|a| a * 2); // b is now [2, 4, 6] -``` - -### fold - -Applies a function to each element of the array, returning the final accumulated value. The first -parameter is the initial value. - -```rust -fn fold(self, mut accumulator: U, f: fn(U, T) -> U) -> U -``` - -This is a left fold, so the given function will be applied to the accumulator and first element of -the array, then the second, and so on. For a given call the expected result would be equivalent to: - -```rust -let a1 = [1]; -let a2 = [1, 2]; -let a3 = [1, 2, 3]; - -let f = |a, b| a - b; -a1.fold(10, f) //=> f(10, 1) -a2.fold(10, f) //=> f(f(10, 1), 2) -a3.fold(10, f) //=> f(f(f(10, 1), 2), 3) -``` - -example: - -```rust - -fn main() { - let arr = [2, 2, 2, 2, 2]; - let folded = arr.fold(0, |a, b| a + b); - assert(folded == 10); -} - -``` - -### reduce - -Same as fold, but uses the first element as starting element. - -```rust -fn reduce(self, f: fn(T, T) -> T) -> T -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let reduced = arr.reduce(|a, b| a + b); - assert(reduced == 10); -} -``` - -### all - -Returns true if all the elements satisfy the given predicate - -```rust -fn all(self, predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let all = arr.all(|a| a == 2); - assert(all); -} -``` - -### any - -Returns true if any of the elements satisfy the given predicate - -```rust -fn any(self, predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 5]; - let any = arr.any(|a| a == 5); - assert(any); -} - -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/booleans.md deleted file mode 100644 index 7211716f63e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/booleans.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Booleans -description: - Delve into the Boolean data type in Noir. Understand its methods, practical examples, and best practices for using Booleans in your Noir programs. -keywords: - [ - noir, - boolean type, - methods, - examples, - logical operations, - ] -sidebar_position: 2 ---- - - -The `bool` type in Noir has two possible values: `true` and `false`: - -```rust -fn main() { - let t = true; - let f: bool = false; -} -``` - -> **Note:** When returning a boolean value, it will show up as a value of 1 for `true` and 0 for -> `false` in _Verifier.toml_. - -The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and -[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/fields.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/fields.md deleted file mode 100644 index a10a4810788..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/fields.md +++ /dev/null @@ -1,192 +0,0 @@ ---- -title: Fields -description: - Dive deep into the Field data type in Noir. Understand its methods, practical examples, and best practices to effectively use Fields in your Noir programs. -keywords: - [ - noir, - field type, - methods, - examples, - best practices, - ] -sidebar_position: 0 ---- - -The field type corresponds to the native field type of the proving backend. - -The size of a Noir field depends on the elliptic curve's finite field for the proving backend -adopted. For example, a field would be a 254-bit integer when paired with the default backend that -spans the Grumpkin curve. - -Fields support integer arithmetic and are often used as the default numeric type in Noir: - -```rust -fn main(x : Field, y : Field) { - let z = x + y; -} -``` - -`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new -private value `z` constrained to be equal to `x + y`. - -If proving efficiency is of priority, fields should be used as a default for solving problems. -Smaller integer types (e.g. `u64`) incur extra range constraints. - -## Methods - -After declaring a Field, you can use these common methods on it: - -### to_le_bits - -Transforms the field into an array of bits, Little Endian. - -```rust -fn to_le_bits(_x : Field, _bit_size: u32) -> [u1] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_le_bits(32); -} -``` - -### to_be_bits - -Transforms the field into an array of bits, Big Endian. - -```rust -fn to_be_bits(_x : Field, _bit_size: u32) -> [u1] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_be_bits(32); -} -``` - -### to_le_bytes - -Transforms into an array of bytes, Little Endian - -```rust -fn to_le_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_le_bytes(4); -} -``` - -### to_be_bytes - -Transforms into an array of bytes, Big Endian - -```rust -fn to_be_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_be_bytes(4); -} -``` - -### to_le_radix - -Decomposes into a vector over the specified base, Little Endian - -```rust -fn to_le_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_le_radix(256, 4); -} -``` - -### to_be_radix - -Decomposes into a vector over the specified base, Big Endian - -```rust -fn to_be_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_be_radix(256, 4); -} -``` - -### pow_32 - -Returns the value to the power of the specified exponent - -```rust -fn pow_32(self, exponent: Field) -> Field -``` - -example: - -```rust -fn main() { - let field = 2 - let pow = field.pow_32(4); - assert(pow == 16); -} -``` - -### assert_max_bit_size - -Adds a constraint to specify that the field can be represented with `bit_size` number of bits - -```rust -fn assert_max_bit_size(self, bit_size: u32) -``` - -example: - -```rust -fn main() { - let field = 2 - field.assert_max_bit_size(32); -} -``` - -### sgn0 - -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. - -```rust -fn sgn0(self) -> u1 -``` - - -### lt - -Returns true if the field is less than the other field - -```rust -pub fn lt(self, another: Field) -> bool -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/function_types.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/function_types.md deleted file mode 100644 index f6121af17e2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/function_types.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Function types -sidebar_position: 10 ---- - -Noir supports higher-order functions. The syntax for a function type is as follows: - -```rust -fn(arg1_type, arg2_type, ...) -> return_type -``` - -Example: - -```rust -fn assert_returns_100(f: fn() -> Field) { // f takes no args and returns a Field - assert(f() == 100); -} - -fn main() { - assert_returns_100(|| 100); // ok - assert_returns_100(|| 150); // fails -} -``` - -A function type also has an optional capture environment - this is necessary to support closures. -See [Lambdas](../lambdas.md) for more details. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/index.md deleted file mode 100644 index 357813c147a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/index.md +++ /dev/null @@ -1,110 +0,0 @@ ---- -title: Data Types -description: - Get a clear understanding of the two categories of Noir data types - primitive types and compound - types. Learn about their characteristics, differences, and how to use them in your Noir - programming. -keywords: - [ - noir, - data types, - primitive types, - compound types, - private types, - public types, - ] ---- - -Every value in Noir has a type, which determines which operations are valid for it. - -All values in Noir are fundamentally composed of `Field` elements. For a more approachable -developing experience, abstractions are added on top to introduce different data types in Noir. - -Noir has two category of data types: primitive types (e.g. `Field`, integers, `bool`) and compound -types that group primitive types (e.g. arrays, tuples, structs). Each value can either be private or -public. - -## Private & Public Types - -A **private value** is known only to the Prover, while a **public value** is known by both the -Prover and Verifier. Mark values as `private` when the value should only be known to the prover. All -primitive types (including individual fields of compound types) in Noir are private by default, and -can be marked public when certain values are intended to be revealed to the Verifier. - -> **Note:** For public values defined in Noir programs paired with smart contract verifiers, once -> the proofs are verified on-chain the values can be considered known to everyone that has access to -> that blockchain. - -Public data types are treated no differently to private types apart from the fact that their values -will be revealed in proofs generated. Simply changing the value of a public type will not change the -circuit (where the same goes for changing values of private types as well). - -_Private values_ are also referred to as _witnesses_ sometimes. - -> **Note:** The terms private and public when applied to a type (e.g. `pub Field`) have a different -> meaning than when applied to a function (e.g. `pub fn foo() {}`). -> -> The former is a visibility modifier for the Prover to interpret if a value should be made known to -> the Verifier, while the latter is a visibility modifier for the compiler to interpret if a -> function should be made accessible to external Noir programs like in other languages. - -### pub Modifier - -All data types in Noir are private by default. Types are explicitly declared as public using the -`pub` modifier: - -```rust -fn main(x : Field, y : pub Field) -> pub Field { - x + y -} -``` - -In this example, `x` is **private** while `y` and `x + y` (the return value) are **public**. Note -that visibility is handled **per variable**, so it is perfectly valid to have one input that is -private and another that is public. - -> **Note:** Public types can only be declared through parameters on `main`. - -## Type Aliases - -A type alias is a new name for an existing type. Type aliases are declared with the keyword `type`: - -```rust -type Id = u8; - -fn main() { - let id: Id = 1; - let zero: u8 = 0; - assert(zero + 1 == id); -} -``` - -Type aliases can also be used with [generics](../generics.md): - -```rust -type Id = Size; - -fn main() { - let id: Id = 1; - let zero: u32 = 0; - assert(zero + 1 == id); -} -``` - -Type aliases can even refer to other aliases. An error will be issued if they form a cycle: - -```rust -// Ok! -type A = B; -type B = Field; - -type Bad1 = Bad2; - -// error: Dependency cycle found -type Bad2 = Bad1; -// ^^^^^^^^^^^ 'Bad2' recursively depends on itself: Bad2 -> Bad1 -> Bad2 -``` - -### BigInt - -You can achieve BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/integers.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/integers.md deleted file mode 100644 index 1c6b375db49..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/integers.md +++ /dev/null @@ -1,155 +0,0 @@ ---- -title: Integers -description: Explore the Integer data type in Noir. Learn about its methods, see real-world examples, and grasp how to efficiently use Integers in your Noir code. -keywords: [noir, integer types, methods, examples, arithmetic] -sidebar_position: 1 ---- - -An integer type is a range constrained field type. The Noir frontend supports both unsigned and signed integer types. The allowed sizes are 1, 8, 32 and 64 bits. - -:::info - -When an integer is defined in Noir without a specific type, it will default to `Field`. - -The one exception is for loop indices which default to `u64` since comparisons on `Field`s are not possible. - -::: - -## Unsigned Integers - -An unsigned integer type is specified first with the letter `u` (indicating its unsigned nature) followed by its bit size (e.g. `8`): - -```rust -fn main() { - let x: u8 = 1; - let y: u8 = 1; - let z = x + y; - assert (z == 2); -} -``` - -The bit size determines the maximum value the integer type can store. For example, a `u8` variable can store a value in the range of 0 to 255 (i.e. $\\2^{8}-1\\$). - -## Signed Integers - -A signed integer type is specified first with the letter `i` (which stands for integer) followed by its bit size (e.g. `8`): - -```rust -fn main() { - let x: i8 = -1; - let y: i8 = -1; - let z = x + y; - assert (z == -2); -} -``` - -The bit size determines the maximum and minimum range of value the integer type can store. For example, an `i8` variable can store a value in the range of -128 to 127 (i.e. $\\-2^{7}\\$ to $\\2^{7}-1\\$). - -## 128 bits Unsigned Integers - -The built-in structure `U128` allows you to use 128-bit unsigned integers almost like a native integer type. However, there are some differences to keep in mind: -- You cannot cast between a native integer and `U128` -- There is a higher performance cost when using `U128`, compared to a native type. - -Conversion between unsigned integer types and U128 are done through the use of `from_integer` and `to_integer` functions. `from_integer` also accepts the `Field` type as input. - -```rust -fn main() { - let x = U128::from_integer(23); - let y = U128::from_hex("0x7"); - let z = x + y; - assert(z.to_integer() == 30); -} -``` - -`U128` is implemented with two 64 bits limbs, representing the low and high bits, which explains the performance cost. You should expect `U128` to be twice more costly for addition and four times more costly for multiplication. -You can construct a U128 from its limbs: -```rust -fn main(x: u64, y: u64) { - let x = U128::from_u64s_be(x,y); - assert(z.hi == x as Field); - assert(z.lo == y as Field); -} -``` - -Note that the limbs are stored as Field elements in order to avoid unnecessary conversions. -Apart from this, most operations will work as usual: - -```rust -fn main(x: U128, y: U128) { - // multiplication - let c = x * y; - // addition and subtraction - let c = c - x + y; - // division - let c = x / y; - // bit operation; - let c = x & y | y; - // bit shift - let c = x << y; - // comparisons; - let c = x < y; - let c = x == y; -} -``` - -## Overflows - -Computations that exceed the type boundaries will result in overflow errors. This happens with both signed and unsigned integers. For example, attempting to prove: - -```rust -fn main(x: u8, y: u8) { - let z = x + y; -} -``` - -With: - -```toml -x = "255" -y = "1" -``` - -Would result in: - -``` -$ nargo prove -error: Assertion failed: 'attempt to add with overflow' -┌─ ~/src/main.nr:9:13 -│ -│ let z = x + y; -│ ----- -│ -= Call stack: - ... -``` - -A similar error would happen with signed integers: - -```rust -fn main() { - let x: i8 = -118; - let y: i8 = -11; - let z = x + y; -} -``` - -### Wrapping methods - -Although integer overflow is expected to error, some use-cases rely on wrapping. For these use-cases, the standard library provides `wrapping` variants of certain common operations: - -```rust -fn wrapping_add(x: T, y: T) -> T; -fn wrapping_sub(x: T, y: T) -> T; -fn wrapping_mul(x: T, y: T) -> T; -``` - -Example of how it is used: - -```rust -use dep::std; - -fn main(x: u8, y: u8) -> pub u8 { - std::wrapping_add(x, y) -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/references.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/references.md deleted file mode 100644 index a5293d11cfb..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/references.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: References -sidebar_position: 9 ---- - -Noir supports first-class references. References are a bit like pointers: they point to a specific address that can be followed to access the data stored at that address. You can use Rust-like syntax to use pointers in Noir: the `&` operator references the variable, the `*` operator dereferences it. - -Example: - -```rust -fn main() { - let mut x = 2; - - // you can reference x as &mut and pass it to multiplyBy2 - multiplyBy2(&mut x); -} - -// you can access &mut here -fn multiplyBy2(x: &mut Field) { - // and dereference it with * - *x = *x * 2; -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/slices.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/slices.mdx deleted file mode 100644 index 4eccc677b80..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/slices.mdx +++ /dev/null @@ -1,195 +0,0 @@ ---- -title: Slices -description: Explore the Slice data type in Noir. Understand its methods, see real-world examples, and learn how to effectively use Slices in your Noir programs. -keywords: [noir, slice type, methods, examples, subarrays] -sidebar_position: 5 ---- - -import Experimental from '@site/src/components/Notes/_experimental.mdx'; - - - -A slice is a dynamically-sized view into a sequence of elements. They can be resized at runtime, but because they don't own the data, they cannot be returned from a circuit. You can treat slices as arrays without a constrained size. - -```rust -use dep::std::slice; - -fn main() -> pub Field { - let mut slice: [Field] = &[0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -To write a slice literal, use a preceeding ampersand as in: `&[0; 2]` or -`&[1, 2, 3]`. - -It is important to note that slices are not references to arrays. In Noir, -`&[..]` is more similar to an immutable, growable vector. - -View the corresponding test file [here][test-file]. - -[test-file]: https://github.com/noir-lang/noir/blob/f387ec1475129732f72ba294877efdf6857135ac/crates/nargo_cli/tests/test_data_ssa_refactor/slices/src/main.nr - -## Methods - -For convenience, the STD provides some ready-to-use, common methods for slices: - -### push_back - -Pushes a new element to the end of the slice, returning a new slice with a length one greater than the original unmodified slice. - -```rust -fn push_back(_self: [T], _elem: T) -> [T] -``` - -example: - -```rust -fn main() -> pub Field { - let mut slice: [Field] = &[0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -View the corresponding test file [here][test-file]. - -### push_front - -Returns a new array with the specified element inserted at index 0. The existing elements indexes are incremented by 1. - -```rust -fn push_front(_self: Self, _elem: T) -> Self -``` - -Example: - -```rust -let mut new_slice: [Field] = &[]; -new_slice = new_slice.push_front(20); -assert(new_slice[0] == 20); // returns true -``` - -View the corresponding test file [here][test-file]. - -### pop_front - -Returns a tuple of two items, the first element of the array and the rest of the array. - -```rust -fn pop_front(_self: Self) -> (T, Self) -``` - -Example: - -```rust -let (first_elem, rest_of_slice) = slice.pop_front(); -``` - -View the corresponding test file [here][test-file]. - -### pop_back - -Returns a tuple of two items, the beginning of the array with the last element omitted and the last element. - -```rust -fn pop_back(_self: Self) -> (Self, T) -``` - -Example: - -```rust -let (popped_slice, last_elem) = slice.pop_back(); -``` - -View the corresponding test file [here][test-file]. - -### append - -Loops over a slice and adds it to the end of another. - -```rust -fn append(mut self, other: Self) -> Self -``` - -Example: - -```rust -let append = &[1, 2].append(&[3, 4, 5]); -``` - -### insert - -Inserts an element at a specified index and shifts all following elements by 1. - -```rust -fn insert(_self: Self, _index: Field, _elem: T) -> Self -``` - -Example: - -```rust -new_slice = rest_of_slice.insert(2, 100); -assert(new_slice[2] == 100); -``` - -View the corresponding test file [here][test-file]. - -### remove - -Remove an element at a specified index, shifting all elements after it to the left, returning the altered slice and the removed element. - -```rust -fn remove(_self: Self, _index: Field) -> (Self, T) -``` - -Example: - -```rust -let (remove_slice, removed_elem) = slice.remove(3); -``` - -### len - -Returns the length of a slice - -```rust -fn len(self) -> Field -``` - -Example: - -```rust -fn main() { - let slice = &[42, 42]; - assert(slice.len() == 2); -} -``` - -### as_array - -Converts this slice into an array. - -Make sure to specify the size of the resulting array. -Panics if the resulting array length is different than the slice's length. - -```rust -fn as_array(self) -> [T; N] -``` - -Example: - -```rust -fn main() { - let slice = &[5, 6]; - - // Always specify the length of the resulting array! - let array: [Field; 2] = slice.as_array(); - - assert(array[0] == slice[0]); - assert(array[1] == slice[1]); -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/strings.md deleted file mode 100644 index 8ab5825a4c4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/strings.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: Strings -description: - Discover the String data type in Noir. Learn about its methods, see real-world examples, and understand how to effectively manipulate and use Strings in Noir. -keywords: - [ - noir, - string type, - methods, - examples, - concatenation, - ] -sidebar_position: 3 ---- - - -The string type is a fixed length value defined with `str`. - -You can use strings in `assert()` functions or print them with -`println()`. See more about [Logging](../../standard_library/logging.md). - -```rust -use dep::std; - -fn main(message : pub str<11>, hex_as_string : str<4>) { - println(message); - assert(message == "hello world"); - assert(hex_as_string == "0x41"); -} -``` - -You can convert a `str` to a byte array by calling `as_bytes()` -or a vector by calling `as_bytes_vec()`. - -```rust -fn main() { - let message = "hello world"; - let message_bytes = message.as_bytes(); - let mut message_vec = message.as_bytes_vec(); - assert(message_bytes.len() == 11); - assert(message_bytes[0] == 104); - assert(message_bytes[0] == message_vec.get(0)); -} -``` - -## Escape characters - -You can use escape characters for your strings: - -| Escape Sequence | Description | -|-----------------|-----------------| -| `\r` | Carriage Return | -| `\n` | Newline | -| `\t` | Tab | -| `\0` | Null Character | -| `\"` | Double Quote | -| `\\` | Backslash | - -Example: - -```rust -let s = "Hello \"world" // prints "Hello "world" -let s = "hey \tyou"; // prints "hey you" -``` - -## Raw strings - -A raw string begins with the letter `r` and is optionally delimited by a number of hashes `#`. - -Escape characters are *not* processed within raw strings. All contents are interpreted literally. - -Example: - -```rust -let s = r"Hello world"; -let s = r#"Simon says "hello world""#; - -// Any number of hashes may be used (>= 1) as long as the string also terminates with the same number of hashes -let s = r#####"One "#, Two "##, Three "###, Four "####, Five will end the string."#####; -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/structs.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/structs.md deleted file mode 100644 index dbf68c99813..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/structs.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -title: Structs -description: - Explore the Struct data type in Noir. Learn about its methods, see real-world examples, and grasp how to effectively define and use Structs in your Noir programs. -keywords: - [ - noir, - struct type, - methods, - examples, - data structures, - ] -sidebar_position: 8 ---- - -A struct also allows for grouping multiple values of different types. Unlike tuples, we can also -name each field. - -> **Note:** The usage of _field_ here refers to each element of the struct and is unrelated to the -> field type of Noir. - -Defining a struct requires giving it a name and listing each field within as `: ` pairs: - -```rust -struct Animal { - hands: Field, - legs: Field, - eyes: u8, -} -``` - -An instance of a struct can then be created with actual values in `: ` pairs in any -order. Struct fields are accessible using their given names: - -```rust -fn main() { - let legs = 4; - - let dog = Animal { - eyes: 2, - hands: 0, - legs, - }; - - let zero = dog.hands; -} -``` - -Structs can also be destructured in a pattern, binding each field to a new variable: - -```rust -fn main() { - let Animal { hands, legs: feet, eyes } = get_octopus(); - - let ten = hands + feet + eyes as u8; -} - -fn get_octopus() -> Animal { - let octopus = Animal { - hands: 0, - legs: 8, - eyes: 2, - }; - - octopus -} -``` - -The new variables can be bound with names different from the original struct field names, as -showcased in the `legs --> feet` binding in the example above. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/tuples.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/tuples.md deleted file mode 100644 index 2ec5c9c4113..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/tuples.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Tuples -description: - Dive into the Tuple data type in Noir. Understand its methods, practical examples, and best practices for efficiently using Tuples in your Noir code. -keywords: - [ - noir, - tuple type, - methods, - examples, - multi-value containers, - ] -sidebar_position: 7 ---- - -A tuple collects multiple values like an array, but with the added ability to collect values of -different types: - -```rust -fn main() { - let tup: (u8, u64, Field) = (255, 500, 1000); -} -``` - -One way to access tuple elements is via destructuring using pattern matching: - -```rust -fn main() { - let tup = (1, 2); - - let (one, two) = tup; - - let three = one + two; -} -``` - -Another way to access tuple elements is via direct member access, using a period (`.`) followed by -the index of the element we want to access. Index `0` corresponds to the first tuple element, `1` to -the second and so on: - -```rust -fn main() { - let tup = (5, 6, 7, 8); - - let five = tup.0; - let eight = tup.3; -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/functions.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/functions.md deleted file mode 100644 index f656cdfd97a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/functions.md +++ /dev/null @@ -1,226 +0,0 @@ ---- -title: Functions -description: - Learn how to declare functions and methods in Noir, a programming language with Rust semantics. - This guide covers parameter declaration, return types, call expressions, and more. -keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] -sidebar_position: 1 ---- - -Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. - -To declare a function the `fn` keyword is used. - -```rust -fn foo() {} -``` - -By default, functions are visible only within the package they are defined. To make them visible outside of that package (for example, as part of a [library](../modules_packages_crates/crates_and_packages.md#libraries)), you should mark them as `pub`: - -```rust -pub fn foo() {} -``` - -You can also restrict the visibility of the function to only the crate it was defined in, by specifying `pub(crate)`: - -```rust -pub(crate) fn foo() {} //foo can only be called within its crate -``` - -All parameters in a function must have a type and all types are known at compile time. The parameter -is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. - -```rust -fn foo(x : Field, y : Field){} -``` - -The return type of a function can be stated by using the `->` arrow notation. The function below -states that the foo function must return a `Field`. If the function returns no value, then the arrow -is omitted. - -```rust -fn foo(x : Field, y : Field) -> Field { - x + y -} -``` - -Note that a `return` keyword is unneeded in this case - the last expression in a function's body is -returned. - -## Main function - -If you're writing a binary, the `main` function is the starting point of your program. You can pass all types of expressions to it, as long as they have a fixed size at compile time: - -```rust -fn main(x : Field) // this is fine: passing a Field -fn main(x : [Field; 2]) // this is also fine: passing a Field with known size at compile-time -fn main(x : (Field, bool)) // 👌: passing a (Field, bool) tuple means size 2 -fn main(x : str<5>) // this is fine, as long as you pass a string of size 5 - -fn main(x : Vec) // can't compile, has variable size -fn main(x : [Field]) // can't compile, has variable size -fn main(....// i think you got it by now -``` - -Keep in mind [tests](../../tooling/testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: - -```rust -fn main(x : [Field]) { - assert(x[0] == 1); -} - -#[test] -fn test_one() { - main(&[1, 2]); -} -``` - -```bash -$ nargo test -[testing] Running 1 test functions -[testing] Testing test_one... ok -[testing] All tests passed - -$ nargo check -The application panicked (crashed). -Message: Cannot have variable sized arrays as a parameter to main -``` - -## Call Expressions - -Calling a function in Noir is executed by using the function name and passing in the necessary -arguments. - -Below we show how to call the `foo` function from the `main` function using a call expression: - -```rust -fn main(x : Field, y : Field) { - let z = foo(x); -} - -fn foo(x : Field) -> Field { - x + x -} -``` - -## Methods - -You can define methods in Noir on any struct type in scope. - -```rust -struct MyStruct { - foo: Field, - bar: Field, -} - -impl MyStruct { - fn new(foo: Field) -> MyStruct { - MyStruct { - foo, - bar: 2, - } - } - - fn sum(self) -> Field { - self.foo + self.bar - } -} - -fn main() { - let s = MyStruct::new(40); - assert(s.sum() == 42); -} -``` - -Methods are just syntactic sugar for functions, so if we wanted to we could also call `sum` as -follows: - -```rust -assert(MyStruct::sum(s) == 42); -``` - -It is also possible to specialize which method is chosen depending on the [generic](./generics.md) type that is used. In this example, the `foo` function returns different values depending on its type: - -```rust -struct Foo {} - -impl Foo { - fn foo(self) -> Field { 1 } -} - -impl Foo { - fn foo(self) -> Field { 2 } -} - -fn main() { - let f1: Foo = Foo{}; - let f2: Foo = Foo{}; - assert(f1.foo() + f2.foo() == 3); -} -``` - -Also note that impls with the same method name defined in them cannot overlap. For example, if we already have `foo` defined for `Foo` and `Foo` like we do above, we cannot also define `foo` in an `impl Foo` since it would be ambiguous which version of `foo` to choose. - -```rust -// Including this impl in the same project as the above snippet would -// cause an overlapping impls error -impl Foo { - fn foo(self) -> Field { 3 } -} -``` - -## Lambdas - -Lambdas are anonymous functions. They follow the syntax of Rust - `|arg1, arg2, ..., argN| return_expression`. - -```rust -let add_50 = |val| val + 50; -assert(add_50(100) == 150); -``` - -See [Lambdas](./lambdas.md) for more details. - -## Attributes - -Attributes are metadata that can be applied to a function, using the following syntax: `#[attribute(value)]`. - -Supported attributes include: - -- **builtin**: the function is implemented by the compiler, for efficiency purposes. -- **deprecated**: mark the function as _deprecated_. Calling the function will generate a warning: `warning: use of deprecated function` -- **field**: Used to enable conditional compilation of code depending on the field size. See below for more details -- **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./unconstrained.md) and [NoirJS](../../reference/NoirJS/noir_js/index.md) for more details. -- **test**: mark the function as unit tests. See [Tests](../../tooling/testing.md) for more details - -### Field Attribute - -The field attribute defines which field the function is compatible for. The function is conditionally compiled, under the condition that the field attribute matches the Noir native field. -The field can be defined implicitly, by using the name of the elliptic curve usually associated to it - for instance bn254, bls12_381 - or explicitly by using the field (prime) order, in decimal or hexadecimal form. -As a result, it is possible to define multiple versions of a function with each version specialized for a different field attribute. This can be useful when a function requires different parameters depending on the underlying elliptic curve. - -Example: we define the function `foo()` three times below. Once for the default Noir bn254 curve, once for the field $\mathbb F_{23}$, which will normally never be used by Noir, and once again for the bls12_381 curve. - -```rust -#[field(bn254)] -fn foo() -> u32 { - 1 -} - -#[field(23)] -fn foo() -> u32 { - 2 -} - -// This commented code would not compile as foo would be defined twice because it is the same field as bn254 -// #[field(21888242871839275222246405745257275088548364400416034343698204186575808495617)] -// fn foo() -> u32 { -// 2 -// } - -#[field(bls12_381)] -fn foo() -> u32 { - 3 -} -``` - -If the field name is not known to Noir, it will discard the function. Field names are case insensitive. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/generics.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/generics.md deleted file mode 100644 index 0c1c27a2221..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/generics.md +++ /dev/null @@ -1,106 +0,0 @@ ---- -title: Generics -description: Learn how to use Generics in Noir -keywords: [Noir, Rust, generics, functions, structs] -sidebar_position: 7 ---- - -Generics allow you to use the same functions with multiple different concrete data types. You can -read more about the concept of generics in the Rust documentation -[here](https://doc.rust-lang.org/book/ch10-01-syntax.html). - -Here is a trivial example showing the identity function that supports any type. In Rust, it is -common to refer to the most general type as `T`. We follow the same convention in Noir. - -```rust -fn id(x: T) -> T { - x -} -``` - -## In Structs - -Generics are useful for specifying types in structs. For example, we can specify that a field in a -struct will be of a certain generic type. In this case `value` is of type `T`. - -```rust -struct RepeatedValue { - value: T, - count: Field, -} - -impl RepeatedValue { - fn print(self) { - for _i in 0 .. self.count { - println(self.value); - } - } -} - -fn main() { - let repeated = RepeatedValue { value: "Hello!", count: 2 }; - repeated.print(); -} -``` - -The `print` function will print `Hello!` an arbitrary number of times, twice in this case. - -If we want to be generic over array lengths (which are type-level integers), we can use numeric -generics. Using these looks just like using regular generics, but these generics can resolve to -integers at compile-time, rather than resolving to types. Here's an example of a struct that is -generic over the size of the array it contains internally: - -```rust -struct BigInt { - limbs: [u32; N], -} - -impl BigInt { - // `N` is in scope of all methods in the impl - fn first(first: BigInt, second: BigInt) -> Self { - assert(first.limbs != second.limbs); - first - - fn second(first: BigInt, second: Self) -> Self { - assert(first.limbs != second.limbs); - second - } -} -``` - -## Calling functions on generic parameters - -Since a generic type `T` can represent any type, how can we call functions on the underlying type? -In other words, how can we go from "any type `T`" to "any type `T` that has certain methods available?" - -This is what [traits](../concepts/traits.md) are for in Noir. Here's an example of a function generic over -any type `T` that implements the `Eq` trait for equality: - -```rust -fn first_element_is_equal(array1: [T; N], array2: [T; N]) -> bool - where T: Eq -{ - if (array1.len() == 0) | (array2.len() == 0) { - true - } else { - array1[0] == array2[0] - } -} - -fn main() { - assert(first_element_is_equal([1, 2, 3], [1, 5, 6])); - - // We can use first_element_is_equal for arrays of any type - // as long as we have an Eq impl for the types we pass in - let array = [MyStruct::new(), MyStruct::new()]; - assert(array_eq(array, array, MyStruct::eq)); -} - -impl Eq for MyStruct { - fn eq(self, other: MyStruct) -> bool { - self.foo == other.foo - } -} -``` - -You can find more details on traits and trait implementations on the [traits page](../concepts/traits.md). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/globals.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/globals.md deleted file mode 100644 index 063a3d89248..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/globals.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -title: Global Variables -description: - Learn about global variables in Noir. Discover how - to declare, modify, and use them in your programs. -keywords: [noir programming language, globals, global variables, constants] -sidebar_position: 8 ---- - -## Globals - - -Noir supports global variables. The global's type can be inferred by the compiler entirely: - -```rust -global N = 5; // Same as `global N: Field = 5` - -global TUPLE = (3, 2); - -fn main() { - assert(N == 5); - assert(N == TUPLE.0 + TUPLE.1); -} -``` - -:::info - -Globals can be defined as any expression, so long as they don't depend on themselves - otherwise there would be a dependency cycle! For example: - -```rust -global T = foo(T); // dependency error -``` - -::: - - -If they are initialized to a literal integer, globals can be used to specify an array's length: - -```rust -global N: Field = 2; - -fn main(y : [Field; N]) { - assert(y[0] == y[1]) -} -``` - -A global from another module can be imported or referenced externally like any other name: - -```rust -global N = 20; - -fn main() { - assert(my_submodule::N != N); -} - -mod my_submodule { - global N: Field = 10; -} -``` - -When a global is used, Noir replaces the name with its definition on each occurrence. -This means globals defined using function calls will repeat the call each time they're used: - -```rust -global RESULT = foo(); - -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. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/lambdas.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/lambdas.md deleted file mode 100644 index be3c7e0b5ca..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/lambdas.md +++ /dev/null @@ -1,81 +0,0 @@ ---- -title: Lambdas -description: Learn how to use anonymous functions in Noir programming language. -keywords: [Noir programming language, lambda, closure, function, anonymous function] -sidebar_position: 9 ---- - -## Introduction - -Lambdas are anonymous functions. The syntax is `|arg1, arg2, ..., argN| return_expression`. - -```rust -let add_50 = |val| val + 50; -assert(add_50(100) == 150); -``` - -A block can be used as the body of a lambda, allowing you to declare local variables inside it: - -```rust -let cool = || { - let x = 100; - let y = 100; - x + y -} - -assert(cool() == 200); -``` - -## Closures - -Inside the body of a lambda, you can use variables defined in the enclosing function. Such lambdas are called **closures**. In this example `x` is defined inside `main` and is accessed from within the lambda: - -```rust -fn main() { - let x = 100; - let closure = || x + 150; - assert(closure() == 250); -} -``` - -## Passing closures to higher-order functions - -It may catch you by surprise that the following code fails to compile: - -```rust -fn foo(f: fn () -> Field) -> Field { - f() -} - -fn main() { - let (x, y) = (50, 50); - assert(foo(|| x + y) == 100); // error :( -} -``` - -The reason is that the closure's capture environment affects its type - we have a closure that captures two Fields and `foo` -expects a regular function as an argument - those are incompatible. -:::note - -Variables contained within the `||` are the closure's parameters, and the expression that follows it is the closure's body. The capture environment is comprised of any variables used in the closure's body that are not parameters. - -E.g. in |x| x + y, y would be a captured variable, but x would not be, since it is a parameter of the closure. - -::: -The syntax for the type of a closure is `fn[env](args) -> ret_type`, where `env` is the capture environment of the closure - -in this example that's `(Field, Field)`. - -The best solution in our case is to make `foo` generic over the environment type of its parameter, so that it can be called -with closures with any environment, as well as with regular functions: - -```rust -fn foo(f: fn[Env]() -> Field) -> Field { - f() -} - -fn main() { - let (x, y) = (50, 50); - assert(foo(|| x + y) == 100); // compiles fine - assert(foo(|| 60) == 60); // compiles fine -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/mutability.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/mutability.md deleted file mode 100644 index fdeef6a87c5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/mutability.md +++ /dev/null @@ -1,121 +0,0 @@ ---- -title: Mutability -description: - Learn about mutable variables in Noir. Discover how - to declare, modify, and use them in your programs. -keywords: [noir programming language, mutability in noir, mutable variables] -sidebar_position: 8 ---- - -Variables in noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned -to via an assignment expression. - -```rust -let x = 2; -x = 3; // error: x must be mutable to be assigned to - -let mut y = 3; -let y = 4; // OK -``` - -The `mut` modifier can also apply to patterns: - -```rust -let (a, mut b) = (1, 2); -a = 11; // error: a must be mutable to be assigned to -b = 12; // OK - -let mut (c, d) = (3, 4); -c = 13; // OK -d = 14; // OK - -// etc. -let MyStruct { x: mut y } = MyStruct { x: a }; -// y is now in scope -``` - -Note that mutability in noir is local and everything is passed by value, so if a called function -mutates its parameters then the parent function will keep the old value of the parameters. - -```rust -fn main() -> pub Field { - let x = 3; - helper(x); - x // x is still 3 -} - -fn helper(mut x: i32) { - x = 4; -} -``` - -## Non-local mutability - -Non-local mutability can be achieved through the mutable reference type `&mut T`: - -```rust -fn set_to_zero(x: &mut Field) { - *x = 0; -} - -fn main() { - let mut y = 42; - set_to_zero(&mut y); - assert(*y == 0); -} -``` - -When creating a mutable reference, the original variable being referred to (`y` in this -example) must also be mutable. Since mutable references are a reference type, they must -be explicitly dereferenced via `*` to retrieve the underlying value. Note that this yields -a copy of the value, so mutating this copy will not change the original value behind the -reference: - -```rust -fn main() { - let mut x = 1; - let x_ref = &mut x; - - let mut y = *x_ref; - let y_ref = &mut y; - - x = 2; - *x_ref = 3; - - y = 4; - *y_ref = 5; - - assert(x == 3); - assert(*x_ref == 3); - assert(y == 5); - assert(*y_ref == 5); -} -``` - -Note that types in Noir are actually deeply immutable so the copy that occurs when -dereferencing is only a conceptual copy - no additional constraints will occur. - -Mutable references can also be stored within structs. Note that there is also -no lifetime parameter on these unlike rust. This is because the allocated memory -always lasts the entire program - as if it were an array of one element. - -```rust -struct Foo { - x: &mut Field -} - -impl Foo { - fn incr(mut self) { - *self.x += 1; - } -} - -fn main() { - let foo = Foo { x: &mut 0 }; - foo.incr(); - assert(*foo.x == 1); -} -``` - -In general, you should avoid non-local & shared mutability unless it is needed. Sticking -to only local mutability will improve readability and potentially improve compiler optimizations as well. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/oracles.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/oracles.md deleted file mode 100644 index aa380b5f7b8..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/oracles.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Oracles -description: Dive into how Noir supports Oracles via RPC calls, and learn how to declare an Oracle in Noir with our comprehensive guide. -keywords: - - Noir - - Oracles - - RPC Calls - - Unconstrained Functions - - Programming - - Blockchain -sidebar_position: 6 ---- - -:::note - -This is an experimental feature that is not fully documented. If you notice any outdated information or potential improvements to this page, pull request contributions are very welcome: https://github.com/noir-lang/noir - -::: - -Noir has support for Oracles via RPC calls. This means Noir will make an RPC call and use the return value for proof generation. - -Since Oracles are not resolved by Noir, they are [`unconstrained` functions](./unconstrained.md) - -You can declare an Oracle through the `#[oracle()]` flag. Example: - -```rust -#[oracle(get_number_sequence)] -unconstrained fn get_number_sequence(_size: Field) -> [Field] {} -``` - -The timeout for when using an external RPC oracle resolver can be set with the `NARGO_FOREIGN_CALL_TIMEOUT` environment variable. This timeout is in units of milliseconds. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/shadowing.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/shadowing.md deleted file mode 100644 index 5ce6130d201..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/shadowing.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Shadowing -sidebar_position: 12 ---- - -Noir allows for inheriting variables' values and re-declaring them with the same name similar to Rust, known as shadowing. - -For example, the following function is valid in Noir: - -```rust -fn main() { - let x = 5; - - { - let x = x * 2; - assert (x == 10); - } - - assert (x == 5); -} -``` - -In this example, a variable x is first defined with the value 5. - -The local scope that follows shadows the original x, i.e. creates a local mutable x based on the value of the original x. It is given a value of 2 times the original x. - -When we return to the main scope, x once again refers to just the original x, which stays at the value of 5. - -## Temporal mutability - -One way that shadowing is useful, in addition to ergonomics across scopes, is for temporarily mutating variables. - -```rust -fn main() { - let age = 30; - // age = age + 5; // Would error as `age` is immutable by default. - - let mut age = age + 5; // Temporarily mutates `age` with a new value. - - let age = age; // Locks `age`'s mutability again. - - assert (age == 35); -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/traits.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/traits.md deleted file mode 100644 index ef1445a5907..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/traits.md +++ /dev/null @@ -1,389 +0,0 @@ ---- -title: Traits -description: - Traits in Noir can be used to abstract out a common interface for functions across - several data types. -keywords: [noir programming language, traits, interfaces, generic, protocol] -sidebar_position: 14 ---- - -## Overview - -Traits in Noir are a useful abstraction similar to interfaces or protocols in other languages. Each trait defines -the interface of several methods contained within the trait. Types can then implement this trait by providing -implementations for these methods. For example in the program: - -```rust -struct Rectangle { - width: Field, - height: Field, -} - -impl Rectangle { - fn area(self) -> Field { - self.width * self.height - } -} - -fn log_area(r: Rectangle) { - println(r.area()); -} -``` - -We have a function `log_area` to log the area of a `Rectangle`. Now how should we change the program if we want this -function to work on `Triangle`s as well?: - -```rust -struct Triangle { - width: Field, - height: Field, -} - -impl Triangle { - fn area(self) -> Field { - self.width * self.height / 2 - } -} -``` - -Making `log_area` generic over all types `T` would be invalid since not all types have an `area` method. Instead, we can -introduce a new `Area` trait and make `log_area` generic over all types `T` that implement `Area`: - -```rust -trait Area { - fn area(self) -> Field; -} - -fn log_area(shape: T) where T: Area { - println(shape.area()); -} -``` - -We also need to explicitly implement `Area` for `Rectangle` and `Triangle`. We can do that by changing their existing -impls slightly. Note that the parameter types and return type of each of our `area` methods must match those defined -by the `Area` trait. - -```rust -impl Area for Rectangle { - fn area(self) -> Field { - self.width * self.height - } -} - -impl Area for Triangle { - fn area(self) -> Field { - self.width * self.height / 2 - } -} -``` - -Now we have a working program that is generic over any type of Shape that is used! Others can even use this program -as a library with their own types - such as `Circle` - as long as they also implement `Area` for these types. - -## Where Clauses - -As seen in `log_area` above, when we want to create a function or method that is generic over any type that implements -a trait, we can add a where clause to the generic function. - -```rust -fn log_area(shape: T) where T: Area { - println(shape.area()); -} -``` - -It is also possible to apply multiple trait constraints on the same variable at once by combining traits with the `+` -operator. Similarly, we can have multiple trait constraints by separating each with a comma: - -```rust -fn foo(elements: [T], thing: U) where - T: Default + Add + Eq, - U: Bar, -{ - let mut sum = T::default(); - - for element in elements { - sum += element; - } - - if sum == T::default() { - thing.bar(); - } -} -``` - -## Generic Implementations - -You can add generics to a trait implementation by adding the generic list after the `impl` keyword: - -```rust -trait Second { - fn second(self) -> Field; -} - -impl Second for (T, Field) { - fn second(self) -> Field { - self.1 - } -} -``` - -You can also implement a trait for every type this way: - -```rust -trait Debug { - fn debug(self); -} - -impl Debug for T { - fn debug(self) { - println(self); - } -} - -fn main() { - 1.debug(); -} -``` - -### Generic Trait Implementations With Where Clauses - -Where clauses can also be placed on trait implementations themselves to restrict generics in a similar way. -For example, while `impl Foo for T` implements the trait `Foo` for every type, `impl Foo for T where T: Bar` -will implement `Foo` only for types that also implement `Bar`. This is often used for implementing generic types. -For example, here is the implementation for array equality: - -```rust -impl Eq for [T; N] where T: Eq { - // Test if two arrays have the same elements. - // Because both arrays must have length N, we know their lengths already match. - fn eq(self, other: Self) -> bool { - let mut result = true; - - for i in 0 .. self.len() { - // The T: Eq constraint is needed to call == on the array elements here - result &= self[i] == other[i]; - } - - result - } -} -``` - -## Generic Traits - -Traits themselves can also be generic by placing the generic arguments after the trait name. These generics are in -scope of every item within the trait. - -```rust -trait Into { - // Convert `self` to type `T` - fn into(self) -> T; -} -``` - -When implementing generic traits the generic arguments of the trait must be specified. This is also true anytime -when referencing a generic trait (e.g. in a `where` clause). - -```rust -struct MyStruct { - array: [Field; 2], -} - -impl Into<[Field; 2]> for MyStruct { - fn into(self) -> [Field; 2] { - self.array - } -} - -fn as_array(x: T) -> [Field; 2] - where T: Into<[Field; 2]> -{ - x.into() -} - -fn main() { - let array = [1, 2]; - let my_struct = MyStruct { array }; - - assert_eq(as_array(my_struct), array); -} -``` - -## Trait Methods With No `self` - -A trait can contain any number of methods, each of which have access to the `Self` type which represents each type -that eventually implements the trait. Similarly, the `self` variable is available as well but is not required to be used. -For example, we can define a trait to create a default value for a type. This trait will need to return the `Self` type -but doesn't need to take any parameters: - -```rust -trait Default { - fn default() -> Self; -} -``` - -Implementing this trait can be done similarly to any other trait: - -```rust -impl Default for Field { - fn default() -> Field { - 0 - } -} - -struct MyType {} - -impl Default for MyType { - fn default() -> Field { - MyType {} - } -} -``` - -However, since there is no `self` parameter, we cannot call it via the method call syntax `object.method()`. -Instead, we'll need to refer to the function directly. This can be done either by referring to the -specific impl `MyType::default()` or referring to the trait itself `Default::default()`. In the later -case, type inference determines the impl that is selected. - -```rust -let my_struct = MyStruct::default(); - -let x: Field = Default::default(); -let result = x + Default::default(); -``` - -:::warning - -```rust -let _ = Default::default(); -``` - -If type inference cannot select which impl to use because of an ambiguous `Self` type, an impl will be -arbitrarily selected. This occurs most often when the result of a trait function call with no parameters -is unused. To avoid this, when calling a trait function with no `self` or `Self` parameters or return type, -always refer to it via the implementation type's namespace - e.g. `MyType::default()`. -This is set to change to an error in future Noir versions. - -::: - -## Default Method Implementations - -A trait can also have default implementations of its methods by giving a body to the desired functions. -Note that this body must be valid for all types that may implement the trait. As a result, the only -valid operations on `self` will be operations valid for any type or other operations on the trait itself. - -```rust -trait Numeric { - fn add(self, other: Self) -> Self; - - // Default implementation of double is (self + self) - fn double(self) -> Self { - self.add(self) - } -} -``` - -When implementing a trait with default functions, a type may choose to implement only the required functions: - -```rust -impl Numeric for Field { - fn add(self, other: Field) -> Field { - self + other - } -} -``` - -Or it may implement the optional methods as well: - -```rust -impl Numeric for u32 { - fn add(self, other: u32) -> u32 { - self + other - } - - fn double(self) -> u32 { - self * 2 - } -} -``` - -## Impl Specialization - -When implementing traits for a generic type it is possible to implement the trait for only a certain combination -of generics. This can be either as an optimization or because those specific generics are required to implement the trait. - -```rust -trait Sub { - fn sub(self, other: Self) -> Self; -} - -struct NonZero { - value: T, -} - -impl Sub for NonZero { - fn sub(self, other: Self) -> Self { - let value = self.value - other.value; - assert(value != 0); - NonZero { value } - } -} -``` - -## Overlapping Implementations - -Overlapping implementations are disallowed by Noir to ensure Noir's decision on which impl to select is never ambiguous. -This means if a trait `Foo` is already implemented -by a type `Bar` for all `T`, then we cannot also have a separate impl for `Bar` (or any other -type argument). Similarly, if there is an impl for all `T` such as `impl Debug for T`, we cannot create -any more impls to `Debug` for other types since it would be ambiguous which impl to choose for any given -method call. - -```rust -trait Trait {} - -// Previous impl defined here -impl Trait for (A, B) {} - -// error: Impl for type `(Field, Field)` overlaps with existing impl -impl Trait for (Field, Field) {} -``` - -## Trait Coherence - -Another restriction on trait implementations is coherence. This restriction ensures other crates cannot create -impls that may overlap with other impls, even if several unrelated crates are used as dependencies in the same -program. - -The coherence restriction is: to implement a trait, either the trait itself or the object type must be declared -in the crate the impl is in. - -In practice this often comes up when using types provided by libraries. If a library provides a type `Foo` that does -not implement a trait in the standard library such as `Default`, you may not `impl Default for Foo` in your own crate. -While restrictive, this prevents later issues or silent changes in the program if the `Foo` library later added its -own impl for `Default`. If you are a user of the `Foo` library in this scenario and need a trait not implemented by the -library your choices are to either submit a patch to the library or use the newtype pattern. - -### The Newtype Pattern - -The newtype pattern gets around the coherence restriction by creating a new wrapper type around the library type -that we cannot create `impl`s for. Since the new wrapper type is defined in our current crate, we can create -impls for any trait we need on it. - -```rust -struct Wrapper { - foo: dep::some_library::Foo, -} - -impl Default for Wrapper { - fn default() -> Wrapper { - Wrapper { - foo: dep::some_library::Foo::new(), - } - } -} -``` - -Since we have an impl for our own type, the behavior of this code will not change even if `some_library` is updated -to provide its own `impl Default for Foo`. The downside of this pattern is that it requires extra wrapping and -unwrapping of values when converting to and from the `Wrapper` and `Foo` types. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/unconstrained.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/unconstrained.md deleted file mode 100644 index 96f824c5e42..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/unconstrained.md +++ /dev/null @@ -1,99 +0,0 @@ ---- -title: Unconstrained Functions -description: "Learn about what unconstrained functions in Noir are, how to use them and when you'd want to." - -keywords: [Noir programming language, unconstrained, open] -sidebar_position: 5 ---- - -Unconstrained functions are functions which do not constrain any of the included computation and allow for non-deterministic computation. - -## Why? - -Zero-knowledge (ZK) domain-specific languages (DSL) enable developers to generate ZK proofs from their programs by compiling code down to the constraints of an NP complete language (such as R1CS or PLONKish languages). However, the hard bounds of a constraint system can be very limiting to the functionality of a ZK DSL. - -Enabling a circuit language to perform unconstrained execution is a powerful tool. Said another way, unconstrained execution lets developers generate witnesses from code that does not generate any constraints. Being able to execute logic outside of a circuit is critical for both circuit performance and constructing proofs on information that is external to a circuit. - -Fetching information from somewhere external to a circuit can also be used to enable developers to improve circuit efficiency. - -A ZK DSL does not just prove computation, but proves that some computation was handled correctly. Thus, it is necessary that when we switch from performing some operation directly inside of a circuit to inside of an unconstrained environment that the appropriate constraints are still laid down elsewhere in the circuit. - -## Example - -An in depth example might help drive the point home. This example comes from the excellent [post](https://discord.com/channels/1113924620781883405/1124022445054111926/1128747641853972590) by Tom in the Noir Discord. - -Let's look at how we can optimize a function to turn a `u72` into an array of `u8`s. - -```rust -fn main(num: u72) -> pub [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8)) as u72 & 0xff) as u8; - } - - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 91 -Backend circuit size: 3619 -``` - -A lot of the operations in this function are optimized away by the compiler (all the bit-shifts turn into divisions by constants). However we can save a bunch of gates by casting to u8 a bit earlier. This automatically truncates the bit-shifted value to fit in a u8 which allows us to remove the AND against 0xff. This saves us ~480 gates in total. - -```rust -fn main(num: u72) -> pub [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8)) as u8; - } - - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 75 -Backend circuit size: 3143 -``` - -Those are some nice savings already but we can do better. This code is all constrained so we're proving every step of calculating out using num, but we don't actually care about how we calculate this, just that it's correct. This is where brillig comes in. - -It turns out that truncating a u72 into a u8 is hard to do inside a snark, each time we do as u8 we lay down 4 ACIR opcodes which get converted into multiple gates. It's actually much easier to calculate num from out than the other way around. All we need to do is multiply each element of out by a constant and add them all together, both relatively easy operations inside a snark. - -We can then run u72_to_u8 as unconstrained brillig code in order to calculate out, then use that result in our constrained function and assert that if we were to do the reverse calculation we'd get back num. This looks a little like the below: - -```rust -fn main(num: u72) -> pub [u8; 8] { - let out = u72_to_u8(num); - - let mut reconstructed_num: u72 = 0; - for i in 0..8 { - reconstructed_num += (out[i] as u72 << (56 - (8 * i))); - } - assert(num == reconstructed_num); - out -} - -unconstrained fn u72_to_u8(num: u72) -> [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8))) as u8; - } - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 78 -Backend circuit size: 2902 -``` - -This ends up taking off another ~250 gates from our circuit! We've ended up with more ACIR opcodes than before but they're easier for the backend to prove (resulting in fewer gates). - -Generally we want to use brillig whenever there's something that's easy to verify but hard to compute within the circuit. For example, if you wanted to calculate a square root of a number it'll be a much better idea to calculate this in brillig and then assert that if you square the result you get back your number. - -## Break and Continue - -In addition to loops over runtime bounds, `break` and `continue` are also available in unconstrained code. See [break and continue](../concepts/control_flow.md#break-and-continue) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/_category_.json deleted file mode 100644 index 1debcfe7675..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Modules, Packages and Crates", - "position": 2, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/crates_and_packages.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/crates_and_packages.md deleted file mode 100644 index 95ee9f52ab2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/crates_and_packages.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Crates and Packages -description: Learn how to use Crates and Packages in your Noir project -keywords: [Nargo, dependencies, package management, crates, package] -sidebar_position: 0 ---- - -## Crates - -A crate is the smallest amount of code that the Noir compiler considers at a time. -Crates can contain modules, and the modules may be defined in other files that get compiled with the crate, as we’ll see in the coming sections. - -### Crate Types - -A Noir crate can come in several forms: binaries, libraries or contracts. - -#### Binaries - -_Binary crates_ are programs which you can compile to an ACIR circuit which you can then create proofs against. Each must have a function called `main` that defines the ACIR circuit which is to be proved. - -#### Libraries - -_Library crates_ don't have a `main` function and they don't compile down to ACIR. Instead they define functionality intended to be shared with multiple projects, and eventually included in a binary crate. - -#### Contracts - -Contract crates are similar to binary crates in that they compile to ACIR which you can create proofs against. They are different in that they do not have a single `main` function, but are a collection of functions to be deployed to the [Aztec network](https://aztec.network). You can learn more about the technical details of Aztec in the [monorepo](https://github.com/AztecProtocol/aztec-packages) or contract [examples](https://github.com/AztecProtocol/aztec-packages/tree/master/noir-projects/noir-contracts/contracts). - -### Crate Root - -Every crate has a root, which is the source file that the compiler starts, this is also known as the root module. The Noir compiler does not enforce any conditions on the name of the file which is the crate root, however if you are compiling via Nargo the crate root must be called `lib.nr` or `main.nr` for library or binary crates respectively. - -## Packages - -A Nargo _package_ is a collection of one of more crates that provides a set of functionality. A package must include a Nargo.toml file. - -A package _must_ contain either a library or a binary crate, but not both. - -### Differences from Cargo Packages - -One notable difference between Rust's Cargo and Noir's Nargo is that while Cargo allows a package to contain an unlimited number of binary crates and a single library crate, Nargo currently only allows a package to contain a single crate. - -In future this restriction may be lifted to allow a Nargo package to contain both a binary and library crate or multiple binary crates. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/dependencies.md deleted file mode 100644 index 2c028d85853..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/dependencies.md +++ /dev/null @@ -1,124 +0,0 @@ ---- -title: Dependencies -description: - Learn how to specify and manage dependencies in Nargo, allowing you to upload packages to GitHub - and use them easily in your project. -keywords: [Nargo, dependencies, GitHub, package management, versioning] -sidebar_position: 1 ---- - -Nargo allows you to upload packages to GitHub and use them as dependencies. - -## Specifying a dependency - -Specifying a dependency requires a tag to a specific commit and the git url to the url containing -the package. - -Currently, there are no requirements on the tag contents. If requirements are added, it would follow -semver 2.0 guidelines. - -> Note: Without a `tag` , there would be no versioning and dependencies would change each time you -> compile your project. - -For example, to add the [ecrecover-noir library](https://github.com/colinnielsen/ecrecover-noir) to your project, add it to `Nargo.toml`: - -```toml -# Nargo.toml - -[dependencies] -ecrecover = {tag = "v0.8.0", git = "https://github.com/colinnielsen/ecrecover-noir"} -``` - -If the module is in a subdirectory, you can define a subdirectory in your git repository, for example: - -```toml -# Nargo.toml - -[dependencies] -easy_private_token_contract = {tag ="v0.1.0-alpha62", git = "https://github.com/AztecProtocol/aztec-packages", directory = "noir-contracts/contracts/easy_private_token_contract"} -``` - -## Specifying a local dependency - -You can also specify dependencies that are local to your machine. - -For example, this file structure has a library and binary crate - -```tree -├── binary_crate -│   ├── Nargo.toml -│   └── src -│   └── main.nr -└── lib_a - ├── Nargo.toml - └── src - └── lib.nr -``` - -Inside of the binary crate, you can specify: - -```toml -# Nargo.toml - -[dependencies] -lib_a = { path = "../lib_a" } -``` - -## Importing dependencies - -You can import a dependency to a Noir file using the following syntax. For example, to import the -ecrecover-noir library and local lib_a referenced above: - -```rust -use dep::ecrecover; -use dep::lib_a; -``` - -You can also import only the specific parts of dependency that you want to use, like so: - -```rust -use dep::std::hash::sha256; -use dep::std::scalar_mul::fixed_base_embedded_curve; -``` - -Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you -can import multiple items in the same line by enclosing them in curly braces: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; -``` - -We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. - -Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. - -## Dependencies of Dependencies - -Note that when you import a dependency, you also get access to all of the dependencies of that package. - -For example, the [phy_vector](https://github.com/resurgencelabs/phy_vector) library imports an [fraction](https://github.com/resurgencelabs/fraction) library. If you're importing the phy_vector library, then you can access the functions in fractions library like so: - -```rust -use dep::phy_vector; - -fn main(x : Field, y : pub Field) { - //... - let f = phy_vector::fraction::toFraction(true, 2, 1); - //... -} -``` - -## Available Libraries - -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). - -Some libraries that are available today include: - -- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library -- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) -- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers -- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address -- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees -- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir -- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/modules.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/modules.md deleted file mode 100644 index ae822a1cff4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/modules.md +++ /dev/null @@ -1,105 +0,0 @@ ---- -title: Modules -description: - Learn how to organize your files using modules in Noir, following the same convention as Rust's - module system. Examples included. -keywords: [Noir, Rust, modules, organizing files, sub-modules] -sidebar_position: 2 ---- - -Noir's module system follows the same convention as the _newer_ version of Rust's module system. - -## Purpose of Modules - -Modules are used to organize files. Without modules all of your code would need to live in a single -file. In Noir, the compiler does not automatically scan all of your files to detect modules. This -must be done explicitly by the developer. - -## Examples - -### Importing a module in the crate root - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::hello_world(); -} -``` - -Filename : `src/foo.nr` - -```rust -fn from_foo() {} -``` - -In the above snippet, the crate root is the `src/main.nr` file. The compiler sees the module -declaration `mod foo` which prompts it to look for a foo.nr file. - -Visually this module hierarchy looks like the following : - -``` -crate - ├── main - │ - └── foo - └── from_foo - -``` - -### Importing a module throughout the tree - -All modules are accessible from the `crate::` namespace. - -``` -crate - ├── bar - ├── foo - └── main - -``` - -In the above snippet, if `bar` would like to use functions in `foo`, it can do so by `use crate::foo::function_name`. - -### Sub-modules - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::from_foo(); -} -``` - -Filename : `src/foo.nr` - -```rust -mod bar; -fn from_foo() {} -``` - -Filename : `src/foo/bar.nr` - -```rust -fn from_bar() {} -``` - -In the above snippet, we have added an extra module to the module tree; `bar`. `bar` is a submodule -of `foo` hence we declare bar in `foo.nr` with `mod bar`. Since `foo` is not the crate root, the -compiler looks for the file associated with the `bar` module in `src/foo/bar.nr` - -Visually the module hierarchy looks as follows: - -``` -crate - ├── main - │ - └── foo - ├── from_foo - └── bar - └── from_bar -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/workspaces.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/workspaces.md deleted file mode 100644 index 513497f12bf..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/workspaces.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Workspaces -sidebar_position: 3 ---- - -Workspaces are a feature of nargo that allow you to manage multiple related Noir packages in a single repository. A workspace is essentially a group of related projects that share common build output directories and configurations. - -Each Noir project (with it's own Nargo.toml file) can be thought of as a package. Each package is expected to contain exactly one "named circuit", being the "name" defined in Nargo.toml with the program logic defined in `./src/main.nr`. - -For a project with the following structure: - -```tree -├── crates -│ ├── a -│ │ ├── Nargo.toml -│ │ └── Prover.toml -│ │ └── src -│ │ └── main.nr -│ └── b -│ ├── Nargo.toml -│ └── Prover.toml -│ └── src -│ └── main.nr -│ -└── Nargo.toml -``` - -You can define a workspace in Nargo.toml like so: - -```toml -[workspace] -members = ["crates/a", "crates/b"] -default-member = "crates/a" -``` - -`members` indicates which packages are included in the workspace. As such, all member packages of a workspace will be processed when the `--workspace` flag is used with various commands or if a `default-member` is not specified. - -`default-member` indicates which package various commands process by default. - -Libraries can be defined in a workspace. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. - -Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/_category_.json deleted file mode 100644 index af04c0933fd..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Standard Library", - "position": 1, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/bigint.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/bigint.md deleted file mode 100644 index 2bfdeec6631..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/bigint.md +++ /dev/null @@ -1,122 +0,0 @@ ---- -title: Big Integers -description: How to use big integers from Noir standard library -keywords: - [ - Big Integer, - Noir programming language, - Noir libraries, - ] ---- - -The BigInt module in the standard library exposes some class of integers which do not fit (well) into a Noir native field. It implements modulo arithmetic, modulo a 'big' prime number. - -:::note - -The module can currently be considered as `Field`s with fixed modulo sizes used by a set of elliptic curves, in addition to just the native curve. [More work](https://github.com/noir-lang/noir/issues/510) is needed to achieve arbitrarily sized big integers. - -::: - -Currently 6 classes of integers (i.e 'big' prime numbers) are available in the module, namely: - -- BN254 Fq: Bn254Fq -- BN254 Fr: Bn254Fr -- Secp256k1 Fq: Secpk1Fq -- Secp256k1 Fr: Secpk1Fr -- Secp256r1 Fr: Secpr1Fr -- Secp256r1 Fq: Secpr1Fq - -Where XXX Fq and XXX Fr denote respectively the order of the base and scalar field of the (usual) elliptic curve XXX. -For instance the big integer 'Secpk1Fq' in the standard library refers to integers modulo $2^{256}-2^{32}-977$. - -Feel free to explore the source code for the other primes: - -```rust title="big_int_definition" showLineNumbers -struct BigInt { - pointer: u32, - modulus: u32, -} -``` -> Source code: noir_stdlib/src/bigint.nr#L14-L19 - - -## Example usage - -A common use-case is when constructing a big integer from its bytes representation, and performing arithmetic operations on it: - -```rust title="big_int_example" showLineNumbers -fn big_int_example(x: u8, y: u8) { - let a = Secpk1Fq::from_le_bytes(&[x, y, 0, 45, 2]); - let b = Secpk1Fq::from_le_bytes(&[y, x, 9]); - let c = (a + b) * b / a; - let d = c.to_le_bytes(); - println(d[0]); -} -``` -> Source code: test_programs/execution_success/bigint/src/main.nr#L70-L78 - - -## Methods - -The available operations for each big integer are: - -### from_le_bytes - -Construct a big integer from its little-endian bytes representation. Example: - -```rust - // Construct a big integer from a slice of bytes - let a = Secpk1Fq::from_le_bytes(&[x, y, 0, 45, 2]); - // Construct a big integer from an array of 32 bytes - let a = Secpk1Fq::from_le_bytes_32([1;32]); - ``` - -Sure, here's the formatted version of the remaining methods: - -### to_le_bytes - -Return the little-endian bytes representation of a big integer. Example: - -```rust -let bytes = a.to_le_bytes(); -``` - -### add - -Add two big integers. Example: - -```rust -let sum = a + b; -``` - -### sub - -Subtract two big integers. Example: - -```rust -let difference = a - b; -``` - -### mul - -Multiply two big integers. Example: - -```rust -let product = a * b; -``` - -### div - -Divide two big integers. Note that division is field division and not euclidean division. Example: - -```rust -let quotient = a / b; -``` - -### eq - -Compare two big integers. Example: - -```rust -let are_equal = a == b; -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/black_box_fns.md deleted file mode 100644 index e8b62f21d4e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/black_box_fns.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Black Box Functions -description: Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. -keywords: [noir, black box functions] ---- - -Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. This makes certain zk-snark unfriendly computations cheaper than if they were implemented in Noir. - -The ACVM spec defines a set of blackbox functions which backends will be expected to implement. This allows backends to use optimized implementations of these constraints if they have them, however they may also fallback to less efficient naive implementations if not. - -## Function list - -Here is a list of the current black box functions: - -- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) -- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) -- [Blake3](./cryptographic_primitives/hashes.mdx#blake3) -- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash) -- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx) -- AND -- XOR -- RANGE -- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion.md) - -Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. - -You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/noir/blob/master/acvm-repo/acir/src/circuit/black_box_functions.rs). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/bn254.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/bn254.md deleted file mode 100644 index 3294f005dbb..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/bn254.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: Bn254 Field Library ---- - -Noir provides a module in standard library with some optimized functions for bn254 Fr in `std::field::bn254`. - -## decompose - -```rust -fn decompose(x: Field) -> (Field, Field) {} -``` - -Decomposes a single field into two fields, low and high. The low field contains the lower 16 bytes of the input field and the high field contains the upper 16 bytes of the input field. Both field results are range checked to 128 bits. - - -## assert_gt - -```rust -fn assert_gt(a: Field, b: Field) {} -``` - -Asserts that a > b. This will generate less constraints than using `assert(gt(a, b))`. - -## assert_lt - -```rust -fn assert_lt(a: Field, b: Field) {} -``` - -Asserts that a < b. This will generate less constraints than using `assert(lt(a, b))`. - -## gt - -```rust -fn gt(a: Field, b: Field) -> bool {} -``` - -Returns true if a > b. - -## lt - -```rust -fn lt(a: Field, b: Field) -> bool {} -``` - -Returns true if a < b. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/containers/boundedvec.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/containers/boundedvec.md deleted file mode 100644 index ce4529f6e57..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/containers/boundedvec.md +++ /dev/null @@ -1,326 +0,0 @@ ---- -title: Bounded Vectors -keywords: [noir, vector, bounded vector, slice] -sidebar_position: 1 ---- - -A `BoundedVec` is a growable storage similar to a `Vec` except that it -is bounded with a maximum possible length. Unlike `Vec`, `BoundedVec` is not implemented -via slices and thus is not subject to the same restrictions slices are (notably, nested -slices - and thus nested vectors as well - are disallowed). - -Since a BoundedVec is backed by a normal array under the hood, growing the BoundedVec by -pushing an additional element is also more efficient - the length only needs to be increased -by one. - -For these reasons `BoundedVec` should generally be preferred over `Vec` when there -is a reasonable maximum bound that can be placed on the vector. - -Example: - -```rust -let mut vector: BoundedVec = BoundedVec::new(); -for i in 0..5 { - vector.push(i); -} -assert(vector.len() == 5); -assert(vector.max_len() == 10); -``` - -## Methods - -### new - -```rust -pub fn new() -> Self -``` - -Creates a new, empty vector of length zero. - -Since this container is backed by an array internally, it still needs an initial value -to give each element. To resolve this, each element is zeroed internally. This value -is guaranteed to be inaccessible unless `get_unchecked` is used. - -Example: - -```rust -let empty_vector: BoundedVec = BoundedVec::new(); -assert(empty_vector.len() == 0); -``` - -Note that whenever calling `new` the maximum length of the vector should always be specified -via a type signature: - -```rust title="new_example" showLineNumbers -fn foo() -> BoundedVec { - // Ok! MaxLen is specified with a type annotation - let v1: BoundedVec = BoundedVec::new(); - let v2 = BoundedVec::new(); - - // Ok! MaxLen is known from the type of foo's return value - v2 -} - -fn bad() { - let mut v3 = BoundedVec::new(); - - // Not Ok! We don't know if v3's MaxLen is at least 1, and the compiler often infers 0 by default. - v3.push(5); -} -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L11-L27 - - -This defaulting of `MaxLen` (and numeric generics in general) to zero may change in future noir versions -but for now make sure to use type annotations when using bounded vectors. Otherwise, you will receive a constraint failure at runtime when the vec is pushed to. - -### get - -```rust -pub fn get(mut self: Self, index: u64) -> T { -``` - -Retrieves an element from the vector at the given index, starting from zero. - -If the given index is equal to or greater than the length of the vector, this -will issue a constraint failure. - -Example: - -```rust -fn foo(v: BoundedVec) { - let first = v.get(0); - let last = v.get(v.len() - 1); - assert(first != last); -} -``` - -### get_unchecked - -```rust -pub fn get_unchecked(mut self: Self, index: u64) -> T { -``` - -Retrieves an element from the vector at the given index, starting from zero, without -performing a bounds check. - -Since this function does not perform a bounds check on length before accessing the element, -it is unsafe! Use at your own risk! - -Example: - -```rust title="get_unchecked_example" showLineNumbers -fn sum_of_first_three(v: BoundedVec) -> u32 { - // Always ensure the length is larger than the largest - // index passed to get_unchecked - assert(v.len() > 2); - let first = v.get_unchecked(0); - let second = v.get_unchecked(1); - let third = v.get_unchecked(2); - first + second + third -} -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L54-L64 - - - -### push - -```rust -pub fn push(&mut self, elem: T) { -``` - -Pushes an element to the end of the vector. This increases the length -of the vector by one. - -Panics if the new length of the vector will be greater than the max length. - -Example: - -```rust title="bounded-vec-push-example" showLineNumbers -let mut v: BoundedVec = BoundedVec::new(); - - v.push(1); - v.push(2); - - // Panics with failed assertion "push out of bounds" - v.push(3); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L68-L76 - - -### pop - -```rust -pub fn pop(&mut self) -> T -``` - -Pops the element at the end of the vector. This will decrease the length -of the vector by one. - -Panics if the vector is empty. - -Example: - -```rust title="bounded-vec-pop-example" showLineNumbers -let mut v: BoundedVec = BoundedVec::new(); - v.push(1); - v.push(2); - - let two = v.pop(); - let one = v.pop(); - - assert(two == 2); - assert(one == 1); - // error: cannot pop from an empty vector - // let _ = v.pop(); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L81-L93 - - -### len - -```rust -pub fn len(self) -> u64 { -``` - -Returns the current length of this vector - -Example: - -```rust title="bounded-vec-len-example" showLineNumbers -let mut v: BoundedVec = BoundedVec::new(); - assert(v.len() == 0); - - v.push(100); - assert(v.len() == 1); - - v.push(200); - v.push(300); - v.push(400); - assert(v.len() == 4); - - let _ = v.pop(); - let _ = v.pop(); - assert(v.len() == 2); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L98-L113 - - -### max_len - -```rust -pub fn max_len(_self: BoundedVec) -> u64 { -``` - -Returns the maximum length of this vector. This is always -equal to the `MaxLen` parameter this vector was initialized with. - -Example: - -```rust title="bounded-vec-max-len-example" showLineNumbers -let mut v: BoundedVec = BoundedVec::new(); - - assert(v.max_len() == 5); - v.push(10); - assert(v.max_len() == 5); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L118-L124 - - -### storage - -```rust -pub fn storage(self) -> [T; MaxLen] { -``` - -Returns the internal array within this vector. -Since arrays in Noir are immutable, mutating the returned storage array will not mutate -the storage held internally by this vector. - -Note that uninitialized elements may be zeroed out! - -Example: - -```rust title="bounded-vec-storage-example" showLineNumbers -let mut v: BoundedVec = BoundedVec::new(); - - assert(v.storage() == [0, 0, 0, 0, 0]); - - v.push(57); - assert(v.storage() == [57, 0, 0, 0, 0]); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L129-L136 - - -### extend_from_array - -```rust -pub fn extend_from_array(&mut self, array: [T; Len]) -``` - -Pushes each element from the given array to this vector. - -Panics if pushing each element would cause the length of this vector -to exceed the maximum length. - -Example: - -```rust title="bounded-vec-extend-from-array-example" showLineNumbers -let mut vec: BoundedVec = BoundedVec::new(); - vec.extend_from_array([2, 4]); - - assert(vec.len == 2); - assert(vec.get(0) == 2); - assert(vec.get(1) == 4); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L141-L148 - - -### extend_from_bounded_vec - -```rust -pub fn extend_from_bounded_vec(&mut self, vec: BoundedVec) -``` - -Pushes each element from the other vector to this vector. The length of -the other vector is left unchanged. - -Panics if pushing each element would cause the length of this vector -to exceed the maximum length. - -Example: - -```rust title="bounded-vec-extend-from-bounded-vec-example" showLineNumbers -let mut v1: BoundedVec = BoundedVec::new(); - let mut v2: BoundedVec = BoundedVec::new(); - - v2.extend_from_array([1, 2, 3]); - v1.extend_from_bounded_vec(v2); - - assert(v1.storage() == [1, 2, 3, 0, 0]); - assert(v2.storage() == [1, 2, 3, 0, 0, 0, 0]); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L153-L162 - - -### any - -```rust -pub fn any(self, predicate: fn[Env](T) -> bool) -> bool -``` - -Returns true if the given predicate returns true for any element -in this vector. - -Example: - -```rust title="bounded-vec-any-example" showLineNumbers -let mut v: BoundedVec = BoundedVec::new(); - v.extend_from_array([2, 4, 6]); - - let all_even = !v.any(|elem: u32| elem % 2 != 0); - assert(all_even); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L229-L235 - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/containers/hashmap.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/containers/hashmap.md deleted file mode 100644 index 47faa99aba6..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/containers/hashmap.md +++ /dev/null @@ -1,570 +0,0 @@ ---- -title: HashMap -keywords: [noir, map, hash, hashmap] -sidebar_position: 1 ---- - -`HashMap` is used to efficiently store and look up key-value pairs. - -`HashMap` is a bounded type which can store anywhere from zero to `MaxLen` total elements. -Note that due to hash collisions, the actual maximum number of elements stored by any particular -hashmap is likely lower than `MaxLen`. This is true even with cryptographic hash functions since -every hash value will be performed modulo `MaxLen`. - -When creating `HashMap`s, the `MaxLen` generic should always be specified if it is not already -known. Otherwise, the compiler may infer a different value for `MaxLen` (such as zero), which -will likely change the result of the program. This behavior is set to become an error in future -versions instead. - -Example: - -```rust -// Create a mapping from Fields to u32s with a maximum length of 12 -// using a poseidon2 hasher -use dep::std::hash::poseidon2::Poseidon2Hasher; -let mut map: HashMap> = HashMap::default(); - -map.insert(1, 2); -map.insert(3, 4); - -let two = map.get(1).unwrap(); -``` - -## Methods - -### default - -```rust title="default" showLineNumbers -impl Default for HashMap -where - B: BuildHasher + Default, - H: Hasher + Default -{ - fn default() -> Self { -``` -> Source code: noir_stdlib/src/collections/map.nr#L462-L469 - - -Creates a fresh, empty HashMap. - -When using this function, always make sure to specify the maximum size of the hash map. - -This is the same `default` from the `Default` implementation given further below. It is -repeated here for convenience since it is the recommended way to create a hashmap. - -Example: - -```rust title="default_example" showLineNumbers -let hashmap: HashMap> = HashMap::default(); - assert(hashmap.is_empty()); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L202-L205 - - -Because `HashMap` has so many generic arguments that are likely to be the same throughout -your program, it may be helpful to create a type alias: - -```rust title="type_alias" showLineNumbers -type MyMap = HashMap>; -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L196-L198 - - -### with_hasher - -```rust title="with_hasher" showLineNumbers -pub fn with_hasher(_build_hasher: B) -> Self - where - B: BuildHasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L82-L86 - - -Creates a hashmap with an existing `BuildHasher`. This can be used to ensure multiple -hashmaps are created with the same hasher instance. - -Example: - -```rust title="with_hasher_example" showLineNumbers -let my_hasher: BuildHasherDefault = Default::default(); - let hashmap: HashMap> = HashMap::with_hasher(my_hasher); - assert(hashmap.is_empty()); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L207-L211 - - -### get - -```rust title="get" showLineNumbers -pub fn get( - self, - key: K - ) -> Option - where - K: Eq + Hash, - B: BuildHasher, - H: Hasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L278-L287 - - -Retrieves a value from the hashmap, returning `Option::none()` if it was not found. - -Example: - -```rust title="get_example" showLineNumbers -fn get_example(map: HashMap>) { - let x = map.get(12); - - if x.is_some() { - assert(x.unwrap() == 42); - } -} -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L299-L307 - - -### insert - -```rust title="insert" showLineNumbers -pub fn insert( - &mut self, - key: K, - value: V - ) - where - K: Eq + Hash, - B: BuildHasher, - H: Hasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L313-L323 - - -Inserts a new key-value pair into the map. If the key was already in the map, its -previous value will be overridden with the newly provided one. - -Example: - -```rust title="insert_example" showLineNumbers -let mut map: HashMap> = HashMap::default(); - map.insert(12, 42); - assert(map.len() == 1); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L213-L217 - - -### remove - -```rust title="remove" showLineNumbers -pub fn remove( - &mut self, - key: K - ) - where - K: Eq + Hash, - B: BuildHasher, - H: Hasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L356-L365 - - -Removes the given key-value pair from the map. If the key was not already present -in the map, this does nothing. - -Example: - -```rust title="remove_example" showLineNumbers -map.remove(12); - assert(map.is_empty()); - - // If a key was not present in the map, remove does nothing - map.remove(12); - assert(map.is_empty()); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L221-L228 - - -### is_empty - -```rust title="is_empty" showLineNumbers -pub fn is_empty(self) -> bool { -``` -> Source code: noir_stdlib/src/collections/map.nr#L115-L117 - - -True if the length of the hash map is empty. - -Example: - -```rust title="is_empty_example" showLineNumbers -assert(map.is_empty()); - - map.insert(1, 2); - assert(!map.is_empty()); - - map.remove(1); - assert(map.is_empty()); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L230-L238 - - -### len - -```rust title="len" showLineNumbers -pub fn len(self) -> u64 { -``` -> Source code: noir_stdlib/src/collections/map.nr#L264-L266 - - -Returns the current length of this hash map. - -Example: - -```rust title="len_example" showLineNumbers -// This is equivalent to checking map.is_empty() - assert(map.len() == 0); - - map.insert(1, 2); - map.insert(3, 4); - map.insert(5, 6); - assert(map.len() == 3); - - // 3 was already present as a key in the hash map, so the length is unchanged - map.insert(3, 7); - assert(map.len() == 3); - - map.remove(1); - assert(map.len() == 2); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L240-L255 - - -### capacity - -```rust title="capacity" showLineNumbers -pub fn capacity(_self: Self) -> u64 { -``` -> Source code: noir_stdlib/src/collections/map.nr#L271-L273 - - -Returns the maximum capacity of this hashmap. This is always equal to the capacity -specified in the hashmap's type. - -Unlike hashmaps in general purpose programming languages, hashmaps in Noir have a -static capacity that does not increase as the map grows larger. Thus, this capacity -is also the maximum possible element count that can be inserted into the hashmap. -Due to hash collisions (modulo the hashmap length), it is likely the actual maximum -element count will be lower than the full capacity. - -Example: - -```rust title="capacity_example" showLineNumbers -let empty_map: HashMap> = HashMap::default(); - assert(empty_map.len() == 0); - assert(empty_map.capacity() == 42); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L257-L261 - - -### clear - -```rust title="clear" showLineNumbers -pub fn clear(&mut self) { -``` -> Source code: noir_stdlib/src/collections/map.nr#L93-L95 - - -Clears the hashmap, removing all key-value pairs from it. - -Example: - -```rust title="clear_example" showLineNumbers -assert(!map.is_empty()); - map.clear(); - assert(map.is_empty()); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L263-L267 - - -### contains_key - -```rust title="contains_key" showLineNumbers -pub fn contains_key( - self, - key: K - ) -> bool - where - K: Hash + Eq, - B: BuildHasher, - H: Hasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L101-L110 - - -True if the hashmap contains the given key. Unlike `get`, this will not also return -the value associated with the key. - -Example: - -```rust title="contains_key_example" showLineNumbers -if map.contains_key(7) { - let value = map.get(7); - assert(value.is_some()); - } else { - println("No value for key 7!"); - } -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L269-L276 - - -### entries - -```rust title="entries" showLineNumbers -pub fn entries(self) -> BoundedVec<(K, V), N> { -``` -> Source code: noir_stdlib/src/collections/map.nr#L123-L125 - - -Returns a vector of each key-value pair present in the hashmap. - -The length of the returned vector is always equal to the length of the hashmap. - -Example: - -```rust title="entries_example" showLineNumbers -let entries = map.entries(); - - // The length of a hashmap may not be compile-time known, so we - // need to loop over its capacity instead - for i in 0..map.capacity() { - if i < entries.len() { - let (key, value) = entries.get(i); - println(f"{key} -> {value}"); - } - } -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L310-L321 - - -### keys - -```rust title="keys" showLineNumbers -pub fn keys(self) -> BoundedVec { -``` -> Source code: noir_stdlib/src/collections/map.nr#L144-L146 - - -Returns a vector of each key present in the hashmap. - -The length of the returned vector is always equal to the length of the hashmap. - -Example: - -```rust title="keys_example" showLineNumbers -let keys = map.keys(); - - for i in 0..keys.max_len() { - if i < keys.len() { - let key = keys.get_unchecked(i); - let value = map.get(key).unwrap_unchecked(); - println(f"{key} -> {value}"); - } - } -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L323-L333 - - -### values - -```rust title="values" showLineNumbers -pub fn values(self) -> BoundedVec { -``` -> Source code: noir_stdlib/src/collections/map.nr#L164-L166 - - -Returns a vector of each value present in the hashmap. - -The length of the returned vector is always equal to the length of the hashmap. - -Example: - -```rust title="values_example" showLineNumbers -let values = map.values(); - - for i in 0..values.max_len() { - if i < values.len() { - let value = values.get_unchecked(i); - println(f"Found value {value}"); - } - } -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L335-L344 - - -### iter_mut - -```rust title="iter_mut" showLineNumbers -pub fn iter_mut( - &mut self, - f: fn(K, V) -> (K, V) - ) - where - K: Eq + Hash, - B: BuildHasher, - H: Hasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L183-L192 - - -Iterates through each key-value pair of the HashMap, setting each key-value pair to the -result returned from the given function. - -Note that since keys can be mutated, the HashMap needs to be rebuilt as it is iterated -through. If this is not desired, use `iter_values_mut` if only values need to be mutated, -or `entries` if neither keys nor values need to be mutated. - -The iteration order is left unspecified. As a result, if two keys are mutated to become -equal, which of the two values that will be present for the key in the resulting map is also unspecified. - -Example: - -```rust title="iter_mut_example" showLineNumbers -// Add 1 to each key in the map, and double the value associated with that key. - map.iter_mut(|k, v| (k + 1, v * 2)); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L348-L351 - - -### iter_keys_mut - -```rust title="iter_keys_mut" showLineNumbers -pub fn iter_keys_mut( - &mut self, - f: fn(K) -> K - ) - where - K: Eq + Hash, - B: BuildHasher, - H: Hasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L208-L217 - - -Iterates through the HashMap, mutating each key to the result returned from -the given function. - -Note that since keys can be mutated, the HashMap needs to be rebuilt as it is iterated -through. If only iteration is desired and the keys are not intended to be mutated, -prefer using `entries` instead. - -The iteration order is left unspecified. As a result, if two keys are mutated to become -equal, which of the two values that will be present for the key in the resulting map is also unspecified. - -Example: - -```rust title="iter_keys_mut_example" showLineNumbers -// Double each key, leaving the value associated with that key untouched - map.iter_keys_mut(|k| k * 2); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L353-L356 - - -### iter_values_mut - -```rust title="iter_values_mut" showLineNumbers -pub fn iter_values_mut(&mut self, f: fn(V) -> V) { -``` -> Source code: noir_stdlib/src/collections/map.nr#L233-L235 - - -Iterates through the HashMap, applying the given function to each value and mutating the -value to equal the result. This function is more efficient than `iter_mut` and `iter_keys_mut` -because the keys are untouched and the underlying hashmap thus does not need to be reordered. - -Example: - -```rust title="iter_values_mut_example" showLineNumbers -// Halve each value - map.iter_values_mut(|v| v / 2); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L358-L361 - - -### retain - -```rust title="retain" showLineNumbers -pub fn retain(&mut self, f: fn(K, V) -> bool) { -``` -> Source code: noir_stdlib/src/collections/map.nr#L247-L249 - - -Retains only the key-value pairs for which the given function returns true. -Any key-value pairs for which the function returns false will be removed from the map. - -Example: - -```rust title="retain_example" showLineNumbers -map.retain(|k, v| (k != 0) & (v != 0)); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L281-L283 - - -## Trait Implementations - -### default - -```rust title="default" showLineNumbers -impl Default for HashMap -where - B: BuildHasher + Default, - H: Hasher + Default -{ - fn default() -> Self { -``` -> Source code: noir_stdlib/src/collections/map.nr#L462-L469 - - -Constructs an empty HashMap. - -Example: - -```rust title="default_example" showLineNumbers -let hashmap: HashMap> = HashMap::default(); - assert(hashmap.is_empty()); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L202-L205 - - -### eq - -```rust title="eq" showLineNumbers -impl Eq for HashMap -where - K: Eq + Hash, - V: Eq, - B: BuildHasher, - H: Hasher -{ - fn eq(self, other: HashMap) -> bool { -``` -> Source code: noir_stdlib/src/collections/map.nr#L426-L435 - - -Checks if two HashMaps are equal. - -Example: - -```rust title="eq_example" showLineNumbers -let mut map1: HashMap> = HashMap::default(); - let mut map2: HashMap> = HashMap::default(); - - map1.insert(1, 2); - map1.insert(3, 4); - - map2.insert(3, 4); - map2.insert(1, 2); - - assert(map1 == map2); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L285-L296 - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/containers/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/containers/index.md deleted file mode 100644 index ea84c6d5c21..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/containers/index.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Containers -description: Container types provided by Noir's standard library for storing and retrieving data -keywords: [containers, data types, vec, hashmap] ---- diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/containers/vec.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/containers/vec.mdx deleted file mode 100644 index fcfd7e07aa0..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/containers/vec.mdx +++ /dev/null @@ -1,151 +0,0 @@ ---- -title: Vectors -description: Delve into the Vec data type in Noir. Learn about its methods, practical examples, and best practices for using Vectors in your Noir code. -keywords: [noir, vector type, methods, examples, dynamic arrays] -sidebar_position: 6 ---- - -import Experimental from '@site/src/components/Notes/_experimental.mdx'; - - - -A vector is a collection type similar to Rust's `Vec` type. In Noir, it is a convenient way to use slices as mutable arrays. - -Example: - -```rust -let mut vector: Vec = Vec::new(); -for i in 0..5 { - vector.push(i); -} -assert(vector.len() == 5); -``` - -## Methods - -### new - -Creates a new, empty vector. - -```rust -pub fn new() -> Self -``` - -Example: - -```rust -let empty_vector: Vec = Vec::new(); -assert(empty_vector.len() == 0); -``` - -### from_slice - -Creates a vector containing each element from a given slice. Mutations to the resulting vector will not affect the original slice. - -```rust -pub fn from_slice(slice: [T]) -> Self -``` - -Example: - -```rust -let slice: [Field] = &[1, 2, 3]; -let vector_from_slice = Vec::from_slice(slice); -assert(vector_from_slice.len() == 3); -``` - -### len - -Returns the number of elements in the vector. - -```rust -pub fn len(self) -> Field -``` - -Example: - -```rust -let empty_vector: Vec = Vec::new(); -assert(empty_vector.len() == 0); -``` - -### get - -Retrieves an element from the vector at a given index. Panics if the index points beyond the vector's end. - -```rust -pub fn get(self, index: Field) -> T -``` - -Example: - -```rust -let vector: Vec = Vec::from_slice(&[10, 20, 30]); -assert(vector.get(1) == 20); -``` - -### push - -Adds a new element to the vector's end, returning a new vector with a length one greater than the original unmodified vector. - -```rust -pub fn push(&mut self, elem: T) -``` - -Example: - -```rust -let mut vector: Vec = Vec::new(); -vector.push(10); -assert(vector.len() == 1); -``` - -### pop - -Removes an element from the vector's end, returning a new vector with a length one less than the original vector, along with the removed element. Panics if the vector's length is zero. - -```rust -pub fn pop(&mut self) -> T -``` - -Example: - -```rust -let mut vector = Vec::from_slice(&[10, 20]); -let popped_elem = vector.pop(); -assert(popped_elem == 20); -assert(vector.len() == 1); -``` - -### insert - -Inserts an element at a specified index, shifting subsequent elements to the right. - -```rust -pub fn insert(&mut self, index: Field, elem: T) -``` - -Example: - -```rust -let mut vector = Vec::from_slice(&[10, 30]); -vector.insert(1, 20); -assert(vector.get(1) == 20); -``` - -### remove - -Removes an element at a specified index, shifting subsequent elements to the left, and returns the removed element. - -```rust -pub fn remove(&mut self, index: Field) -> T -``` - -Example: - -```rust -let mut vector = Vec::from_slice(&[10, 20, 30]); -let removed_elem = vector.remove(1); -assert(removed_elem == 20); -assert(vector.len() == 2); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/_category_.json deleted file mode 100644 index 5d694210bbf..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 0, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/ec_primitives.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/ec_primitives.md deleted file mode 100644 index f8a1c25ccf6..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/ec_primitives.md +++ /dev/null @@ -1,102 +0,0 @@ ---- -title: Elliptic Curve Primitives -keywords: [cryptographic primitives, Noir project] -sidebar_position: 4 ---- - -Data structures and methods on them that allow you to carry out computations involving elliptic -curves over the (mathematical) field corresponding to `Field`. For the field currently at our -disposal, applications would involve a curve embedded in BN254, e.g. the -[Baby Jubjub curve](https://eips.ethereum.org/EIPS/eip-2494). - -## Data structures - -### Elliptic curve configurations - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Curve`), i.e. the specific elliptic -curve you want to use, which would be specified using any one of the methods -`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::new` which take the coefficients in the -defining equation together with a generator point as parameters. You can find more detail in the -comments in -[`noir_stdlib/src/ec.nr`](https://github.com/noir-lang/noir/blob/v0.29.0/noir_stdlib/src/ec.nr), but -the gist of it is that the elliptic curves of interest are usually expressed in one of the standard -forms implemented here (Twisted Edwards, Montgomery and Short Weierstraß), and in addition to that, -you could choose to use `affine` coordinates (Cartesian coordinates - the usual (x,y) - possibly -together with a point at infinity) or `curvegroup` coordinates (some form of projective coordinates -requiring more coordinates but allowing for more efficient implementations of elliptic curve -operations). Conversions between all of these forms are provided, and under the hood these -conversions are done whenever an operation is more efficient in a different representation (or a -mixed coordinate representation is employed). - -### Points - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Point`), i.e. points lying on the -elliptic curve. For a curve configuration `c` and a point `p`, it may be checked that `p` -does indeed lie on `c` by calling `c.contains(p1)`. - -## Methods - -(given a choice of curve representation, e.g. use `std::ec::tecurve::affine::Curve` and use -`std::ec::tecurve::affine::Point`) - -- The **zero element** is given by `Point::zero()`, and we can verify whether a point `p: Point` is - zero by calling `p.is_zero()`. -- **Equality**: Points `p1: Point` and `p2: Point` may be checked for equality by calling - `p1.eq(p2)`. -- **Addition**: For `c: Curve` and points `p1: Point` and `p2: Point` on the curve, adding these two - points is accomplished by calling `c.add(p1,p2)`. -- **Negation**: For a point `p: Point`, `p.negate()` is its negation. -- **Subtraction**: For `c` and `p1`, `p2` as above, subtracting `p2` from `p1` is accomplished by - calling `c.subtract(p1,p2)`. -- **Scalar multiplication**: For `c` as above, `p: Point` a point on the curve and `n: Field`, - scalar multiplication is given by `c.mul(n,p)`. If instead `n :: [u1; N]`, i.e. `n` is a bit - array, the `bit_mul` method may be used instead: `c.bit_mul(n,p)` -- **Multi-scalar multiplication**: For `c` as above and arrays `n: [Field; N]` and `p: [Point; N]`, - multi-scalar multiplication is given by `c.msm(n,p)`. -- **Coordinate representation conversions**: The `into_group` method converts a point or curve - configuration in the affine representation to one in the CurveGroup representation, and - `into_affine` goes in the other direction. -- **Curve representation conversions**: `tecurve` and `montcurve` curves and points are equivalent - and may be converted between one another by calling `into_montcurve` or `into_tecurve` on their - configurations or points. `swcurve` is more general and a curve c of one of the other two types - may be converted to this representation by calling `c.into_swcurve()`, whereas a point `p` lying - on the curve given by `c` may be mapped to its corresponding `swcurve` point by calling - `c.map_into_swcurve(p)`. -- **Map-to-curve methods**: The Elligator 2 method of mapping a field element `n: Field` into a - `tecurve` or `montcurve` with configuration `c` may be called as `c.elligator2_map(n)`. For all of - the curve configurations, the SWU map-to-curve method may be called as `c.swu_map(z,n)`, where - `z: Field` depends on `Field` and `c` and must be chosen by the user (the conditions it needs to - satisfy are specified in the comments - [here](https://github.com/noir-lang/noir/blob/v0.29.0/noir_stdlib/src/ec.nr). - -## Examples - -The -[ec_baby_jubjub test](https://github.com/noir-lang/noir/blob/master/test_programs/compile_success_empty/ec_baby_jubjub/src/main.nr) -illustrates all of the above primitives on various forms of the Baby Jubjub curve. A couple of more -interesting examples in Noir would be: - -Public-key cryptography: Given an elliptic curve and a 'base point' on it, determine the public key -from the private key. This is a matter of using scalar multiplication. In the case of Baby Jubjub, -for example, this code would do: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; - -fn bjj_pub_key(priv_key: Field) -> Point -{ - - let bjj = Curve::new(168700, 168696, G::new(995203441582195749578291179787384436505546430278305826713579947235728471134,5472060717959818805561601436314318772137091100104008585924551046643952123905)); - - let base_pt = Point::new(5299619240641551281634865583518297030282874472190772894086521144482721001553, 16950150798460657717958625567821834550301663161624707787222815936182638968203); - - bjj.mul(priv_key,base_pt) -} -``` - -This would come in handy in a Merkle proof. - -- EdDSA signature verification: This is a matter of combining these primitives with a suitable hash - function. See - [feat(stdlib): EdDSA sig verification noir#1136](https://github.com/noir-lang/noir/pull/1136) for - the case of Baby Jubjub and the Poseidon hash function. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx deleted file mode 100644 index 4394b48f907..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx +++ /dev/null @@ -1,98 +0,0 @@ ---- -title: ECDSA Signature Verification -description: Learn about the cryptographic primitives regarding ECDSA over the secp256k1 and secp256r1 curves -keywords: [cryptographic primitives, Noir project, ecdsa, secp256k1, secp256r1, signatures] -sidebar_position: 3 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -Noir supports ECDSA signatures verification over the secp256k1 and secp256r1 curves. - -## ecdsa_secp256k1::verify_signature - -Verifier for ECDSA Secp256k1 signatures. -See ecdsa_secp256k1::verify_signature_slice for a version that accepts slices directly. - -```rust title="ecdsa_secp256k1" showLineNumbers -pub fn verify_signature( - public_key_x: [u8; 32], - public_key_y: [u8; 32], - signature: [u8; 64], - message_hash: [u8; N] -) -> bool -``` -> Source code: noir_stdlib/src/ecdsa_secp256k1.nr#L2-L9 - - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - - - -## ecdsa_secp256k1::verify_signature_slice - -Verifier for ECDSA Secp256k1 signatures where the message is a slice. - -```rust title="ecdsa_secp256k1_slice" showLineNumbers -pub fn verify_signature_slice( - public_key_x: [u8; 32], - public_key_y: [u8; 32], - signature: [u8; 64], - message_hash: [u8] -) -> bool -``` -> Source code: noir_stdlib/src/ecdsa_secp256k1.nr#L13-L20 - - - - -## ecdsa_secp256r1::verify_signature - -Verifier for ECDSA Secp256r1 signatures. -See ecdsa_secp256r1::verify_signature_slice for a version that accepts slices directly. - -```rust title="ecdsa_secp256r1" showLineNumbers -pub fn verify_signature( - public_key_x: [u8; 32], - public_key_y: [u8; 32], - signature: [u8; 64], - message_hash: [u8; N] -) -> bool -``` -> Source code: noir_stdlib/src/ecdsa_secp256r1.nr#L2-L9 - - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - - - -## ecdsa_secp256r1::verify_signature - -Verifier for ECDSA Secp256r1 signatures where the message is a slice. - -```rust title="ecdsa_secp256r1_slice" showLineNumbers -pub fn verify_signature_slice( - public_key_x: [u8; 32], - public_key_y: [u8; 32], - signature: [u8; 64], - message_hash: [u8] -) -> bool -``` -> Source code: noir_stdlib/src/ecdsa_secp256r1.nr#L13-L20 - - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/eddsa.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/eddsa.mdx deleted file mode 100644 index c2c0624dfad..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/eddsa.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: EdDSA Verification -description: Learn about the cryptographic primitives regarding EdDSA -keywords: [cryptographic primitives, Noir project, eddsa, signatures] -sidebar_position: 5 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## eddsa::eddsa_poseidon_verify - -Verifier for EdDSA signatures - -```rust -fn eddsa_poseidon_verify(public_key_x : Field, public_key_y : Field, signature_s: Field, signature_r8_x: Field, signature_r8_y: Field, message: Field) -> bool -``` - -It is also possible to specify the hash algorithm used for the signature by using the `eddsa_verify_with_hasher` function with a parameter implementing the Hasher trait. For instance, if you want to use Poseidon2 instead, you can do the following: -```rust -use dep::std::hash::poseidon2::Poseidon2Hasher; - -let mut hasher = Poseidon2Hasher::default(); -eddsa_verify_with_hasher(pub_key_a.x, pub_key_a.y, s_a, r8_a.x, r8_a.y, msg, &mut hasher); -``` - - - -## eddsa::eddsa_to_pub - -Private to public key conversion. - -Returns `(pub_key_x, pub_key_y)` - -```rust -fn eddsa_to_pub(secret : Field) -> (Field, Field) -``` - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/hashes.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/hashes.mdx deleted file mode 100644 index 3b83d9ec31a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/hashes.mdx +++ /dev/null @@ -1,257 +0,0 @@ ---- -title: Hash methods -description: - Learn about the cryptographic primitives ready to use for any Noir project, including sha256, - blake2s, pedersen, mimc_bn254 and mimc -keywords: - [cryptographic primitives, Noir project, sha256, blake2s, pedersen, mimc_bn254, mimc, hash] -sidebar_position: 0 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## sha256 - -Given an array of bytes, returns the resulting sha256 hash. -Specify a message_size to hash only the first `message_size` bytes of the input. - -```rust title="sha256" showLineNumbers -pub fn sha256(input: [u8; N]) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L10-L12 - - -example: -```rust title="sha256_var" showLineNumbers -let digest = std::hash::sha256_var([x as u8], 1); -``` -> Source code: test_programs/execution_success/sha256/src/main.nr#L17-L19 - - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::sha256::sha256_var(x, 4); -} -``` - - - - -## blake2s - -Given an array of bytes, returns an array with the Blake2 hash - -```rust title="blake2s" showLineNumbers -pub fn blake2s(input: [u8; N]) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L16-L18 - - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::blake2s(x); -} -``` - - - -## blake3 - -Given an array of bytes, returns an array with the Blake3 hash - -```rust title="blake3" showLineNumbers -pub fn blake3(input: [u8; N]) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L22-L24 - - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::blake3(x); -} -``` - - - -## pedersen_hash - -Given an array of Fields, returns the Pedersen hash. - -```rust title="pedersen_hash" showLineNumbers -pub fn pedersen_hash(input: [Field; N]) -> Field -``` -> Source code: noir_stdlib/src/hash.nr#L46-L48 - - -example: - -```rust title="pedersen-hash" showLineNumbers -use dep::std; - -fn main(x: Field, y: Field, expected_hash: Field) { - let hash = std::hash::pedersen_hash([x, y]); - assert_eq(hash, expected_hash); -} -``` -> Source code: test_programs/execution_success/pedersen_hash/src/main.nr#L1-L8 - - - - -## pedersen_commitment - -Given an array of Fields, returns the Pedersen commitment. - -```rust title="pedersen_commitment" showLineNumbers -struct PedersenPoint { - x : Field, - y : Field, -} - -pub fn pedersen_commitment(input: [Field; N]) -> PedersenPoint { -``` -> Source code: noir_stdlib/src/hash.nr#L27-L34 - - -example: - -```rust title="pedersen-commitment" showLineNumbers -use dep::std; - -fn main(x: Field, y: Field, expected_commitment: std::hash::PedersenPoint) { - let commitment = std::hash::pedersen_commitment([x, y]); - assert_eq(commitment.x, expected_commitment.x); - assert_eq(commitment.y, expected_commitment.y); -} -``` -> Source code: test_programs/execution_success/pedersen_commitment/src/main.nr#L1-L9 - - - - -## keccak256 - -Given an array of bytes (`u8`), returns the resulting keccak hash as an array of -32 bytes (`[u8; 32]`). Specify a message_size to hash only the first -`message_size` bytes of the input. - -```rust title="keccak256" showLineNumbers -pub fn keccak256(input: [u8; N], message_size: u32) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L68-L70 - - -example: - -```rust title="keccak256" showLineNumbers -use dep::std; - -fn main(x: Field, result: [u8; 32]) { - // We use the `as` keyword here to denote the fact that we want to take just the first byte from the x Field - // The padding is taken care of by the program - let digest = std::hash::keccak256([x as u8], 1); - assert(digest == result); - - //#1399: variable message size - let message_size = 4; - let hash_a = std::hash::keccak256([1, 2, 3, 4], message_size); - let hash_b = std::hash::keccak256([1, 2, 3, 4, 0, 0, 0, 0], message_size); - - assert(hash_a == hash_b); - - let message_size_big = 8; - let hash_c = std::hash::keccak256([1, 2, 3, 4, 0, 0, 0, 0], message_size_big); - - assert(hash_a != hash_c); -} -``` -> Source code: test_programs/execution_success/keccak256/src/main.nr#L1-L22 - - - - -## poseidon - -Given an array of Fields, returns a new Field with the Poseidon Hash. Mind that you need to specify -how many inputs are there to your Poseidon function. - -```rust -// example for hash_1, hash_2 accepts an array of length 2, etc -fn hash_1(input: [Field; 1]) -> Field -``` - -example: - -```rust title="poseidon" showLineNumbers -use dep::std::hash::poseidon; -use dep::std::hash::poseidon2; - -fn main(x1: [Field; 2], y1: pub Field, x2: [Field; 4], y2: pub Field, x3: [Field; 4], y3: Field) { - let hash1 = poseidon::bn254::hash_2(x1); - assert(hash1 == y1); - - let hash2 = poseidon::bn254::hash_4(x2); - assert(hash2 == y2); - - let hash3 = poseidon2::Poseidon2::hash(x3, x3.len()); - assert(hash3 == y3); -} -``` -> Source code: test_programs/execution_success/poseidon_bn254_hash/src/main.nr#L1-L15 - - -## poseidon 2 - -Given an array of Fields, returns a new Field with the Poseidon2 Hash. Contrary to the Poseidon -function, there is only one hash and you can specify a message_size to hash only the first -`message_size` bytes of the input, - -```rust -// example for hashing the first three elements of the input -Poseidon2::hash(input, 3); -``` - -The above example for Poseidon also includes Poseidon2. - -## mimc_bn254 and mimc - -`mimc_bn254` is `mimc`, but with hardcoded parameters for the BN254 curve. You can use it by -providing an array of Fields, and it returns a Field with the hash. You can use the `mimc` method if -you're willing to input your own constants: - -```rust -fn mimc(x: Field, k: Field, constants: [Field; N], exp : Field) -> Field -``` - -otherwise, use the `mimc_bn254` method: - -```rust -fn mimc_bn254(array: [Field; N]) -> Field -``` - -example: - -```rust - -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::mimc::mimc_bn254(x); -} -``` - -## hash_to_field - -```rust -fn hash_to_field(_input : [Field]) -> Field {} -``` - -Calculates the `blake2s` hash of the inputs and returns the hash modulo the field modulus to return -a value which can be represented as a `Field`. - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/index.md deleted file mode 100644 index 650f30165d5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/index.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Cryptographic Primitives -description: - Learn about the cryptographic primitives ready to use for any Noir project -keywords: - [ - cryptographic primitives, - Noir project, - ] ---- - -The Noir team is progressively adding new cryptographic primitives to the standard library. Reach out for news or if you would be interested in adding more of these calculations in Noir. - -Some methods are available thanks to the Aztec backend, not being performed using Noir. When using other backends, these methods may or may not be supplied. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/scalar.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/scalar.mdx deleted file mode 100644 index df411ca5443..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/scalar.mdx +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Scalar multiplication -description: See how you can perform scalar multiplications over a fixed base in Noir -keywords: [cryptographic primitives, Noir project, scalar multiplication] -sidebar_position: 1 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## scalar_mul::fixed_base_embedded_curve - -Performs scalar multiplication over the embedded curve whose coordinates are defined by the -configured noir field. For the BN254 scalar field, this is BabyJubJub or Grumpkin. - -```rust title="fixed_base_embedded_curve" showLineNumbers -pub fn fixed_base_embedded_curve( - low: Field, - high: Field -) -> [Field; 2] -``` -> Source code: noir_stdlib/src/scalar_mul.nr#L27-L32 - - -example - -```rust -fn main(x : Field) { - let scal = std::scalar_mul::fixed_base_embedded_curve(x); - println(scal); -} -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/schnorr.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/schnorr.mdx deleted file mode 100644 index b59e69c8f07..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/schnorr.mdx +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: Schnorr Signatures -description: Learn how you can verify Schnorr signatures using Noir -keywords: [cryptographic primitives, Noir project, schnorr, signatures] -sidebar_position: 2 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## schnorr::verify_signature - -Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin). -See schnorr::verify_signature_slice for a version that works directly on slices. - -```rust title="schnorr_verify" showLineNumbers -pub fn verify_signature( - public_key_x: Field, - public_key_y: Field, - signature: [u8; 64], - message: [u8; N] -) -> bool -``` -> Source code: noir_stdlib/src/schnorr.nr#L2-L9 - - -where `_signature` can be generated like so using the npm package -[@noir-lang/barretenberg](https://www.npmjs.com/package/@noir-lang/barretenberg) - -```js -const { BarretenbergWasm } = require('@noir-lang/barretenberg/dest/wasm'); -const { Schnorr } = require('@noir-lang/barretenberg/dest/crypto/schnorr'); - -... - -const barretenberg = await BarretenbergWasm.new(); -const schnorr = new Schnorr(barretenberg); -const pubKey = schnorr.computePublicKey(privateKey); -const message = ... -const signature = Array.from( - schnorr.constructSignature(hash, privateKey).toBuffer() -); - -... -``` - - - -## schnorr::verify_signature_slice - -Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin) -where the message is a slice. - -```rust title="schnorr_verify_slice" showLineNumbers -pub fn verify_signature_slice( - public_key_x: Field, - public_key_y: Field, - signature: [u8; 64], - message: [u8] -) -> bool -``` -> Source code: noir_stdlib/src/schnorr.nr#L13-L20 - - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/logging.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/logging.md deleted file mode 100644 index db75ef9f86f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/logging.md +++ /dev/null @@ -1,78 +0,0 @@ ---- -title: Logging -description: - Learn how to use the println statement for debugging in Noir with this tutorial. Understand the - basics of logging in Noir and how to implement it in your code. -keywords: - [ - noir logging, - println statement, - print statement, - debugging in noir, - noir std library, - logging tutorial, - basic logging in noir, - noir logging implementation, - noir debugging techniques, - rust, - ] ---- - -The standard library provides two familiar statements you can use: `println` and `print`. Despite being a limited implementation of rust's `println!` and `print!` macros, these constructs can be useful for debugging. - -You can print the output of both statements in your Noir code by using the `nargo execute` command or the `--show-output` flag when using `nargo test` (provided there are print statements in your tests). - -It is recommended to use `nargo execute` if you want to debug failing constraints with `println` or `print` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). Neither `println`, nor `print` are callable for failed constraints caught at compile time. - -Both `print` and `println` are generic functions which can work on integers, fields, strings, and even structs or expressions. Note however, that slices are currently unsupported. For example: - -```rust -struct Person { - age: Field, - height: Field, -} - -fn main(age: Field, height: Field) { - let person = Person { - age: age, - height: height, - }; - println(person); - println(age + height); - println("Hello world!"); -} -``` - -You can print different types in the same statement (including strings) with a type called `fmtstr`. It can be specified in the same way as a normal string, just prepended with an "f" character: - -```rust - let fmt_str = f"i: {i}, j: {j}"; - println(fmt_str); - - let s = myStruct { y: x, x: y }; - println(s); - - println(f"i: {i}, s: {s}"); - - println(x); - println([x, y]); - - let foo = fooStruct { my_struct: s, foo: 15 }; - println(f"s: {s}, foo: {foo}"); - - println(15); // prints 0x0f, implicit Field - println(-1 as u8); // prints 255 - println(-1 as i8); // prints -1 -``` - -Examples shown above are interchangeable between the two `print` statements: - -```rust -let person = Person { age : age, height : height }; - -println(person); -print(person); - -println("Hello world!"); // Prints with a newline at the end of the input -print("Hello world!"); // Prints the input and keeps cursor on the same line -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/merkle_trees.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/merkle_trees.md deleted file mode 100644 index 6a9ebf72ada..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/merkle_trees.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: Merkle Trees -description: Learn about Merkle Trees in Noir with this tutorial. Explore the basics of computing a merkle root using a proof, with examples. -keywords: - [ - Merkle trees in Noir, - Noir programming language, - check membership, - computing root from leaf, - Noir Merkle tree implementation, - Merkle tree tutorial, - Merkle tree code examples, - Noir libraries, - pedersen hash., - ] ---- - -## compute_merkle_root - -Returns the root of the tree from the provided leaf and its hash path, using a [Pedersen hash](./cryptographic_primitives/hashes.mdx#pedersen_hash). - -```rust -fn compute_merkle_root(leaf : Field, index : Field, hash_path: [Field]) -> Field -``` - -example: - -```rust -/** - // these values are for this example only - index = "0" - priv_key = "0x000000000000000000000000000000000000000000000000000000616c696365" - secret = "0x1929ea3ab8d9106a899386883d9428f8256cfedb3c4f6b66bf4aa4d28a79988f" - note_hash_path = [ - "0x1e61bdae0f027b1b2159e1f9d3f8d00fa668a952dddd822fda80dc745d6f65cc", - "0x0e4223f3925f98934393c74975142bd73079ab0621f4ee133cee050a3c194f1a", - "0x2fd7bb412155bf8693a3bd2a3e7581a679c95c68a052f835dddca85fa1569a40" - ] - */ -fn main(index: Field, priv_key: Field, secret: Field, note_hash_path: [Field; 3]) { - - let pubkey = std::scalar_mul::fixed_base_embedded_curve(priv_key); - let pubkey_x = pubkey[0]; - let pubkey_y = pubkey[1]; - let note_commitment = std::hash::pedersen(&[pubkey_x, pubkey_y, secret]); - - let root = std::merkle::compute_merkle_root(note_commitment[0], index, note_hash_path.as_slice()); - println(root); -} -``` - -To check merkle tree membership: - -1. Include a merkle root as a program input. -2. Compute the merkle root of a given leaf, index and hash path. -3. Assert the merkle roots are equal. - -For more info about merkle trees, see the Wikipedia [page](https://en.wikipedia.org/wiki/Merkle_tree). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/options.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/options.md deleted file mode 100644 index a1bd4e1de5f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/options.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -title: Option Type ---- - -The `Option` type is a way to express that a value might be present (`Some(T))` or absent (`None`). It's a safer way to handle potential absence of values, compared to using nulls in many other languages. - -```rust -struct Option { - None, - Some(T), -} -``` - -The `Option` type, already imported into your Noir program, can be used directly: - -```rust -fn main() { - let none = Option::none(); - let some = Option::some(3); -} -``` - -See [this test](https://github.com/noir-lang/noir/blob/5cbfb9c4a06c8865c98ff2b594464b037d821a5c/crates/nargo_cli/tests/test_data/option/src/main.nr) for a more comprehensive set of examples of each of the methods described below. - -## Methods - -### none - -Constructs a none value. - -### some - -Constructs a some wrapper around a given value. - -### is_none - -Returns true if the Option is None. - -### is_some - -Returns true of the Option is Some. - -### unwrap - -Asserts `self.is_some()` and returns the wrapped value. - -### unwrap_unchecked - -Returns the inner value without asserting `self.is_some()`. This method can be useful within an if condition when we already know that `option.is_some()`. If the option is None, there is no guarantee what value will be returned, only that it will be of type T for an `Option`. - -### unwrap_or - -Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value. - -### unwrap_or_else - -Returns the wrapped value if `self.is_some()`. Otherwise, calls the given function to return a default value. - -### expect - -Asserts `self.is_some()` with a provided custom message and returns the contained `Some` value. The custom message is expected to be a format string. - -### map - -If self is `Some(x)`, this returns `Some(f(x))`. Otherwise, this returns `None`. - -### map_or - -If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns the given default value. - -### map_or_else - -If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns `default()`. - -### and - -Returns None if self is None. Otherwise, this returns `other`. - -### and_then - -If self is None, this returns None. Otherwise, this calls the given function with the Some value contained within self, and returns the result of that call. In some languages this function is called `flat_map` or `bind`. - -### or - -If self is Some, return self. Otherwise, return `other`. - -### or_else - -If self is Some, return self. Otherwise, return `default()`. - -### xor - -If only one of the two Options is Some, return that option. Otherwise, if both options are Some or both are None, None is returned. - -### filter - -Returns `Some(x)` if self is `Some(x)` and `predicate(x)` is true. Otherwise, this returns `None`. - -### flatten - -Flattens an `Option>` into a `Option`. This returns `None` if the outer Option is None. Otherwise, this returns the inner Option. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/recursion.md deleted file mode 100644 index f33c285cf4e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/recursion.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -title: Recursive Proofs -description: Learn about how to write recursive proofs in Noir. -keywords: [recursion, recursive proofs, verification_key, verify_proof] ---- - -Noir supports recursively verifying proofs, meaning you verify the proof of a Noir program in another Noir program. This enables creating proofs of arbitrary size by doing step-wise verification of smaller components of a large proof. - -Read [the explainer on recursion](../../explainers/explainer-recursion.md) to know more about this function and the [guide on how to use it.](../../how_to/how-to-recursion.md) - -## The `#[recursive]` Attribute - -In Noir, the `#[recursive]` attribute is used to indicate that a circuit is designed for recursive proof generation. When applied, it informs the compiler and the tooling that the circuit should be compiled in a way that makes its proofs suitable for recursive verification. This attribute eliminates the need for manual flagging of recursion at the tooling level, streamlining the proof generation process for recursive circuits. - -### Example usage with `#[recursive]` - -```rust -#[recursive] -fn main(x: Field, y: pub Field) { - assert(x == y, "x and y are not equal"); -} - -// This marks the circuit as recursion-friendly and indicates that proofs generated from this circuit -// are intended for recursive verification. -``` - -By incorporating this attribute directly in the circuit's definition, tooling like Nargo and NoirJS can automatically execute recursive-specific duties for Noir programs (e.g. recursive-friendly proof artifact generation) without additional flags or configurations. - -## Verifying Recursive Proofs - -```rust -#[foreign(recursive_aggregation)] -pub fn verify_proof(verification_key: [Field], proof: [Field], public_inputs: [Field], key_hash: Field) {} -``` - -:::info - -This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. - -::: - -## Example usage - -```rust -use dep::std; - -fn main( - verification_key : [Field; 114], - proof : [Field; 93], - public_inputs : [Field; 1], - key_hash : Field, - proof_b : [Field; 93], -) { - std::verify_proof( - verification_key.as_slice(), - proof.as_slice(), - public_inputs.as_slice(), - key_hash - ); - - std::verify_proof( - verification_key.as_slice(), - proof_b.as_slice(), - public_inputs.as_slice(), - key_hash - ); -} -``` - -You can see a full example of recursive proofs in [this example recursion demo repo](https://github.com/noir-lang/noir-examples/tree/master/recursion). - -## Parameters - -### `verification_key` - -The verification key for the zk program that is being verified. - -### `proof` - -The proof for the zk program that is being verified. - -### `public_inputs` - -These represent the public inputs of the proof we are verifying. - -### `key_hash` - -A key hash is used to check the validity of the verification key. The circuit implementing this opcode can use this hash to ensure that the key provided to the circuit matches the key produced by the circuit creator. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/traits.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/traits.md deleted file mode 100644 index 04dc40f0dac..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/traits.md +++ /dev/null @@ -1,410 +0,0 @@ ---- -title: Traits -description: Noir's stdlib provides a few commonly used traits. -keywords: [traits, trait, interface, protocol, default, add, eq] ---- - -## `std::default` - -### `std::default::Default` - -```rust title="default-trait" showLineNumbers -trait Default { - fn default() -> Self; -} -``` -> Source code: noir_stdlib/src/default.nr#L1-L5 - - -Constructs a default value of a type. - -Implementations: -```rust -impl Default for Field { .. } - -impl Default for i8 { .. } -impl Default for i16 { .. } -impl Default for i32 { .. } -impl Default for i64 { .. } - -impl Default for u8 { .. } -impl Default for u16 { .. } -impl Default for u32 { .. } -impl Default for u64 { .. } - -impl Default for () { .. } -impl Default for bool { .. } - -impl Default for [T; N] - where T: Default { .. } - -impl Default for [T] { .. } - -impl Default for (A, B) - where A: Default, B: Default { .. } - -impl Default for (A, B, C) - where A: Default, B: Default, C: Default { .. } - -impl Default for (A, B, C, D) - where A: Default, B: Default, C: Default, D: Default { .. } - -impl Default for (A, B, C, D, E) - where A: Default, B: Default, C: Default, D: Default, E: Default { .. } -``` - -For primitive integer types, the return value of `default` is `0`. Container -types such as arrays are filled with default values of their element type, -except slices whose length is unknown and thus defaulted to zero. - - -## `std::convert` - -### `std::convert::From` - -```rust title="from-trait" showLineNumbers -trait From { - fn from(input: T) -> Self; -} -``` -> Source code: noir_stdlib/src/convert.nr#L1-L5 - - -The `From` trait defines how to convert from a given type `T` to the type on which the trait is implemented. - -The Noir standard library provides a number of implementations of `From` between primitive types. -```rust title="from-impls" showLineNumbers -// Unsigned integers - -impl From for u32 { fn from(value: u8) -> u32 { value as u32 } } - -impl From for u64 { fn from(value: u8) -> u64 { value as u64 } } -impl From for u64 { fn from(value: u32) -> u64 { value as u64 } } - -impl From for Field { fn from(value: u8) -> Field { value as Field } } -impl From for Field { fn from(value: u32) -> Field { value as Field } } -impl From for Field { fn from(value: u64) -> Field { value as Field } } - -// Signed integers - -impl From for i32 { fn from(value: i8) -> i32 { value as i32 } } - -impl From for i64 { fn from(value: i8) -> i64 { value as i64 } } -impl From for i64 { fn from(value: i32) -> i64 { value as i64 } } - -// Booleans -impl From for u8 { fn from(value: bool) -> u8 { value as u8 } } -impl From for u32 { fn from(value: bool) -> u32 { value as u32 } } -impl From for u64 { fn from(value: bool) -> u64 { value as u64 } } -impl From for i8 { fn from(value: bool) -> i8 { value as i8 } } -impl From for i32 { fn from(value: bool) -> i32 { value as i32 } } -impl From for i64 { fn from(value: bool) -> i64 { value as i64 } } -impl From for Field { fn from(value: bool) -> Field { value as Field } } -``` -> Source code: noir_stdlib/src/convert.nr#L25-L52 - - -#### When to implement `From` - -As a general rule of thumb, `From` may be implemented in the [situations where it would be suitable in Rust](https://doc.rust-lang.org/std/convert/trait.From.html#when-to-implement-from): - -- The conversion is *infallible*: Noir does not provide an equivalent to Rust's `TryFrom`, if the conversion can fail then provide a named method instead. -- The conversion is *lossless*: semantically, it should not lose or discard information. For example, `u32: From` can losslessly convert any `u16` into a valid `u32` such that the original `u16` can be recovered. On the other hand, `u16: From` should not be implemented as `2**16` is a `u32` which cannot be losslessly converted into a `u16`. -- The conversion is *value-preserving*: the conceptual kind and meaning of the resulting value is the same, even though the Noir type and technical representation might be different. While it's possible to infallibly and losslessly convert a `u8` into a `str<2>` hex representation, `4u8` and `"04"` are too different for `str<2>: From` to be implemented. -- The conversion is *obvious*: it's the only reasonable conversion between the two types. If there's ambiguity on how to convert between them such that the same input could potentially map to two different values then a named method should be used. For instance rather than implementing `U128: From<[u8; 16]>`, the methods `U128::from_le_bytes` and `U128::from_be_bytes` are used as otherwise the endianness of the array would be ambiguous, resulting in two potential values of `U128` from the same byte array. - -One additional recommendation specific to Noir is: -- The conversion is *efficient*: it's relatively cheap to convert between the two types. Due to being a ZK DSL, it's more important to avoid unnecessary computation compared to Rust. If the implementation of `From` would encourage users to perform unnecessary conversion, resulting in additional proving time, then it may be preferable to expose functionality such that this conversion may be avoided. - -### `std::convert::Into` - -The `Into` trait is defined as the reciprocal of `From`. It should be easy to convince yourself that if we can convert to type `A` from type `B`, then it's possible to convert type `B` into type `A`. - -For this reason, implementing `From` on a type will automatically generate a matching `Into` implementation. One should always prefer implementing `From` over `Into` as implementing `Into` will not generate a matching `From` implementation. - -```rust title="into-trait" showLineNumbers -trait Into { - fn into(self) -> T; -} - -impl Into for U where T: From { - fn into(self) -> T { - T::from(self) - } -} -``` -> Source code: noir_stdlib/src/convert.nr#L13-L23 - - -`Into` is most useful when passing function arguments where the types don't quite match up with what the function expects. In this case, the compiler has enough type information to perform the necessary conversion by just appending `.into()` onto the arguments in question. - - -## `std::cmp` - -### `std::cmp::Eq` - -```rust title="eq-trait" showLineNumbers -trait Eq { - fn eq(self, other: Self) -> bool; -} -``` -> Source code: noir_stdlib/src/cmp.nr#L1-L5 - - -Returns `true` if `self` is equal to `other`. Implementing this trait on a type -allows the type to be used with `==` and `!=`. - -Implementations: -```rust -impl Eq for Field { .. } - -impl Eq for i8 { .. } -impl Eq for i16 { .. } -impl Eq for i32 { .. } -impl Eq for i64 { .. } - -impl Eq for u8 { .. } -impl Eq for u16 { .. } -impl Eq for u32 { .. } -impl Eq for u64 { .. } - -impl Eq for () { .. } -impl Eq for bool { .. } - -impl Eq for [T; N] - where T: Eq { .. } - -impl Eq for [T] - where T: Eq { .. } - -impl Eq for (A, B) - where A: Eq, B: Eq { .. } - -impl Eq for (A, B, C) - where A: Eq, B: Eq, C: Eq { .. } - -impl Eq for (A, B, C, D) - where A: Eq, B: Eq, C: Eq, D: Eq { .. } - -impl Eq for (A, B, C, D, E) - where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq { .. } -``` - -### `std::cmp::Ord` - -```rust title="ord-trait" showLineNumbers -trait Ord { - fn cmp(self, other: Self) -> Ordering; -} -``` -> Source code: noir_stdlib/src/cmp.nr#L102-L106 - - -`a.cmp(b)` compares two values returning `Ordering::less()` if `a < b`, -`Ordering::equal()` if `a == b`, or `Ordering::greater()` if `a > b`. -Implementing this trait on a type allows `<`, `<=`, `>`, and `>=` to be -used on values of the type. - -`std::cmp` also provides `max` and `min` functions for any type which implements the `Ord` trait. - -Implementations: - -```rust -impl Ord for u8 { .. } -impl Ord for u16 { .. } -impl Ord for u32 { .. } -impl Ord for u64 { .. } - -impl Ord for i8 { .. } -impl Ord for i16 { .. } -impl Ord for i32 { .. } - -impl Ord for i64 { .. } - -impl Ord for () { .. } -impl Ord for bool { .. } - -impl Ord for [T; N] - where T: Ord { .. } - -impl Ord for [T] - where T: Ord { .. } - -impl Ord for (A, B) - where A: Ord, B: Ord { .. } - -impl Ord for (A, B, C) - where A: Ord, B: Ord, C: Ord { .. } - -impl Ord for (A, B, C, D) - where A: Ord, B: Ord, C: Ord, D: Ord { .. } - -impl Ord for (A, B, C, D, E) - where A: Ord, B: Ord, C: Ord, D: Ord, E: Ord { .. } -``` - -## `std::ops` - -### `std::ops::Add`, `std::ops::Sub`, `std::ops::Mul`, and `std::ops::Div` - -These traits abstract over addition, subtraction, multiplication, and division respectively. -Implementing these traits for a given type will also allow that type to be used with the corresponding operator -for that trait (`+` for Add, etc) in addition to the normal method names. - -```rust title="add-trait" showLineNumbers -trait Add { - fn add(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L1-L5 - -```rust title="sub-trait" showLineNumbers -trait Sub { - fn sub(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L17-L21 - -```rust title="mul-trait" showLineNumbers -trait Mul { - fn mul(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L33-L37 - -```rust title="div-trait" showLineNumbers -trait Div { - fn div(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L49-L53 - - -The implementations block below is given for the `Add` trait, but the same types that implement -`Add` also implement `Sub`, `Mul`, and `Div`. - -Implementations: -```rust -impl Add for Field { .. } - -impl Add for i8 { .. } -impl Add for i16 { .. } -impl Add for i32 { .. } -impl Add for i64 { .. } - -impl Add for u8 { .. } -impl Add for u16 { .. } -impl Add for u32 { .. } -impl Add for u64 { .. } -``` - -### `std::ops::Rem` - -```rust title="rem-trait" showLineNumbers -trait Rem{ - fn rem(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L65-L69 - - -`Rem::rem(a, b)` is the remainder function returning the result of what is -left after dividing `a` and `b`. Implementing `Rem` allows the `%` operator -to be used with the implementation type. - -Unlike other numeric traits, `Rem` is not implemented for `Field`. - -Implementations: -```rust -impl Rem for u8 { fn rem(self, other: u8) -> u8 { self % other } } -impl Rem for u16 { fn rem(self, other: u16) -> u16 { self % other } } -impl Rem for u32 { fn rem(self, other: u32) -> u32 { self % other } } -impl Rem for u64 { fn rem(self, other: u64) -> u64 { self % other } } - -impl Rem for i8 { fn rem(self, other: i8) -> i8 { self % other } } -impl Rem for i16 { fn rem(self, other: i16) -> i16 { self % other } } -impl Rem for i32 { fn rem(self, other: i32) -> i32 { self % other } } -impl Rem for i64 { fn rem(self, other: i64) -> i64 { self % other } } -``` - -### `std::ops::{ BitOr, BitAnd, BitXor }` - -```rust title="bitor-trait" showLineNumbers -trait BitOr { - fn bitor(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L79-L83 - -```rust title="bitand-trait" showLineNumbers -trait BitAnd { - fn bitand(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L95-L99 - -```rust title="bitxor-trait" showLineNumbers -trait BitXor { - fn bitxor(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L111-L115 - - -Traits for the bitwise operations `|`, `&`, and `^`. - -Implementing `BitOr`, `BitAnd` or `BitXor` for a type allows the `|`, `&`, or `^` operator respectively -to be used with the type. - -The implementations block below is given for the `BitOr` trait, but the same types that implement -`BitOr` also implement `BitAnd` and `BitXor`. - -Implementations: -```rust -impl BitOr for bool { fn bitor(self, other: bool) -> bool { self | other } } - -impl BitOr for u8 { fn bitor(self, other: u8) -> u8 { self | other } } -impl BitOr for u16 { fn bitor(self, other: u16) -> u16 { self | other } } -impl BitOr for u32 { fn bitor(self, other: u32) -> u32 { self | other } } -impl BitOr for u64 { fn bitor(self, other: u64) -> u64 { self | other } } - -impl BitOr for i8 { fn bitor(self, other: i8) -> i8 { self | other } } -impl BitOr for i16 { fn bitor(self, other: i16) -> i16 { self | other } } -impl BitOr for i32 { fn bitor(self, other: i32) -> i32 { self | other } } -impl BitOr for i64 { fn bitor(self, other: i64) -> i64 { self | other } } -``` - -### `std::ops::{ Shl, Shr }` - -```rust title="shl-trait" showLineNumbers -trait Shl { - fn shl(self, other: u8) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L127-L131 - -```rust title="shr-trait" showLineNumbers -trait Shr { - fn shr(self, other: u8) -> Self; -} -``` -> Source code: noir_stdlib/src/ops.nr#L142-L146 - - -Traits for a bit shift left and bit shift right. - -Implementing `Shl` for a type allows the left shift operator (`<<`) to be used with the implementation type. -Similarly, implementing `Shr` allows the right shift operator (`>>`) to be used with the type. - -Note that bit shifting is not currently implemented for signed types. - -The implementations block below is given for the `Shl` trait, but the same types that implement -`Shl` also implement `Shr`. - -Implementations: -```rust -impl Shl for u8 { fn shl(self, other: u8) -> u8 { self << other } } -impl Shl for u16 { fn shl(self, other: u16) -> u16 { self << other } } -impl Shl for u32 { fn shl(self, other: u32) -> u32 { self << other } } -impl Shl for u64 { fn shl(self, other: u64) -> u64 { self << other } } -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/zeroed.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/zeroed.md deleted file mode 100644 index f450fecdd36..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/zeroed.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Zeroed Function -description: - The zeroed function returns a zeroed value of any type. -keywords: - [ - zeroed - ] ---- - -Implements `fn zeroed() -> T` to return a zeroed value of any type. This function is generally unsafe to use as the zeroed bit pattern is not guaranteed to be valid for all types. It can however, be useful in cases when the value is guaranteed not to be used such as in a BoundedVec library implementing a growable vector, up to a certain length, backed by an array. The array can be initialized with zeroed values which are guaranteed to be inaccessible until the vector is pushed to. Similarly, enumerations in noir can be implemented using this method by providing zeroed values for the unused variants. - -You can access the function at `std::unsafe::zeroed`. - -This function currently supports the following types: - -- Field -- Bool -- Uint -- Array -- Slice -- String -- Tuple -- Function - -Using it on other types could result in unexpected behavior. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/.nojekyll deleted file mode 100644 index e2ac6616add..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md deleted file mode 100644 index d7249d24330..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md +++ /dev/null @@ -1,160 +0,0 @@ -# BarretenbergBackend - -## Extends - -- `BarretenbergVerifierBackend` - -## Implements - -- [`Backend`](../index.md#backend) - -## Constructors - -### new BarretenbergBackend(acirCircuit, options) - -```ts -new BarretenbergBackend(acirCircuit, options): BarretenbergBackend -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `acirCircuit` | `CompiledCircuit` | -| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | - -#### Returns - -[`BarretenbergBackend`](BarretenbergBackend.md) - -#### Inherited from - -BarretenbergVerifierBackend.constructor - -## Properties - -| Property | Type | Description | Inheritance | -| :------ | :------ | :------ | :------ | -| `acirComposer` | `any` | - | BarretenbergVerifierBackend.acirComposer | -| `acirUncompressedBytecode` | `Uint8Array` | - | BarretenbergVerifierBackend.acirUncompressedBytecode | -| `api` | `Barretenberg` | - | BarretenbergVerifierBackend.api | -| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | - | BarretenbergVerifierBackend.options | - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Inherited from - -BarretenbergVerifierBackend.destroy - -*** - -### generateProof() - -```ts -generateProof(compressedWitness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `compressedWitness` | `Uint8Array` | - -#### Returns - -`Promise`\<`ProofData`\> - -#### Description - -Generates a proof - -*** - -### generateRecursiveProofArtifacts() - -```ts -generateRecursiveProofArtifacts(proofData, numOfPublicInputs): Promise -``` - -Generates artifacts that will be passed to a circuit that will verify this proof. - -Instead of passing the proof and verification key as a byte array, we pass them -as fields which makes it cheaper to verify in a circuit. - -The proof that is passed here will have been created using a circuit -that has the #[recursive] attribute on its `main` method. - -The number of public inputs denotes how many public inputs are in the inner proof. - -#### Parameters - -| Parameter | Type | Default value | -| :------ | :------ | :------ | -| `proofData` | `ProofData` | `undefined` | -| `numOfPublicInputs` | `number` | `0` | - -#### Returns - -`Promise`\<`object`\> - -#### Example - -```typescript -const artifacts = await backend.generateRecursiveProofArtifacts(proof, numOfPublicInputs); -``` - -*** - -### getVerificationKey() - -```ts -getVerificationKey(): Promise -``` - -#### Returns - -`Promise`\<`Uint8Array`\> - -#### Inherited from - -BarretenbergVerifierBackend.getVerificationKey - -*** - -### verifyProof() - -```ts -verifyProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | `ProofData` | - -#### Returns - -`Promise`\<`boolean`\> - -#### Inherited from - -BarretenbergVerifierBackend.verifyProof - -#### Description - -Verifies a proof - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier.md deleted file mode 100644 index 500276ea748..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier.md +++ /dev/null @@ -1,58 +0,0 @@ -# BarretenbergVerifier - -## Constructors - -### new BarretenbergVerifier(options) - -```ts -new BarretenbergVerifier(options): BarretenbergVerifier -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | - -#### Returns - -[`BarretenbergVerifier`](BarretenbergVerifier.md) - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -*** - -### verifyProof() - -```ts -verifyProof(proofData, verificationKey): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | `ProofData` | -| `verificationKey` | `Uint8Array` | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Verifies a proof - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/index.md deleted file mode 100644 index 64971973196..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/index.md +++ /dev/null @@ -1,59 +0,0 @@ -# backend_barretenberg - -## Exports - -### Classes - -| Class | Description | -| :------ | :------ | -| [BarretenbergBackend](classes/BarretenbergBackend.md) | - | -| [BarretenbergVerifier](classes/BarretenbergVerifier.md) | - | - -### Type Aliases - -| Type alias | Description | -| :------ | :------ | -| [BackendOptions](type-aliases/BackendOptions.md) | - | - -## References - -### CompiledCircuit - -Renames and re-exports [Backend](index.md#backend) - -*** - -### ProofData - -Renames and re-exports [Backend](index.md#backend) - -## Variables - -### Backend - -```ts -Backend: any; -``` - -## Functions - -### publicInputsToWitnessMap() - -```ts -publicInputsToWitnessMap(publicInputs, abi): Backend -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `publicInputs` | `string`[] | -| `abi` | `Abi` | - -#### Returns - -[`Backend`](index.md#backend) - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md deleted file mode 100644 index b49a479f4f4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md +++ /dev/null @@ -1,21 +0,0 @@ -# BackendOptions - -```ts -type BackendOptions: object; -``` - -## Description - -An options object, currently only used to specify the number of threads to use. - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `memory` | `object` | - | -| `memory.maximum` | `number` | - | -| `threads` | `number` | **Description**

Number of threads | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs deleted file mode 100644 index d7d5128f9e3..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend","label":"BarretenbergBackend"},{"type":"doc","id":"reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier","label":"BarretenbergVerifier"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions","label":"BackendOptions"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/.nojekyll deleted file mode 100644 index e2ac6616add..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/classes/Noir.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/classes/Noir.md deleted file mode 100644 index 45dd62ee57e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/classes/Noir.md +++ /dev/null @@ -1,132 +0,0 @@ -# Noir - -## Constructors - -### new Noir(circuit, backend) - -```ts -new Noir(circuit, backend?): Noir -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `circuit` | `CompiledCircuit` | -| `backend`? | `any` | - -#### Returns - -[`Noir`](Noir.md) - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Description - -Destroys the underlying backend instance. - -#### Example - -```typescript -await noir.destroy(); -``` - -*** - -### execute() - -```ts -execute(inputs, foreignCallHandler?): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `inputs` | `InputMap` | -| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | - -#### Returns - -`Promise`\<`object`\> - -#### Description - -Allows to execute a circuit to get its witness and return value. - -#### Example - -```typescript -async execute(inputs) -``` - -*** - -### generateProof() - -```ts -generateProof(inputs, foreignCallHandler?): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `inputs` | `InputMap` | -| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | - -#### Returns - -`Promise`\<`ProofData`\> - -#### Description - -Generates a witness and a proof given an object as input. - -#### Example - -```typescript -async generateProof(input) -``` - -*** - -### verifyProof() - -```ts -verifyProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | `ProofData` | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Instantiates the verification key and verifies a proof. - -#### Example - -```typescript -async verifyProof(proof) -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/and.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/and.md deleted file mode 100644 index c783283e396..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/and.md +++ /dev/null @@ -1,22 +0,0 @@ -# and() - -```ts -and(lhs, rhs): string -``` - -Performs a bitwise AND operation between `lhs` and `rhs` - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `lhs` | `string` | | -| `rhs` | `string` | | - -## Returns - -`string` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/blake2s256.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/blake2s256.md deleted file mode 100644 index 7882d0da8d5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/blake2s256.md +++ /dev/null @@ -1,21 +0,0 @@ -# blake2s256() - -```ts -blake2s256(inputs): Uint8Array -``` - -Calculates the Blake2s256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md deleted file mode 100644 index 5e3cd53e9d3..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md +++ /dev/null @@ -1,28 +0,0 @@ -# ecdsa\_secp256k1\_verify() - -```ts -ecdsa_secp256k1_verify( - hashed_msg, - public_key_x_bytes, - public_key_y_bytes, - signature): boolean -``` - -Verifies a ECDSA signature over the secp256k1 curve. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `hashed_msg` | `Uint8Array` | | -| `public_key_x_bytes` | `Uint8Array` | | -| `public_key_y_bytes` | `Uint8Array` | | -| `signature` | `Uint8Array` | | - -## Returns - -`boolean` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md deleted file mode 100644 index 0b20ff68957..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md +++ /dev/null @@ -1,28 +0,0 @@ -# ecdsa\_secp256r1\_verify() - -```ts -ecdsa_secp256r1_verify( - hashed_msg, - public_key_x_bytes, - public_key_y_bytes, - signature): boolean -``` - -Verifies a ECDSA signature over the secp256r1 curve. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `hashed_msg` | `Uint8Array` | | -| `public_key_x_bytes` | `Uint8Array` | | -| `public_key_y_bytes` | `Uint8Array` | | -| `signature` | `Uint8Array` | | - -## Returns - -`boolean` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/keccak256.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/keccak256.md deleted file mode 100644 index d10f155ce86..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/keccak256.md +++ /dev/null @@ -1,21 +0,0 @@ -# keccak256() - -```ts -keccak256(inputs): Uint8Array -``` - -Calculates the Keccak256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/sha256.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/sha256.md deleted file mode 100644 index 6ba4ecac022..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/sha256.md +++ /dev/null @@ -1,21 +0,0 @@ -# sha256() - -```ts -sha256(inputs): Uint8Array -``` - -Calculates the SHA256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/xor.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/xor.md deleted file mode 100644 index 8d762b895d3..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/xor.md +++ /dev/null @@ -1,22 +0,0 @@ -# xor() - -```ts -xor(lhs, rhs): string -``` - -Performs a bitwise XOR operation between `lhs` and `rhs` - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `lhs` | `string` | | -| `rhs` | `string` | | - -## Returns - -`string` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/index.md deleted file mode 100644 index cca6b3ace41..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/index.md +++ /dev/null @@ -1,54 +0,0 @@ -# noir_js - -## Exports - -### Classes - -| Class | Description | -| :------ | :------ | -| [Noir](classes/Noir.md) | - | - -### Type Aliases - -| Type alias | Description | -| :------ | :------ | -| [ForeignCallHandler](type-aliases/ForeignCallHandler.md) | A callback which performs an foreign call and returns the response. | -| [ForeignCallInput](type-aliases/ForeignCallInput.md) | - | -| [ForeignCallOutput](type-aliases/ForeignCallOutput.md) | - | -| [WitnessMap](type-aliases/WitnessMap.md) | - | - -### Functions - -| Function | Description | -| :------ | :------ | -| [and](functions/and.md) | Performs a bitwise AND operation between `lhs` and `rhs` | -| [blake2s256](functions/blake2s256.md) | Calculates the Blake2s256 hash of the input bytes | -| [ecdsa\_secp256k1\_verify](functions/ecdsa_secp256k1_verify.md) | Verifies a ECDSA signature over the secp256k1 curve. | -| [ecdsa\_secp256r1\_verify](functions/ecdsa_secp256r1_verify.md) | Verifies a ECDSA signature over the secp256r1 curve. | -| [keccak256](functions/keccak256.md) | Calculates the Keccak256 hash of the input bytes | -| [sha256](functions/sha256.md) | Calculates the SHA256 hash of the input bytes | -| [xor](functions/xor.md) | Performs a bitwise XOR operation between `lhs` and `rhs` | - -## References - -### CompiledCircuit - -Renames and re-exports [InputMap](index.md#inputmap) - -*** - -### ProofData - -Renames and re-exports [InputMap](index.md#inputmap) - -## Variables - -### InputMap - -```ts -InputMap: any; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md deleted file mode 100644 index 812b8b16481..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md +++ /dev/null @@ -1,24 +0,0 @@ -# ForeignCallHandler - -```ts -type ForeignCallHandler: (name, inputs) => Promise; -``` - -A callback which performs an foreign call and returns the response. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `name` | `string` | The identifier for the type of foreign call being performed. | -| `inputs` | [`ForeignCallInput`](ForeignCallInput.md)[] | An array of hex encoded inputs to the foreign call. | - -## Returns - -`Promise`\<[`ForeignCallOutput`](ForeignCallOutput.md)[]\> - -outputs - An array of hex encoded outputs containing the results of the foreign call. - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md deleted file mode 100644 index dd95809186a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md +++ /dev/null @@ -1,9 +0,0 @@ -# ForeignCallInput - -```ts -type ForeignCallInput: string[]; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md deleted file mode 100644 index b71fb78a946..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md +++ /dev/null @@ -1,9 +0,0 @@ -# ForeignCallOutput - -```ts -type ForeignCallOutput: string | string[]; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md deleted file mode 100644 index 258c46f9d0c..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md +++ /dev/null @@ -1,9 +0,0 @@ -# WitnessMap - -```ts -type WitnessMap: Map; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs deleted file mode 100644 index c6d8125eaad..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/noir_js/classes/Noir","label":"Noir"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallHandler","label":"ForeignCallHandler"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallInput","label":"ForeignCallInput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallOutput","label":"ForeignCallOutput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/WitnessMap","label":"WitnessMap"}]},{"type":"category","label":"Functions","items":[{"type":"doc","id":"reference/NoirJS/noir_js/functions/and","label":"and"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/blake2s256","label":"blake2s256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify","label":"ecdsa_secp256k1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify","label":"ecdsa_secp256r1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/keccak256","label":"keccak256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/sha256","label":"sha256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/xor","label":"xor"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/.nojekyll deleted file mode 100644 index e2ac6616add..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/functions/compile.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/functions/compile.md deleted file mode 100644 index 6faf763b37f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/functions/compile.md +++ /dev/null @@ -1,51 +0,0 @@ -# compile() - -```ts -compile( - fileManager, - projectPath?, - logFn?, -debugLogFn?): Promise -``` - -Compiles a Noir project - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `fileManager` | `FileManager` | The file manager to use | -| `projectPath`? | `string` | The path to the project inside the file manager. Defaults to the root of the file manager | -| `logFn`? | `LogFn` | A logging function. If not provided, console.log will be used | -| `debugLogFn`? | `LogFn` | A debug logging function. If not provided, logFn will be used | - -## Returns - -`Promise`\<[`ProgramCompilationArtifacts`](../index.md#programcompilationartifacts)\> - -## Example - -```typescript -// Node.js - -import { compile_program, createFileManager } from '@noir-lang/noir_wasm'; - -const fm = createFileManager(myProjectPath); -const myCompiledCode = await compile_program(fm); -``` - -```typescript -// Browser - -import { compile_program, createFileManager } from '@noir-lang/noir_wasm'; - -const fm = createFileManager('/'); -for (const path of files) { - await fm.writeFile(path, await getFileAsStream(path)); -} -const myCompiledCode = await compile_program(fm); -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/functions/compile_contract.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/functions/compile_contract.md deleted file mode 100644 index 7d0b39a43ef..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/functions/compile_contract.md +++ /dev/null @@ -1,51 +0,0 @@ -# compile\_contract() - -```ts -compile_contract( - fileManager, - projectPath?, - logFn?, -debugLogFn?): Promise -``` - -Compiles a Noir project - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `fileManager` | `FileManager` | The file manager to use | -| `projectPath`? | `string` | The path to the project inside the file manager. Defaults to the root of the file manager | -| `logFn`? | `LogFn` | A logging function. If not provided, console.log will be used | -| `debugLogFn`? | `LogFn` | A debug logging function. If not provided, logFn will be used | - -## Returns - -`Promise`\<[`ContractCompilationArtifacts`](../index.md#contractcompilationartifacts)\> - -## Example - -```typescript -// Node.js - -import { compile_contract, createFileManager } from '@noir-lang/noir_wasm'; - -const fm = createFileManager(myProjectPath); -const myCompiledCode = await compile_contract(fm); -``` - -```typescript -// Browser - -import { compile_contract, createFileManager } from '@noir-lang/noir_wasm'; - -const fm = createFileManager('/'); -for (const path of files) { - await fm.writeFile(path, await getFileAsStream(path)); -} -const myCompiledCode = await compile_contract(fm); -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/functions/createFileManager.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/functions/createFileManager.md deleted file mode 100644 index 7e65c1d69c7..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/functions/createFileManager.md +++ /dev/null @@ -1,21 +0,0 @@ -# createFileManager() - -```ts -createFileManager(dataDir): FileManager -``` - -Creates a new FileManager instance based on fs in node and memfs in the browser (via webpack alias) - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `dataDir` | `string` | root of the file system | - -## Returns - -`FileManager` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md deleted file mode 100644 index fcea9275341..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md +++ /dev/null @@ -1,21 +0,0 @@ -# inflateDebugSymbols() - -```ts -inflateDebugSymbols(debugSymbols): any -``` - -Decompresses and decodes the debug symbols - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `debugSymbols` | `string` | The base64 encoded debug symbols | - -## Returns - -`any` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/index.md deleted file mode 100644 index b6e0f9d1bc0..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/index.md +++ /dev/null @@ -1,49 +0,0 @@ -# noir_wasm - -## Exports - -### Functions - -| Function | Description | -| :------ | :------ | -| [compile](functions/compile.md) | Compiles a Noir project | -| [compile\_contract](functions/compile_contract.md) | Compiles a Noir project | -| [createFileManager](functions/createFileManager.md) | Creates a new FileManager instance based on fs in node and memfs in the browser (via webpack alias) | -| [inflateDebugSymbols](functions/inflateDebugSymbols.md) | Decompresses and decodes the debug symbols | - -## References - -### compile\_program - -Renames and re-exports [compile](functions/compile.md) - -## Interfaces - -### ContractCompilationArtifacts - -The compilation artifacts of a given contract. - -#### Properties - -| Property | Type | Description | -| :------ | :------ | :------ | -| `contract` | `ContractArtifact` | The compiled contract. | -| `warnings` | `unknown`[] | Compilation warnings. | - -*** - -### ProgramCompilationArtifacts - -The compilation artifacts of a given program. - -#### Properties - -| Property | Type | Description | -| :------ | :------ | :------ | -| `name` | `string` | not part of the compilation output, injected later | -| `program` | `ProgramArtifact` | The compiled contract. | -| `warnings` | `unknown`[] | Compilation warnings. | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs deleted file mode 100644 index e0870710349..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"doc","id":"reference/NoirJS/noir_wasm/index","label":"API"},{"type":"category","label":"Functions","items":[{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/compile","label":"compile"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/compile_contract","label":"compile_contract"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/createFileManager","label":"createFileManager"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/inflateDebugSymbols","label":"inflateDebugSymbols"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/_category_.json deleted file mode 100644 index 5b6a20a609a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 4, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/debugger/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/debugger/_category_.json deleted file mode 100644 index 27869205ad3..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/debugger/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Debugger", - "position": 1, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/debugger/debugger_known_limitations.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/debugger/debugger_known_limitations.md deleted file mode 100644 index 936d416ac4b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/debugger/debugger_known_limitations.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: Known limitations -description: - An overview of known limitations of the current version of the Noir debugger -keywords: - [ - Nargo, - Noir Debugger, - VS Code, - ] -sidebar_position: 2 ---- - -# Debugger Known Limitations - -There are currently some limits to what the debugger can observe. - -## Mutable references - -The debugger is currently blind to any state mutated via a mutable reference. For example, in: - -``` -let mut x = 1; -let y = &mut x; -*y = 2; -``` - -The update on `x` will not be observed by the debugger. That means, when running `vars` from the debugger REPL, or inspecting the _local variables_ pane in the VS Code debugger, `x` will appear with value 1 despite having executed `*y = 2;`. - -## Variables of type function or mutable references are opaque - -When inspecting variables, any variable of type `Function` or `MutableReference` will render its value as `<>` or `<>`. - -## Debugger instrumentation affects resulting ACIR - -In order to make the state of local variables observable, the debugger compiles Noir circuits interleaving foreign calls that track any mutations to them. While this works (except in the cases described above) and doesn't introduce any behavior changes, it does as a side effect produce bigger bytecode. In particular, when running the command `opcodes` on the REPL debugger, you will notice Unconstrained VM blocks that look like this: - -``` -... -5 BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [], q_c: 2 }), Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(2))], q_c: 0 })] - | outputs=[] - 5.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } - 5.1 | Mov { destination: RegisterIndex(3), source: RegisterIndex(1) } - 5.2 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } - 5.3 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } - 5.4 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } - 5.5 | Mov { destination: RegisterIndex(3), source: RegisterIndex(3) } - 5.6 | Call { location: 8 } - 5.7 | Stop - 5.8 | ForeignCall { function: "__debug_var_assign", destinations: [], inputs: [RegisterIndex(RegisterIndex(2)), RegisterIndex(RegisterIndex(3))] } -... -``` - -If you are interested in debugging/inspecting compiled ACIR without these synthetic changes, you can invoke the REPL debugger with the `--skip-instrumentation` flag or launch the VS Code debugger with the `skipConfiguration` property set to true in its launch configuration. You can find more details about those in the [Debugger REPL reference](debugger_repl.md) and the [VS Code Debugger reference](debugger_vscode.md). - -:::note -Skipping debugger instrumentation means you won't be able to inspect values of local variables. -::: - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/debugger/debugger_repl.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/debugger/debugger_repl.md deleted file mode 100644 index 46e2011304e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/debugger/debugger_repl.md +++ /dev/null @@ -1,360 +0,0 @@ ---- -title: REPL Debugger -description: - Noir Debugger REPL options and commands. -keywords: - [ - Nargo, - Noir CLI, - Noir Debugger, - REPL, - ] -sidebar_position: 1 ---- - -## Running the REPL debugger - -`nargo debug [OPTIONS] [WITNESS_NAME]` - -Runs the Noir REPL debugger. If a `WITNESS_NAME` is provided the debugger writes the resulting execution witness to a `WITNESS_NAME` file. - -### Options - -| Option | Description | -| --------------------- | ------------------------------------------------------------ | -| `-p, --prover-name ` | The name of the toml file which contains the inputs for the prover [default: Prover]| -| `--package ` | The name of the package to debug | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -None of these options are required. - -:::note -Since the debugger starts by compiling the target package, all Noir compiler options are also available. Check out the [compiler reference](../nargo_commands.md#nargo-compile) to learn more about the compiler options. -::: - -## REPL commands - -Once the debugger is running, it accepts the following commands. - -#### `help` (h) - -Displays the menu of available commands. - -``` -> help -Available commands: - - opcodes display ACIR opcodes - into step into to the next opcode - next step until a new source location is reached - out step until a new source location is reached - and the current stack frame is finished - break LOCATION:OpcodeLocation add a breakpoint at an opcode location - over step until a new source location is reached - without diving into function calls - restart restart the debugging session - delete LOCATION:OpcodeLocation delete breakpoint at an opcode location - witness show witness map - witness index:u32 display a single witness from the witness map - witness index:u32 value:String update a witness with the given value - memset index:usize value:String update a memory cell with the given - value - continue continue execution until the end of the - program - vars show variable values available at this point - in execution - stacktrace display the current stack trace - memory show memory (valid when executing unconstrained code) value - step step to the next ACIR opcode - -Other commands: - - help Show this help message - quit Quit repl - -``` - -### Stepping through programs - -#### `next` (n) - -Step until the next Noir source code location. While other commands, such as [`into`](#into-i) and [`step`](#step-s), allow for finer grained control of the program's execution at the opcode level, `next` is source code centric. For example: - -``` -3 ... -4 fn main(x: u32) { -5 assert(entry_point(x) == 2); -6 swap_entry_point(x, x + 1); -7 -> assert(deep_entry_point(x) == 4); -8 multiple_values_entry_point(x); -9 } -``` - - -Using `next` here would cause the debugger to jump to the definition of `deep_entry_point` (if available). - -If you want to step over `deep_entry_point` and go straight to line 8, use [the `over` command](#over) instead. - -#### `over` - -Step until the next source code location, without diving into function calls. For example: - -``` -3 ... -4 fn main(x: u32) { -5 assert(entry_point(x) == 2); -6 swap_entry_point(x, x + 1); -7 -> assert(deep_entry_point(x) == 4); -8 multiple_values_entry_point(x); -9 } -``` - - -Using `over` here would cause the debugger to execute until line 8 (`multiple_values_entry_point(x);`). - -If you want to step into `deep_entry_point` instead, use [the `next` command](#next-n). - -#### `out` - -Step until the end of the current function call. For example: - -``` - 3 ... - 4 fn main(x: u32) { - 5 assert(entry_point(x) == 2); - 6 swap_entry_point(x, x + 1); - 7 -> assert(deep_entry_point(x) == 4); - 8 multiple_values_entry_point(x); - 9 } - 10 - 11 unconstrained fn returns_multiple_values(x: u32) -> (u32, u32, u32, u32) { - 12 ... - ... - 55 - 56 unconstrained fn deep_entry_point(x: u32) -> u32 { - 57 -> level_1(x + 1) - 58 } - -``` - -Running `out` here will resume execution until line 8. - -#### `step` (s) - -Skips to the next ACIR code. A compiled Noir program is a sequence of ACIR opcodes. However, an unconstrained VM opcode denotes the start of an unconstrained code block, to be executed by the unconstrained VM. For example (redacted for brevity): - -``` -0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] -1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] - 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } - 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } - 1.2 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } - 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } - 1.4 | Call { location: 7 } - ... - 1.43 | Return -2 EXPR [ (1, _1) -2 ] -``` - -The `->` here shows the debugger paused at an ACIR opcode: `BRILLIG`, at index 1, which denotes an unconstrained code block is about to start. - -Using the `step` command at this point would result in the debugger stopping at ACIR opcode 2, `EXPR`, skipping unconstrained computation steps. - -Use [the `into` command](#into-i) instead if you want to follow unconstrained computation step by step. - -#### `into` (i) - -Steps into the next opcode. A compiled Noir program is a sequence of ACIR opcodes. However, a BRILLIG opcode denotes the start of an unconstrained code block, to be executed by the unconstrained VM. For example (redacted for brevity): - -``` -0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] -1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] - 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } - 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } - 1.2 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } - 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } - 1.4 | Call { location: 7 } - ... - 1.43 | Return -2 EXPR [ (1, _1) -2 ] -``` - -The `->` here shows the debugger paused at an ACIR opcode: `BRILLIG`, at index 1, which denotes an unconstrained code block is about to start. - -Using the `into` command at this point would result in the debugger stopping at opcode 1.0, `Mov ...`, allowing the debugger user to follow unconstrained computation step by step. - -Use [the `step` command](#step-s) instead if you want to skip to the next ACIR code directly. - -#### `continue` (c) - -Continues execution until the next breakpoint, or the end of the program. - -#### `restart` (res) - -Interrupts execution, and restarts a new debugging session from scratch. - -#### `opcodes` (o) - -Display the program's ACIR opcode sequence. For example: - -``` -0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] -1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] - 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } - 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } - 1.2 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } - 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } - 1.4 | Call { location: 7 } - ... - 1.43 | Return -2 EXPR [ (1, _1) -2 ] -``` - -### Breakpoints - -#### `break [Opcode]` (or shorthand `b [Opcode]`) - -Sets a breakpoint on the specified opcode index. To get a list of the program opcode numbers, see [the `opcode` command](#opcodes-o). For example: - -``` -0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] -1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] - 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } - 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } - 1.2 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } - 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } - 1.4 | Call { location: 7 } - ... - 1.43 | Return -2 EXPR [ (1, _1) -2 ] -``` - -In this example, issuing a `break 1.2` command adds break on opcode 1.2, as denoted by the `*` character: - -``` -0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] -1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] - 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } - 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } - 1.2 | * Const { destination: RegisterIndex(1), value: Value { inner: 0 } } - 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } - 1.4 | Call { location: 7 } - ... - 1.43 | Return -2 EXPR [ (1, _1) -2 ] -``` - -Running [the `continue` command](#continue-c) at this point would cause the debugger to execute the program until opcode 1.2. - -#### `delete [Opcode]` (or shorthand `d [Opcode]`) - -Deletes a breakpoint at an opcode location. Usage is analogous to [the `break` command](#). - -### Variable inspection - -#### vars - -Show variable values available at this point in execution. - -:::note -The ability to inspect variable values from the debugger depends on compilation to be run in a special debug instrumentation mode. This instrumentation weaves variable tracing code with the original source code. - -So variable value inspection comes at the expense of making the resulting ACIR bytecode bigger and harder to understand and optimize. - -If you find this compromise unacceptable, you can run the debugger with the flag `--skip-debug-instrumentation`. This will compile your circuit without any additional debug information, so the resulting ACIR bytecode will be identical to the one produced by standard Noir compilation. However, if you opt for this, the `vars` command will not be available while debugging. -::: - - -### Stacktrace - -#### `stacktrace` - -Displays the current stack trace. - - -### Witness map - -#### `witness` (w) - -Show witness map. For example: - -``` -_0 = 0 -_1 = 2 -_2 = 1 -``` - -#### `witness [Witness Index]` - -Display a single witness from the witness map. For example: - -``` -> witness 1 -_1 = 2 -``` - -#### `witness [Witness Index] [New value]` - -Overwrite the given index with a new value. For example: - -``` -> witness 1 3 -_1 = 3 -``` - - -### Unconstrained VM memory - -#### `memory` - -Show unconstrained VM memory state. For example: - -``` -> memory -At opcode 1.13: Store { destination_pointer: RegisterIndex(0), source: RegisterIndex(3) } -... -> registers -0 = 0 -1 = 10 -2 = 0 -3 = 1 -4 = 1 -5 = 2³² -6 = 1 -> into -At opcode 1.14: Const { destination: RegisterIndex(5), value: Value { inner: 1 } } -... -> memory -0 = 1 -> -``` - -In the example above: we start with clean memory, then step through a `Store` opcode which stores the value of register 3 (1) into the memory address stored in register 0 (0). Thus now `memory` shows memory address 0 contains value 1. - -:::note -This command is only functional while the debugger is executing unconstrained code. -::: - -#### `memset [Memory address] [New value]` - -Update a memory cell with the given value. For example: - -``` -> memory -0 = 1 -> memset 0 2 -> memory -0 = 2 -> memset 1 4 -> memory -0 = 2 -1 = 4 -> -``` - -:::note -This command is only functional while the debugger is executing unconstrained code. -::: \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/debugger/debugger_vscode.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/debugger/debugger_vscode.md deleted file mode 100644 index c027332b3b0..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/debugger/debugger_vscode.md +++ /dev/null @@ -1,82 +0,0 @@ ---- -title: VS Code Debugger -description: - VS Code Debugger configuration and features. -keywords: - [ - Nargo, - Noir CLI, - Noir Debugger, - VS Code, - IDE, - ] -sidebar_position: 0 ---- - -# VS Code Noir Debugger Reference - -The Noir debugger enabled by the vscode-noir extension ships with default settings such that the most common scenario should run without any additional configuration steps. - -These defaults can nevertheless be overridden by defining a launch configuration file. This page provides a reference for the properties you can override via a launch configuration file, as well as documenting the Nargo `dap` command, which is a dependency of the VS Code Noir debugger. - - -## Creating and editing launch configuration files - -To create a launch configuration file from VS Code, open the _debug pane_, and click on _create a launch.json file_. - -![Creating a launch configuration file](@site/static/img/debugger/ref1-create-launch.png) - -A `launch.json` file will be created, populated with basic defaults. - -### Noir Debugger launch.json properties - -#### projectFolder - -_String, optional._ - -Absolute path to the Nargo project to debug. By default, it is dynamically determined by looking for the nearest `Nargo.toml` file to the active file at the moment of launching the debugger. - -#### proverName - -_String, optional._ - -Name of the prover input to use. Defaults to `Prover`, which looks for a file named `Prover.toml` at the `projectFolder`. - -#### generateAcir - -_Boolean, optional._ - -If true, generate ACIR opcodes instead of unconstrained opcodes which will be closer to release binaries but less convenient for debugging. Defaults to `false`. - -#### skipInstrumentation - -_Boolean, optional._ - -Skips variables debugging instrumentation of code, making debugging less convenient but the resulting binary smaller and closer to production. Defaults to `false`. - -:::note -Skipping instrumentation causes the debugger to be unable to inspect local variables. -::: - -## `nargo dap [OPTIONS]` - -When run without any option flags, it starts the Nargo Debug Adapter Protocol server, which acts as the debugging backend for the VS Code Noir Debugger. - -All option flags are related to preflight checks. The Debug Adapter Protocol specifies how errors are to be informed from a running DAP server, but it doesn't specify mechanisms to communicate server initialization errors between the DAP server and its client IDE. - -Thus `nargo dap` ships with a _preflight check_ mode. If flag `--preflight-check` and the rest of the `--preflight-*` flags are provided, Nargo will run the same initialization routine except it will not start the DAP server. - -`vscode-noir` will then run `nargo dap` in preflight check mode first before a debugging session starts. If the preflight check ends in error, vscode-noir will present stderr and stdout output from this process through its own Output pane in VS Code. This makes it possible for users to diagnose what pieces of configuration might be wrong or missing in case of initialization errors. - -If the preflight check succeeds, `vscode-noir` proceeds to start the DAP server normally but running `nargo dap` without any additional flags. - -### Options - -| Option | Description | -| --------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | -| `--preflight-check` | If present, dap runs in preflight check mode. | -| `--preflight-project-folder ` | Absolute path to the project to debug for preflight check. | -| `--preflight-prover-name ` | Name of prover file to use for preflight check | -| `--preflight-generate-acir` | Optional. If present, compile in ACIR mode while running preflight check. | -| `--preflight-skip-instrumentation` | Optional. If present, compile without introducing debug instrumentation while running preflight check. | -| `-h, --help` | Print help. | diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/nargo_commands.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/nargo_commands.md deleted file mode 100644 index 218fcfb0c8c..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/reference/nargo_commands.md +++ /dev/null @@ -1,381 +0,0 @@ ---- -title: Nargo -description: - Noir CLI Commands for Noir Prover and Verifier to create, execute, prove and verify programs, - generate Solidity verifier smart contract and compile into JSON file containing ACIR - representation and ABI of circuit. -keywords: - [ - Nargo, - Noir CLI, - Noir Prover, - Noir Verifier, - generate Solidity verifier, - compile JSON file, - ACIR representation, - ABI of circuit, - TypeScript, - ] -sidebar_position: 0 ---- - -# Command-Line Help for `nargo` - -This document contains the help content for the `nargo` command-line program. - -**Command Overview:** - -* [`nargo`↴](#nargo) -* [`nargo backend`↴](#nargo-backend) -* [`nargo backend current`↴](#nargo-backend-current) -* [`nargo backend ls`↴](#nargo-backend-ls) -* [`nargo backend use`↴](#nargo-backend-use) -* [`nargo backend install`↴](#nargo-backend-install) -* [`nargo backend uninstall`↴](#nargo-backend-uninstall) -* [`nargo check`↴](#nargo-check) -* [`nargo fmt`↴](#nargo-fmt) -* [`nargo codegen-verifier`↴](#nargo-codegen-verifier) -* [`nargo compile`↴](#nargo-compile) -* [`nargo new`↴](#nargo-new) -* [`nargo init`↴](#nargo-init) -* [`nargo execute`↴](#nargo-execute) -* [`nargo prove`↴](#nargo-prove) -* [`nargo verify`↴](#nargo-verify) -* [`nargo test`↴](#nargo-test) -* [`nargo info`↴](#nargo-info) -* [`nargo lsp`↴](#nargo-lsp) - -## `nargo` - -Noir's package manager - -**Usage:** `nargo ` - -###### **Subcommands:** - -* `backend` — Install and select custom backends used to generate and verify proofs -* `check` — Checks the constraint system for errors -* `fmt` — Format the Noir files in a workspace -* `codegen-verifier` — Generates a Solidity verifier smart contract for the program -* `compile` — Compile the program and its secret execution trace into ACIR format -* `new` — Create a Noir project in a new directory -* `init` — Create a Noir project in the current directory -* `execute` — Executes a circuit to calculate its return value -* `prove` — Create proof for this program. The proof is returned as a hex encoded string -* `verify` — Given a proof and a program, verify whether the proof is valid -* `test` — Run the tests for this program -* `info` — Provides detailed information on each of a program's function (represented by a single circuit) -* `lsp` — Starts the Noir LSP server - -###### **Options:** - - - - -## `nargo backend` - -Install and select custom backends used to generate and verify proofs - -**Usage:** `nargo backend ` - -###### **Subcommands:** - -* `current` — Prints the name of the currently active backend -* `ls` — Prints the list of currently installed backends -* `use` — Select the backend to use -* `install` — Install a new backend from a URL -* `uninstall` — Uninstalls a backend - - - -## `nargo backend current` - -Prints the name of the currently active backend - -**Usage:** `nargo backend current` - - - -## `nargo backend ls` - -Prints the list of currently installed backends - -**Usage:** `nargo backend ls` - - - -## `nargo backend use` - -Select the backend to use - -**Usage:** `nargo backend use ` - -###### **Arguments:** - -* `` - - - -## `nargo backend install` - -Install a new backend from a URL - -**Usage:** `nargo backend install ` - -###### **Arguments:** - -* `` — The name of the backend to install -* `` — The URL from which to download the backend - - - -## `nargo backend uninstall` - -Uninstalls a backend - -**Usage:** `nargo backend uninstall ` - -###### **Arguments:** - -* `` — The name of the backend to uninstall - - - -## `nargo check` - -Checks the constraint system for errors - -**Usage:** `nargo check [OPTIONS]` - -###### **Options:** - -* `--package ` — The name of the package to check -* `--workspace` — Check all packages in the workspace -* `--overwrite` — Force overwrite of existing files -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings - - - -## `nargo fmt` - -Format the Noir files in a workspace - -**Usage:** `nargo fmt [OPTIONS]` - -###### **Options:** - -* `--check` — Run noirfmt in check mode - - - -## `nargo codegen-verifier` - -Generates a Solidity verifier smart contract for the program - -**Usage:** `nargo codegen-verifier [OPTIONS]` - -###### **Options:** - -* `--package ` — The name of the package to codegen -* `--workspace` — Codegen all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings - - - -## `nargo compile` - -Compile the program and its secret execution trace into ACIR format - -**Usage:** `nargo compile [OPTIONS]` - -###### **Options:** - -* `--package ` — The name of the package to compile -* `--workspace` — Compile all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings - - - -## `nargo new` - -Create a Noir project in a new directory - -**Usage:** `nargo new [OPTIONS] ` - -###### **Arguments:** - -* `` — The path to save the new project - -###### **Options:** - -* `--name ` — Name of the package [default: package directory name] -* `--lib` — Use a library template -* `--bin` — Use a binary template [default] -* `--contract` — Use a contract template - - - -## `nargo init` - -Create a Noir project in the current directory - -**Usage:** `nargo init [OPTIONS]` - -###### **Options:** - -* `--name ` — Name of the package [default: current directory name] -* `--lib` — Use a library template -* `--bin` — Use a binary template [default] -* `--contract` — Use a contract template - - - -## `nargo execute` - -Executes a circuit to calculate its return value - -**Usage:** `nargo execute [OPTIONS] [WITNESS_NAME]` - -###### **Arguments:** - -* `` — Write the execution witness to named file - -###### **Options:** - -* `-p`, `--prover-name ` — The name of the toml file which contains the inputs for the prover - - Default value: `Prover` -* `--package ` — The name of the package to execute -* `--workspace` — Execute all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings -* `--oracle-resolver ` — JSON RPC url to solve oracle calls - - - -## `nargo prove` - -Create proof for this program. The proof is returned as a hex encoded string - -**Usage:** `nargo prove [OPTIONS]` - -###### **Options:** - -* `-p`, `--prover-name ` — The name of the toml file which contains the inputs for the prover - - Default value: `Prover` -* `-v`, `--verifier-name ` — The name of the toml file which contains the inputs for the verifier - - Default value: `Verifier` -* `--verify` — Verify proof after proving -* `--package ` — The name of the package to prove -* `--workspace` — Prove all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings -* `--oracle-resolver ` — JSON RPC url to solve oracle calls - - - -## `nargo verify` - -Given a proof and a program, verify whether the proof is valid - -**Usage:** `nargo verify [OPTIONS]` - -###### **Options:** - -* `-v`, `--verifier-name ` — The name of the toml file which contains the inputs for the verifier - - Default value: `Verifier` -* `--package ` — The name of the package verify -* `--workspace` — Verify all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings - - - -## `nargo test` - -Run the tests for this program - -**Usage:** `nargo test [OPTIONS] [TEST_NAME]` - -###### **Arguments:** - -* `` — If given, only tests with names containing this string will be run - -###### **Options:** - -* `--show-output` — Display output of `println` statements -* `--exact` — Only run tests that match exactly -* `--package ` — The name of the package to test -* `--workspace` — Test all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings -* `--oracle-resolver ` — JSON RPC url to solve oracle calls - - - -## `nargo info` - -Provides detailed information on each of a program's function (represented by a single circuit) - -Current information provided per circuit: 1. The number of ACIR opcodes 2. Counts the final number gates in the circuit used by a backend - -**Usage:** `nargo info [OPTIONS]` - -###### **Options:** - -* `--package ` — The name of the package to detail -* `--workspace` — Detail all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings - - - -## `nargo lsp` - -Starts the Noir LSP server - -Starts an LSP server which allows IDEs such as VS Code to display diagnostics in Noir source. - -VS Code Noir Language Support: https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir - -**Usage:** `nargo lsp` - - - -
- - - This document was generated automatically by - clap-markdown. - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/tooling/debugger.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/tooling/debugger.md deleted file mode 100644 index 9b7565ba9ff..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/tooling/debugger.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Debugger -description: Learn about the Noir Debugger, in its REPL or VS Code versions. -keywords: [Nargo, VSCode, Visual Studio Code, REPL, Debugger] -sidebar_position: 2 ---- - -# Noir Debugger - -There are currently two ways of debugging Noir programs: - -1. From VS Code, via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). -2. Via the REPL debugger, which ships with Nargo. - -In order to use either version of the debugger, you will need to install recent enough versions of Noir, [Nargo](../getting_started/installation/index.md) and vscode-noir: - -- Noir & Nargo ≥0.28.0 -- Noir's VS Code extension ≥0.0.11 - -:::info -At the moment, the debugger supports debugging binary projects, but not contracts. -::: - -We cover the VS Code Noir debugger more in depth in [its VS Code debugger how-to guide](../how_to/debugger/debugging_with_vs_code.md) and [the reference](../reference/debugger/debugger_vscode.md). - -The REPL debugger is discussed at length in [the REPL debugger how-to guide](../how_to/debugger/debugging_with_the_repl.md) and [the reference](../reference/debugger/debugger_repl.md). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/tooling/language_server.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/tooling/language_server.md deleted file mode 100644 index 81e0356ef8a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/tooling/language_server.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Language Server -description: Learn about the Noir Language Server, how to install the components, and configuration that may be required. -keywords: [Nargo, Language Server, LSP, VSCode, Visual Studio Code] -sidebar_position: 0 ---- - -This section helps you install and configure the Noir Language Server. - -The Language Server Protocol (LSP) has two components, the [Server](#language-server) and the [Client](#language-client). Below we describe each in the context of Noir. - -## Language Server - -The Server component is provided by the Nargo command line tool that you installed at the beginning of this guide. -As long as Nargo is installed and you've used it to run other commands in this guide, it should be good to go! - -If you'd like to verify that the `nargo lsp` command is available, you can run `nargo --help` and look for `lsp` in the list of commands. If you see it, you're using a version of Noir with LSP support. - -## Language Client - -The Client component is usually an editor plugin that launches the Server. It communicates LSP messages between the editor and the Server. For example, when you save a file, the Client will alert the Server, so it can try to compile the project and report any errors. - -Currently, Noir provides a Language Client for Visual Studio Code via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). - -> **Note:** Noir's Language Server Protocol support currently assumes users' VSCode workspace root to be the same as users' Noir project root (i.e. where Nargo.toml lies). -> -> If LSP features seem to be missing / malfunctioning, make sure you are opening your Noir project directly (instead of as a sub-folder) in your VSCode instance. - -When your language server is running correctly and the VSCode plugin is installed, you should see handy codelens buttons for compilation, measuring circuit size, execution, and tests: - -![Compile and Execute](@site/static/img/codelens_compile_execute.png) -![Run test](@site/static/img/codelens_run_test.png) - -You should also see your tests in the `testing` panel: - -![Testing panel](@site/static/img/codelens_testing_panel.png) - -### Configuration - -- **Noir: Enable LSP** - If checked, the extension will launch the Language Server via `nargo lsp` and communicate with it. -- **Noir: Nargo Flags** - Additional flags may be specified if you require them to be added when the extension calls `nargo lsp`. -- **Noir: Nargo Path** - An absolute path to a Nargo binary with the `lsp` command. This may be useful if Nargo is not within the `PATH` of your editor. -- **Noir > Trace: Server** - Setting this to `"messages"` or `"verbose"` will log LSP messages between the Client and Server. Useful for debugging. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/tooling/testing.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/tooling/testing.md deleted file mode 100644 index d3e0c522473..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/tooling/testing.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -title: Testing in Noir -description: Learn how to use Nargo to test your Noir program in a quick and easy way -keywords: [Nargo, testing, Noir, compile, test] -sidebar_position: 1 ---- - -You can test your Noir programs using Noir circuits. - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. - -For example if you have a program like: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test] -fn test_add() { - assert(add(2,2) == 4); - assert(add(0,1) == 1); - assert(add(1,0) == 1); -} -``` - -Running `nargo test` will test that the `test_add` function can be executed while satisfying all -the constraints which allows you to test that add returns the expected values. Test functions can't -have any arguments currently. - -### Test fail - -You can write tests that are expected to fail by using the decorator `#[test(should_fail)]`. For example: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test(should_fail)] -fn test_add() { - assert(add(2,2) == 5); -} -``` - -You can be more specific and make it fail with a specific reason by using `should_fail_with = "`: - -```rust -fn main(african_swallow_avg_speed : Field) { - assert(african_swallow_avg_speed == 65, "What is the airspeed velocity of an unladen swallow"); -} - -#[test] -fn test_king_arthur() { - main(65); -} - -#[test(should_fail_with = "What is the airspeed velocity of an unladen swallow")] -fn test_bridgekeeper() { - main(32); -} - -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/tutorials/noirjs_app.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/tutorials/noirjs_app.md deleted file mode 100644 index 3dd9fe7d2b0..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/tutorials/noirjs_app.md +++ /dev/null @@ -1,326 +0,0 @@ ---- -title: Building a web app with NoirJS -description: Learn how to setup a new app that uses Noir to generate and verify zero-knowledge SNARK proofs in a typescript or javascript environment. -keywords: [how to, guide, javascript, typescript, noir, barretenberg, zero-knowledge, proofs, app] -sidebar_position: 0 -pagination_next: noir/concepts/data_types/index ---- - -NoirJS is a set of packages meant to work both in a browser and a server environment. In this tutorial, we will build a simple web app using them. From here, you should get an idea on how to proceed with your own Noir projects! - -You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). - -## Setup - -:::note - -Feel free to use whatever versions, just keep in mind that Nargo and the NoirJS packages are meant to be in sync. For example, Nargo 0.27.x matches `noir_js@0.27.x`, etc. - -In this guide, we will be pinned to 0.27.0. - -::: - -Before we start, we want to make sure we have Node and Nargo installed. - -We start by opening a terminal and executing `node --version`. If we don't get an output like `v20.10.0`, that means node is not installed. Let's do that by following the handy [nvm guide](https://github.com/nvm-sh/nvm?tab=readme-ov-file#install--update-script). - -As for `Nargo`, we can follow the [Nargo guide](../getting_started/installation/index.md) to install it. If you're lazy, just paste this on a terminal and run `noirup`: - -```sh -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -Easy enough. Onwards! - -## Our project - -ZK is a powerful technology. An app that doesn't reveal one of the inputs to _anyone_ is almost unbelievable, yet Noir makes it as easy as a single line of code. - -In fact, it's so simple that it comes nicely packaged in `nargo`. Let's do that! - -### Nargo - -Run: - -`nargo new circuit` - -And... That's about it. Your program is ready to be compiled and run. - -To compile, let's `cd` into the `circuit` folder to enter our project, and call: - -`nargo compile` - -This compiles our circuit into `json` format and add it to a new `target` folder. - -:::info - -At this point in the tutorial, your folder structure should look like this: - -```tree -. -└── circuit <---- our working directory - ├── Nargo.toml - ├── src - │ └── main.nr - └── target - └── circuit.json -``` - -::: - -### Node and Vite - -If you want to explore Nargo, feel free to go on a side-quest now and follow the steps in the -[getting started](../getting_started/hello_noir/index.md) guide. However, we want our app to run on the browser, so we need Vite. - -Vite is a powerful tool to generate static websites. While it provides all kinds of features, let's just go barebones with some good old vanilla JS. - -To do this this, go back to the previous folder (`cd ..`) and create a new vite project by running `npm create vite` and choosing "Vanilla" and "Javascript". - -A wild `vite-project` directory should now appear in your root folder! Let's not waste any time and dive right in: - -```bash -cd vite-project -``` - -### Setting Up Vite and Configuring the Project - -Before we proceed with any coding, let's get our environment tailored for Noir. We'll start by laying down the foundations with a `vite.config.js` file. This little piece of configuration is our secret sauce for making sure everything meshes well with the NoirJS libraries and other special setups we might need, like handling WebAssembly modules. Here’s how you get that going: - -#### Creating the vite.config.js - -In your freshly minted `vite-project` folder, create a new file named `vite.config.js` and open it in your code editor. Paste the following to set the stage: - -```javascript -import { defineConfig } from "vite"; -import copy from "rollup-plugin-copy"; - -export default defineConfig({ - esbuild: { - target: "esnext", - }, - optimizeDeps: { - esbuildOptions: { - target: "esnext", - }, - }, - plugins: [ - copy({ - targets: [ - { src: "node_modules/**/*.wasm", dest: "node_modules/.vite/dist" }, - ], - copySync: true, - hook: "buildStart", - }), - ], - server: { - port: 3000, - }, -}); -``` - -#### Install Dependencies - -Now that our stage is set, install the necessary NoirJS packages along with our other dependencies: - -```bash -npm install && npm install @noir-lang/backend_barretenberg@0.27.0 @noir-lang/noir_js@0.27.0 -npm install rollup-plugin-copy --save-dev -``` - -:::info - -At this point in the tutorial, your folder structure should look like this: - -```tree -. -└── circuit - └── ...etc... -└── vite-project <---- our working directory - └── ...etc... -``` - -::: - -#### Some cleanup - -`npx create vite` is amazing but it creates a bunch of files we don't really need for our simple example. Actually, let's just delete everything except for `vite.config.js`, `index.html`, `main.js` and `package.json`. I feel lighter already. - -![my heart is ready for you, noir.js](@site/static/img/memes/titanic.jpeg) - -## HTML - -Our app won't run like this, of course. We need some working HTML, at least. Let's open our broken-hearted `index.html` and replace everything with this code snippet: - -```html - - - - - - -

Noir app

-
- - -
-
-

Logs

-

Proof

-
- - -``` - -It _could_ be a beautiful UI... Depending on which universe you live in. - -## Some good old vanilla Javascript - -Our love for Noir needs undivided attention, so let's just open `main.js` and delete everything (this is where the romantic scenery becomes a bit creepy). - -Start by pasting in this boilerplate code: - -```js -const setup = async () => { - await Promise.all([ - import('@noir-lang/noirc_abi').then((module) => - module.default(new URL('@noir-lang/noirc_abi/web/noirc_abi_wasm_bg.wasm', import.meta.url).toString()), - ), - import('@noir-lang/acvm_js').then((module) => - module.default(new URL('@noir-lang/acvm_js/web/acvm_js_bg.wasm', import.meta.url).toString()), - ), - ]); -}; - -function display(container, msg) { - const c = document.getElementById(container); - const p = document.createElement('p'); - p.textContent = msg; - c.appendChild(p); -} - -document.getElementById('submitGuess').addEventListener('click', async () => { - try { - // here's where love happens - } catch (err) { - display('logs', 'Oh 💔 Wrong guess'); - } -}); -``` - -The display function doesn't do much. We're simply manipulating our website to see stuff happening. For example, if the proof fails, it will simply log a broken heart 😢 - -As for the `setup` function, it's just a sad reminder that dealing with `wasm` on the browser is not as easy as it should. Just copy, paste, and forget. - -:::info - -At this point in the tutorial, your folder structure should look like this: - -```tree -. -└── circuit - └── ...same as above -└── vite-project - ├── vite.config.js - ├── main.js - ├── package.json - └── index.html -``` - -You'll see other files and folders showing up (like `package-lock.json`, `node_modules`) but you shouldn't have to care about those. - -::: - -## Some NoirJS - -We're starting with the good stuff now. If you've compiled the circuit as described above, you should have a `json` file we want to import at the very top of our `main.js` file: - -```ts -import circuit from '../circuit/target/circuit.json'; -``` - -[Noir is backend-agnostic](../index.mdx#whats-new-about-noir). We write Noir, but we also need a proving backend. That's why we need to import and instantiate the two dependencies we installed above: `BarretenbergBackend` and `Noir`. Let's import them right below: - -```js -import { BarretenbergBackend, BarretenbergVerifier as Verifier } from '@noir-lang/backend_barretenberg'; -import { Noir } from '@noir-lang/noir_js'; -``` - -And instantiate them inside our try-catch block: - -```ts -// try { -const backend = new BarretenbergBackend(circuit); -const noir = new Noir(circuit, backend); -// } -``` - -:::note - -For the remainder of the tutorial, everything will be happening inside the `try` block - -::: - -## Our app - -Now for the app itself. We're capturing whatever is in the input when people press the submit button. Just add this: - -```js -const x = parseInt(document.getElementById('guessInput').value); -const input = { x, y: 2 }; -``` - -Now we're ready to prove stuff! Let's feed some inputs to our circuit and calculate the proof: - -```js -await setup(); // let's squeeze our wasm inits here - -display('logs', 'Generating proof... ⌛'); -const proof = await noir.generateProof(input); -display('logs', 'Generating proof... ✅'); -display('results', proof.proof); -``` - -You're probably eager to see stuff happening, so go and run your app now! - -From your terminal, run `npm run dev`. If it doesn't open a browser for you, just visit `localhost:5173`. You should now see the worst UI ever, with an ugly input. - -![Getting Started 0](@site/static/img/noir_getting_started_1.png) - -Now, our circuit says `fn main(x: Field, y: pub Field)`. This means only the `y` value is public, and it's hardcoded above: `input = { x, y: 2 }`. In other words, you won't need to send your secret`x` to the verifier! - -By inputting any number other than 2 in the input box and clicking "submit", you should get a valid proof. Otherwise the proof won't even generate correctly. By the way, if you're human, you shouldn't be able to understand anything on the "proof" box. That's OK. We like you, human ❤️. - -## Verifying - -Time to celebrate, yes! But we shouldn't trust machines so blindly. Let's add these lines to see our proof being verified: - -```js -display('logs', 'Verifying proof... ⌛'); -const verificationKey = await backend.getVerificationKey(); -const verifier = new Verifier(); -const isValid = await verifier.verifyProof(proof, verificationKey); -if (isValid) display('logs', 'Verifying proof... ✅'); -``` - -You have successfully generated a client-side Noir web app! - -![coded app without math knowledge](@site/static/img/memes/flextape.jpeg) - -## Further Reading - -You can see how noirjs is used in a full stack Next.js hardhat application in the [noir-starter repo here](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat). The example shows how to calculate a proof in the browser and verify it with a deployed Solidity verifier contract from noirjs. - -You should also check out the more advanced examples in the [noir-examples repo](https://github.com/noir-lang/noir-examples), where you'll find reference usage for some cool apps. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/explainers/explainer-oracle.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/explainers/explainer-oracle.md deleted file mode 100644 index b84ca5dd986..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/explainers/explainer-oracle.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: Oracles -description: This guide provides an in-depth understanding of how Oracles work in Noir programming. Learn how to use outside calculations in your programs, constrain oracles, and understand their uses and limitations. -keywords: - - Noir Programming - - Oracles - - JSON-RPC - - Foreign Call Handlers - - Constrained Functions - - Blockchain Programming -sidebar_position: 1 ---- - -If you've seen "The Matrix" you may recall "The Oracle" as Gloria Foster smoking cigarettes and baking cookies. While she appears to "know things", she is actually providing a calculation of a pre-determined future. Noir Oracles are similar, in a way. They don't calculate the future (yet), but they allow you to use outside calculations in your programs. - -![matrix oracle prediction](@site/static/img/memes/matrix_oracle.jpeg) - -A Noir program is usually self-contained. You can pass certain inputs to it, and it will generate a deterministic output for those inputs. But what if you wanted to defer some calculation to an outside process or source? - -Oracles are functions that provide this feature. - -## Use cases - -An example usage for Oracles is proving something on-chain. For example, proving that the ETH-USDC quote was below a certain target at a certain block time. Or even making more complex proofs like proving the ownership of an NFT as an anonymous login method. - -Another interesting use case is to defer expensive calculations to be made outside of the Noir program, and then constraining the result; similar to the use of [unconstrained functions](../noir/concepts//unconstrained.md). - -In short, anything that can be constrained in a Noir program but needs to be fetched from an external source is a great candidate to be used in oracles. - -## Constraining oracles - -Just like in The Matrix, Oracles are powerful. But with great power, comes great responsibility. Just because you're using them in a Noir program doesn't mean they're true. Noir has no superpowers. If you want to prove that Portugal won the Euro Cup 2016, you're still relying on potentially untrusted information. - -To give a concrete example, Alice wants to login to the [NounsDAO](https://nouns.wtf/) forum with her username "noir_nouner" by proving she owns a noun without revealing her ethereum address. Her Noir program could have a oracle call like this: - -```rust -#[oracle(getNoun)] -unconstrained fn get_noun(address: Field) -> Field -``` - -This oracle could naively resolve with the number of Nouns she possesses. However, it is useless as a trusted source, as the oracle could resolve to anything Alice wants. In order to make this oracle call actually useful, Alice would need to constrain the response from the oracle, by proving her address and the noun count belongs to the state tree of the contract. - -In short, **Oracles don't prove anything. Your Noir program does.** - -:::danger - -If you don't constrain the return of your oracle, you could be clearly opening an attack vector on your Noir program. Make double-triple sure that the return of an oracle call is constrained! - -::: - -## How to use Oracles - -On CLI, Nargo resolves oracles by making JSON RPC calls, which means it would require an RPC node to be running. - -In JavaScript, NoirJS accepts and resolves arbitrary call handlers (that is, not limited to JSON) as long as they matches the expected types the developer defines. Refer to [Foreign Call Handler](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) to learn more about NoirJS's call handling. - -If you want to build using oracles, follow through to the [oracle guide](../how_to/how-to-oracles.md) for a simple example on how to do that. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/explainers/explainer-recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/explainers/explainer-recursion.md deleted file mode 100644 index 18846176ca7..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/explainers/explainer-recursion.md +++ /dev/null @@ -1,176 +0,0 @@ ---- -title: Recursive proofs -description: Explore the concept of recursive proofs in Zero-Knowledge programming. Understand how recursion works in Noir, a language for writing smart contracts on the EVM blockchain. Learn through practical examples like Alice and Bob's guessing game, Charlie's recursive merkle tree, and Daniel's reusable components. Discover how to use recursive proofs to optimize computational resources and improve efficiency. - -keywords: - [ - "Recursive Proofs", - "Zero-Knowledge Programming", - "Noir", - "EVM Blockchain", - "Smart Contracts", - "Recursion in Noir", - "Alice and Bob Guessing Game", - "Recursive Merkle Tree", - "Reusable Components", - "Optimizing Computational Resources", - "Improving Efficiency", - "Verification Key", - "Aggregation", - "Recursive zkSNARK schemes", - "PLONK", - "Proving and Verification Keys" - ] -sidebar_position: 1 -pagination_next: how_to/how-to-recursion ---- - -In programming, we tend to think of recursion as something calling itself. A classic example would be the calculation of the factorial of a number: - -```js -function factorial(n) { - if (n === 0 || n === 1) { - return 1; - } else { - return n * factorial(n - 1); - } -} -``` - -In this case, while `n` is not `1`, this function will keep calling itself until it hits the base case, bubbling up the result on the call stack: - -```md - Is `n` 1? <--------- - /\ / - / \ n = n -1 - / \ / - Yes No -------- -``` - -In Zero-Knowledge, recursion has some similarities. - -It is not a Noir function calling itself, but a proof being used as an input to another circuit. In short, you verify one proof *inside* another proof, returning the proof that both proofs are valid. - -This means that, given enough computational resources, you can prove the correctness of any arbitrary number of proofs in a single proof. This could be useful to design state channels (for which a common example would be [Bitcoin's Lightning Network](https://en.wikipedia.org/wiki/Lightning_Network)), to save on gas costs by settling one proof on-chain, or simply to make business logic less dependent on a consensus mechanism. - -## Examples - -Let us look at some of these examples - -### Alice and Bob - Guessing game - -Alice and Bob are friends, and they like guessing games. They want to play a guessing game online, but for that, they need a trusted third-party that knows both of their secrets and finishes the game once someone wins. - -So, they use zero-knowledge proofs. Alice tries to guess Bob's number, and Bob will generate a ZK proof stating whether she succeeded or failed. - -This ZK proof can go on a smart contract, revealing the winner and even giving prizes. However, this means every turn needs to be verified on-chain. This incurs some cost and waiting time that may simply make the game too expensive or time-consuming to be worth it. - -As a solution, Alice proposes the following: "what if Bob generates his proof, and instead of sending it on-chain, I verify it *within* my own proof before playing my own turn?". - -She can then generate a proof that she verified his proof, and so on. - -```md - Did you fail? <-------------------------- - / \ / - / \ n = n -1 - / \ / - Yes No / - | | / - | | / - | You win / - | / - | / -Generate proof of that / - + / - my own guess ---------------- -``` - -### Charlie - Recursive merkle tree - -Charlie is a concerned citizen, and wants to be sure his vote in an election is accounted for. He votes with a ZK proof, but he has no way of knowing that his ZK proof was included in the total vote count! - -If the vote collector puts all of the votes into a [Merkle tree](https://en.wikipedia.org/wiki/Merkle_tree), everyone can prove the verification of two proofs within one proof, as such: - -```md - abcd - __________|______________ - | | - ab cd - _____|_____ ______|______ - | | | | - alice bob charlie daniel -``` - -Doing this recursively allows us to arrive on a final proof `abcd` which if true, verifies the correctness of all the votes. - -### Daniel - Reusable components - -Daniel has a big circuit and a big headache. A part of his circuit is a setup phase that finishes with some assertions that need to be made. But that section alone takes most of the proving time, and is largely independent of the rest of the circuit. - -He might find it more efficient to generate a proof for that setup phase separately, and verify that proof recursively in the actual business logic section of his circuit. This will allow for parallelization of both proofs, which results in a considerable speedup. - -## What params do I need - -As you can see in the [recursion reference](noir/standard_library/recursion.md), a simple recursive proof requires: - -- The proof to verify -- The Verification Key of the circuit that generated the proof -- A hash of this verification key, as it's needed for some backends -- The public inputs for the proof - -:::info - -Recursive zkSNARK schemes do not necessarily "verify a proof" in the sense that you expect a true or false to be spit out by the verifier. Rather an aggregation object is built over the public inputs. - -So, taking the example of Alice and Bob and their guessing game: - -- Alice makes her guess. Her proof is *not* recursive: it doesn't verify any proof within it! It's just a standard `assert(x != y)` circuit -- Bob verifies Alice's proof and makes his own guess. In this circuit, he doesn't exactly *prove* the verification of Alice's proof. Instead, he *aggregates* his proof to Alice's proof. The actual verification is done when the full proof is verified, for example when using `nargo verify` or through the verifier smart contract. - -We can imagine recursive proofs a [relay race](https://en.wikipedia.org/wiki/Relay_race). The first runner doesn't have to receive the baton from anyone else, as he/she already starts with it. But when his/her turn is over, the next runner needs to receive it, run a bit more, and pass it along. Even though every runner could theoretically verify the baton mid-run (why not? 🏃🔍), only at the end of the race does the referee verify that the whole race is valid. - -::: - -## Some architecture - -As with everything in computer science, there's no one-size-fits all. But there are some patterns that could help understanding and implementing them. To give three examples: - -### Adding some logic to a proof verification - -This would be an approach for something like our guessing game, where proofs are sent back and forth and are verified by each opponent. This circuit would be divided in two sections: - -- A `recursive verification` section, which would be just the call to `std::verify_proof`, and that would be skipped on the first move (since there's no proof to verify) -- A `guessing` section, which is basically the logic part where the actual guessing happens - -In such a situation, and assuming Alice is first, she would skip the first part and try to guess Bob's number. Bob would then verify her proof on the first section of his run, and try to guess Alice's number on the second part, and so on. - -### Aggregating proofs - -In some one-way interaction situations, recursion would allow for aggregation of simple proofs that don't need to be immediately verified on-chain or elsewhere. - -To give a practical example, a barman wouldn't need to verify a "proof-of-age" on-chain every time he serves alcohol to a customer. Instead, the architecture would comprise two circuits: - -- A `main`, non-recursive circuit with some logic -- A `recursive` circuit meant to verify two proofs in one proof - -The customer's proofs would be intermediate, and made on their phones, and the barman could just verify them locally. He would then aggregate them into a final proof sent on-chain (or elsewhere) at the end of the day. - -### Recursively verifying different circuits - -Nothing prevents you from verifying different circuits in a recursive proof, for example: - -- A `circuit1` circuit -- A `circuit2` circuit -- A `recursive` circuit - -In this example, a regulator could verify that taxes were paid for a specific purchase by aggregating both a `payer` circuit (proving that a purchase was made and taxes were paid), and a `receipt` circuit (proving that the payment was received) - -## How fast is it - -At the time of writing, verifying recursive proofs is surprisingly fast. This is because most of the time is spent on generating the verification key that will be used to generate the next proof. So you are able to cache the verification key and reuse it later. - -Currently, Noir JS packages don't expose the functionality of loading proving and verification keys, but that feature exists in the underlying `bb.js` package. - -## How can I try it - -Learn more about using recursion in Nargo and NoirJS in the [how-to guide](../how_to/how-to-recursion.md) and see a full example in [noir-examples](https://github.com/noir-lang/noir-examples). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/getting_started/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/getting_started/_category_.json deleted file mode 100644 index 5d694210bbf..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/getting_started/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 0, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/getting_started/hello_noir/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/getting_started/hello_noir/_category_.json deleted file mode 100644 index 23b560f610b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/getting_started/hello_noir/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 1, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/getting_started/hello_noir/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/getting_started/hello_noir/index.md deleted file mode 100644 index 743c4d8d634..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/getting_started/hello_noir/index.md +++ /dev/null @@ -1,142 +0,0 @@ ---- -title: Creating a Project -description: - Learn how to create and verify your first Noir program using Nargo, a programming language for - zero-knowledge proofs. -keywords: - [ - Nargo, - Noir, - zero-knowledge proofs, - programming language, - create Noir program, - verify Noir program, - step-by-step guide, - ] -sidebar_position: 1 - ---- - -Now that we have installed Nargo, it is time to make our first hello world program! - -## Create a Project Directory - -Noir code can live anywhere on your computer. Let us create a _projects_ folder in the home -directory to house our Noir programs. - -For Linux, macOS, and Windows PowerShell, create the directory and change directory into it by -running: - -```sh -mkdir ~/projects -cd ~/projects -``` - -## Create Our First Nargo Project - -Now that we are in the projects directory, create a new Nargo project by running: - -```sh -nargo new hello_world -``` - -> **Note:** `hello_world` can be any arbitrary project name, we are simply using `hello_world` for -> demonstration. -> -> In production, the common practice is to name the project folder as `circuits` for better -> identifiability when sitting alongside other folders in the codebase (e.g. `contracts`, `scripts`, -> `test`). - -A `hello_world` folder would be created. Similar to Rust, the folder houses _src/main.nr_ and -_Nargo.toml_ which contain the source code and environmental options of your Noir program -respectively. - -### Intro to Noir Syntax - -Let us take a closer look at _main.nr_. The default _main.nr_ generated should look like this: - -```rust -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` - -The first line of the program specifies the program's inputs: - -```rust -x : Field, y : pub Field -``` - -Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the -keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](../../noir/concepts/data_types/index.md) section. - -The next line of the program specifies its body: - -```rust -assert(x != y); -``` - -The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. - -For more Noir syntax, check the [Language Concepts](../../noir/concepts/comments.md) chapter. - -## Build In/Output Files - -Change directory into _hello_world_ and build in/output files for your Noir program by running: - -```sh -cd hello_world -nargo check -``` - -Two additional files would be generated in your project directory: - -_Prover.toml_ houses input values, and _Verifier.toml_ houses public values. - -## Prove Our Noir Program - -Now that the project is set up, we can create a proof of correct execution of our Noir program. - -Fill in input values for execution in the _Prover.toml_ file. For example: - -```toml -x = "1" -y = "2" -``` - -Prove the valid execution of your Noir program: - -```sh -nargo prove -``` - -A new folder _proofs_ would then be generated in your project directory, containing the proof file -`.proof`, where the project name is defined in Nargo.toml. - -The _Verifier.toml_ file would also be updated with the public values computed from program -execution (in this case the value of `y`): - -```toml -y = "0x0000000000000000000000000000000000000000000000000000000000000002" -``` - -> **Note:** Values in _Verifier.toml_ are computed as 32-byte hex values. - -## Verify Our Noir Program - -Once a proof is generated, we can verify correct execution of our Noir program by verifying the -proof file. - -Verify your proof by running: - -```sh -nargo verify -``` - -The verification will complete in silence if it is successful. If it fails, it will log the -corresponding error instead. - -Congratulations, you have now created and verified a proof for your very first Noir program! - -In the [next section](./project_breakdown.md), we will go into more detail on each step performed. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/getting_started/hello_noir/project_breakdown.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/getting_started/hello_noir/project_breakdown.md deleted file mode 100644 index 6160a102c6c..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/getting_started/hello_noir/project_breakdown.md +++ /dev/null @@ -1,199 +0,0 @@ ---- -title: Project Breakdown -description: - Learn about the anatomy of a Nargo project, including the purpose of the Prover and Verifier TOML - files, and how to prove and verify your program. -keywords: - [Nargo, Nargo project, Prover.toml, Verifier.toml, proof verification, private asset transfer] -sidebar_position: 2 ---- - -This section breaks down our hello world program from the previous section. We elaborate on the project -structure and what the `prove` and `verify` commands did. - -## Anatomy of a Nargo Project - -Upon creating a new project with `nargo new` and building the in/output files with `nargo check` -commands, you would get a minimal Nargo project of the following structure: - - - src - - Prover.toml - - Verifier.toml - - Nargo.toml - -The source directory _src_ holds the source code for your Noir program. By default only a _main.nr_ -file will be generated within it. - -### Prover.toml - -_Prover.toml_ is used for specifying the input values for executing and proving the program. You can specify `toml` files with different names by using the `--prover-name` or `-p` flags, see the [Prover](#provertoml) section below. Optionally you may specify expected output values for prove-time checking as well. - -### Verifier.toml - -_Verifier.toml_ contains public in/output values computed when executing the Noir program. - -### Nargo.toml - -_Nargo.toml_ contains the environmental options of your project. It contains a "package" section and a "dependencies" section. - -Example Nargo.toml: - -```toml -[package] -name = "noir_starter" -type = "bin" -authors = ["Alice"] -compiler_version = "0.9.0" -description = "Getting started with Noir" -entry = "circuit/main.nr" -license = "MIT" - -[dependencies] -ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} -``` - -Nargo.toml for a [workspace](../../noir/modules_packages_crates/workspaces.md) will look a bit different. For example: - -```toml -[workspace] -members = ["crates/a", "crates/b"] -default-member = "crates/a" -``` - -#### Package section - -The package section defines a number of fields including: - -- `name` (**required**) - the name of the package -- `type` (**required**) - can be "bin", "lib", or "contract" to specify whether its a binary, library or Aztec contract -- `authors` (optional) - authors of the project -- `compiler_version` - specifies the version of the compiler to use. This is enforced by the compiler and follow's [Rust's versioning](https://doc.rust-lang.org/cargo/reference/manifest.html#the-version-field), so a `compiler_version = 0.18.0` will enforce Nargo version 0.18.0, `compiler_version = ^0.18.0` will enforce anything above 0.18.0 but below 0.19.0, etc. For more information, see how [Rust handles these operators](https://docs.rs/semver/latest/semver/enum.Op.html) -- `description` (optional) -- `entry` (optional) - a relative filepath to use as the entry point into your package (overrides the default of `src/lib.nr` or `src/main.nr`) -- `backend` (optional) -- `license` (optional) - -#### Dependencies section - -This is where you will specify any dependencies for your project. See the [Dependencies page](../../noir/modules_packages_crates/dependencies.md) for more info. - -`./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or -verifier contract respectively. - -### main.nr - -The _main.nr_ file contains a `main` method, this method is the entry point into your Noir program. - -In our sample program, _main.nr_ looks like this: - -```rust -fn main(x : Field, y : Field) { - assert(x != y); -} -``` - -The parameters `x` and `y` can be seen as the API for the program and must be supplied by the -prover. Since neither `x` nor `y` is marked as public, the verifier does not supply any inputs, when -verifying the proof. - -The prover supplies the values for `x` and `y` in the _Prover.toml_ file. - -As for the program body, `assert` ensures that the condition to be satisfied (e.g. `x != y`) is -constrained by the proof of the execution of said program (i.e. if the condition was not met, the -verifier would reject the proof as an invalid proof). - -### Prover.toml - -The _Prover.toml_ file is a file which the prover uses to supply his witness values(both private and -public). - -In our hello world program the _Prover.toml_ file looks like this: - -```toml -x = "1" -y = "2" -``` - -When the command `nargo prove` is executed, two processes happen: - -1. Noir creates a proof that `x`, which holds the value of `1`, and `y`, which holds the value of `2`, - is not equal. This inequality constraint is due to the line `assert(x != y)`. - -2. Noir creates and stores the proof of this statement in the _proofs_ directory in a file called your-project.proof. So if your project is named "private_voting" (defined in the project Nargo.toml), the proof will be saved at `./proofs/private_voting.proof`. Opening this file will display the proof in hex format. - -#### Arrays of Structs - -The following code shows how to pass an array of structs to a Noir program to generate a proof. - -```rust -// main.nr -struct Foo { - bar: Field, - baz: Field, -} - -fn main(foos: [Foo; 3]) -> pub Field { - foos[2].bar + foos[2].baz -} -``` - -Prover.toml: - -```toml -[[foos]] # foos[0] -bar = 0 -baz = 0 - -[[foos]] # foos[1] -bar = 0 -baz = 0 - -[[foos]] # foos[2] -bar = 1 -baz = 2 -``` - -#### Custom toml files - -You can specify a `toml` file with a different name to use for proving by using the `--prover-name` or `-p` flags. - -This command looks for proof inputs in the default **Prover.toml** and generates the proof and saves it at `./proofs/.proof`: - -```bash -nargo prove -``` - -This command looks for proof inputs in the custom **OtherProver.toml** and generates proof and saves it at `./proofs/.proof`: - -```bash -nargo prove -p OtherProver -``` - -## Verifying a Proof - -When the command `nargo verify` is executed, two processes happen: - -1. Noir checks in the _proofs_ directory for a proof file with the project name (eg. test_project.proof) - -2. If that file is found, the proof's validity is checked - -> **Note:** The validity of the proof is linked to the current Noir program; if the program is -> changed and the verifier verifies the proof, it will fail because the proof is not valid for the -> _modified_ Noir program. - -In production, the prover and the verifier are usually two separate entities. A prover would -retrieve the necessary inputs, execute the Noir program, generate a proof and pass it to the -verifier. The verifier would then retrieve the public inputs, usually from external sources, and -verify the validity of the proof against it. - -Take a private asset transfer as an example: - -A person using a browser as the prover would retrieve private inputs locally (e.g. the user's private key) and -public inputs (e.g. the user's encrypted balance on-chain), compute the transfer, generate a proof -and submit it to the verifier smart contract. - -The verifier contract would then draw the user's encrypted balance directly from the blockchain and -verify the proof submitted against it. If the verification passes, additional functions in the -verifier contract could trigger (e.g. approve the asset transfer). - -Now that you understand the concepts, you'll probably want some editor feedback while you are writing more complex code. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/getting_started/installation/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/getting_started/installation/_category_.json deleted file mode 100644 index 0c02fb5d4d7..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/getting_started/installation/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "position": 0, - "label": "Install Nargo", - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/getting_started/installation/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/getting_started/installation/index.md deleted file mode 100644 index 4ef86aa5914..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/getting_started/installation/index.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Nargo Installation -description: - nargo is a command line tool for interacting with Noir programs. This page is a quick guide on how to install Nargo through the most common and easy method, noirup -keywords: [ - Nargo - Noir - Rust - Cargo - Noirup - Installation - Terminal Commands - Version Check - Nightlies - Specific Versions - Branches - Noirup Repository -] -pagination_next: getting_started/hello_noir/index ---- - -`nargo` is the one-stop-shop for almost everything related with Noir. The name comes from our love for Rust and its package manager `cargo`. - -With `nargo`, you can start new projects, compile, execute, prove, verify, test, generate solidity contracts, and do pretty much all that is available in Noir. - -Similarly to `rustup`, we also maintain an easy installation method that covers most machines: `noirup`. - -## Installing Noirup - -Open a terminal on your machine, and write: - -```bash -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -Close the terminal, open another one, and run - -```bash -noirup -``` - -Done. That's it. You should have the latest version working. You can check with `nargo --version`. - -You can also install nightlies, specific versions -or branches. Check out the [noirup repository](https://github.com/noir-lang/noirup) for more -information. - -Now we're ready to start working on [our first Noir program!](../hello_noir/index.md) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/getting_started/installation/other_install_methods.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/getting_started/installation/other_install_methods.md deleted file mode 100644 index 3634723562b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/getting_started/installation/other_install_methods.md +++ /dev/null @@ -1,102 +0,0 @@ ---- -title: Alternative Installations -description: There are different ways to install Nargo, the one-stop shop and command-line tool for developing Noir programs. This guide explains how to specify which version to install when using noirup, and using WSL for windows. -keywords: [ - Installation - Nargo - Noirup - Binaries - Compiling from Source - WSL for Windows - macOS - Linux - Nix - Direnv - Uninstalling Nargo - ] -sidebar_position: 1 ---- - -## Encouraged Installation Method: Noirup - -Noirup is the endorsed method for installing Nargo, streamlining the process of fetching binaries or compiling from source. It supports a range of options to cater to your specific needs, from nightly builds and specific versions to compiling from various sources. - -### Installing Noirup - -First, ensure you have `noirup` installed: - -```sh -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -### Fetching Binaries - -With `noirup`, you can easily switch between different Nargo versions, including nightly builds: - -- **Nightly Version**: Install the latest nightly build. - - ```sh - noirup --version nightly - ``` - -- **Specific Version**: Install a specific version of Nargo. - ```sh - noirup --version - ``` - -### Compiling from Source - -`noirup` also enables compiling Nargo from various sources: - -- **From a Specific Branch**: Install from the latest commit on a branch. - - ```sh - noirup --branch - ``` - -- **From a Fork**: Install from the main branch of a fork. - - ```sh - noirup --repo - ``` - -- **From a Specific Branch in a Fork**: Install from a specific branch in a fork. - - ```sh - noirup --repo --branch - ``` - -- **From a Specific Pull Request**: Install from a specific PR. - - ```sh - noirup --pr - ``` - -- **From a Specific Commit**: Install from a specific commit. - - ```sh - noirup -C - ``` - -- **From Local Source**: Compile and install from a local directory. - ```sh - noirup --path ./path/to/local/source - ``` - -## Installation on Windows - -The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed natively. However, it is available by using Windows Subsystem for Linux (WSL). - -Step 1: Follow the instructions [here](https://learn.microsoft.com/en-us/windows/wsl/install) to install and run WSL. - -step 2: Follow the [Noirup instructions](#encouraged-installation-method-noirup). - -## Uninstalling Nargo - -If you installed Nargo with `noirup`, you can uninstall Nargo by removing the files in `~/.nargo`, `~/nargo`, and `~/noir_cache`. This ensures that all installed binaries, configurations, and cache related to Nargo are fully removed from your system. - -```bash -rm -r ~/.nargo -rm -r ~/nargo -rm -r ~/noir_cache -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/getting_started/tooling/noir_codegen.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/getting_started/tooling/noir_codegen.md deleted file mode 100644 index d65151da0ab..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/getting_started/tooling/noir_codegen.md +++ /dev/null @@ -1,113 +0,0 @@ ---- -title: Noir Codegen for TypeScript -description: Learn how to use Noir codegen to generate TypeScript bindings -keywords: [Nargo, Noir, compile, TypeScript] -sidebar_position: 2 ---- - -When using TypeScript, it is extra work to interpret Noir program outputs in a type-safe way. Third party libraries may exist for popular Noir programs, but they are either hard to find or unmaintained. - -Now you can generate TypeScript bindings for your Noir programs in two steps: -1. Exporting Noir functions using `nargo export` -2. Using the TypeScript module `noir_codegen` to generate TypeScript binding - -**Note:** you can only export functions from a Noir *library* (not binary or contract program types). - -## Installation - -### Your TypeScript project - -If you don't already have a TypeScript project you can add the module with `yarn` (or `npm`), then initialize it: - -```bash -yarn add typescript -D -npx tsc --init -``` - -### Add TypeScript module - `noir_codegen` - -The following command will add the module to your project's devDependencies: - -```bash -yarn add @noir-lang/noir_codegen -D -``` - -### Nargo library -Make sure you have Nargo, v0.25.0 or greater, installed. If you don't, follow the [installation guide](../installation/index.md). - -If you're in a new project, make a `circuits` folder and create a new Noir library: - -```bash -mkdir circuits && cd circuits -nargo new --lib myNoirLib -``` - -## Usage - -### Export ABI of specified functions - -First go to the `.nr` files in your Noir library, and add the `#[export]` macro to each function that you want to use in TypeScript. - -```rust -#[export] -fn your_function(... -``` - -From your Noir library (where `Nargo.toml` is), run the following command: - -```bash -nargo export -``` - -You will now have an `export` directory with a .json file per exported function. - -You can also specify the directory of Noir programs using `--program-dir`, for example: - -```bash -nargo export --program-dir=./circuits/myNoirLib -``` - -### Generate TypeScript bindings from exported functions - -To use the `noir-codegen` package we added to the TypeScript project: - -```bash -yarn noir-codegen ./export/your_function.json -``` - -This creates an `exports` directory with an `index.ts` file containing all exported functions. - -**Note:** adding `--out-dir` allows you to specify an output dir for your TypeScript bindings to go. Eg: - -```bash -yarn noir-codegen ./export/*.json --out-dir ./path/to/output/dir -``` - -## Example .nr function to .ts output - -Consider a Noir library with this function: - -```rust -#[export] -fn not_equal(x: Field, y: Field) -> bool { - x != y -} -``` - -After the export and codegen steps, you should have an `index.ts` like: - -```typescript -export type Field = string; - - -export const is_equal_circuit: CompiledCircuit = {"abi":{"parameters":[{"name":"x","type":{"kind":"field"},"visibility":"private"},{"name":"y","type":{"kind":"field"},"visibility":"private"}],"param_witnesses":{"x":[{"start":0,"end":1}],"y":[{"start":1,"end":2}]},"return_type":{"abi_type":{"kind":"boolean"},"visibility":"private"},"return_witnesses":[4]},"bytecode":"H4sIAAAAAAAA/7WUMQ7DIAxFQ0Krrr2JjSGYLVcpKrn/CaqqDQN12WK+hPBgmWd/wEyHbF1SS923uhOs3pfoChI+wKXMAXzIKyNj4PB0TFTYc0w5RUjoqeAeEu1wqK0F54RGkWvW44LPzExnlkbMEs4JNZmN8PxS42uHv82T8a3Jeyn2Ks+VLPcO558HmyLMCDOXAXXtpPt4R/Rt9T36ss6dS9HGPx/eG17nGegKBQAA"}; - -export async function is_equal(x: Field, y: Field, foreignCallHandler?: ForeignCallHandler): Promise { - const program = new Noir(is_equal_circuit); - const args: InputMap = { x, y }; - const { returnValue } = await program.execute(args, foreignCallHandler); - return returnValue as boolean; -} -``` - -Now the `is_equal()` function and relevant types are readily available for use in TypeScript. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/how_to/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/how_to/_category_.json deleted file mode 100644 index 23b560f610b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/how_to/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 1, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/how_to/debugger/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/how_to/debugger/_category_.json deleted file mode 100644 index cc2cbb1c253..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/how_to/debugger/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Debugging", - "position": 5, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/how_to/debugger/debugging_with_the_repl.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/how_to/debugger/debugging_with_the_repl.md deleted file mode 100644 index 09e5bae68ad..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/how_to/debugger/debugging_with_the_repl.md +++ /dev/null @@ -1,164 +0,0 @@ ---- -title: Using the REPL Debugger -description: - Step by step guide on how to debug your Noir circuits with the REPL Debugger. -keywords: - [ - Nargo, - Noir CLI, - Noir Debugger, - REPL, - ] -sidebar_position: 1 ---- - -#### Pre-requisites - -In order to use the REPL debugger, first you need to install recent enough versions of Nargo and vscode-noir. - -## Debugging a simple circuit - -Let's debug a simple circuit: - -```rust -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` - -To start the REPL debugger, using a terminal, go to a Noir circuit's home directory. Then: - -`$ nargo debug` - -You should be seeing this in your terminal: - -``` -[main] Starting debugger -At ~/noir-examples/recursion/circuits/main/src/main.nr:1:9 - 1 -> fn main(x : Field, y : pub Field) { - 2 assert(x != y); - 3 } -> -``` - -The debugger displays the current Noir code location, and it is now waiting for us to drive it. - -Let's first take a look at the available commands. For that we'll use the `help` command. - -``` -> help -Available commands: - - opcodes display ACIR opcodes - into step into to the next opcode - next step until a new source location is reached - out step until a new source location is reached - and the current stack frame is finished - break LOCATION:OpcodeLocation add a breakpoint at an opcode location - over step until a new source location is reached - without diving into function calls - restart restart the debugging session - delete LOCATION:OpcodeLocation delete breakpoint at an opcode location - witness show witness map - witness index:u32 display a single witness from the witness map - witness index:u32 value:String update a witness with the given value - memset index:usize value:String update a memory cell with the given - value - continue continue execution until the end of the - program - vars show variable values available at this point - in execution - stacktrace display the current stack trace - memory show memory (valid when executing unconstrained code) - step step to the next ACIR opcode - -Other commands: - - help Show this help message - quit Quit repl - -``` - -Some commands operate only for unconstrained functions, such as `memory` and `memset`. If you try to use them while execution is paused at an ACIR opcode, the debugger will simply inform you that you are not executing unconstrained code: - -``` -> memory -Unconstrained VM memory not available -> -``` - -Before continuing, we can take a look at the initial witness map: - -``` -> witness -_0 = 1 -_1 = 2 -> -``` - -Cool, since `x==1`, `y==2`, and we want to check that `x != y`, our circuit should succeed. At this point we could intervene and use the witness setter command to change one of the witnesses. Let's set `y=3`, then back to 2, so we don't affect the expected result: - -``` -> witness -_0 = 1 -_1 = 2 -> witness 1 3 -_1 = 3 -> witness -_0 = 1 -_1 = 3 -> witness 1 2 -_1 = 2 -> witness -_0 = 1 -_1 = 2 -> -``` - -Now we can inspect the current state of local variables. For that we use the `vars` command. - -``` -> vars -> -``` - -We currently have no vars in context, since we are at the entry point of the program. Let's use `next` to execute until the next point in the program. - -``` -> vars -> next -At ~/noir-examples/recursion/circuits/main/src/main.nr:1:20 - 1 -> fn main(x : Field, y : pub Field) { - 2 assert(x != y); - 3 } -> vars -x:Field = 0x01 -``` - -As a result of stepping, the variable `x`, whose initial value comes from the witness map, is now in context and returned by `vars`. - -``` -> next - 1 fn main(x : Field, y : pub Field) { - 2 -> assert(x != y); - 3 } -> vars -y:Field = 0x02 -x:Field = 0x01 -``` - -Stepping again we can finally see both variables and their values. And now we can see that the next assertion should succeed. - -Let's continue to the end: - -``` -> continue -(Continuing execution...) -Finished execution -> q -[main] Circuit witness successfully solved -``` - -Upon quitting the debugger after a solved circuit, the resulting circuit witness gets saved, equivalent to what would happen if we had run the same circuit with `nargo execute`. - -We just went through the basics of debugging using Noir REPL debugger. For a comprehensive reference, check out [the reference page](../../reference/debugger/debugger_repl.md). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/how_to/debugger/debugging_with_vs_code.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/how_to/debugger/debugging_with_vs_code.md deleted file mode 100644 index a5858c1a5eb..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/how_to/debugger/debugging_with_vs_code.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -title: Using the VS Code Debugger -description: - Step by step guide on how to debug your Noir circuits with the VS Code Debugger configuration and features. -keywords: - [ - Nargo, - Noir CLI, - Noir Debugger, - VS Code, - IDE, - ] -sidebar_position: 0 ---- - -This guide will show you how to use VS Code with the vscode-noir extension to debug a Noir project. - -#### Pre-requisites - -- Nargo -- vscode-noir -- A Noir project with a `Nargo.toml`, `Prover.toml` and at least one Noir (`.nr`) containing an entry point function (typically `main`). - -## Running the debugger - -The easiest way to start debugging is to open the file you want to debug, and press `F5`. This will cause the debugger to launch, using your `Prover.toml` file as input. - -You should see something like this: - -![Debugger launched](@site/static/img/debugger/1-started.png) - -Let's inspect the state of the program. For that, we open VS Code's _Debug pane_. Look for this icon: - -![Debug pane icon](@site/static/img/debugger/2-icon.png) - -You will now see two categories of variables: Locals and Witness Map. - -![Debug pane expanded](@site/static/img/debugger/3-debug-pane.png) - -1. **Locals**: variables of your program. At this point in execution this section is empty, but as we step through the code it will get populated by `x`, `result`, `digest`, etc. - -2. **Witness map**: these are initially populated from your project's `Prover.toml` file. In this example, they will be used to populate `x` and `result` at the beginning of the `main` function. - -Most of the time you will probably be focusing mostly on locals, as they represent the high level state of your program. - -You might be interested in inspecting the witness map in case you are trying to solve a really low level issue in the compiler or runtime itself, so this concerns mostly advanced or niche users. - -Let's step through the program, by using the debugger buttons or their corresponding keyboard shortcuts. - -![Debugger buttons](@site/static/img/debugger/4-debugger-buttons.png) - -Now we can see in the variables pane that there's values for `digest`, `result` and `x`. - -![Inspecting locals](@site/static/img/debugger/5-assert.png) - -We can also inspect the values of variables by directly hovering on them on the code. - -![Hover locals](@site/static/img/debugger/6-hover.png) - -Let's set a break point at the `keccak256` function, so we can continue execution up to the point when it's first invoked without having to go one step at a time. - -We just need to click the to the right of the line number 18. Once the breakpoint appears, we can click the `continue` button or use its corresponding keyboard shortcut (`F5` by default). - -![Breakpoint](@site/static/img/debugger/7-break.png) - -Now we are debugging the `keccak256` function, notice the _Call Stack pane_ at the lower right. This lets us inspect the current call stack of our process. - -That covers most of the current debugger functionalities. Check out [the reference](../../reference/debugger/debugger_vscode.md) for more details on how to configure the debugger. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/how_to/how-to-oracles.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/how_to/how-to-oracles.md deleted file mode 100644 index 8cf8035a5c4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/how_to/how-to-oracles.md +++ /dev/null @@ -1,276 +0,0 @@ ---- -title: How to use Oracles -description: Learn how to use oracles in your Noir program with examples in both Nargo and NoirJS. This guide also covers writing a JSON RPC server and providing custom foreign call handlers for NoirJS. -keywords: - - Noir Programming - - Oracles - - Nargo - - NoirJS - - JSON RPC Server - - Foreign Call Handlers -sidebar_position: 1 ---- - -This guide shows you how to use oracles in your Noir program. For the sake of clarity, it assumes that: - -- You have read the [explainer on Oracles](../explainers/explainer-oracle.md) and are comfortable with the concept. -- You have a Noir program to add oracles to. You can create one using the [vite-hardhat starter](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat) as a boilerplate. -- You understand the concept of a JSON-RPC server. Visit the [JSON-RPC website](https://www.jsonrpc.org/) if you need a refresher. -- You are comfortable with server-side JavaScript (e.g. Node.js, managing packages, etc.). - -For reference, you can find the snippets used in this tutorial on the [Aztec DevRel Repository](https://github.com/AztecProtocol/dev-rel/tree/main/code-snippets/how-to-oracles). - -## Rundown - -This guide has 3 major steps: - -1. How to modify our Noir program to make use of oracle calls as unconstrained functions -2. How to write a JSON RPC Server to resolve these oracle calls with Nargo -3. How to use them in Nargo and how to provide a custom resolver in NoirJS - -## Step 1 - Modify your Noir program - -An oracle is defined in a Noir program by defining two methods: - -- An unconstrained method - This tells the compiler that it is executing an [unconstrained functions](../noir/concepts//unconstrained.md). -- A decorated oracle method - This tells the compiler that this method is an RPC call. - -An example of an oracle that returns a `Field` would be: - -```rust -#[oracle(getSqrt)] -unconstrained fn sqrt(number: Field) -> Field { } - -unconstrained fn get_sqrt(number: Field) -> Field { - sqrt(number) -} -``` - -In this example, we're wrapping our oracle function in a unconstrained method, and decorating it with `oracle(getSqrt)`. We can then call the unconstrained function as we would call any other function: - -```rust -fn main(input: Field) { - let sqrt = get_sqrt(input); -} -``` - -In the next section, we will make this `getSqrt` (defined on the `sqrt` decorator) be a method of the RPC server Noir will use. - -:::danger - -As explained in the [Oracle Explainer](../explainers/explainer-oracle.md), this `main` function is unsafe unless you constrain its return value. For example: - -```rust -fn main(input: Field) { - let sqrt = get_sqrt(input); - assert(sqrt.pow_32(2) as u64 == input as u64); // <---- constrain the return of an oracle! -} -``` - -::: - -:::info - -Currently, oracles only work with single params or array params. For example: - -```rust -#[oracle(getSqrt)] -unconstrained fn sqrt([Field; 2]) -> [Field; 2] { } -``` - -::: - -## Step 2 - Write an RPC server - -Brillig will call *one* RPC server. Most likely you will have to write your own, and you can do it in whatever language you prefer. In this guide, we will do it in Javascript. - -Let's use the above example of an oracle that consumes an array with two `Field` and returns their square roots: - -```rust -#[oracle(getSqrt)] -unconstrained fn sqrt(input: [Field; 2]) -> [Field; 2] { } - -unconstrained fn get_sqrt(input: [Field; 2]) -> [Field; 2] { - sqrt(input) -} - -fn main(input: [Field; 2]) { - let sqrt = get_sqrt(input); - assert(sqrt[0].pow_32(2) as u64 == input[0] as u64); - assert(sqrt[1].pow_32(2) as u64 == input[1] as u64); -} -``` - -:::info - -Why square root? - -In general, computing square roots is computationally more expensive than multiplications, which takes a toll when speaking about ZK applications. In this case, instead of calculating the square root in Noir, we are using our oracle to offload that computation to be made in plain. In our circuit we can simply multiply the two values. - -::: - -Now, we should write the correspondent RPC server, starting with the [default JSON-RPC 2.0 boilerplate](https://www.npmjs.com/package/json-rpc-2.0#example): - -```js -import { JSONRPCServer } from "json-rpc-2.0"; -import express from "express"; -import bodyParser from "body-parser"; - -const app = express(); -app.use(bodyParser.json()); - -const server = new JSONRPCServer(); -app.post("/", (req, res) => { - const jsonRPCRequest = req.body; - server.receive(jsonRPCRequest).then((jsonRPCResponse) => { - if (jsonRPCResponse) { - res.json(jsonRPCResponse); - } else { - res.sendStatus(204); - } - }); -}); - -app.listen(5555); -``` - -Now, we will add our `getSqrt` method, as expected by the `#[oracle(getSqrt)]` decorator in our Noir code. It maps through the params array and returns their square roots: - -```js -server.addMethod("getSqrt", async (params) => { - const values = params[0].Array.map((field) => { - return `${Math.sqrt(parseInt(field, 16))}`; - }); - return { values: [{ Array: values }] }; -}); -``` - -:::tip - -Brillig expects an object with an array of values. Each value is an object declaring to be `Single` or `Array` and returning a field element *as a string*. For example: - -```json -{ "values": [{ "Array": ["1", "2"] }]} -{ "values": [{ "Single": "1" }]} -{ "values": [{ "Single": "1" }, { "Array": ["1", "2"] }]} -``` - -If you're using Typescript, the following types may be helpful in understanding the expected return value and making sure they're easy to follow: - -```js -interface SingleForeignCallParam { - Single: string, -} - -interface ArrayForeignCallParam { - Array: string[], -} - -type ForeignCallParam = SingleForeignCallParam | ArrayForeignCallParam; - -interface ForeignCallResult { - values: ForeignCallParam[], -} -``` - -::: - -## Step 3 - Usage with Nargo - -Using the [`nargo` CLI tool](../getting_started/installation/index.md), you can use oracles in the `nargo test`, `nargo execute` and `nargo prove` commands by passing a value to `--oracle-resolver`. For example: - -```bash -nargo test --oracle-resolver http://localhost:5555 -``` - -This tells `nargo` to use your RPC Server URL whenever it finds an oracle decorator. - -## Step 4 - Usage with NoirJS - -In a JS environment, an RPC server is not strictly necessary, as you may want to resolve your oracles without needing any JSON call at all. NoirJS simply expects that you pass a callback function when you generate proofs, and that callback function can be anything. - -For example, if your Noir program expects the host machine to provide CPU pseudo-randomness, you could simply pass it as the `foreignCallHandler`. You don't strictly need to create an RPC server to serve pseudo-randomness, as you may as well get it directly in your app: - -```js -const foreignCallHandler = (name, inputs) => crypto.randomBytes(16) // etc - -await noir.generateProof(inputs, foreignCallHandler) -``` - -As one can see, in NoirJS, the [`foreignCallHandler`](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) function simply means "a callback function that returns a value of type [`ForeignCallOutput`](../reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md). It doesn't have to be an RPC call like in the case for Nargo. - -:::tip - -Does this mean you don't have to write an RPC server like in [Step #2](#step-2---write-an-rpc-server)? - -You don't technically have to, but then how would you run `nargo test` or `nargo prove`? To use both `Nargo` and `NoirJS` in your development flow, you will have to write a JSON RPC server. - -::: - -In this case, let's make `foreignCallHandler` call the JSON RPC Server we created in [Step #2](#step-2---write-an-rpc-server), by making it a JSON RPC Client. - -For example, using the same `getSqrt` program in [Step #1](#step-1---modify-your-noir-program) (comments in the code): - -```js -import { JSONRPCClient } from "json-rpc-2.0"; - -// declaring the JSONRPCClient -const client = new JSONRPCClient((jsonRPCRequest) => { -// hitting the same JSON RPC Server we coded above - return fetch("http://localhost:5555", { - method: "POST", - headers: { - "content-type": "application/json", - }, - body: JSON.stringify(jsonRPCRequest), - }).then((response) => { - if (response.status === 200) { - return response - .json() - .then((jsonRPCResponse) => client.receive(jsonRPCResponse)); - } else if (jsonRPCRequest.id !== undefined) { - return Promise.reject(new Error(response.statusText)); - } - }); -}); - -// declaring a function that takes the name of the foreign call (getSqrt) and the inputs -const foreignCallHandler = async (name, input) => { - // notice that the "inputs" parameter contains *all* the inputs - // in this case we to make the RPC request with the first parameter "numbers", which would be input[0] - const oracleReturn = await client.request(name, [ - { Array: input[0].map((i) => i.toString("hex")) }, - ]); - return [oracleReturn.values[0].Array]; -}; - -// the rest of your NoirJS code -const input = { input: [4, 16] }; -const { witness } = await noir.execute(numbers, foreignCallHandler); -``` - -:::tip - -If you're in a NoirJS environment running your RPC server together with a frontend app, you'll probably hit a familiar problem in full-stack development: requests being blocked by [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) policy. For development only, you can simply install and use the [`cors` npm package](https://www.npmjs.com/package/cors) to get around the problem: - -```bash -yarn add cors -``` - -and use it as a middleware: - -```js -import cors from "cors"; - -const app = express(); -app.use(cors()) -``` - -::: - -## Conclusion - -Hopefully by the end of this guide, you should be able to: - -- Write your own logic around Oracles and how to write a JSON RPC server to make them work with your Nargo commands. -- Provide custom foreign call handlers for NoirJS. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/how_to/how-to-recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/how_to/how-to-recursion.md deleted file mode 100644 index 4c45bb87ae2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/how_to/how-to-recursion.md +++ /dev/null @@ -1,179 +0,0 @@ ---- -title: How to use recursion on NoirJS -description: Learn how to implement recursion with NoirJS, a powerful tool for creating smart contracts on the EVM blockchain. This guide assumes familiarity with NoirJS, solidity verifiers, and the Barretenberg proving backend. Discover how to generate both final and intermediate proofs using `noir_js` and `backend_barretenberg`. -keywords: - [ - "NoirJS", - "EVM blockchain", - "smart contracts", - "recursion", - "solidity verifiers", - "Barretenberg backend", - "noir_js", - "backend_barretenberg", - "intermediate proofs", - "final proofs", - "nargo compile", - "json import", - "recursive circuit", - "recursive app" - ] -sidebar_position: 1 ---- - -This guide shows you how to use recursive proofs in your NoirJS app. For the sake of clarity, it is assumed that: - -- You already have a NoirJS app. If you don't, please visit the [NoirJS tutorial](../tutorials/noirjs_app.md) and the [reference](../reference/NoirJS/noir_js/index.md). -- You are familiar with what are recursive proofs and you have read the [recursion explainer](../explainers/explainer-recursion.md) -- You already built a recursive circuit following [the reference](../noir/standard_library/recursion.md), and understand how it works. - -It is also assumed that you're not using `noir_wasm` for compilation, and instead you've used [`nargo compile`](../reference/nargo_commands.md) to generate the `json` you're now importing into your project. However, the guide should work just the same if you're using `noir_wasm`. - -:::info - -As you've read in the [explainer](../explainers/explainer-recursion.md), a recursive proof is an intermediate proof. This means that it doesn't necessarily generate the final step that makes it verifiable in a smart contract. However, it is easy to verify within another circuit. - -While "standard" usage of NoirJS packages abstracts final proofs, it currently lacks the necessary interface to abstract away intermediate proofs. This means that these proofs need to be created by using the backend directly. - -In short: - -- `noir_js` generates *only* final proofs -- `backend_barretenberg` generates both types of proofs - -::: - -In a standard recursive app, you're also dealing with at least two circuits. For the purpose of this guide, we will assume the following: - -- `main`: a circuit of type `assert(x != y)`, where `main` is marked with a `#[recursive]` attribute. This attribute states that the backend should generate proofs that are friendly for verification within another circuit. -- `recursive`: a circuit that verifies `main` - -For a full example on how recursive proofs work, please refer to the [noir-examples](https://github.com/noir-lang/noir-examples) repository. We will *not* be using it as a reference for this guide. - -## Step 1: Setup - -In a common NoirJS app, you need to instantiate a backend with something like `const backend = new Backend(circuit)`. Then you feed it to the `noir_js` interface. - -For recursion, this doesn't happen, and the only need for `noir_js` is only to `execute` a circuit and get its witness and return value. Everything else is not interfaced, so it needs to happen on the `backend` object. - -It is also recommended that you instantiate the backend with as many threads as possible, to allow for maximum concurrency: - -```js -const backend = new Backend(circuit, { threads: 8 }) -``` - -:::tip -You can use the [`os.cpus()`](https://nodejs.org/api/os.html#oscpus) object in `nodejs` or [`navigator.hardwareConcurrency`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/hardwareConcurrency) on the browser to make the most out of those glorious cpu cores -::: - -## Step 2: Generating the witness and the proof for `main` - -After instantiating the backend, you should also instantiate `noir_js`. We will use it to execute the circuit and get the witness. - -```js -const noir = new Noir(circuit, backend) -const { witness } = noir.execute(input) -``` - -With this witness, you are now able to generate the intermediate proof for the main circuit: - -```js -const { proof, publicInputs } = await backend.generateProof(witness) -``` - -:::warning - -Always keep in mind what is actually happening on your development process, otherwise you'll quickly become confused about what circuit we are actually running and why! - -In this case, you can imagine that Alice (running the `main` circuit) is proving something to Bob (running the `recursive` circuit), and Bob is verifying her proof within his proof. - -With this in mind, it becomes clear that our intermediate proof is the one *meant to be verified within another circuit*, so it must be Alice's. Actually, the only final proof in this theoretical scenario would be the last one, sent on-chain. - -::: - -## Step 3 - Verification and proof artifacts - -Optionally, you are able to verify the intermediate proof: - -```js -const verified = await backend.verifyProof({ proof, publicInputs }) -``` - -This can be useful to make sure our intermediate proof was correctly generated. But the real goal is to do it within another circuit. For that, we need to generate recursive proof artifacts that will be passed to the circuit that is verifying the proof we just generated. Instead of passing the proof and verification key as a byte array, we pass them as fields which makes it cheaper to verify in a circuit: - -```js -const { proofAsFields, vkAsFields, vkHash } = await backend.generateRecursiveProofArtifacts( { publicInputs, proof }, publicInputsCount) -``` - -This call takes the public inputs and the proof, but also the public inputs count. While this is easily retrievable by simply counting the `publicInputs` length, the backend interface doesn't currently abstract it away. - -:::info - -The `proofAsFields` has a constant size `[Field; 93]` and verification keys in Barretenberg are always `[Field; 114]`. - -::: - -:::warning - -One common mistake is to forget *who* makes this call. - -In a situation where Alice is generating the `main` proof, if she generates the proof artifacts and sends them to Bob, which gladly takes them as true, this would mean Alice could prove anything! - -Instead, Bob needs to make sure *he* extracts the proof artifacts, using his own instance of the `main` circuit backend. This way, Alice has to provide a valid proof for the correct `main` circuit. - -::: - -## Step 4 - Recursive proof generation - -With the artifacts, generating a recursive proof is no different from a normal proof. You simply use the `backend` (with the recursive circuit) to generate it: - -```js -const recursiveInputs = { - verification_key: vkAsFields, // array of length 114 - proof: proofAsFields, // array of length 93 + size of public inputs - publicInputs: [mainInput.y], // using the example above, where `y` is the only public input - key_hash: vkHash, -} - -const { witness, returnValue } = noir.execute(recursiveInputs) // we're executing the recursive circuit now! -const { proof, publicInputs } = backend.generateProof(witness) -const verified = backend.verifyProof({ proof, publicInputs }) -``` - -You can obviously chain this proof into another proof. In fact, if you're using recursive proofs, you're probably interested of using them this way! - -:::tip - -Managing circuits and "who does what" can be confusing. To make sure your naming is consistent, you can keep them in an object. For example: - -```js -const circuits = { - main: mainJSON, - recursive: recursiveJSON -} -const backends = { - main: new BarretenbergBackend(circuits.main), - recursive: new BarretenbergBackend(circuits.recursive) -} -const noir_programs = { - main: new Noir(circuits.main, backends.main), - recursive: new Noir(circuits.recursive, backends.recursive) -} -``` - -This allows you to neatly call exactly the method you want without conflicting names: - -```js -// Alice runs this 👇 -const { witness: mainWitness } = await noir_programs.main.execute(input) -const proof = await backends.main.generateProof(mainWitness) - -// Bob runs this 👇 -const verified = await backends.main.verifyProof(proof) -const { proofAsFields, vkAsFields, vkHash } = await backends.main.generateRecursiveProofArtifacts( - proof, - numPublicInputs, -); -const recursiveProof = await noir_programs.recursive.generateProof(recursiveInputs) -``` - -::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/how_to/how-to-solidity-verifier.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/how_to/how-to-solidity-verifier.md deleted file mode 100644 index e3c7c1065da..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/how_to/how-to-solidity-verifier.md +++ /dev/null @@ -1,231 +0,0 @@ ---- -title: Generate a Solidity Verifier -description: - Learn how to run the verifier as a smart contract on the blockchain. Compile a Solidity verifier - contract for your Noir program and deploy it on any EVM blockchain acting as a verifier smart - contract. Read more to find out -keywords: - [ - solidity verifier, - smart contract, - blockchain, - compiler, - plonk_vk.sol, - EVM blockchain, - verifying Noir programs, - proving backend, - Barretenberg, - ] -sidebar_position: 0 -pagination_next: tutorials/noirjs_app ---- - -Noir has the ability to generate a verifier contract in Solidity, which can be deployed in many EVM-compatible blockchains such as Ethereum. - -This allows for a powerful feature set, as one can make use of the conciseness and the privacy provided by Noir in an immutable ledger. Applications can range from simple P2P guessing games, to complex private DeFi interactions. - -This guide shows you how to generate a Solidity Verifier and deploy it on the [Remix IDE](https://remix.ethereum.org/). It is assumed that: - -- You are comfortable with the Solidity programming language and understand how contracts are deployed on the Ethereum network -- You have Noir installed and you have a Noir program. If you don't, [get started](../getting_started/installation/index.md) with Nargo and the example Hello Noir circuit -- You are comfortable navigating RemixIDE. If you aren't or you need a refresher, you can find some video tutorials [here](https://www.youtube.com/channel/UCjTUPyFEr2xDGN6Cg8nKDaA) that could help you. - -## Rundown - -Generating a Solidity Verifier contract is actually a one-command process. However, compiling it and deploying it can have some caveats. Here's the rundown of this guide: - -1. How to generate a solidity smart contract -2. How to compile the smart contract in the RemixIDE -3. How to deploy it to a testnet - -## Step 1 - Generate a contract - -This is by far the most straight-forward step. Just run: - -```sh -nargo codegen-verifier -``` - -A new `contract` folder would then be generated in your project directory, containing the Solidity -file `plonk_vk.sol`. It can be deployed to any EVM blockchain acting as a verifier smart contract. - -:::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. - -Barretenberg, the default proving backend for Nargo, supports generation of verifier contracts, for the time being these are only in Solidity. -::: - -## Step 2 - Compiling - -We will mostly skip the details of RemixIDE, as the UI can change from version to version. For now, we can just open -Remix and create a blank workspace. - -![Create Workspace](@site/static/img/how-tos/solidity_verifier_1.png) - -We will create a new file to contain the contract Nargo generated, and copy-paste its content. - -:::warning - -You'll likely see a warning advising you to not trust pasted code. While it is an important warning, it is irrelevant in the context of this guide and can be ignored. We will not be deploying anywhere near a mainnet. - -::: - -To compile our the verifier, we can navigate to the compilation tab: - -![Compilation Tab](@site/static/img/how-tos/solidity_verifier_2.png) - -Remix should automatically match a suitable compiler version. However, hitting the "Compile" button will most likely generate a "Stack too deep" error: - -![Stack too deep](@site/static/img/how-tos/solidity_verifier_3.png) - -This is due to the verify function needing to put many variables on the stack, but enabling the optimizer resolves the issue. To do this, let's open the "Advanced Configurations" tab and enable optimization. The default 200 runs will suffice. - -:::info - -This time we will see a warning about an unused function parameter. This is expected, as the `verify` function doesn't use the `_proof` parameter inside a solidity block, it is loaded from calldata and used in assembly. - -::: - -![Compilation success](@site/static/img/how-tos/solidity_verifier_4.png) - -## Step 3 - Deploying - -At this point we should have a compiled contract read to deploy. If we navigate to the deploy section in Remix, we will see many different environments we can deploy to. The steps to deploy on each environment would be out-of-scope for this guide, so we will just use the default Remix VM. - -Looking closely, we will notice that our "Solidity Verifier" is actually three contracts working together: - -- An `UltraVerificationKey` library which simply stores the verification key for our circuit. -- An abstract contract `BaseUltraVerifier` containing most of the verifying logic. -- A main `UltraVerifier` contract that inherits from the Base and uses the Key contract. - -Remix will take care of the dependencies for us so we can simply deploy the UltraVerifier contract by selecting it and hitting "deploy": - -![Deploying UltraVerifier](@site/static/img/how-tos/solidity_verifier_5.png) - -A contract will show up in the "Deployed Contracts" section, where we can retrieve the Verification Key Hash. This is particularly useful for double-checking the deployer contract is the correct one. - -:::note - -Why "UltraVerifier"? - -To be precise, the Noir compiler (`nargo`) doesn't generate the verifier contract directly. It compiles the Noir code into an intermediate language (ACIR), which is then executed by the backend. So it is the backend that returns the verifier smart contract, not Noir. - -In this case, the Barretenberg Backend uses the UltraPlonk proving system, hence the "UltraVerifier" name. - -::: - -## Step 4 - Verifying - -To verify a proof using the Solidity verifier contract, we call the `verify` function in this extended contract: - -```solidity -function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) -``` - -When using the default example in the [Hello Noir](../getting_started/hello_noir/index.md) guide, the easiest way to confirm that the verifier contract is doing its job is by calling the `verify` function via remix with the required parameters. For `_proof`, run `nargo prove` and use the string in `proof/.proof` (adding the hex `0x` prefix). We can also copy the public input from `Verifier.toml`, as it will be properly formatted as 32-byte strings: - -``` -0x...... , [0x0000.....02] -``` - -A programmatic example of how the `verify` function is called can be seen in the example zk voting application [here](https://github.com/noir-lang/noir-examples/blob/33e598c257e2402ea3a6b68dd4c5ad492bce1b0a/foundry-voting/src/zkVote.sol#L35): - -```solidity -function castVote(bytes calldata proof, uint proposalId, uint vote, bytes32 nullifierHash) public returns (bool) { - // ... - bytes32[] memory publicInputs = new bytes32[](4); - publicInputs[0] = merkleRoot; - publicInputs[1] = bytes32(proposalId); - publicInputs[2] = bytes32(vote); - publicInputs[3] = nullifierHash; - require(verifier.verify(proof, publicInputs), "Invalid proof"); -``` - -:::info[Return Values] - -A circuit doesn't have the concept of a return value. Return values are just syntactic sugar in -Noir. - -Under the hood, the return value is passed as an input to the circuit and is checked at the end of -the circuit program. - -For example, if you have Noir program like this: - -```rust -fn main( - // Public inputs - pubkey_x: pub Field, - pubkey_y: pub Field, - // Private inputs - priv_key: Field, -) -> pub Field -``` - -the `verify` function will expect the public inputs array (second function parameter) to be of length 3, the two inputs and the return value. Like before, these values are populated in Verifier.toml after running `nargo prove`. - -Passing only two inputs will result in an error such as `PUBLIC_INPUT_COUNT_INVALID(3, 2)`. - -In this case, the inputs parameter to `verify` would be an array ordered as `[pubkey_x, pubkey_y, return]`. - -::: - -:::tip[Structs] - -You can pass structs to the verifier contract. They will be flattened so that the array of inputs is 1-dimensional array. - -For example, consider the following program: - -```rust -struct Type1 { - val1: Field, - val2: Field, -} - -struct Nested { - t1: Type1, - is_true: bool, -} - -fn main(x: pub Field, nested: pub Nested, y: pub Field) { - //... -} -``` - -The order of these inputs would be flattened to: `[x, nested.t1.val1, nested.t1.val2, nested.is_true, y]` - -::: - -The other function you can call is our entrypoint `verify` function, as defined above. - -:::tip - -It's worth noticing that the `verify` function is actually a `view` function. A `view` function does not alter the blockchain state, so it doesn't need to be distributed (i.e. it will run only on the executing node), and therefore doesn't cost any gas. - -This can be particularly useful in some situations. If Alice generated a proof and wants Bob to verify its correctness, Bob doesn't need to run Nargo, NoirJS, or any Noir specific infrastructure. He can simply make a call to the blockchain with the proof and verify it is correct without paying any gas. - -It would be incorrect to say that a Noir proof verification costs any gas at all. However, most of the time the result of `verify` is used to modify state (for example, to update a balance, a game state, etc). In that case the whole network needs to execute it, which does incur gas costs (calldata and execution, but not storage). - -::: - -## A Note on EVM chains - -ZK-SNARK verification depends on some precompiled cryptographic primitives such as Elliptic Curve Pairings (if you like complex math, you can read about EC Pairings [here](https://medium.com/@VitalikButerin/exploring-elliptic-curve-pairings-c73c1864e627)). Not all EVM chains support EC Pairings, notably some of the ZK-EVMs. This means that you won't be able to use the verifier contract in all of them. - -For example, chains like `zkSync ERA` and `Polygon zkEVM` do not currently support these precompiles, so proof verification via Solidity verifier contracts won't work. Here's a quick list of EVM chains that have been tested and are known to work: - -- Optimism -- Arbitrum -- Polygon PoS -- Scroll -- Celo - -If you test any other chains, please open a PR on this page to update the list. See [this doc](https://github.com/noir-lang/noir-starter/tree/main/with-foundry#testing-on-chain) for more info about testing verifier contracts on different EVM chains. - -## What's next - -Now that you know how to call a Noir Solidity Verifier on a smart contract using Remix, you should be comfortable with using it with some programmatic frameworks, such as [hardhat](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat) and [foundry](https://github.com/noir-lang/noir-starter/tree/main/with-foundry). - -You can find other tools, examples, boilerplates and libraries in the [awesome-noir](https://github.com/noir-lang/awesome-noir) repository. - -You should also be ready to write and deploy your first NoirJS app and start generating proofs on websites, phones, and NodeJS environments! Head on to the [NoirJS tutorial](../tutorials/noirjs_app.md) to learn how to do that. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/how_to/merkle-proof.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/how_to/merkle-proof.mdx deleted file mode 100644 index 16c425bed76..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/how_to/merkle-proof.mdx +++ /dev/null @@ -1,49 +0,0 @@ ---- -title: Prove Merkle Tree Membership -description: - Learn how to use merkle membership proof in Noir to prove that a given leaf is a member of a - merkle tree with a specified root, at a given index. -keywords: - [merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree] -sidebar_position: 4 ---- - -Let's walk through an example of a merkle membership proof in Noir that proves that a given leaf is -in a merkle tree. - -```rust -use dep::std; - -fn main(message : [Field; 62], index : Field, hashpath : [Field; 40], root : Field) { - let leaf = std::hash::hash_to_field(message.as_slice()); - let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); - assert(merkle_root == root); -} - -``` - -The message is hashed using `hash_to_field`. The specific hash function that is being used is chosen -by the backend. The only requirement is that this hash function can heuristically be used as a -random oracle. If only collision resistance is needed, then one can call `std::hash::pedersen_hash` -instead. - -```rust -let leaf = std::hash::hash_to_field(message.as_slice()); -``` - -The leaf is then passed to a compute_merkle_root function with the root, index and hashpath. The returned root can then be asserted to be the same as the provided root. - -```rust -let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); -assert (merkle_root == root); -``` - -> **Note:** It is possible to re-implement the merkle tree implementation without standard library. -> However, for most usecases, it is enough. In general, the standard library will always opt to be -> as conservative as possible, while striking a balance with efficiency. - -An example, the merkle membership proof, only requires a hash function that has collision -resistance, hence a hash function like Pedersen is allowed, which in most cases is more efficient -than the even more conservative sha256. - -[View an example on the starter repo](https://github.com/noir-lang/noir-examples/blob/3ea09545cabfa464124ec2f3ea8e60c608abe6df/stealthdrop/circuits/src/main.nr#L20) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/how_to/using-devcontainers.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/how_to/using-devcontainers.mdx deleted file mode 100644 index 727ec6ca667..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/how_to/using-devcontainers.mdx +++ /dev/null @@ -1,110 +0,0 @@ ---- -title: Developer Containers and Codespaces -description: "Learn how to set up a devcontainer in your GitHub repository for a seamless coding experience with Codespaces. Follow our easy 8-step guide to create your own Noir environment without installing Nargo locally." -keywords: ["Devcontainer", "Codespaces", "GitHub", "Noir Environment", "Docker Image", "Development Environment", "Remote Coding", "GitHub Codespaces", "Noir Programming", "Nargo", "VSCode Extensions", "Noirup"] -sidebar_position: 1 ---- - -Adding a developer container configuration file to your Noir project is one of the easiest way to unlock coding in browser. - -## What's a devcontainer after all? - -A [Developer Container](https://containers.dev/) (devcontainer for short) is a Docker image that comes preloaded with tools, extensions, and other tools you need to quickly get started or continue a project, without having to install Nargo locally. Think of it as a development environment in a box. - -There are many advantages to this: - -- It's platform and architecture agnostic -- You don't need to have an IDE installed, or Nargo, or use a terminal at all -- It's safer for using on a public machine or public network - -One of the best ways of using devcontainers is... not using your machine at all, for maximum control, performance, and ease of use. -Enter Codespaces. - -## Codespaces - -If a devcontainer is just a Docker image, then what stops you from provisioning a `p3dn.24xlarge` AWS EC2 instance with 92 vCPUs and 768 GiB RAM and using it to prove your 10-gate SNARK proof? - -Nothing! Except perhaps the 30-40$ per hour it will cost you. - -The problem is that provisioning takes time, and I bet you don't want to see the AWS console every time you want to code something real quick. - -Fortunately, there's an easy and free way to get a decent remote machine ready and loaded in less than 2 minutes: Codespaces. [Codespaces is a Github feature](https://github.com/features/codespaces) that allows you to code in a remote machine by using devcontainers, and it's pretty cool: - -- You can start coding Noir in less than a minute -- It uses the resources of a remote machine, so you can code on your grandma's phone if needed be -- It makes it easy to share work with your frens -- It's fully reusable, you can stop and restart whenever you need to - -:::info - -Don't take out your wallet just yet. Free GitHub accounts get about [15-60 hours of coding](https://github.com/features/codespaces) for free per month, depending on the size of your provisioned machine. - -::: - -## Tell me it's _actually_ easy - -It is! - -Github comes with a default codespace and you can use it to code your own devcontainer. That's exactly what we will be doing in this guide. - - - -8 simple steps: - -#### 1. Create a new repository on GitHub. - -#### 2. Click "Start coding with Codespaces". This will use the default image. - -#### 3. Create a folder called `.devcontainer` in the root of your repository. - -#### 4. Create a Dockerfile in that folder, and paste the following code: - -```docker -FROM --platform=linux/amd64 node:lts-bookworm-slim -SHELL ["/bin/bash", "-c"] -RUN apt update && apt install -y curl bash git tar gzip libc++-dev -RUN curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -ENV PATH="/root/.nargo/bin:$PATH" -RUN noirup -ENTRYPOINT ["nargo"] -``` -#### 5. Create a file called `devcontainer.json` in the same folder, and paste the following code: - -```json -{ - "name": "Noir on Codespaces", - "build": { - "context": ".", - "dockerfile": "Dockerfile" - }, - "customizations": { - "vscode": { - "extensions": ["noir-lang.vscode-noir"] - } - } -} -``` -#### 6. Commit and push your changes - -This will pull the new image and build it, so it could take a minute or so - -#### 8. Done! -Just wait for the build to finish, and there's your easy Noir environment. - - -Refer to [noir-starter](https://github.com/noir-lang/noir-starter/) as an example of how devcontainers can be used together with codespaces. - - - -## How do I use it? - -Using the codespace is obviously much easier than setting it up. -Just navigate to your repository and click "Code" -> "Open with Codespaces". It should take a few seconds to load, and you're ready to go. - -:::info - -If you really like the experience, you can add a badge to your readme, links to existing codespaces, and more. -Check out the [official docs](https://docs.github.com/en/codespaces/setting-up-your-project-for-codespaces/setting-up-your-repository/facilitating-quick-creation-and-resumption-of-codespaces) for more info. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/index.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/index.mdx deleted file mode 100644 index 75086ddcdde..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/index.mdx +++ /dev/null @@ -1,67 +0,0 @@ ---- -title: Noir Lang -hide_title: true -description: - Learn about the public alpha release of Noir, a domain specific language heavily influenced by Rust that compiles to - an intermediate language which can be compiled to an arithmetic circuit or a rank-1 constraint system. -keywords: - [Noir, - Domain Specific Language, - Rust, - Intermediate Language, - Arithmetic Circuit, - Rank-1 Constraint System, - Ethereum Developers, - Protocol Developers, - Blockchain Developers, - Proving System, - Smart Contract Language] -sidebar_position: 0 ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -Noir Logo - -Noir is a Domain-Specific Language for SNARK proving systems developed by [Aztec Labs](https://aztec.network/). It allows you to generate complex Zero-Knowledge Programs (ZKP) by using simple and flexible syntax, requiring no previous knowledge on the underlying mathematics or cryptography. - -ZK programs are programs that can generate short proofs of a certain statement without revealing some details about it. You can read more about ZKPs [here](https://dev.to/spalladino/a-beginners-intro-to-coding-zero-knowledge-proofs-c56). - -## What's new about Noir? - -Noir works differently from most ZK languages by taking a two-pronged path. First, it compiles the program to an adaptable intermediate language known as ACIR. From there, depending on a given project's needs, ACIR can be further compiled into an arithmetic circuit for integration with the proving backend. - -:::info - -Noir is backend agnostic, which means it makes no assumptions on which proving backend powers the ZK proof. Being the language that powers [Aztec Contracts](https://docs.aztec.network/developers/contracts/main), it defaults to Aztec's Barretenberg proving backend. - -However, the ACIR output can be transformed to be compatible with other PLONK-based backends, or into a [rank-1 constraint system](https://www.rareskills.io/post/rank-1-constraint-system) suitable for backends such as Arkwork's Marlin. - -::: - -## Who is Noir for? - -Noir can be used both in complex cloud-based backends and in user's smartphones, requiring no knowledge on the underlying math or cryptography. From authorization systems that keep a password in the user's device, to complex on-chain verification of recursive proofs, Noir is designed to abstract away complexity without any significant overhead. Here are some examples of situations where Noir can be used: - - - - Noir Logo - - Aztec Contracts leverage Noir to allow for the storage and execution of private information. Writing an Aztec Contract is as easy as writing Noir, and Aztec developers can easily interact with the network storage and execution through the [Aztec.nr](https://docs.aztec.network/developers/contracts/main) library. - - - Soliditry Verifier Example - Noir can auto-generate Solidity verifier contracts that verify Noir proofs. This allows for non-interactive verification of proofs containing private information in an immutable system. This feature powers a multitude of use-case scenarios, from P2P chess tournaments, to [Aztec Layer-2 Blockchain](https://docs.aztec.network/) - - - Aztec Labs developed NoirJS, an easy interface to generate and verify Noir proofs in a Javascript environment. This allows for Noir to be used in webpages, mobile apps, games, and any other environment supporting JS execution in a standalone manner. - - - - -## Libraries - -Noir is meant to be easy to extend by simply importing Noir libraries just like in Rust. -The [awesome-noir repo](https://github.com/noir-lang/awesome-noir#libraries) is a collection of libraries developed by the Noir community. -Writing a new library is easy and makes code be composable and easy to reuse. See the section on [dependencies](noir/modules_packages_crates/dependencies.md) for more information. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/migration_notes.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/migration_notes.md deleted file mode 100644 index 6bd740024e5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/migration_notes.md +++ /dev/null @@ -1,105 +0,0 @@ ---- -title: Migration notes -description: Read about migration notes from previous versions, which could solve problems while updating -keywords: [Noir, notes, migration, updating, upgrading] ---- - -Noir is in full-speed development. Things break fast, wild, and often. This page attempts to leave some notes on errors you might encounter when upgrading and how to resolve them until proper patches are built. - -### `backend encountered an error: libc++.so.1` - -Depending on your OS, you may encounter the following error when running `nargo prove` for the first time: - -```text -The backend encountered an error: "/home/codespace/.nargo/backends/acvm-backend-barretenberg/backend_binary: error while loading shared libraries: libc++.so.1: cannot open shared object file: No such file or directory\n" -``` - -Install the `libc++-dev` library with: - -```bash -sudo apt install libc++-dev -``` - -## ≥0.19 - -### Enforcing `compiler_version` - -From this version on, the compiler will check for the `compiler_version` field in `Nargo.toml`, and will error if it doesn't match the current Nargo version in use. - -To update, please make sure this field in `Nargo.toml` matches the output of `nargo --version`. - -## ≥0.14 - -The index of the [for loops](noir/concepts/control_flow.md#loops) is now of type `u64` instead of `Field`. An example refactor would be: - -```rust -for i in 0..10 { - let i = i as Field; -} -``` - -## ≥v0.11.0 and Nargo backend - -From this version onwards, Nargo starts managing backends through the `nargo backend` command. Upgrading to the versions per usual steps might lead to: - -### `backend encountered an error` - -This is likely due to the existing locally installed version of proving backend (e.g. barretenberg) is incompatible with the version of Nargo in use. - -To fix the issue: - -1. Uninstall the existing backend - -```bash -nargo backend uninstall acvm-backend-barretenberg -``` - -You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. - -2. Reinstall a compatible version of the proving backend. - -If you are using the default barretenberg backend, simply run: - -``` -nargo prove -``` - -with your Noir program. - -This will trigger the download and installation of the latest version of barretenberg compatible with your Nargo in use. - -### `backend encountered an error: illegal instruction` - -On certain Intel-based systems, an `illegal instruction` error may arise due to incompatibility of barretenberg with certain CPU instructions. - -To fix the issue: - -1. Uninstall the existing backend - -```bash -nargo backend uninstall acvm-backend-barretenberg -``` - -You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. - -2. Reinstall a compatible version of the proving backend. - -If you are using the default barretenberg backend, simply run: - -``` -nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/barretenberg-js-binary/raw/master/run-bb.tar.gz -``` - -This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. - -The gzipped file is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. - -Then run: - -``` -DESIRED_BINARY_VERSION=0.8.1 nargo info -``` - -This overrides the bb native binary with a bb.js node application instead, which should be compatible with most if not all hardware. This does come with the drawback of being generally slower than native binary. - -0.8.1 indicates bb.js version 0.8.1, so if you change that it will update to a different version or the default version in the script if none was supplied. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/_category_.json deleted file mode 100644 index 7da08f8a8c5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Concepts", - "position": 0, - "collapsible": true, - "collapsed": true -} \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/assert.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/assert.md deleted file mode 100644 index bcff613a695..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/assert.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Assert Function -description: - Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or - comparison expression that follows to be true, and what happens if the expression is false at - runtime. -keywords: [Noir programming language, assert statement, predicate expression, comparison expression] -sidebar_position: 4 ---- - -Noir includes a special `assert` function which will explicitly constrain the predicate/comparison -expression that follows to be true. If this expression is false at runtime, the program will fail to -be proven. Example: - -```rust -fn main(x : Field, y : Field) { - assert(x == y); -} -``` - -> Assertions only work for predicate operations, such as `==`. If there's any ambiguity on the operation, the program will fail to compile. For example, it is unclear if `assert(x + y)` would check for `x + y == 0` or simply would return `true`. - -You can optionally provide a message to be logged when the assertion fails: - -```rust -assert(x == y, "x and y are not equal"); -``` - -Aside string literals, the optional message can be a format string or any other type supported as input for Noir's [print](../standard_library/logging.md) functions. This feature lets you incorporate runtime variables into your failed assertion logs: - -```rust -assert(x == y, f"Expected x == y, but got {x} == {y}"); -``` - -Using a variable as an assertion message directly: - -```rust -struct myStruct { - myField: Field -} - -let s = myStruct { myField: y }; -assert(s.myField == x, s); -``` - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/comments.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/comments.md deleted file mode 100644 index b51a85f5c94..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/comments.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Comments -description: - Learn how to write comments in Noir programming language. A comment is a line of code that is - ignored by the compiler, but it can be read by programmers. Single-line and multi-line comments - are supported in Noir. -keywords: [Noir programming language, comments, single-line comments, multi-line comments] -sidebar_position: 10 ---- - -A comment is a line in your codebase which the compiler ignores, however it can be read by -programmers. - -Here is a single line comment: - -```rust -// This is a comment and is ignored -``` - -`//` is used to tell the compiler to ignore the rest of the line. - -Noir also supports multi-line block comments. Start a block comment with `/*` and end the block with `*/`. - -Noir does not natively support doc comments. You may be able to use [Rust doc comments](https://doc.rust-lang.org/reference/comments.html) in your code to leverage some Rust documentation build tools with Noir code. - -```rust -/* - This is a block comment describing a complex function. -*/ -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/control_flow.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/control_flow.md deleted file mode 100644 index 045d3c3a5f5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/control_flow.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -title: Control Flow -description: - Learn how to use loops and if expressions in the Noir programming language. Discover the syntax - and examples for for loops and if-else statements. -keywords: [Noir programming language, loops, for loop, if-else statements, Rust syntax] -sidebar_position: 2 ---- - -## If Expressions - -Noir supports `if-else` statements. The syntax is most similar to Rust's where it is not required -for the statement's conditional to be surrounded by parentheses. - -```rust -let a = 0; -let mut x: u32 = 0; - -if a == 0 { - if a != 0 { - x = 6; - } else { - x = 2; - } -} else { - x = 5; - assert(x == 5); -} -assert(x == 2); -``` - -## Loops - -Noir has one kind of loop: the `for` loop. `for` loops allow you to repeat a block of code multiple -times. - -The following block of code between the braces is run 10 times. - -```rust -for i in 0..10 { - // do something -} -``` - -The index for loops is of type `u64`. - -### Break and Continue - -In unconstrained code, `break` and `continue` are also allowed in `for` loops. These are only allowed -in unconstrained code since normal constrained code requires that Noir knows exactly how many iterations -a loop may have. `break` and `continue` can be used like so: - -```rust -for i in 0 .. 10 { - println("Iteration start") - - if i == 2 { - continue; - } - - if i == 5 { - break; - } - - println(i); -} -println("Loop end") -``` - -When used, `break` will end the current loop early and jump to the statement after the for loop. In the example -above, the `break` will stop the loop and jump to the `println("Loop end")`. - -`continue` will stop the current iteration of the loop, and jump to the start of the next iteration. In the example -above, `continue` will jump to `println("Iteration start")` when used. Note that the loop continues as normal after this. -The iteration variable `i` is still increased by one as normal when `continue` is used. - -`break` and `continue` cannot currently be used to jump out of more than a single loop at a time. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_bus.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_bus.md deleted file mode 100644 index e54fc861257..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_bus.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: Data Bus -sidebar_position: 13 ---- -**Disclaimer** this feature is experimental, do not use it! - -The data bus is an optimization that the backend can use to make recursion more efficient. -In order to use it, you must define some inputs of the program entry points (usually the `main()` -function) with the `call_data` modifier, and the return values with the `return_data` modifier. -These modifiers are incompatible with `pub` and `mut` modifiers. - -## Example - -```rust -fn main(mut x: u32, y: call_data u32, z: call_data [u32;4] ) -> return_data u32 { - let a = z[x]; - a+y -} -``` - -As a result, both call_data and return_data will be treated as private inputs and encapsulated into a read-only array each, for the backend to process. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/_category_.json deleted file mode 100644 index 5d694210bbf..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 0, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/arrays.md deleted file mode 100644 index 9b02d52e8a8..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/arrays.md +++ /dev/null @@ -1,253 +0,0 @@ ---- -title: Arrays -description: - Dive into the Array data type in Noir. Grasp its methods, practical examples, and best practices for efficiently using Arrays in your Noir code. -keywords: - [ - noir, - array type, - methods, - examples, - indexing, - ] -sidebar_position: 4 ---- - -An array is one way of grouping together values into one compound type. Array types can be inferred -or explicitly specified via the syntax `[; ]`: - -```rust -fn main(x : Field, y : Field) { - let my_arr = [x, y]; - let your_arr: [Field; 2] = [x, y]; -} -``` - -Here, both `my_arr` and `your_arr` are instantiated as an array containing two `Field` elements. - -Array elements can be accessed using indexing: - -```rust -fn main() { - let a = [1, 2, 3, 4, 5]; - - let first = a[0]; - let second = a[1]; -} -``` - -All elements in an array must be of the same type (i.e. homogeneous). That is, an array cannot group -a `Field` value and a `u8` value together for example. - -You can write mutable arrays, like: - -```rust -fn main() { - let mut arr = [1, 2, 3, 4, 5]; - assert(arr[0] == 1); - - arr[0] = 42; - assert(arr[0] == 42); -} -``` - -You can instantiate a new array of a fixed size with the same value repeated for each element. The following example instantiates an array of length 32 where each element is of type Field and has the value 0. - -```rust -let array: [Field; 32] = [0; 32]; -``` - -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: - -```rust -let array: [Field; 32] = [0; 32]; -let sl = array.as_slice() -``` - -You can define multidimensional arrays: - -```rust -let array : [[Field; 2]; 2]; -let element = array[0][0]; -``` - -However, multidimensional slices are not supported. For example, the following code will error at compile time: - -```rust -let slice : [[Field]] = &[]; -``` - -## Types - -You can create arrays of primitive types or structs. There is not yet support for nested arrays -(arrays of arrays) or arrays of structs that contain arrays. - -## Methods - -For convenience, the STD provides some ready-to-use, common methods for arrays. -Each of these functions are located within the generic impl `impl [T; N] {`. -So anywhere `self` appears, it refers to the variable `self: [T; N]`. - -### len - -Returns the length of an array - -```rust -fn len(self) -> Field -``` - -example - -```rust -fn main() { - let array = [42, 42]; - assert(array.len() == 2); -} -``` - -### sort - -Returns a new sorted array. The original array remains untouched. Notice that this function will -only work for arrays of fields or integers, not for any arbitrary type. This is because the sorting -logic it uses internally is optimized specifically for these values. If you need a sort function to -sort any type, you should use the function `sort_via` described below. - -```rust -fn sort(self) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32]; - let sorted = arr.sort(); - assert(sorted == [32, 42]); -} -``` - -### sort_via - -Sorts the array with a custom comparison function - -```rust -fn sort_via(self, ordering: fn(T, T) -> bool) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32] - let sorted_ascending = arr.sort_via(|a, b| a <= b); - assert(sorted_ascending == [32, 42]); // verifies - - let sorted_descending = arr.sort_via(|a, b| a >= b); - assert(sorted_descending == [32, 42]); // does not verify -} -``` - -### map - -Applies a function to each element of the array, returning a new array containing the mapped elements. - -```rust -fn map(self, f: fn(T) -> U) -> [U; N] -``` - -example - -```rust -let a = [1, 2, 3]; -let b = a.map(|a| a * 2); // b is now [2, 4, 6] -``` - -### fold - -Applies a function to each element of the array, returning the final accumulated value. The first -parameter is the initial value. - -```rust -fn fold(self, mut accumulator: U, f: fn(U, T) -> U) -> U -``` - -This is a left fold, so the given function will be applied to the accumulator and first element of -the array, then the second, and so on. For a given call the expected result would be equivalent to: - -```rust -let a1 = [1]; -let a2 = [1, 2]; -let a3 = [1, 2, 3]; - -let f = |a, b| a - b; -a1.fold(10, f) //=> f(10, 1) -a2.fold(10, f) //=> f(f(10, 1), 2) -a3.fold(10, f) //=> f(f(f(10, 1), 2), 3) -``` - -example: - -```rust - -fn main() { - let arr = [2, 2, 2, 2, 2]; - let folded = arr.fold(0, |a, b| a + b); - assert(folded == 10); -} - -``` - -### reduce - -Same as fold, but uses the first element as starting element. - -```rust -fn reduce(self, f: fn(T, T) -> T) -> T -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let reduced = arr.reduce(|a, b| a + b); - assert(reduced == 10); -} -``` - -### all - -Returns true if all the elements satisfy the given predicate - -```rust -fn all(self, predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let all = arr.all(|a| a == 2); - assert(all); -} -``` - -### any - -Returns true if any of the elements satisfy the given predicate - -```rust -fn any(self, predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 5]; - let any = arr.any(|a| a == 5); - assert(any); -} - -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/booleans.md deleted file mode 100644 index 7211716f63e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/booleans.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Booleans -description: - Delve into the Boolean data type in Noir. Understand its methods, practical examples, and best practices for using Booleans in your Noir programs. -keywords: - [ - noir, - boolean type, - methods, - examples, - logical operations, - ] -sidebar_position: 2 ---- - - -The `bool` type in Noir has two possible values: `true` and `false`: - -```rust -fn main() { - let t = true; - let f: bool = false; -} -``` - -> **Note:** When returning a boolean value, it will show up as a value of 1 for `true` and 0 for -> `false` in _Verifier.toml_. - -The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and -[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/fields.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/fields.md deleted file mode 100644 index a10a4810788..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/fields.md +++ /dev/null @@ -1,192 +0,0 @@ ---- -title: Fields -description: - Dive deep into the Field data type in Noir. Understand its methods, practical examples, and best practices to effectively use Fields in your Noir programs. -keywords: - [ - noir, - field type, - methods, - examples, - best practices, - ] -sidebar_position: 0 ---- - -The field type corresponds to the native field type of the proving backend. - -The size of a Noir field depends on the elliptic curve's finite field for the proving backend -adopted. For example, a field would be a 254-bit integer when paired with the default backend that -spans the Grumpkin curve. - -Fields support integer arithmetic and are often used as the default numeric type in Noir: - -```rust -fn main(x : Field, y : Field) { - let z = x + y; -} -``` - -`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new -private value `z` constrained to be equal to `x + y`. - -If proving efficiency is of priority, fields should be used as a default for solving problems. -Smaller integer types (e.g. `u64`) incur extra range constraints. - -## Methods - -After declaring a Field, you can use these common methods on it: - -### to_le_bits - -Transforms the field into an array of bits, Little Endian. - -```rust -fn to_le_bits(_x : Field, _bit_size: u32) -> [u1] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_le_bits(32); -} -``` - -### to_be_bits - -Transforms the field into an array of bits, Big Endian. - -```rust -fn to_be_bits(_x : Field, _bit_size: u32) -> [u1] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_be_bits(32); -} -``` - -### to_le_bytes - -Transforms into an array of bytes, Little Endian - -```rust -fn to_le_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_le_bytes(4); -} -``` - -### to_be_bytes - -Transforms into an array of bytes, Big Endian - -```rust -fn to_be_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_be_bytes(4); -} -``` - -### to_le_radix - -Decomposes into a vector over the specified base, Little Endian - -```rust -fn to_le_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_le_radix(256, 4); -} -``` - -### to_be_radix - -Decomposes into a vector over the specified base, Big Endian - -```rust -fn to_be_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_be_radix(256, 4); -} -``` - -### pow_32 - -Returns the value to the power of the specified exponent - -```rust -fn pow_32(self, exponent: Field) -> Field -``` - -example: - -```rust -fn main() { - let field = 2 - let pow = field.pow_32(4); - assert(pow == 16); -} -``` - -### assert_max_bit_size - -Adds a constraint to specify that the field can be represented with `bit_size` number of bits - -```rust -fn assert_max_bit_size(self, bit_size: u32) -``` - -example: - -```rust -fn main() { - let field = 2 - field.assert_max_bit_size(32); -} -``` - -### sgn0 - -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. - -```rust -fn sgn0(self) -> u1 -``` - - -### lt - -Returns true if the field is less than the other field - -```rust -pub fn lt(self, another: Field) -> bool -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/function_types.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/function_types.md deleted file mode 100644 index f6121af17e2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/function_types.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Function types -sidebar_position: 10 ---- - -Noir supports higher-order functions. The syntax for a function type is as follows: - -```rust -fn(arg1_type, arg2_type, ...) -> return_type -``` - -Example: - -```rust -fn assert_returns_100(f: fn() -> Field) { // f takes no args and returns a Field - assert(f() == 100); -} - -fn main() { - assert_returns_100(|| 100); // ok - assert_returns_100(|| 150); // fails -} -``` - -A function type also has an optional capture environment - this is necessary to support closures. -See [Lambdas](../lambdas.md) for more details. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/index.md deleted file mode 100644 index 357813c147a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/index.md +++ /dev/null @@ -1,110 +0,0 @@ ---- -title: Data Types -description: - Get a clear understanding of the two categories of Noir data types - primitive types and compound - types. Learn about their characteristics, differences, and how to use them in your Noir - programming. -keywords: - [ - noir, - data types, - primitive types, - compound types, - private types, - public types, - ] ---- - -Every value in Noir has a type, which determines which operations are valid for it. - -All values in Noir are fundamentally composed of `Field` elements. For a more approachable -developing experience, abstractions are added on top to introduce different data types in Noir. - -Noir has two category of data types: primitive types (e.g. `Field`, integers, `bool`) and compound -types that group primitive types (e.g. arrays, tuples, structs). Each value can either be private or -public. - -## Private & Public Types - -A **private value** is known only to the Prover, while a **public value** is known by both the -Prover and Verifier. Mark values as `private` when the value should only be known to the prover. All -primitive types (including individual fields of compound types) in Noir are private by default, and -can be marked public when certain values are intended to be revealed to the Verifier. - -> **Note:** For public values defined in Noir programs paired with smart contract verifiers, once -> the proofs are verified on-chain the values can be considered known to everyone that has access to -> that blockchain. - -Public data types are treated no differently to private types apart from the fact that their values -will be revealed in proofs generated. Simply changing the value of a public type will not change the -circuit (where the same goes for changing values of private types as well). - -_Private values_ are also referred to as _witnesses_ sometimes. - -> **Note:** The terms private and public when applied to a type (e.g. `pub Field`) have a different -> meaning than when applied to a function (e.g. `pub fn foo() {}`). -> -> The former is a visibility modifier for the Prover to interpret if a value should be made known to -> the Verifier, while the latter is a visibility modifier for the compiler to interpret if a -> function should be made accessible to external Noir programs like in other languages. - -### pub Modifier - -All data types in Noir are private by default. Types are explicitly declared as public using the -`pub` modifier: - -```rust -fn main(x : Field, y : pub Field) -> pub Field { - x + y -} -``` - -In this example, `x` is **private** while `y` and `x + y` (the return value) are **public**. Note -that visibility is handled **per variable**, so it is perfectly valid to have one input that is -private and another that is public. - -> **Note:** Public types can only be declared through parameters on `main`. - -## Type Aliases - -A type alias is a new name for an existing type. Type aliases are declared with the keyword `type`: - -```rust -type Id = u8; - -fn main() { - let id: Id = 1; - let zero: u8 = 0; - assert(zero + 1 == id); -} -``` - -Type aliases can also be used with [generics](../generics.md): - -```rust -type Id = Size; - -fn main() { - let id: Id = 1; - let zero: u32 = 0; - assert(zero + 1 == id); -} -``` - -Type aliases can even refer to other aliases. An error will be issued if they form a cycle: - -```rust -// Ok! -type A = B; -type B = Field; - -type Bad1 = Bad2; - -// error: Dependency cycle found -type Bad2 = Bad1; -// ^^^^^^^^^^^ 'Bad2' recursively depends on itself: Bad2 -> Bad1 -> Bad2 -``` - -### BigInt - -You can achieve BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/integers.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/integers.md deleted file mode 100644 index 6b2d3773912..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/integers.md +++ /dev/null @@ -1,157 +0,0 @@ ---- -title: Integers -description: Explore the Integer data type in Noir. Learn about its methods, see real-world examples, and grasp how to efficiently use Integers in your Noir code. -keywords: [noir, integer types, methods, examples, arithmetic] -sidebar_position: 1 ---- - -An integer type is a range constrained field type. -The Noir frontend supports both unsigned and signed integer types. -The allowed sizes are 1, 8, 16, 32 and 64 bits. - -:::info - -When an integer is defined in Noir without a specific type, it will default to `Field`. - -The one exception is for loop indices which default to `u64` since comparisons on `Field`s are not possible. - -::: - -## Unsigned Integers - -An unsigned integer type is specified first with the letter `u` (indicating its unsigned nature) followed by its bit size (e.g. `8`): - -```rust -fn main() { - let x: u8 = 1; - let y: u8 = 1; - let z = x + y; - assert (z == 2); -} -``` - -The bit size determines the maximum value the integer type can store. For example, a `u8` variable can store a value in the range of 0 to 255 (i.e. $\\2^{8}-1\\$). - -## Signed Integers - -A signed integer type is specified first with the letter `i` (which stands for integer) followed by its bit size (e.g. `8`): - -```rust -fn main() { - let x: i8 = -1; - let y: i8 = -1; - let z = x + y; - assert (z == -2); -} -``` - -The bit size determines the maximum and minimum range of value the integer type can store. For example, an `i8` variable can store a value in the range of -128 to 127 (i.e. $\\-2^{7}\\$ to $\\2^{7}-1\\$). - -## 128 bits Unsigned Integers - -The built-in structure `U128` allows you to use 128-bit unsigned integers almost like a native integer type. However, there are some differences to keep in mind: -- You cannot cast between a native integer and `U128` -- There is a higher performance cost when using `U128`, compared to a native type. - -Conversion between unsigned integer types and U128 are done through the use of `from_integer` and `to_integer` functions. `from_integer` also accepts the `Field` type as input. - -```rust -fn main() { - let x = U128::from_integer(23); - let y = U128::from_hex("0x7"); - let z = x + y; - assert(z.to_integer() == 30); -} -``` - -`U128` is implemented with two 64 bits limbs, representing the low and high bits, which explains the performance cost. You should expect `U128` to be twice more costly for addition and four times more costly for multiplication. -You can construct a U128 from its limbs: -```rust -fn main(x: u64, y: u64) { - let x = U128::from_u64s_be(x,y); - assert(z.hi == x as Field); - assert(z.lo == y as Field); -} -``` - -Note that the limbs are stored as Field elements in order to avoid unnecessary conversions. -Apart from this, most operations will work as usual: - -```rust -fn main(x: U128, y: U128) { - // multiplication - let c = x * y; - // addition and subtraction - let c = c - x + y; - // division - let c = x / y; - // bit operation; - let c = x & y | y; - // bit shift - let c = x << y; - // comparisons; - let c = x < y; - let c = x == y; -} -``` - -## Overflows - -Computations that exceed the type boundaries will result in overflow errors. This happens with both signed and unsigned integers. For example, attempting to prove: - -```rust -fn main(x: u8, y: u8) { - let z = x + y; -} -``` - -With: - -```toml -x = "255" -y = "1" -``` - -Would result in: - -``` -$ nargo prove -error: Assertion failed: 'attempt to add with overflow' -┌─ ~/src/main.nr:9:13 -│ -│ let z = x + y; -│ ----- -│ -= Call stack: - ... -``` - -A similar error would happen with signed integers: - -```rust -fn main() { - let x: i8 = -118; - let y: i8 = -11; - let z = x + y; -} -``` - -### Wrapping methods - -Although integer overflow is expected to error, some use-cases rely on wrapping. For these use-cases, the standard library provides `wrapping` variants of certain common operations: - -```rust -fn wrapping_add(x: T, y: T) -> T; -fn wrapping_sub(x: T, y: T) -> T; -fn wrapping_mul(x: T, y: T) -> T; -``` - -Example of how it is used: - -```rust -use dep::std; - -fn main(x: u8, y: u8) -> pub u8 { - std::wrapping_add(x, y) -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/references.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/references.md deleted file mode 100644 index a5293d11cfb..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/references.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: References -sidebar_position: 9 ---- - -Noir supports first-class references. References are a bit like pointers: they point to a specific address that can be followed to access the data stored at that address. You can use Rust-like syntax to use pointers in Noir: the `&` operator references the variable, the `*` operator dereferences it. - -Example: - -```rust -fn main() { - let mut x = 2; - - // you can reference x as &mut and pass it to multiplyBy2 - multiplyBy2(&mut x); -} - -// you can access &mut here -fn multiplyBy2(x: &mut Field) { - // and dereference it with * - *x = *x * 2; -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/slices.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/slices.mdx deleted file mode 100644 index 4eccc677b80..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/slices.mdx +++ /dev/null @@ -1,195 +0,0 @@ ---- -title: Slices -description: Explore the Slice data type in Noir. Understand its methods, see real-world examples, and learn how to effectively use Slices in your Noir programs. -keywords: [noir, slice type, methods, examples, subarrays] -sidebar_position: 5 ---- - -import Experimental from '@site/src/components/Notes/_experimental.mdx'; - - - -A slice is a dynamically-sized view into a sequence of elements. They can be resized at runtime, but because they don't own the data, they cannot be returned from a circuit. You can treat slices as arrays without a constrained size. - -```rust -use dep::std::slice; - -fn main() -> pub Field { - let mut slice: [Field] = &[0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -To write a slice literal, use a preceeding ampersand as in: `&[0; 2]` or -`&[1, 2, 3]`. - -It is important to note that slices are not references to arrays. In Noir, -`&[..]` is more similar to an immutable, growable vector. - -View the corresponding test file [here][test-file]. - -[test-file]: https://github.com/noir-lang/noir/blob/f387ec1475129732f72ba294877efdf6857135ac/crates/nargo_cli/tests/test_data_ssa_refactor/slices/src/main.nr - -## Methods - -For convenience, the STD provides some ready-to-use, common methods for slices: - -### push_back - -Pushes a new element to the end of the slice, returning a new slice with a length one greater than the original unmodified slice. - -```rust -fn push_back(_self: [T], _elem: T) -> [T] -``` - -example: - -```rust -fn main() -> pub Field { - let mut slice: [Field] = &[0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -View the corresponding test file [here][test-file]. - -### push_front - -Returns a new array with the specified element inserted at index 0. The existing elements indexes are incremented by 1. - -```rust -fn push_front(_self: Self, _elem: T) -> Self -``` - -Example: - -```rust -let mut new_slice: [Field] = &[]; -new_slice = new_slice.push_front(20); -assert(new_slice[0] == 20); // returns true -``` - -View the corresponding test file [here][test-file]. - -### pop_front - -Returns a tuple of two items, the first element of the array and the rest of the array. - -```rust -fn pop_front(_self: Self) -> (T, Self) -``` - -Example: - -```rust -let (first_elem, rest_of_slice) = slice.pop_front(); -``` - -View the corresponding test file [here][test-file]. - -### pop_back - -Returns a tuple of two items, the beginning of the array with the last element omitted and the last element. - -```rust -fn pop_back(_self: Self) -> (Self, T) -``` - -Example: - -```rust -let (popped_slice, last_elem) = slice.pop_back(); -``` - -View the corresponding test file [here][test-file]. - -### append - -Loops over a slice and adds it to the end of another. - -```rust -fn append(mut self, other: Self) -> Self -``` - -Example: - -```rust -let append = &[1, 2].append(&[3, 4, 5]); -``` - -### insert - -Inserts an element at a specified index and shifts all following elements by 1. - -```rust -fn insert(_self: Self, _index: Field, _elem: T) -> Self -``` - -Example: - -```rust -new_slice = rest_of_slice.insert(2, 100); -assert(new_slice[2] == 100); -``` - -View the corresponding test file [here][test-file]. - -### remove - -Remove an element at a specified index, shifting all elements after it to the left, returning the altered slice and the removed element. - -```rust -fn remove(_self: Self, _index: Field) -> (Self, T) -``` - -Example: - -```rust -let (remove_slice, removed_elem) = slice.remove(3); -``` - -### len - -Returns the length of a slice - -```rust -fn len(self) -> Field -``` - -Example: - -```rust -fn main() { - let slice = &[42, 42]; - assert(slice.len() == 2); -} -``` - -### as_array - -Converts this slice into an array. - -Make sure to specify the size of the resulting array. -Panics if the resulting array length is different than the slice's length. - -```rust -fn as_array(self) -> [T; N] -``` - -Example: - -```rust -fn main() { - let slice = &[5, 6]; - - // Always specify the length of the resulting array! - let array: [Field; 2] = slice.as_array(); - - assert(array[0] == slice[0]); - assert(array[1] == slice[1]); -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/strings.md deleted file mode 100644 index 8ab5825a4c4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/strings.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: Strings -description: - Discover the String data type in Noir. Learn about its methods, see real-world examples, and understand how to effectively manipulate and use Strings in Noir. -keywords: - [ - noir, - string type, - methods, - examples, - concatenation, - ] -sidebar_position: 3 ---- - - -The string type is a fixed length value defined with `str`. - -You can use strings in `assert()` functions or print them with -`println()`. See more about [Logging](../../standard_library/logging.md). - -```rust -use dep::std; - -fn main(message : pub str<11>, hex_as_string : str<4>) { - println(message); - assert(message == "hello world"); - assert(hex_as_string == "0x41"); -} -``` - -You can convert a `str` to a byte array by calling `as_bytes()` -or a vector by calling `as_bytes_vec()`. - -```rust -fn main() { - let message = "hello world"; - let message_bytes = message.as_bytes(); - let mut message_vec = message.as_bytes_vec(); - assert(message_bytes.len() == 11); - assert(message_bytes[0] == 104); - assert(message_bytes[0] == message_vec.get(0)); -} -``` - -## Escape characters - -You can use escape characters for your strings: - -| Escape Sequence | Description | -|-----------------|-----------------| -| `\r` | Carriage Return | -| `\n` | Newline | -| `\t` | Tab | -| `\0` | Null Character | -| `\"` | Double Quote | -| `\\` | Backslash | - -Example: - -```rust -let s = "Hello \"world" // prints "Hello "world" -let s = "hey \tyou"; // prints "hey you" -``` - -## Raw strings - -A raw string begins with the letter `r` and is optionally delimited by a number of hashes `#`. - -Escape characters are *not* processed within raw strings. All contents are interpreted literally. - -Example: - -```rust -let s = r"Hello world"; -let s = r#"Simon says "hello world""#; - -// Any number of hashes may be used (>= 1) as long as the string also terminates with the same number of hashes -let s = r#####"One "#, Two "##, Three "###, Four "####, Five will end the string."#####; -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/structs.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/structs.md deleted file mode 100644 index dbf68c99813..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/structs.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -title: Structs -description: - Explore the Struct data type in Noir. Learn about its methods, see real-world examples, and grasp how to effectively define and use Structs in your Noir programs. -keywords: - [ - noir, - struct type, - methods, - examples, - data structures, - ] -sidebar_position: 8 ---- - -A struct also allows for grouping multiple values of different types. Unlike tuples, we can also -name each field. - -> **Note:** The usage of _field_ here refers to each element of the struct and is unrelated to the -> field type of Noir. - -Defining a struct requires giving it a name and listing each field within as `: ` pairs: - -```rust -struct Animal { - hands: Field, - legs: Field, - eyes: u8, -} -``` - -An instance of a struct can then be created with actual values in `: ` pairs in any -order. Struct fields are accessible using their given names: - -```rust -fn main() { - let legs = 4; - - let dog = Animal { - eyes: 2, - hands: 0, - legs, - }; - - let zero = dog.hands; -} -``` - -Structs can also be destructured in a pattern, binding each field to a new variable: - -```rust -fn main() { - let Animal { hands, legs: feet, eyes } = get_octopus(); - - let ten = hands + feet + eyes as u8; -} - -fn get_octopus() -> Animal { - let octopus = Animal { - hands: 0, - legs: 8, - eyes: 2, - }; - - octopus -} -``` - -The new variables can be bound with names different from the original struct field names, as -showcased in the `legs --> feet` binding in the example above. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/tuples.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/tuples.md deleted file mode 100644 index 2ec5c9c4113..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/tuples.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Tuples -description: - Dive into the Tuple data type in Noir. Understand its methods, practical examples, and best practices for efficiently using Tuples in your Noir code. -keywords: - [ - noir, - tuple type, - methods, - examples, - multi-value containers, - ] -sidebar_position: 7 ---- - -A tuple collects multiple values like an array, but with the added ability to collect values of -different types: - -```rust -fn main() { - let tup: (u8, u64, Field) = (255, 500, 1000); -} -``` - -One way to access tuple elements is via destructuring using pattern matching: - -```rust -fn main() { - let tup = (1, 2); - - let (one, two) = tup; - - let three = one + two; -} -``` - -Another way to access tuple elements is via direct member access, using a period (`.`) followed by -the index of the element we want to access. Index `0` corresponds to the first tuple element, `1` to -the second and so on: - -```rust -fn main() { - let tup = (5, 6, 7, 8); - - let five = tup.0; - let eight = tup.3; -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/functions.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/functions.md deleted file mode 100644 index f656cdfd97a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/functions.md +++ /dev/null @@ -1,226 +0,0 @@ ---- -title: Functions -description: - Learn how to declare functions and methods in Noir, a programming language with Rust semantics. - This guide covers parameter declaration, return types, call expressions, and more. -keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] -sidebar_position: 1 ---- - -Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. - -To declare a function the `fn` keyword is used. - -```rust -fn foo() {} -``` - -By default, functions are visible only within the package they are defined. To make them visible outside of that package (for example, as part of a [library](../modules_packages_crates/crates_and_packages.md#libraries)), you should mark them as `pub`: - -```rust -pub fn foo() {} -``` - -You can also restrict the visibility of the function to only the crate it was defined in, by specifying `pub(crate)`: - -```rust -pub(crate) fn foo() {} //foo can only be called within its crate -``` - -All parameters in a function must have a type and all types are known at compile time. The parameter -is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. - -```rust -fn foo(x : Field, y : Field){} -``` - -The return type of a function can be stated by using the `->` arrow notation. The function below -states that the foo function must return a `Field`. If the function returns no value, then the arrow -is omitted. - -```rust -fn foo(x : Field, y : Field) -> Field { - x + y -} -``` - -Note that a `return` keyword is unneeded in this case - the last expression in a function's body is -returned. - -## Main function - -If you're writing a binary, the `main` function is the starting point of your program. You can pass all types of expressions to it, as long as they have a fixed size at compile time: - -```rust -fn main(x : Field) // this is fine: passing a Field -fn main(x : [Field; 2]) // this is also fine: passing a Field with known size at compile-time -fn main(x : (Field, bool)) // 👌: passing a (Field, bool) tuple means size 2 -fn main(x : str<5>) // this is fine, as long as you pass a string of size 5 - -fn main(x : Vec) // can't compile, has variable size -fn main(x : [Field]) // can't compile, has variable size -fn main(....// i think you got it by now -``` - -Keep in mind [tests](../../tooling/testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: - -```rust -fn main(x : [Field]) { - assert(x[0] == 1); -} - -#[test] -fn test_one() { - main(&[1, 2]); -} -``` - -```bash -$ nargo test -[testing] Running 1 test functions -[testing] Testing test_one... ok -[testing] All tests passed - -$ nargo check -The application panicked (crashed). -Message: Cannot have variable sized arrays as a parameter to main -``` - -## Call Expressions - -Calling a function in Noir is executed by using the function name and passing in the necessary -arguments. - -Below we show how to call the `foo` function from the `main` function using a call expression: - -```rust -fn main(x : Field, y : Field) { - let z = foo(x); -} - -fn foo(x : Field) -> Field { - x + x -} -``` - -## Methods - -You can define methods in Noir on any struct type in scope. - -```rust -struct MyStruct { - foo: Field, - bar: Field, -} - -impl MyStruct { - fn new(foo: Field) -> MyStruct { - MyStruct { - foo, - bar: 2, - } - } - - fn sum(self) -> Field { - self.foo + self.bar - } -} - -fn main() { - let s = MyStruct::new(40); - assert(s.sum() == 42); -} -``` - -Methods are just syntactic sugar for functions, so if we wanted to we could also call `sum` as -follows: - -```rust -assert(MyStruct::sum(s) == 42); -``` - -It is also possible to specialize which method is chosen depending on the [generic](./generics.md) type that is used. In this example, the `foo` function returns different values depending on its type: - -```rust -struct Foo {} - -impl Foo { - fn foo(self) -> Field { 1 } -} - -impl Foo { - fn foo(self) -> Field { 2 } -} - -fn main() { - let f1: Foo = Foo{}; - let f2: Foo = Foo{}; - assert(f1.foo() + f2.foo() == 3); -} -``` - -Also note that impls with the same method name defined in them cannot overlap. For example, if we already have `foo` defined for `Foo` and `Foo` like we do above, we cannot also define `foo` in an `impl Foo` since it would be ambiguous which version of `foo` to choose. - -```rust -// Including this impl in the same project as the above snippet would -// cause an overlapping impls error -impl Foo { - fn foo(self) -> Field { 3 } -} -``` - -## Lambdas - -Lambdas are anonymous functions. They follow the syntax of Rust - `|arg1, arg2, ..., argN| return_expression`. - -```rust -let add_50 = |val| val + 50; -assert(add_50(100) == 150); -``` - -See [Lambdas](./lambdas.md) for more details. - -## Attributes - -Attributes are metadata that can be applied to a function, using the following syntax: `#[attribute(value)]`. - -Supported attributes include: - -- **builtin**: the function is implemented by the compiler, for efficiency purposes. -- **deprecated**: mark the function as _deprecated_. Calling the function will generate a warning: `warning: use of deprecated function` -- **field**: Used to enable conditional compilation of code depending on the field size. See below for more details -- **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./unconstrained.md) and [NoirJS](../../reference/NoirJS/noir_js/index.md) for more details. -- **test**: mark the function as unit tests. See [Tests](../../tooling/testing.md) for more details - -### Field Attribute - -The field attribute defines which field the function is compatible for. The function is conditionally compiled, under the condition that the field attribute matches the Noir native field. -The field can be defined implicitly, by using the name of the elliptic curve usually associated to it - for instance bn254, bls12_381 - or explicitly by using the field (prime) order, in decimal or hexadecimal form. -As a result, it is possible to define multiple versions of a function with each version specialized for a different field attribute. This can be useful when a function requires different parameters depending on the underlying elliptic curve. - -Example: we define the function `foo()` three times below. Once for the default Noir bn254 curve, once for the field $\mathbb F_{23}$, which will normally never be used by Noir, and once again for the bls12_381 curve. - -```rust -#[field(bn254)] -fn foo() -> u32 { - 1 -} - -#[field(23)] -fn foo() -> u32 { - 2 -} - -// This commented code would not compile as foo would be defined twice because it is the same field as bn254 -// #[field(21888242871839275222246405745257275088548364400416034343698204186575808495617)] -// fn foo() -> u32 { -// 2 -// } - -#[field(bls12_381)] -fn foo() -> u32 { - 3 -} -``` - -If the field name is not known to Noir, it will discard the function. Field names are case insensitive. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/generics.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/generics.md deleted file mode 100644 index 0c1c27a2221..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/generics.md +++ /dev/null @@ -1,106 +0,0 @@ ---- -title: Generics -description: Learn how to use Generics in Noir -keywords: [Noir, Rust, generics, functions, structs] -sidebar_position: 7 ---- - -Generics allow you to use the same functions with multiple different concrete data types. You can -read more about the concept of generics in the Rust documentation -[here](https://doc.rust-lang.org/book/ch10-01-syntax.html). - -Here is a trivial example showing the identity function that supports any type. In Rust, it is -common to refer to the most general type as `T`. We follow the same convention in Noir. - -```rust -fn id(x: T) -> T { - x -} -``` - -## In Structs - -Generics are useful for specifying types in structs. For example, we can specify that a field in a -struct will be of a certain generic type. In this case `value` is of type `T`. - -```rust -struct RepeatedValue { - value: T, - count: Field, -} - -impl RepeatedValue { - fn print(self) { - for _i in 0 .. self.count { - println(self.value); - } - } -} - -fn main() { - let repeated = RepeatedValue { value: "Hello!", count: 2 }; - repeated.print(); -} -``` - -The `print` function will print `Hello!` an arbitrary number of times, twice in this case. - -If we want to be generic over array lengths (which are type-level integers), we can use numeric -generics. Using these looks just like using regular generics, but these generics can resolve to -integers at compile-time, rather than resolving to types. Here's an example of a struct that is -generic over the size of the array it contains internally: - -```rust -struct BigInt { - limbs: [u32; N], -} - -impl BigInt { - // `N` is in scope of all methods in the impl - fn first(first: BigInt, second: BigInt) -> Self { - assert(first.limbs != second.limbs); - first - - fn second(first: BigInt, second: Self) -> Self { - assert(first.limbs != second.limbs); - second - } -} -``` - -## Calling functions on generic parameters - -Since a generic type `T` can represent any type, how can we call functions on the underlying type? -In other words, how can we go from "any type `T`" to "any type `T` that has certain methods available?" - -This is what [traits](../concepts/traits.md) are for in Noir. Here's an example of a function generic over -any type `T` that implements the `Eq` trait for equality: - -```rust -fn first_element_is_equal(array1: [T; N], array2: [T; N]) -> bool - where T: Eq -{ - if (array1.len() == 0) | (array2.len() == 0) { - true - } else { - array1[0] == array2[0] - } -} - -fn main() { - assert(first_element_is_equal([1, 2, 3], [1, 5, 6])); - - // We can use first_element_is_equal for arrays of any type - // as long as we have an Eq impl for the types we pass in - let array = [MyStruct::new(), MyStruct::new()]; - assert(array_eq(array, array, MyStruct::eq)); -} - -impl Eq for MyStruct { - fn eq(self, other: MyStruct) -> bool { - self.foo == other.foo - } -} -``` - -You can find more details on traits and trait implementations on the [traits page](../concepts/traits.md). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/globals.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/globals.md deleted file mode 100644 index 063a3d89248..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/globals.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -title: Global Variables -description: - Learn about global variables in Noir. Discover how - to declare, modify, and use them in your programs. -keywords: [noir programming language, globals, global variables, constants] -sidebar_position: 8 ---- - -## Globals - - -Noir supports global variables. The global's type can be inferred by the compiler entirely: - -```rust -global N = 5; // Same as `global N: Field = 5` - -global TUPLE = (3, 2); - -fn main() { - assert(N == 5); - assert(N == TUPLE.0 + TUPLE.1); -} -``` - -:::info - -Globals can be defined as any expression, so long as they don't depend on themselves - otherwise there would be a dependency cycle! For example: - -```rust -global T = foo(T); // dependency error -``` - -::: - - -If they are initialized to a literal integer, globals can be used to specify an array's length: - -```rust -global N: Field = 2; - -fn main(y : [Field; N]) { - assert(y[0] == y[1]) -} -``` - -A global from another module can be imported or referenced externally like any other name: - -```rust -global N = 20; - -fn main() { - assert(my_submodule::N != N); -} - -mod my_submodule { - global N: Field = 10; -} -``` - -When a global is used, Noir replaces the name with its definition on each occurrence. -This means globals defined using function calls will repeat the call each time they're used: - -```rust -global RESULT = foo(); - -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. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/lambdas.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/lambdas.md deleted file mode 100644 index be3c7e0b5ca..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/lambdas.md +++ /dev/null @@ -1,81 +0,0 @@ ---- -title: Lambdas -description: Learn how to use anonymous functions in Noir programming language. -keywords: [Noir programming language, lambda, closure, function, anonymous function] -sidebar_position: 9 ---- - -## Introduction - -Lambdas are anonymous functions. The syntax is `|arg1, arg2, ..., argN| return_expression`. - -```rust -let add_50 = |val| val + 50; -assert(add_50(100) == 150); -``` - -A block can be used as the body of a lambda, allowing you to declare local variables inside it: - -```rust -let cool = || { - let x = 100; - let y = 100; - x + y -} - -assert(cool() == 200); -``` - -## Closures - -Inside the body of a lambda, you can use variables defined in the enclosing function. Such lambdas are called **closures**. In this example `x` is defined inside `main` and is accessed from within the lambda: - -```rust -fn main() { - let x = 100; - let closure = || x + 150; - assert(closure() == 250); -} -``` - -## Passing closures to higher-order functions - -It may catch you by surprise that the following code fails to compile: - -```rust -fn foo(f: fn () -> Field) -> Field { - f() -} - -fn main() { - let (x, y) = (50, 50); - assert(foo(|| x + y) == 100); // error :( -} -``` - -The reason is that the closure's capture environment affects its type - we have a closure that captures two Fields and `foo` -expects a regular function as an argument - those are incompatible. -:::note - -Variables contained within the `||` are the closure's parameters, and the expression that follows it is the closure's body. The capture environment is comprised of any variables used in the closure's body that are not parameters. - -E.g. in |x| x + y, y would be a captured variable, but x would not be, since it is a parameter of the closure. - -::: -The syntax for the type of a closure is `fn[env](args) -> ret_type`, where `env` is the capture environment of the closure - -in this example that's `(Field, Field)`. - -The best solution in our case is to make `foo` generic over the environment type of its parameter, so that it can be called -with closures with any environment, as well as with regular functions: - -```rust -fn foo(f: fn[Env]() -> Field) -> Field { - f() -} - -fn main() { - let (x, y) = (50, 50); - assert(foo(|| x + y) == 100); // compiles fine - assert(foo(|| 60) == 60); // compiles fine -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/mutability.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/mutability.md deleted file mode 100644 index fdeef6a87c5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/mutability.md +++ /dev/null @@ -1,121 +0,0 @@ ---- -title: Mutability -description: - Learn about mutable variables in Noir. Discover how - to declare, modify, and use them in your programs. -keywords: [noir programming language, mutability in noir, mutable variables] -sidebar_position: 8 ---- - -Variables in noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned -to via an assignment expression. - -```rust -let x = 2; -x = 3; // error: x must be mutable to be assigned to - -let mut y = 3; -let y = 4; // OK -``` - -The `mut` modifier can also apply to patterns: - -```rust -let (a, mut b) = (1, 2); -a = 11; // error: a must be mutable to be assigned to -b = 12; // OK - -let mut (c, d) = (3, 4); -c = 13; // OK -d = 14; // OK - -// etc. -let MyStruct { x: mut y } = MyStruct { x: a }; -// y is now in scope -``` - -Note that mutability in noir is local and everything is passed by value, so if a called function -mutates its parameters then the parent function will keep the old value of the parameters. - -```rust -fn main() -> pub Field { - let x = 3; - helper(x); - x // x is still 3 -} - -fn helper(mut x: i32) { - x = 4; -} -``` - -## Non-local mutability - -Non-local mutability can be achieved through the mutable reference type `&mut T`: - -```rust -fn set_to_zero(x: &mut Field) { - *x = 0; -} - -fn main() { - let mut y = 42; - set_to_zero(&mut y); - assert(*y == 0); -} -``` - -When creating a mutable reference, the original variable being referred to (`y` in this -example) must also be mutable. Since mutable references are a reference type, they must -be explicitly dereferenced via `*` to retrieve the underlying value. Note that this yields -a copy of the value, so mutating this copy will not change the original value behind the -reference: - -```rust -fn main() { - let mut x = 1; - let x_ref = &mut x; - - let mut y = *x_ref; - let y_ref = &mut y; - - x = 2; - *x_ref = 3; - - y = 4; - *y_ref = 5; - - assert(x == 3); - assert(*x_ref == 3); - assert(y == 5); - assert(*y_ref == 5); -} -``` - -Note that types in Noir are actually deeply immutable so the copy that occurs when -dereferencing is only a conceptual copy - no additional constraints will occur. - -Mutable references can also be stored within structs. Note that there is also -no lifetime parameter on these unlike rust. This is because the allocated memory -always lasts the entire program - as if it were an array of one element. - -```rust -struct Foo { - x: &mut Field -} - -impl Foo { - fn incr(mut self) { - *self.x += 1; - } -} - -fn main() { - let foo = Foo { x: &mut 0 }; - foo.incr(); - assert(*foo.x == 1); -} -``` - -In general, you should avoid non-local & shared mutability unless it is needed. Sticking -to only local mutability will improve readability and potentially improve compiler optimizations as well. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/ops.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/ops.md deleted file mode 100644 index c35c36c38a9..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/ops.md +++ /dev/null @@ -1,98 +0,0 @@ ---- -title: Logical Operations -description: - Learn about the supported arithmetic and logical operations in the Noir programming language. - Discover how to perform operations on private input types, integers, and booleans. -keywords: - [ - Noir programming language, - supported operations, - arithmetic operations, - logical operations, - predicate operators, - bitwise operations, - short-circuiting, - backend, - ] -sidebar_position: 3 ---- - -# Operations - -## Table of Supported Operations - -| Operation | Description | Requirements | -| :-------- | :------------------------------------------------------------: | -------------------------------------: | -| + | Adds two private input types together | Types must be private input | -| - | Subtracts two private input types together | Types must be private input | -| \* | Multiplies two private input types together | Types must be private input | -| / | Divides two private input types together | Types must be private input | -| ^ | XOR two private input types together | Types must be integer | -| & | AND two private input types together | Types must be integer | -| \| | OR two private input types together | Types must be integer | -| \<\< | Left shift an integer by another integer amount | Types must be integer, shift must be u8 | -| >> | Right shift an integer by another integer amount | Types must be integer, shift must be u8 | -| ! | Bitwise not of a value | Type must be integer or boolean | -| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | -| > | returns a bool if one value is more than the other | Upper bound must have a known bit size | -| >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | -| == | returns a bool if one value is equal to the other | Both types must not be constants | -| != | returns a bool if one value is not equal to the other | Both types must not be constants | - -### Predicate Operators - -`<,<=, !=, == , >, >=` are known as predicate/comparison operations because they compare two values. -This differs from the operations such as `+` where the operands are used in _computation_. - -### Bitwise Operations Example - -```rust -fn main(x : Field) { - let y = x as u32; - let z = y & y; -} -``` - -`z` is implicitly constrained to be the result of `y & y`. The `&` operand is used to denote bitwise -`&`. - -> `x & x` would not compile as `x` is a `Field` and not an integer type. - -### Logical Operators - -Noir has no support for the logical operators `||` and `&&`. This is because encoding the -short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can -use the bitwise operators `|` and `&` which operate identically for booleans, just without the -short-circuiting. - -```rust -let my_val = 5; - -let mut flag = 1; -if (my_val > 6) | (my_val == 0) { - flag = 0; -} -assert(flag == 1); - -if (my_val != 10) & (my_val < 50) { - flag = 0; -} -assert(flag == 0); -``` - -### Shorthand operators - -Noir shorthand operators for most of the above operators, namely `+=, -=, *=, /=, %=, &=, |=, ^=, <<=`, and `>>=`. These allow for more concise syntax. For example: - -```rust -let mut i = 0; -i = i + 1; -``` - -could be written as: - -```rust -let mut i = 0; -i += 1; -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/oracles.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/oracles.md deleted file mode 100644 index aa380b5f7b8..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/oracles.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Oracles -description: Dive into how Noir supports Oracles via RPC calls, and learn how to declare an Oracle in Noir with our comprehensive guide. -keywords: - - Noir - - Oracles - - RPC Calls - - Unconstrained Functions - - Programming - - Blockchain -sidebar_position: 6 ---- - -:::note - -This is an experimental feature that is not fully documented. If you notice any outdated information or potential improvements to this page, pull request contributions are very welcome: https://github.com/noir-lang/noir - -::: - -Noir has support for Oracles via RPC calls. This means Noir will make an RPC call and use the return value for proof generation. - -Since Oracles are not resolved by Noir, they are [`unconstrained` functions](./unconstrained.md) - -You can declare an Oracle through the `#[oracle()]` flag. Example: - -```rust -#[oracle(get_number_sequence)] -unconstrained fn get_number_sequence(_size: Field) -> [Field] {} -``` - -The timeout for when using an external RPC oracle resolver can be set with the `NARGO_FOREIGN_CALL_TIMEOUT` environment variable. This timeout is in units of milliseconds. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/shadowing.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/shadowing.md deleted file mode 100644 index 5ce6130d201..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/shadowing.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Shadowing -sidebar_position: 12 ---- - -Noir allows for inheriting variables' values and re-declaring them with the same name similar to Rust, known as shadowing. - -For example, the following function is valid in Noir: - -```rust -fn main() { - let x = 5; - - { - let x = x * 2; - assert (x == 10); - } - - assert (x == 5); -} -``` - -In this example, a variable x is first defined with the value 5. - -The local scope that follows shadows the original x, i.e. creates a local mutable x based on the value of the original x. It is given a value of 2 times the original x. - -When we return to the main scope, x once again refers to just the original x, which stays at the value of 5. - -## Temporal mutability - -One way that shadowing is useful, in addition to ergonomics across scopes, is for temporarily mutating variables. - -```rust -fn main() { - let age = 30; - // age = age + 5; // Would error as `age` is immutable by default. - - let mut age = age + 5; // Temporarily mutates `age` with a new value. - - let age = age; // Locks `age`'s mutability again. - - assert (age == 35); -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/traits.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/traits.md deleted file mode 100644 index ef1445a5907..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/traits.md +++ /dev/null @@ -1,389 +0,0 @@ ---- -title: Traits -description: - Traits in Noir can be used to abstract out a common interface for functions across - several data types. -keywords: [noir programming language, traits, interfaces, generic, protocol] -sidebar_position: 14 ---- - -## Overview - -Traits in Noir are a useful abstraction similar to interfaces or protocols in other languages. Each trait defines -the interface of several methods contained within the trait. Types can then implement this trait by providing -implementations for these methods. For example in the program: - -```rust -struct Rectangle { - width: Field, - height: Field, -} - -impl Rectangle { - fn area(self) -> Field { - self.width * self.height - } -} - -fn log_area(r: Rectangle) { - println(r.area()); -} -``` - -We have a function `log_area` to log the area of a `Rectangle`. Now how should we change the program if we want this -function to work on `Triangle`s as well?: - -```rust -struct Triangle { - width: Field, - height: Field, -} - -impl Triangle { - fn area(self) -> Field { - self.width * self.height / 2 - } -} -``` - -Making `log_area` generic over all types `T` would be invalid since not all types have an `area` method. Instead, we can -introduce a new `Area` trait and make `log_area` generic over all types `T` that implement `Area`: - -```rust -trait Area { - fn area(self) -> Field; -} - -fn log_area(shape: T) where T: Area { - println(shape.area()); -} -``` - -We also need to explicitly implement `Area` for `Rectangle` and `Triangle`. We can do that by changing their existing -impls slightly. Note that the parameter types and return type of each of our `area` methods must match those defined -by the `Area` trait. - -```rust -impl Area for Rectangle { - fn area(self) -> Field { - self.width * self.height - } -} - -impl Area for Triangle { - fn area(self) -> Field { - self.width * self.height / 2 - } -} -``` - -Now we have a working program that is generic over any type of Shape that is used! Others can even use this program -as a library with their own types - such as `Circle` - as long as they also implement `Area` for these types. - -## Where Clauses - -As seen in `log_area` above, when we want to create a function or method that is generic over any type that implements -a trait, we can add a where clause to the generic function. - -```rust -fn log_area(shape: T) where T: Area { - println(shape.area()); -} -``` - -It is also possible to apply multiple trait constraints on the same variable at once by combining traits with the `+` -operator. Similarly, we can have multiple trait constraints by separating each with a comma: - -```rust -fn foo(elements: [T], thing: U) where - T: Default + Add + Eq, - U: Bar, -{ - let mut sum = T::default(); - - for element in elements { - sum += element; - } - - if sum == T::default() { - thing.bar(); - } -} -``` - -## Generic Implementations - -You can add generics to a trait implementation by adding the generic list after the `impl` keyword: - -```rust -trait Second { - fn second(self) -> Field; -} - -impl Second for (T, Field) { - fn second(self) -> Field { - self.1 - } -} -``` - -You can also implement a trait for every type this way: - -```rust -trait Debug { - fn debug(self); -} - -impl Debug for T { - fn debug(self) { - println(self); - } -} - -fn main() { - 1.debug(); -} -``` - -### Generic Trait Implementations With Where Clauses - -Where clauses can also be placed on trait implementations themselves to restrict generics in a similar way. -For example, while `impl Foo for T` implements the trait `Foo` for every type, `impl Foo for T where T: Bar` -will implement `Foo` only for types that also implement `Bar`. This is often used for implementing generic types. -For example, here is the implementation for array equality: - -```rust -impl Eq for [T; N] where T: Eq { - // Test if two arrays have the same elements. - // Because both arrays must have length N, we know their lengths already match. - fn eq(self, other: Self) -> bool { - let mut result = true; - - for i in 0 .. self.len() { - // The T: Eq constraint is needed to call == on the array elements here - result &= self[i] == other[i]; - } - - result - } -} -``` - -## Generic Traits - -Traits themselves can also be generic by placing the generic arguments after the trait name. These generics are in -scope of every item within the trait. - -```rust -trait Into { - // Convert `self` to type `T` - fn into(self) -> T; -} -``` - -When implementing generic traits the generic arguments of the trait must be specified. This is also true anytime -when referencing a generic trait (e.g. in a `where` clause). - -```rust -struct MyStruct { - array: [Field; 2], -} - -impl Into<[Field; 2]> for MyStruct { - fn into(self) -> [Field; 2] { - self.array - } -} - -fn as_array(x: T) -> [Field; 2] - where T: Into<[Field; 2]> -{ - x.into() -} - -fn main() { - let array = [1, 2]; - let my_struct = MyStruct { array }; - - assert_eq(as_array(my_struct), array); -} -``` - -## Trait Methods With No `self` - -A trait can contain any number of methods, each of which have access to the `Self` type which represents each type -that eventually implements the trait. Similarly, the `self` variable is available as well but is not required to be used. -For example, we can define a trait to create a default value for a type. This trait will need to return the `Self` type -but doesn't need to take any parameters: - -```rust -trait Default { - fn default() -> Self; -} -``` - -Implementing this trait can be done similarly to any other trait: - -```rust -impl Default for Field { - fn default() -> Field { - 0 - } -} - -struct MyType {} - -impl Default for MyType { - fn default() -> Field { - MyType {} - } -} -``` - -However, since there is no `self` parameter, we cannot call it via the method call syntax `object.method()`. -Instead, we'll need to refer to the function directly. This can be done either by referring to the -specific impl `MyType::default()` or referring to the trait itself `Default::default()`. In the later -case, type inference determines the impl that is selected. - -```rust -let my_struct = MyStruct::default(); - -let x: Field = Default::default(); -let result = x + Default::default(); -``` - -:::warning - -```rust -let _ = Default::default(); -``` - -If type inference cannot select which impl to use because of an ambiguous `Self` type, an impl will be -arbitrarily selected. This occurs most often when the result of a trait function call with no parameters -is unused. To avoid this, when calling a trait function with no `self` or `Self` parameters or return type, -always refer to it via the implementation type's namespace - e.g. `MyType::default()`. -This is set to change to an error in future Noir versions. - -::: - -## Default Method Implementations - -A trait can also have default implementations of its methods by giving a body to the desired functions. -Note that this body must be valid for all types that may implement the trait. As a result, the only -valid operations on `self` will be operations valid for any type or other operations on the trait itself. - -```rust -trait Numeric { - fn add(self, other: Self) -> Self; - - // Default implementation of double is (self + self) - fn double(self) -> Self { - self.add(self) - } -} -``` - -When implementing a trait with default functions, a type may choose to implement only the required functions: - -```rust -impl Numeric for Field { - fn add(self, other: Field) -> Field { - self + other - } -} -``` - -Or it may implement the optional methods as well: - -```rust -impl Numeric for u32 { - fn add(self, other: u32) -> u32 { - self + other - } - - fn double(self) -> u32 { - self * 2 - } -} -``` - -## Impl Specialization - -When implementing traits for a generic type it is possible to implement the trait for only a certain combination -of generics. This can be either as an optimization or because those specific generics are required to implement the trait. - -```rust -trait Sub { - fn sub(self, other: Self) -> Self; -} - -struct NonZero { - value: T, -} - -impl Sub for NonZero { - fn sub(self, other: Self) -> Self { - let value = self.value - other.value; - assert(value != 0); - NonZero { value } - } -} -``` - -## Overlapping Implementations - -Overlapping implementations are disallowed by Noir to ensure Noir's decision on which impl to select is never ambiguous. -This means if a trait `Foo` is already implemented -by a type `Bar` for all `T`, then we cannot also have a separate impl for `Bar` (or any other -type argument). Similarly, if there is an impl for all `T` such as `impl Debug for T`, we cannot create -any more impls to `Debug` for other types since it would be ambiguous which impl to choose for any given -method call. - -```rust -trait Trait {} - -// Previous impl defined here -impl Trait for (A, B) {} - -// error: Impl for type `(Field, Field)` overlaps with existing impl -impl Trait for (Field, Field) {} -``` - -## Trait Coherence - -Another restriction on trait implementations is coherence. This restriction ensures other crates cannot create -impls that may overlap with other impls, even if several unrelated crates are used as dependencies in the same -program. - -The coherence restriction is: to implement a trait, either the trait itself or the object type must be declared -in the crate the impl is in. - -In practice this often comes up when using types provided by libraries. If a library provides a type `Foo` that does -not implement a trait in the standard library such as `Default`, you may not `impl Default for Foo` in your own crate. -While restrictive, this prevents later issues or silent changes in the program if the `Foo` library later added its -own impl for `Default`. If you are a user of the `Foo` library in this scenario and need a trait not implemented by the -library your choices are to either submit a patch to the library or use the newtype pattern. - -### The Newtype Pattern - -The newtype pattern gets around the coherence restriction by creating a new wrapper type around the library type -that we cannot create `impl`s for. Since the new wrapper type is defined in our current crate, we can create -impls for any trait we need on it. - -```rust -struct Wrapper { - foo: dep::some_library::Foo, -} - -impl Default for Wrapper { - fn default() -> Wrapper { - Wrapper { - foo: dep::some_library::Foo::new(), - } - } -} -``` - -Since we have an impl for our own type, the behavior of this code will not change even if `some_library` is updated -to provide its own `impl Default for Foo`. The downside of this pattern is that it requires extra wrapping and -unwrapping of values when converting to and from the `Wrapper` and `Foo` types. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/unconstrained.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/unconstrained.md deleted file mode 100644 index 96f824c5e42..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/unconstrained.md +++ /dev/null @@ -1,99 +0,0 @@ ---- -title: Unconstrained Functions -description: "Learn about what unconstrained functions in Noir are, how to use them and when you'd want to." - -keywords: [Noir programming language, unconstrained, open] -sidebar_position: 5 ---- - -Unconstrained functions are functions which do not constrain any of the included computation and allow for non-deterministic computation. - -## Why? - -Zero-knowledge (ZK) domain-specific languages (DSL) enable developers to generate ZK proofs from their programs by compiling code down to the constraints of an NP complete language (such as R1CS or PLONKish languages). However, the hard bounds of a constraint system can be very limiting to the functionality of a ZK DSL. - -Enabling a circuit language to perform unconstrained execution is a powerful tool. Said another way, unconstrained execution lets developers generate witnesses from code that does not generate any constraints. Being able to execute logic outside of a circuit is critical for both circuit performance and constructing proofs on information that is external to a circuit. - -Fetching information from somewhere external to a circuit can also be used to enable developers to improve circuit efficiency. - -A ZK DSL does not just prove computation, but proves that some computation was handled correctly. Thus, it is necessary that when we switch from performing some operation directly inside of a circuit to inside of an unconstrained environment that the appropriate constraints are still laid down elsewhere in the circuit. - -## Example - -An in depth example might help drive the point home. This example comes from the excellent [post](https://discord.com/channels/1113924620781883405/1124022445054111926/1128747641853972590) by Tom in the Noir Discord. - -Let's look at how we can optimize a function to turn a `u72` into an array of `u8`s. - -```rust -fn main(num: u72) -> pub [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8)) as u72 & 0xff) as u8; - } - - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 91 -Backend circuit size: 3619 -``` - -A lot of the operations in this function are optimized away by the compiler (all the bit-shifts turn into divisions by constants). However we can save a bunch of gates by casting to u8 a bit earlier. This automatically truncates the bit-shifted value to fit in a u8 which allows us to remove the AND against 0xff. This saves us ~480 gates in total. - -```rust -fn main(num: u72) -> pub [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8)) as u8; - } - - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 75 -Backend circuit size: 3143 -``` - -Those are some nice savings already but we can do better. This code is all constrained so we're proving every step of calculating out using num, but we don't actually care about how we calculate this, just that it's correct. This is where brillig comes in. - -It turns out that truncating a u72 into a u8 is hard to do inside a snark, each time we do as u8 we lay down 4 ACIR opcodes which get converted into multiple gates. It's actually much easier to calculate num from out than the other way around. All we need to do is multiply each element of out by a constant and add them all together, both relatively easy operations inside a snark. - -We can then run u72_to_u8 as unconstrained brillig code in order to calculate out, then use that result in our constrained function and assert that if we were to do the reverse calculation we'd get back num. This looks a little like the below: - -```rust -fn main(num: u72) -> pub [u8; 8] { - let out = u72_to_u8(num); - - let mut reconstructed_num: u72 = 0; - for i in 0..8 { - reconstructed_num += (out[i] as u72 << (56 - (8 * i))); - } - assert(num == reconstructed_num); - out -} - -unconstrained fn u72_to_u8(num: u72) -> [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8))) as u8; - } - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 78 -Backend circuit size: 2902 -``` - -This ends up taking off another ~250 gates from our circuit! We've ended up with more ACIR opcodes than before but they're easier for the backend to prove (resulting in fewer gates). - -Generally we want to use brillig whenever there's something that's easy to verify but hard to compute within the circuit. For example, if you wanted to calculate a square root of a number it'll be a much better idea to calculate this in brillig and then assert that if you square the result you get back your number. - -## Break and Continue - -In addition to loops over runtime bounds, `break` and `continue` are also available in unconstrained code. See [break and continue](../concepts/control_flow.md#break-and-continue) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/_category_.json deleted file mode 100644 index 1debcfe7675..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Modules, Packages and Crates", - "position": 2, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/crates_and_packages.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/crates_and_packages.md deleted file mode 100644 index 95ee9f52ab2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/crates_and_packages.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Crates and Packages -description: Learn how to use Crates and Packages in your Noir project -keywords: [Nargo, dependencies, package management, crates, package] -sidebar_position: 0 ---- - -## Crates - -A crate is the smallest amount of code that the Noir compiler considers at a time. -Crates can contain modules, and the modules may be defined in other files that get compiled with the crate, as we’ll see in the coming sections. - -### Crate Types - -A Noir crate can come in several forms: binaries, libraries or contracts. - -#### Binaries - -_Binary crates_ are programs which you can compile to an ACIR circuit which you can then create proofs against. Each must have a function called `main` that defines the ACIR circuit which is to be proved. - -#### Libraries - -_Library crates_ don't have a `main` function and they don't compile down to ACIR. Instead they define functionality intended to be shared with multiple projects, and eventually included in a binary crate. - -#### Contracts - -Contract crates are similar to binary crates in that they compile to ACIR which you can create proofs against. They are different in that they do not have a single `main` function, but are a collection of functions to be deployed to the [Aztec network](https://aztec.network). You can learn more about the technical details of Aztec in the [monorepo](https://github.com/AztecProtocol/aztec-packages) or contract [examples](https://github.com/AztecProtocol/aztec-packages/tree/master/noir-projects/noir-contracts/contracts). - -### Crate Root - -Every crate has a root, which is the source file that the compiler starts, this is also known as the root module. The Noir compiler does not enforce any conditions on the name of the file which is the crate root, however if you are compiling via Nargo the crate root must be called `lib.nr` or `main.nr` for library or binary crates respectively. - -## Packages - -A Nargo _package_ is a collection of one of more crates that provides a set of functionality. A package must include a Nargo.toml file. - -A package _must_ contain either a library or a binary crate, but not both. - -### Differences from Cargo Packages - -One notable difference between Rust's Cargo and Noir's Nargo is that while Cargo allows a package to contain an unlimited number of binary crates and a single library crate, Nargo currently only allows a package to contain a single crate. - -In future this restriction may be lifted to allow a Nargo package to contain both a binary and library crate or multiple binary crates. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/dependencies.md deleted file mode 100644 index 2c028d85853..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/dependencies.md +++ /dev/null @@ -1,124 +0,0 @@ ---- -title: Dependencies -description: - Learn how to specify and manage dependencies in Nargo, allowing you to upload packages to GitHub - and use them easily in your project. -keywords: [Nargo, dependencies, GitHub, package management, versioning] -sidebar_position: 1 ---- - -Nargo allows you to upload packages to GitHub and use them as dependencies. - -## Specifying a dependency - -Specifying a dependency requires a tag to a specific commit and the git url to the url containing -the package. - -Currently, there are no requirements on the tag contents. If requirements are added, it would follow -semver 2.0 guidelines. - -> Note: Without a `tag` , there would be no versioning and dependencies would change each time you -> compile your project. - -For example, to add the [ecrecover-noir library](https://github.com/colinnielsen/ecrecover-noir) to your project, add it to `Nargo.toml`: - -```toml -# Nargo.toml - -[dependencies] -ecrecover = {tag = "v0.8.0", git = "https://github.com/colinnielsen/ecrecover-noir"} -``` - -If the module is in a subdirectory, you can define a subdirectory in your git repository, for example: - -```toml -# Nargo.toml - -[dependencies] -easy_private_token_contract = {tag ="v0.1.0-alpha62", git = "https://github.com/AztecProtocol/aztec-packages", directory = "noir-contracts/contracts/easy_private_token_contract"} -``` - -## Specifying a local dependency - -You can also specify dependencies that are local to your machine. - -For example, this file structure has a library and binary crate - -```tree -├── binary_crate -│   ├── Nargo.toml -│   └── src -│   └── main.nr -└── lib_a - ├── Nargo.toml - └── src - └── lib.nr -``` - -Inside of the binary crate, you can specify: - -```toml -# Nargo.toml - -[dependencies] -lib_a = { path = "../lib_a" } -``` - -## Importing dependencies - -You can import a dependency to a Noir file using the following syntax. For example, to import the -ecrecover-noir library and local lib_a referenced above: - -```rust -use dep::ecrecover; -use dep::lib_a; -``` - -You can also import only the specific parts of dependency that you want to use, like so: - -```rust -use dep::std::hash::sha256; -use dep::std::scalar_mul::fixed_base_embedded_curve; -``` - -Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you -can import multiple items in the same line by enclosing them in curly braces: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; -``` - -We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. - -Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. - -## Dependencies of Dependencies - -Note that when you import a dependency, you also get access to all of the dependencies of that package. - -For example, the [phy_vector](https://github.com/resurgencelabs/phy_vector) library imports an [fraction](https://github.com/resurgencelabs/fraction) library. If you're importing the phy_vector library, then you can access the functions in fractions library like so: - -```rust -use dep::phy_vector; - -fn main(x : Field, y : pub Field) { - //... - let f = phy_vector::fraction::toFraction(true, 2, 1); - //... -} -``` - -## Available Libraries - -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). - -Some libraries that are available today include: - -- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library -- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) -- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers -- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address -- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees -- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir -- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/modules.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/modules.md deleted file mode 100644 index ae822a1cff4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/modules.md +++ /dev/null @@ -1,105 +0,0 @@ ---- -title: Modules -description: - Learn how to organize your files using modules in Noir, following the same convention as Rust's - module system. Examples included. -keywords: [Noir, Rust, modules, organizing files, sub-modules] -sidebar_position: 2 ---- - -Noir's module system follows the same convention as the _newer_ version of Rust's module system. - -## Purpose of Modules - -Modules are used to organize files. Without modules all of your code would need to live in a single -file. In Noir, the compiler does not automatically scan all of your files to detect modules. This -must be done explicitly by the developer. - -## Examples - -### Importing a module in the crate root - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::hello_world(); -} -``` - -Filename : `src/foo.nr` - -```rust -fn from_foo() {} -``` - -In the above snippet, the crate root is the `src/main.nr` file. The compiler sees the module -declaration `mod foo` which prompts it to look for a foo.nr file. - -Visually this module hierarchy looks like the following : - -``` -crate - ├── main - │ - └── foo - └── from_foo - -``` - -### Importing a module throughout the tree - -All modules are accessible from the `crate::` namespace. - -``` -crate - ├── bar - ├── foo - └── main - -``` - -In the above snippet, if `bar` would like to use functions in `foo`, it can do so by `use crate::foo::function_name`. - -### Sub-modules - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::from_foo(); -} -``` - -Filename : `src/foo.nr` - -```rust -mod bar; -fn from_foo() {} -``` - -Filename : `src/foo/bar.nr` - -```rust -fn from_bar() {} -``` - -In the above snippet, we have added an extra module to the module tree; `bar`. `bar` is a submodule -of `foo` hence we declare bar in `foo.nr` with `mod bar`. Since `foo` is not the crate root, the -compiler looks for the file associated with the `bar` module in `src/foo/bar.nr` - -Visually the module hierarchy looks as follows: - -``` -crate - ├── main - │ - └── foo - ├── from_foo - └── bar - └── from_bar -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/workspaces.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/workspaces.md deleted file mode 100644 index 513497f12bf..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/workspaces.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Workspaces -sidebar_position: 3 ---- - -Workspaces are a feature of nargo that allow you to manage multiple related Noir packages in a single repository. A workspace is essentially a group of related projects that share common build output directories and configurations. - -Each Noir project (with it's own Nargo.toml file) can be thought of as a package. Each package is expected to contain exactly one "named circuit", being the "name" defined in Nargo.toml with the program logic defined in `./src/main.nr`. - -For a project with the following structure: - -```tree -├── crates -│ ├── a -│ │ ├── Nargo.toml -│ │ └── Prover.toml -│ │ └── src -│ │ └── main.nr -│ └── b -│ ├── Nargo.toml -│ └── Prover.toml -│ └── src -│ └── main.nr -│ -└── Nargo.toml -``` - -You can define a workspace in Nargo.toml like so: - -```toml -[workspace] -members = ["crates/a", "crates/b"] -default-member = "crates/a" -``` - -`members` indicates which packages are included in the workspace. As such, all member packages of a workspace will be processed when the `--workspace` flag is used with various commands or if a `default-member` is not specified. - -`default-member` indicates which package various commands process by default. - -Libraries can be defined in a workspace. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. - -Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/_category_.json deleted file mode 100644 index af04c0933fd..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Standard Library", - "position": 1, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/bn254.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/bn254.md deleted file mode 100644 index 3294f005dbb..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/bn254.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: Bn254 Field Library ---- - -Noir provides a module in standard library with some optimized functions for bn254 Fr in `std::field::bn254`. - -## decompose - -```rust -fn decompose(x: Field) -> (Field, Field) {} -``` - -Decomposes a single field into two fields, low and high. The low field contains the lower 16 bytes of the input field and the high field contains the upper 16 bytes of the input field. Both field results are range checked to 128 bits. - - -## assert_gt - -```rust -fn assert_gt(a: Field, b: Field) {} -``` - -Asserts that a > b. This will generate less constraints than using `assert(gt(a, b))`. - -## assert_lt - -```rust -fn assert_lt(a: Field, b: Field) {} -``` - -Asserts that a < b. This will generate less constraints than using `assert(lt(a, b))`. - -## gt - -```rust -fn gt(a: Field, b: Field) -> bool {} -``` - -Returns true if a > b. - -## lt - -```rust -fn lt(a: Field, b: Field) -> bool {} -``` - -Returns true if a < b. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/containers/boundedvec.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/containers/boundedvec.md deleted file mode 100644 index c22fe8c5045..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/containers/boundedvec.md +++ /dev/null @@ -1,340 +0,0 @@ ---- -title: Bounded Vectors -keywords: [noir, vector, bounded vector, slice] -sidebar_position: 1 ---- - -A `BoundedVec` is a growable storage similar to a `Vec` except that it -is bounded with a maximum possible length. Unlike `Vec`, `BoundedVec` is not implemented -via slices and thus is not subject to the same restrictions slices are (notably, nested -slices - and thus nested vectors as well - are disallowed). - -Since a BoundedVec is backed by a normal array under the hood, growing the BoundedVec by -pushing an additional element is also more efficient - the length only needs to be increased -by one. - -For these reasons `BoundedVec` should generally be preferred over `Vec` when there -is a reasonable maximum bound that can be placed on the vector. - -Example: - -```rust -let mut vector: BoundedVec = BoundedVec::new(); -for i in 0..5 { - vector.push(i); -} -assert(vector.len() == 5); -assert(vector.max_len() == 10); -``` - -## Methods - -### new - -```rust -pub fn new() -> Self -``` - -Creates a new, empty vector of length zero. - -Since this container is backed by an array internally, it still needs an initial value -to give each element. To resolve this, each element is zeroed internally. This value -is guaranteed to be inaccessible unless `get_unchecked` is used. - -Example: - -```rust -let empty_vector: BoundedVec = BoundedVec::new(); -assert(empty_vector.len() == 0); -``` - -Note that whenever calling `new` the maximum length of the vector should always be specified -via a type signature: - -```rust title="new_example" showLineNumbers -fn foo() -> BoundedVec { - // Ok! MaxLen is specified with a type annotation - let v1: BoundedVec = BoundedVec::new(); - let v2 = BoundedVec::new(); - - // Ok! MaxLen is known from the type of foo's return value - v2 -} - -fn bad() { - let mut v3 = BoundedVec::new(); - - // Not Ok! We don't know if v3's MaxLen is at least 1, and the compiler often infers 0 by default. - v3.push(5); -} -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L11-L27 - - -This defaulting of `MaxLen` (and numeric generics in general) to zero may change in future noir versions -but for now make sure to use type annotations when using bounded vectors. Otherwise, you will receive a constraint failure at runtime when the vec is pushed to. - -### get - -```rust -pub fn get(mut self: Self, index: u64) -> T { -``` - -Retrieves an element from the vector at the given index, starting from zero. - -If the given index is equal to or greater than the length of the vector, this -will issue a constraint failure. - -Example: - -```rust -fn foo(v: BoundedVec) { - let first = v.get(0); - let last = v.get(v.len() - 1); - assert(first != last); -} -``` - -### get_unchecked - -```rust -pub fn get_unchecked(mut self: Self, index: u64) -> T { -``` - -Retrieves an element from the vector at the given index, starting from zero, without -performing a bounds check. - -Since this function does not perform a bounds check on length before accessing the element, -it is unsafe! Use at your own risk! - -Example: - -```rust title="get_unchecked_example" showLineNumbers -fn sum_of_first_three(v: BoundedVec) -> u32 { - // Always ensure the length is larger than the largest - // index passed to get_unchecked - assert(v.len() > 2); - let first = v.get_unchecked(0); - let second = v.get_unchecked(1); - let third = v.get_unchecked(2); - first + second + third -} -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L54-L64 - - - -### push - -```rust -pub fn push(&mut self, elem: T) { -``` - -Pushes an element to the end of the vector. This increases the length -of the vector by one. - -Panics if the new length of the vector will be greater than the max length. - -Example: - -```rust title="bounded-vec-push-example" showLineNumbers -let mut v: BoundedVec = BoundedVec::new(); - - v.push(1); - v.push(2); - - // Panics with failed assertion "push out of bounds" - v.push(3); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L68-L76 - - -### pop - -```rust -pub fn pop(&mut self) -> T -``` - -Pops the element at the end of the vector. This will decrease the length -of the vector by one. - -Panics if the vector is empty. - -Example: - -```rust title="bounded-vec-pop-example" showLineNumbers -let mut v: BoundedVec = BoundedVec::new(); - v.push(1); - v.push(2); - - let two = v.pop(); - let one = v.pop(); - - assert(two == 2); - assert(one == 1); - // error: cannot pop from an empty vector - // let _ = v.pop(); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L81-L93 - - -### len - -```rust -pub fn len(self) -> u64 { -``` - -Returns the current length of this vector - -Example: - -```rust title="bounded-vec-len-example" showLineNumbers -let mut v: BoundedVec = BoundedVec::new(); - assert(v.len() == 0); - - v.push(100); - assert(v.len() == 1); - - v.push(200); - v.push(300); - v.push(400); - assert(v.len() == 4); - - let _ = v.pop(); - let _ = v.pop(); - assert(v.len() == 2); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L98-L113 - - -### max_len - -```rust -pub fn max_len(_self: BoundedVec) -> u64 { -``` - -Returns the maximum length of this vector. This is always -equal to the `MaxLen` parameter this vector was initialized with. - -Example: - -```rust title="bounded-vec-max-len-example" showLineNumbers -let mut v: BoundedVec = BoundedVec::new(); - - assert(v.max_len() == 5); - v.push(10); - assert(v.max_len() == 5); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L118-L124 - - -### storage - -```rust -pub fn storage(self) -> [T; MaxLen] { -``` - -Returns the internal array within this vector. -Since arrays in Noir are immutable, mutating the returned storage array will not mutate -the storage held internally by this vector. - -Note that uninitialized elements may be zeroed out! - -Example: - -```rust title="bounded-vec-storage-example" showLineNumbers -let mut v: BoundedVec = BoundedVec::new(); - - assert(v.storage() == [0, 0, 0, 0, 0]); - - v.push(57); - assert(v.storage() == [57, 0, 0, 0, 0]); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L129-L136 - - -### extend_from_array - -```rust -pub fn extend_from_array(&mut self, array: [T; Len]) -``` - -Pushes each element from the given array to this vector. - -Panics if pushing each element would cause the length of this vector -to exceed the maximum length. - -Example: - -```rust title="bounded-vec-extend-from-array-example" showLineNumbers -let mut vec: BoundedVec = BoundedVec::new(); - vec.extend_from_array([2, 4]); - - assert(vec.len == 2); - assert(vec.get(0) == 2); - assert(vec.get(1) == 4); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L141-L148 - - -### extend_from_bounded_vec - -```rust -pub fn extend_from_bounded_vec(&mut self, vec: BoundedVec) -``` - -Pushes each element from the other vector to this vector. The length of -the other vector is left unchanged. - -Panics if pushing each element would cause the length of this vector -to exceed the maximum length. - -Example: - -```rust title="bounded-vec-extend-from-bounded-vec-example" showLineNumbers -let mut v1: BoundedVec = BoundedVec::new(); - let mut v2: BoundedVec = BoundedVec::new(); - - v2.extend_from_array([1, 2, 3]); - v1.extend_from_bounded_vec(v2); - - assert(v1.storage() == [1, 2, 3, 0, 0]); - assert(v2.storage() == [1, 2, 3, 0, 0, 0, 0]); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L153-L162 - - -### from_array - -```rust -pub fn from_array(array: [T; Len]) -> Self -``` - -Creates a new vector, populating it with values derived from an array input. -The maximum length of the vector is determined based on the type signature. - -Example: -```rust -let bounded_vec: BoundedVec = BoundedVec::from_array([1, 2, 3]) -``` - -### any - -```rust -pub fn any(self, predicate: fn[Env](T) -> bool) -> bool -``` - -Returns true if the given predicate returns true for any element -in this vector. - -Example: - -```rust title="bounded-vec-any-example" showLineNumbers -let mut v: BoundedVec = BoundedVec::new(); - v.extend_from_array([2, 4, 6]); - - let all_even = !v.any(|elem: u32| elem % 2 != 0); - assert(all_even); -``` -> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L229-L235 - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/containers/hashmap.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/containers/hashmap.md deleted file mode 100644 index 47faa99aba6..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/containers/hashmap.md +++ /dev/null @@ -1,570 +0,0 @@ ---- -title: HashMap -keywords: [noir, map, hash, hashmap] -sidebar_position: 1 ---- - -`HashMap` is used to efficiently store and look up key-value pairs. - -`HashMap` is a bounded type which can store anywhere from zero to `MaxLen` total elements. -Note that due to hash collisions, the actual maximum number of elements stored by any particular -hashmap is likely lower than `MaxLen`. This is true even with cryptographic hash functions since -every hash value will be performed modulo `MaxLen`. - -When creating `HashMap`s, the `MaxLen` generic should always be specified if it is not already -known. Otherwise, the compiler may infer a different value for `MaxLen` (such as zero), which -will likely change the result of the program. This behavior is set to become an error in future -versions instead. - -Example: - -```rust -// Create a mapping from Fields to u32s with a maximum length of 12 -// using a poseidon2 hasher -use dep::std::hash::poseidon2::Poseidon2Hasher; -let mut map: HashMap> = HashMap::default(); - -map.insert(1, 2); -map.insert(3, 4); - -let two = map.get(1).unwrap(); -``` - -## Methods - -### default - -```rust title="default" showLineNumbers -impl Default for HashMap -where - B: BuildHasher + Default, - H: Hasher + Default -{ - fn default() -> Self { -``` -> Source code: noir_stdlib/src/collections/map.nr#L462-L469 - - -Creates a fresh, empty HashMap. - -When using this function, always make sure to specify the maximum size of the hash map. - -This is the same `default` from the `Default` implementation given further below. It is -repeated here for convenience since it is the recommended way to create a hashmap. - -Example: - -```rust title="default_example" showLineNumbers -let hashmap: HashMap> = HashMap::default(); - assert(hashmap.is_empty()); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L202-L205 - - -Because `HashMap` has so many generic arguments that are likely to be the same throughout -your program, it may be helpful to create a type alias: - -```rust title="type_alias" showLineNumbers -type MyMap = HashMap>; -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L196-L198 - - -### with_hasher - -```rust title="with_hasher" showLineNumbers -pub fn with_hasher(_build_hasher: B) -> Self - where - B: BuildHasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L82-L86 - - -Creates a hashmap with an existing `BuildHasher`. This can be used to ensure multiple -hashmaps are created with the same hasher instance. - -Example: - -```rust title="with_hasher_example" showLineNumbers -let my_hasher: BuildHasherDefault = Default::default(); - let hashmap: HashMap> = HashMap::with_hasher(my_hasher); - assert(hashmap.is_empty()); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L207-L211 - - -### get - -```rust title="get" showLineNumbers -pub fn get( - self, - key: K - ) -> Option - where - K: Eq + Hash, - B: BuildHasher, - H: Hasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L278-L287 - - -Retrieves a value from the hashmap, returning `Option::none()` if it was not found. - -Example: - -```rust title="get_example" showLineNumbers -fn get_example(map: HashMap>) { - let x = map.get(12); - - if x.is_some() { - assert(x.unwrap() == 42); - } -} -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L299-L307 - - -### insert - -```rust title="insert" showLineNumbers -pub fn insert( - &mut self, - key: K, - value: V - ) - where - K: Eq + Hash, - B: BuildHasher, - H: Hasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L313-L323 - - -Inserts a new key-value pair into the map. If the key was already in the map, its -previous value will be overridden with the newly provided one. - -Example: - -```rust title="insert_example" showLineNumbers -let mut map: HashMap> = HashMap::default(); - map.insert(12, 42); - assert(map.len() == 1); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L213-L217 - - -### remove - -```rust title="remove" showLineNumbers -pub fn remove( - &mut self, - key: K - ) - where - K: Eq + Hash, - B: BuildHasher, - H: Hasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L356-L365 - - -Removes the given key-value pair from the map. If the key was not already present -in the map, this does nothing. - -Example: - -```rust title="remove_example" showLineNumbers -map.remove(12); - assert(map.is_empty()); - - // If a key was not present in the map, remove does nothing - map.remove(12); - assert(map.is_empty()); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L221-L228 - - -### is_empty - -```rust title="is_empty" showLineNumbers -pub fn is_empty(self) -> bool { -``` -> Source code: noir_stdlib/src/collections/map.nr#L115-L117 - - -True if the length of the hash map is empty. - -Example: - -```rust title="is_empty_example" showLineNumbers -assert(map.is_empty()); - - map.insert(1, 2); - assert(!map.is_empty()); - - map.remove(1); - assert(map.is_empty()); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L230-L238 - - -### len - -```rust title="len" showLineNumbers -pub fn len(self) -> u64 { -``` -> Source code: noir_stdlib/src/collections/map.nr#L264-L266 - - -Returns the current length of this hash map. - -Example: - -```rust title="len_example" showLineNumbers -// This is equivalent to checking map.is_empty() - assert(map.len() == 0); - - map.insert(1, 2); - map.insert(3, 4); - map.insert(5, 6); - assert(map.len() == 3); - - // 3 was already present as a key in the hash map, so the length is unchanged - map.insert(3, 7); - assert(map.len() == 3); - - map.remove(1); - assert(map.len() == 2); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L240-L255 - - -### capacity - -```rust title="capacity" showLineNumbers -pub fn capacity(_self: Self) -> u64 { -``` -> Source code: noir_stdlib/src/collections/map.nr#L271-L273 - - -Returns the maximum capacity of this hashmap. This is always equal to the capacity -specified in the hashmap's type. - -Unlike hashmaps in general purpose programming languages, hashmaps in Noir have a -static capacity that does not increase as the map grows larger. Thus, this capacity -is also the maximum possible element count that can be inserted into the hashmap. -Due to hash collisions (modulo the hashmap length), it is likely the actual maximum -element count will be lower than the full capacity. - -Example: - -```rust title="capacity_example" showLineNumbers -let empty_map: HashMap> = HashMap::default(); - assert(empty_map.len() == 0); - assert(empty_map.capacity() == 42); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L257-L261 - - -### clear - -```rust title="clear" showLineNumbers -pub fn clear(&mut self) { -``` -> Source code: noir_stdlib/src/collections/map.nr#L93-L95 - - -Clears the hashmap, removing all key-value pairs from it. - -Example: - -```rust title="clear_example" showLineNumbers -assert(!map.is_empty()); - map.clear(); - assert(map.is_empty()); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L263-L267 - - -### contains_key - -```rust title="contains_key" showLineNumbers -pub fn contains_key( - self, - key: K - ) -> bool - where - K: Hash + Eq, - B: BuildHasher, - H: Hasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L101-L110 - - -True if the hashmap contains the given key. Unlike `get`, this will not also return -the value associated with the key. - -Example: - -```rust title="contains_key_example" showLineNumbers -if map.contains_key(7) { - let value = map.get(7); - assert(value.is_some()); - } else { - println("No value for key 7!"); - } -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L269-L276 - - -### entries - -```rust title="entries" showLineNumbers -pub fn entries(self) -> BoundedVec<(K, V), N> { -``` -> Source code: noir_stdlib/src/collections/map.nr#L123-L125 - - -Returns a vector of each key-value pair present in the hashmap. - -The length of the returned vector is always equal to the length of the hashmap. - -Example: - -```rust title="entries_example" showLineNumbers -let entries = map.entries(); - - // The length of a hashmap may not be compile-time known, so we - // need to loop over its capacity instead - for i in 0..map.capacity() { - if i < entries.len() { - let (key, value) = entries.get(i); - println(f"{key} -> {value}"); - } - } -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L310-L321 - - -### keys - -```rust title="keys" showLineNumbers -pub fn keys(self) -> BoundedVec { -``` -> Source code: noir_stdlib/src/collections/map.nr#L144-L146 - - -Returns a vector of each key present in the hashmap. - -The length of the returned vector is always equal to the length of the hashmap. - -Example: - -```rust title="keys_example" showLineNumbers -let keys = map.keys(); - - for i in 0..keys.max_len() { - if i < keys.len() { - let key = keys.get_unchecked(i); - let value = map.get(key).unwrap_unchecked(); - println(f"{key} -> {value}"); - } - } -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L323-L333 - - -### values - -```rust title="values" showLineNumbers -pub fn values(self) -> BoundedVec { -``` -> Source code: noir_stdlib/src/collections/map.nr#L164-L166 - - -Returns a vector of each value present in the hashmap. - -The length of the returned vector is always equal to the length of the hashmap. - -Example: - -```rust title="values_example" showLineNumbers -let values = map.values(); - - for i in 0..values.max_len() { - if i < values.len() { - let value = values.get_unchecked(i); - println(f"Found value {value}"); - } - } -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L335-L344 - - -### iter_mut - -```rust title="iter_mut" showLineNumbers -pub fn iter_mut( - &mut self, - f: fn(K, V) -> (K, V) - ) - where - K: Eq + Hash, - B: BuildHasher, - H: Hasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L183-L192 - - -Iterates through each key-value pair of the HashMap, setting each key-value pair to the -result returned from the given function. - -Note that since keys can be mutated, the HashMap needs to be rebuilt as it is iterated -through. If this is not desired, use `iter_values_mut` if only values need to be mutated, -or `entries` if neither keys nor values need to be mutated. - -The iteration order is left unspecified. As a result, if two keys are mutated to become -equal, which of the two values that will be present for the key in the resulting map is also unspecified. - -Example: - -```rust title="iter_mut_example" showLineNumbers -// Add 1 to each key in the map, and double the value associated with that key. - map.iter_mut(|k, v| (k + 1, v * 2)); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L348-L351 - - -### iter_keys_mut - -```rust title="iter_keys_mut" showLineNumbers -pub fn iter_keys_mut( - &mut self, - f: fn(K) -> K - ) - where - K: Eq + Hash, - B: BuildHasher, - H: Hasher { -``` -> Source code: noir_stdlib/src/collections/map.nr#L208-L217 - - -Iterates through the HashMap, mutating each key to the result returned from -the given function. - -Note that since keys can be mutated, the HashMap needs to be rebuilt as it is iterated -through. If only iteration is desired and the keys are not intended to be mutated, -prefer using `entries` instead. - -The iteration order is left unspecified. As a result, if two keys are mutated to become -equal, which of the two values that will be present for the key in the resulting map is also unspecified. - -Example: - -```rust title="iter_keys_mut_example" showLineNumbers -// Double each key, leaving the value associated with that key untouched - map.iter_keys_mut(|k| k * 2); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L353-L356 - - -### iter_values_mut - -```rust title="iter_values_mut" showLineNumbers -pub fn iter_values_mut(&mut self, f: fn(V) -> V) { -``` -> Source code: noir_stdlib/src/collections/map.nr#L233-L235 - - -Iterates through the HashMap, applying the given function to each value and mutating the -value to equal the result. This function is more efficient than `iter_mut` and `iter_keys_mut` -because the keys are untouched and the underlying hashmap thus does not need to be reordered. - -Example: - -```rust title="iter_values_mut_example" showLineNumbers -// Halve each value - map.iter_values_mut(|v| v / 2); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L358-L361 - - -### retain - -```rust title="retain" showLineNumbers -pub fn retain(&mut self, f: fn(K, V) -> bool) { -``` -> Source code: noir_stdlib/src/collections/map.nr#L247-L249 - - -Retains only the key-value pairs for which the given function returns true. -Any key-value pairs for which the function returns false will be removed from the map. - -Example: - -```rust title="retain_example" showLineNumbers -map.retain(|k, v| (k != 0) & (v != 0)); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L281-L283 - - -## Trait Implementations - -### default - -```rust title="default" showLineNumbers -impl Default for HashMap -where - B: BuildHasher + Default, - H: Hasher + Default -{ - fn default() -> Self { -``` -> Source code: noir_stdlib/src/collections/map.nr#L462-L469 - - -Constructs an empty HashMap. - -Example: - -```rust title="default_example" showLineNumbers -let hashmap: HashMap> = HashMap::default(); - assert(hashmap.is_empty()); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L202-L205 - - -### eq - -```rust title="eq" showLineNumbers -impl Eq for HashMap -where - K: Eq + Hash, - V: Eq, - B: BuildHasher, - H: Hasher -{ - fn eq(self, other: HashMap) -> bool { -``` -> Source code: noir_stdlib/src/collections/map.nr#L426-L435 - - -Checks if two HashMaps are equal. - -Example: - -```rust title="eq_example" showLineNumbers -let mut map1: HashMap> = HashMap::default(); - let mut map2: HashMap> = HashMap::default(); - - map1.insert(1, 2); - map1.insert(3, 4); - - map2.insert(3, 4); - map2.insert(1, 2); - - assert(map1 == map2); -``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L285-L296 - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/containers/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/containers/index.md deleted file mode 100644 index ea84c6d5c21..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/containers/index.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Containers -description: Container types provided by Noir's standard library for storing and retrieving data -keywords: [containers, data types, vec, hashmap] ---- diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/containers/vec.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/containers/vec.mdx deleted file mode 100644 index fcfd7e07aa0..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/containers/vec.mdx +++ /dev/null @@ -1,151 +0,0 @@ ---- -title: Vectors -description: Delve into the Vec data type in Noir. Learn about its methods, practical examples, and best practices for using Vectors in your Noir code. -keywords: [noir, vector type, methods, examples, dynamic arrays] -sidebar_position: 6 ---- - -import Experimental from '@site/src/components/Notes/_experimental.mdx'; - - - -A vector is a collection type similar to Rust's `Vec` type. In Noir, it is a convenient way to use slices as mutable arrays. - -Example: - -```rust -let mut vector: Vec = Vec::new(); -for i in 0..5 { - vector.push(i); -} -assert(vector.len() == 5); -``` - -## Methods - -### new - -Creates a new, empty vector. - -```rust -pub fn new() -> Self -``` - -Example: - -```rust -let empty_vector: Vec = Vec::new(); -assert(empty_vector.len() == 0); -``` - -### from_slice - -Creates a vector containing each element from a given slice. Mutations to the resulting vector will not affect the original slice. - -```rust -pub fn from_slice(slice: [T]) -> Self -``` - -Example: - -```rust -let slice: [Field] = &[1, 2, 3]; -let vector_from_slice = Vec::from_slice(slice); -assert(vector_from_slice.len() == 3); -``` - -### len - -Returns the number of elements in the vector. - -```rust -pub fn len(self) -> Field -``` - -Example: - -```rust -let empty_vector: Vec = Vec::new(); -assert(empty_vector.len() == 0); -``` - -### get - -Retrieves an element from the vector at a given index. Panics if the index points beyond the vector's end. - -```rust -pub fn get(self, index: Field) -> T -``` - -Example: - -```rust -let vector: Vec = Vec::from_slice(&[10, 20, 30]); -assert(vector.get(1) == 20); -``` - -### push - -Adds a new element to the vector's end, returning a new vector with a length one greater than the original unmodified vector. - -```rust -pub fn push(&mut self, elem: T) -``` - -Example: - -```rust -let mut vector: Vec = Vec::new(); -vector.push(10); -assert(vector.len() == 1); -``` - -### pop - -Removes an element from the vector's end, returning a new vector with a length one less than the original vector, along with the removed element. Panics if the vector's length is zero. - -```rust -pub fn pop(&mut self) -> T -``` - -Example: - -```rust -let mut vector = Vec::from_slice(&[10, 20]); -let popped_elem = vector.pop(); -assert(popped_elem == 20); -assert(vector.len() == 1); -``` - -### insert - -Inserts an element at a specified index, shifting subsequent elements to the right. - -```rust -pub fn insert(&mut self, index: Field, elem: T) -``` - -Example: - -```rust -let mut vector = Vec::from_slice(&[10, 30]); -vector.insert(1, 20); -assert(vector.get(1) == 20); -``` - -### remove - -Removes an element at a specified index, shifting subsequent elements to the left, and returns the removed element. - -```rust -pub fn remove(&mut self, index: Field) -> T -``` - -Example: - -```rust -let mut vector = Vec::from_slice(&[10, 20, 30]); -let removed_elem = vector.remove(1); -assert(removed_elem == 20); -assert(vector.len() == 2); -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/_category_.json deleted file mode 100644 index 5d694210bbf..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 0, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/ec_primitives.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/ec_primitives.md deleted file mode 100644 index 8f9f47ce7d0..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/ec_primitives.md +++ /dev/null @@ -1,102 +0,0 @@ ---- -title: Elliptic Curve Primitives -keywords: [cryptographic primitives, Noir project] -sidebar_position: 4 ---- - -Data structures and methods on them that allow you to carry out computations involving elliptic -curves over the (mathematical) field corresponding to `Field`. For the field currently at our -disposal, applications would involve a curve embedded in BN254, e.g. the -[Baby Jubjub curve](https://eips.ethereum.org/EIPS/eip-2494). - -## Data structures - -### Elliptic curve configurations - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Curve`), i.e. the specific elliptic -curve you want to use, which would be specified using any one of the methods -`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::new` which take the coefficients in the -defining equation together with a generator point as parameters. You can find more detail in the -comments in -[`noir_stdlib/src/ec.nr`](https://github.com/noir-lang/noir/blob/v0.30.0/noir_stdlib/src/ec.nr), but -the gist of it is that the elliptic curves of interest are usually expressed in one of the standard -forms implemented here (Twisted Edwards, Montgomery and Short Weierstraß), and in addition to that, -you could choose to use `affine` coordinates (Cartesian coordinates - the usual (x,y) - possibly -together with a point at infinity) or `curvegroup` coordinates (some form of projective coordinates -requiring more coordinates but allowing for more efficient implementations of elliptic curve -operations). Conversions between all of these forms are provided, and under the hood these -conversions are done whenever an operation is more efficient in a different representation (or a -mixed coordinate representation is employed). - -### Points - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Point`), i.e. points lying on the -elliptic curve. For a curve configuration `c` and a point `p`, it may be checked that `p` -does indeed lie on `c` by calling `c.contains(p1)`. - -## Methods - -(given a choice of curve representation, e.g. use `std::ec::tecurve::affine::Curve` and use -`std::ec::tecurve::affine::Point`) - -- The **zero element** is given by `Point::zero()`, and we can verify whether a point `p: Point` is - zero by calling `p.is_zero()`. -- **Equality**: Points `p1: Point` and `p2: Point` may be checked for equality by calling - `p1.eq(p2)`. -- **Addition**: For `c: Curve` and points `p1: Point` and `p2: Point` on the curve, adding these two - points is accomplished by calling `c.add(p1,p2)`. -- **Negation**: For a point `p: Point`, `p.negate()` is its negation. -- **Subtraction**: For `c` and `p1`, `p2` as above, subtracting `p2` from `p1` is accomplished by - calling `c.subtract(p1,p2)`. -- **Scalar multiplication**: For `c` as above, `p: Point` a point on the curve and `n: Field`, - scalar multiplication is given by `c.mul(n,p)`. If instead `n :: [u1; N]`, i.e. `n` is a bit - array, the `bit_mul` method may be used instead: `c.bit_mul(n,p)` -- **Multi-scalar multiplication**: For `c` as above and arrays `n: [Field; N]` and `p: [Point; N]`, - multi-scalar multiplication is given by `c.msm(n,p)`. -- **Coordinate representation conversions**: The `into_group` method converts a point or curve - configuration in the affine representation to one in the CurveGroup representation, and - `into_affine` goes in the other direction. -- **Curve representation conversions**: `tecurve` and `montcurve` curves and points are equivalent - and may be converted between one another by calling `into_montcurve` or `into_tecurve` on their - configurations or points. `swcurve` is more general and a curve c of one of the other two types - may be converted to this representation by calling `c.into_swcurve()`, whereas a point `p` lying - on the curve given by `c` may be mapped to its corresponding `swcurve` point by calling - `c.map_into_swcurve(p)`. -- **Map-to-curve methods**: The Elligator 2 method of mapping a field element `n: Field` into a - `tecurve` or `montcurve` with configuration `c` may be called as `c.elligator2_map(n)`. For all of - the curve configurations, the SWU map-to-curve method may be called as `c.swu_map(z,n)`, where - `z: Field` depends on `Field` and `c` and must be chosen by the user (the conditions it needs to - satisfy are specified in the comments - [here](https://github.com/noir-lang/noir/blob/v0.30.0/noir_stdlib/src/ec.nr). - -## Examples - -The -[ec_baby_jubjub test](https://github.com/noir-lang/noir/blob/master/test_programs/compile_success_empty/ec_baby_jubjub/src/main.nr) -illustrates all of the above primitives on various forms of the Baby Jubjub curve. A couple of more -interesting examples in Noir would be: - -Public-key cryptography: Given an elliptic curve and a 'base point' on it, determine the public key -from the private key. This is a matter of using scalar multiplication. In the case of Baby Jubjub, -for example, this code would do: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; - -fn bjj_pub_key(priv_key: Field) -> Point -{ - - let bjj = Curve::new(168700, 168696, G::new(995203441582195749578291179787384436505546430278305826713579947235728471134,5472060717959818805561601436314318772137091100104008585924551046643952123905)); - - let base_pt = Point::new(5299619240641551281634865583518297030282874472190772894086521144482721001553, 16950150798460657717958625567821834550301663161624707787222815936182638968203); - - bjj.mul(priv_key,base_pt) -} -``` - -This would come in handy in a Merkle proof. - -- EdDSA signature verification: This is a matter of combining these primitives with a suitable hash - function. See - [feat(stdlib): EdDSA sig verification noir#1136](https://github.com/noir-lang/noir/pull/1136) for - the case of Baby Jubjub and the Poseidon hash function. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx deleted file mode 100644 index 4394b48f907..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx +++ /dev/null @@ -1,98 +0,0 @@ ---- -title: ECDSA Signature Verification -description: Learn about the cryptographic primitives regarding ECDSA over the secp256k1 and secp256r1 curves -keywords: [cryptographic primitives, Noir project, ecdsa, secp256k1, secp256r1, signatures] -sidebar_position: 3 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -Noir supports ECDSA signatures verification over the secp256k1 and secp256r1 curves. - -## ecdsa_secp256k1::verify_signature - -Verifier for ECDSA Secp256k1 signatures. -See ecdsa_secp256k1::verify_signature_slice for a version that accepts slices directly. - -```rust title="ecdsa_secp256k1" showLineNumbers -pub fn verify_signature( - public_key_x: [u8; 32], - public_key_y: [u8; 32], - signature: [u8; 64], - message_hash: [u8; N] -) -> bool -``` -> Source code: noir_stdlib/src/ecdsa_secp256k1.nr#L2-L9 - - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - - - -## ecdsa_secp256k1::verify_signature_slice - -Verifier for ECDSA Secp256k1 signatures where the message is a slice. - -```rust title="ecdsa_secp256k1_slice" showLineNumbers -pub fn verify_signature_slice( - public_key_x: [u8; 32], - public_key_y: [u8; 32], - signature: [u8; 64], - message_hash: [u8] -) -> bool -``` -> Source code: noir_stdlib/src/ecdsa_secp256k1.nr#L13-L20 - - - - -## ecdsa_secp256r1::verify_signature - -Verifier for ECDSA Secp256r1 signatures. -See ecdsa_secp256r1::verify_signature_slice for a version that accepts slices directly. - -```rust title="ecdsa_secp256r1" showLineNumbers -pub fn verify_signature( - public_key_x: [u8; 32], - public_key_y: [u8; 32], - signature: [u8; 64], - message_hash: [u8; N] -) -> bool -``` -> Source code: noir_stdlib/src/ecdsa_secp256r1.nr#L2-L9 - - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - - - -## ecdsa_secp256r1::verify_signature - -Verifier for ECDSA Secp256r1 signatures where the message is a slice. - -```rust title="ecdsa_secp256r1_slice" showLineNumbers -pub fn verify_signature_slice( - public_key_x: [u8; 32], - public_key_y: [u8; 32], - signature: [u8; 64], - message_hash: [u8] -) -> bool -``` -> Source code: noir_stdlib/src/ecdsa_secp256r1.nr#L13-L20 - - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/eddsa.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/eddsa.mdx deleted file mode 100644 index c2c0624dfad..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/eddsa.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: EdDSA Verification -description: Learn about the cryptographic primitives regarding EdDSA -keywords: [cryptographic primitives, Noir project, eddsa, signatures] -sidebar_position: 5 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## eddsa::eddsa_poseidon_verify - -Verifier for EdDSA signatures - -```rust -fn eddsa_poseidon_verify(public_key_x : Field, public_key_y : Field, signature_s: Field, signature_r8_x: Field, signature_r8_y: Field, message: Field) -> bool -``` - -It is also possible to specify the hash algorithm used for the signature by using the `eddsa_verify_with_hasher` function with a parameter implementing the Hasher trait. For instance, if you want to use Poseidon2 instead, you can do the following: -```rust -use dep::std::hash::poseidon2::Poseidon2Hasher; - -let mut hasher = Poseidon2Hasher::default(); -eddsa_verify_with_hasher(pub_key_a.x, pub_key_a.y, s_a, r8_a.x, r8_a.y, msg, &mut hasher); -``` - - - -## eddsa::eddsa_to_pub - -Private to public key conversion. - -Returns `(pub_key_x, pub_key_y)` - -```rust -fn eddsa_to_pub(secret : Field) -> (Field, Field) -``` - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/embedded_curve_ops.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/embedded_curve_ops.mdx deleted file mode 100644 index 9dab7dd1047..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/embedded_curve_ops.mdx +++ /dev/null @@ -1,98 +0,0 @@ ---- -title: Scalar multiplication -description: See how you can perform scalar multiplication in Noir -keywords: [cryptographic primitives, Noir project, scalar multiplication] -sidebar_position: 1 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -The following functions perform operations over the embedded curve whose coordinates are defined by the configured noir field. -For the BN254 scalar field, this is BabyJubJub or Grumpkin. - -:::note -Suffixes `_low` and `_high` denote low and high limbs of a scalar. -::: - -## embedded_curve_ops::multi_scalar_mul - -Performs multi scalar multiplication over the embedded curve. -The function accepts arbitrary amount of point-scalar pairs on the input, it multiplies the individual pairs over -the curve and returns a sum of the resulting points. - -Points represented as x and y coordinates [x1, y1, x2, y2, ...], scalars as low and high limbs [low1, high1, low2, high2, ...]. - -```rust title="multi_scalar_mul" showLineNumbers -pub fn multi_scalar_mul( - points: [Field; N], // points represented as x and y coordinates [x1, y1, x2, y2, ...] - scalars: [Field; N] // scalars represented as low and high limbs [low1, high1, low2, high2, ...] -) -> [Field; 2] -``` -> Source code: noir_stdlib/src/embedded_curve_ops.nr#L43-L48 - - -example - -```rust -fn main(point_x: Field, point_y: Field, scalar_low: Field, scalar_high: Field) { - let point = std::embedded_curve_ops::multi_scalar_mul([point_x, point_y], [scalar_low, scalar_high]); - println(point); -} -``` - -## embedded_curve_ops::fixed_base_scalar_mul - -Performs fixed base scalar multiplication over the embedded curve (multiplies input scalar with a generator point). -The function accepts a single scalar on the input represented as 2 fields. - -```rust title="fixed_base_scalar_mul" showLineNumbers -pub fn fixed_base_scalar_mul( - scalar_low: Field, - scalar_high: Field -) -> [Field; 2] -``` -> Source code: noir_stdlib/src/embedded_curve_ops.nr#L51-L56 - - -example - -```rust -fn main(scalar_low: Field, scalar_high: Field) { - let point = std::embedded_curve_ops::fixed_base_scalar_mul(scalar_low, scalar_high); - println(point); -} -``` - -## embedded_curve_ops::embedded_curve_add - -Adds two points on the embedded curve. -This function takes two `EmbeddedCurvePoint` structures as parameters, representing points on the curve, and returns a new `EmbeddedCurvePoint` structure that represents their sum. - -### Parameters: -- `point1` (`EmbeddedCurvePoint`): The first point to add. -- `point2` (`EmbeddedCurvePoint`): The second point to add. - -### Returns: -- `EmbeddedCurvePoint`: The resulting point after the addition of `point1` and `point2`. - -```rust title="embedded_curve_add" showLineNumbers -fn embedded_curve_add( - point1: EmbeddedCurvePoint, - point2: EmbeddedCurvePoint -) -> EmbeddedCurvePoint -``` -> Source code: noir_stdlib/src/embedded_curve_ops.nr#L65-L70 - - -example - -```rust -fn main() { - let point1 = EmbeddedCurvePoint { x: 1, y: 2 }; - let point2 = EmbeddedCurvePoint { x: 3, y: 4 }; - let result = std::embedded_curve_ops::embedded_curve_add(point1, point2); - println!("Resulting Point: ({}, {})", result.x, result.y); -} -``` - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/hashes.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/hashes.mdx deleted file mode 100644 index 3b83d9ec31a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/hashes.mdx +++ /dev/null @@ -1,257 +0,0 @@ ---- -title: Hash methods -description: - Learn about the cryptographic primitives ready to use for any Noir project, including sha256, - blake2s, pedersen, mimc_bn254 and mimc -keywords: - [cryptographic primitives, Noir project, sha256, blake2s, pedersen, mimc_bn254, mimc, hash] -sidebar_position: 0 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## sha256 - -Given an array of bytes, returns the resulting sha256 hash. -Specify a message_size to hash only the first `message_size` bytes of the input. - -```rust title="sha256" showLineNumbers -pub fn sha256(input: [u8; N]) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L10-L12 - - -example: -```rust title="sha256_var" showLineNumbers -let digest = std::hash::sha256_var([x as u8], 1); -``` -> Source code: test_programs/execution_success/sha256/src/main.nr#L17-L19 - - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::sha256::sha256_var(x, 4); -} -``` - - - - -## blake2s - -Given an array of bytes, returns an array with the Blake2 hash - -```rust title="blake2s" showLineNumbers -pub fn blake2s(input: [u8; N]) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L16-L18 - - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::blake2s(x); -} -``` - - - -## blake3 - -Given an array of bytes, returns an array with the Blake3 hash - -```rust title="blake3" showLineNumbers -pub fn blake3(input: [u8; N]) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L22-L24 - - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::blake3(x); -} -``` - - - -## pedersen_hash - -Given an array of Fields, returns the Pedersen hash. - -```rust title="pedersen_hash" showLineNumbers -pub fn pedersen_hash(input: [Field; N]) -> Field -``` -> Source code: noir_stdlib/src/hash.nr#L46-L48 - - -example: - -```rust title="pedersen-hash" showLineNumbers -use dep::std; - -fn main(x: Field, y: Field, expected_hash: Field) { - let hash = std::hash::pedersen_hash([x, y]); - assert_eq(hash, expected_hash); -} -``` -> Source code: test_programs/execution_success/pedersen_hash/src/main.nr#L1-L8 - - - - -## pedersen_commitment - -Given an array of Fields, returns the Pedersen commitment. - -```rust title="pedersen_commitment" showLineNumbers -struct PedersenPoint { - x : Field, - y : Field, -} - -pub fn pedersen_commitment(input: [Field; N]) -> PedersenPoint { -``` -> Source code: noir_stdlib/src/hash.nr#L27-L34 - - -example: - -```rust title="pedersen-commitment" showLineNumbers -use dep::std; - -fn main(x: Field, y: Field, expected_commitment: std::hash::PedersenPoint) { - let commitment = std::hash::pedersen_commitment([x, y]); - assert_eq(commitment.x, expected_commitment.x); - assert_eq(commitment.y, expected_commitment.y); -} -``` -> Source code: test_programs/execution_success/pedersen_commitment/src/main.nr#L1-L9 - - - - -## keccak256 - -Given an array of bytes (`u8`), returns the resulting keccak hash as an array of -32 bytes (`[u8; 32]`). Specify a message_size to hash only the first -`message_size` bytes of the input. - -```rust title="keccak256" showLineNumbers -pub fn keccak256(input: [u8; N], message_size: u32) -> [u8; 32] -``` -> Source code: noir_stdlib/src/hash.nr#L68-L70 - - -example: - -```rust title="keccak256" showLineNumbers -use dep::std; - -fn main(x: Field, result: [u8; 32]) { - // We use the `as` keyword here to denote the fact that we want to take just the first byte from the x Field - // The padding is taken care of by the program - let digest = std::hash::keccak256([x as u8], 1); - assert(digest == result); - - //#1399: variable message size - let message_size = 4; - let hash_a = std::hash::keccak256([1, 2, 3, 4], message_size); - let hash_b = std::hash::keccak256([1, 2, 3, 4, 0, 0, 0, 0], message_size); - - assert(hash_a == hash_b); - - let message_size_big = 8; - let hash_c = std::hash::keccak256([1, 2, 3, 4, 0, 0, 0, 0], message_size_big); - - assert(hash_a != hash_c); -} -``` -> Source code: test_programs/execution_success/keccak256/src/main.nr#L1-L22 - - - - -## poseidon - -Given an array of Fields, returns a new Field with the Poseidon Hash. Mind that you need to specify -how many inputs are there to your Poseidon function. - -```rust -// example for hash_1, hash_2 accepts an array of length 2, etc -fn hash_1(input: [Field; 1]) -> Field -``` - -example: - -```rust title="poseidon" showLineNumbers -use dep::std::hash::poseidon; -use dep::std::hash::poseidon2; - -fn main(x1: [Field; 2], y1: pub Field, x2: [Field; 4], y2: pub Field, x3: [Field; 4], y3: Field) { - let hash1 = poseidon::bn254::hash_2(x1); - assert(hash1 == y1); - - let hash2 = poseidon::bn254::hash_4(x2); - assert(hash2 == y2); - - let hash3 = poseidon2::Poseidon2::hash(x3, x3.len()); - assert(hash3 == y3); -} -``` -> Source code: test_programs/execution_success/poseidon_bn254_hash/src/main.nr#L1-L15 - - -## poseidon 2 - -Given an array of Fields, returns a new Field with the Poseidon2 Hash. Contrary to the Poseidon -function, there is only one hash and you can specify a message_size to hash only the first -`message_size` bytes of the input, - -```rust -// example for hashing the first three elements of the input -Poseidon2::hash(input, 3); -``` - -The above example for Poseidon also includes Poseidon2. - -## mimc_bn254 and mimc - -`mimc_bn254` is `mimc`, but with hardcoded parameters for the BN254 curve. You can use it by -providing an array of Fields, and it returns a Field with the hash. You can use the `mimc` method if -you're willing to input your own constants: - -```rust -fn mimc(x: Field, k: Field, constants: [Field; N], exp : Field) -> Field -``` - -otherwise, use the `mimc_bn254` method: - -```rust -fn mimc_bn254(array: [Field; N]) -> Field -``` - -example: - -```rust - -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::mimc::mimc_bn254(x); -} -``` - -## hash_to_field - -```rust -fn hash_to_field(_input : [Field]) -> Field {} -``` - -Calculates the `blake2s` hash of the inputs and returns the hash modulo the field modulus to return -a value which can be represented as a `Field`. - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/index.md deleted file mode 100644 index 650f30165d5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/index.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Cryptographic Primitives -description: - Learn about the cryptographic primitives ready to use for any Noir project -keywords: - [ - cryptographic primitives, - Noir project, - ] ---- - -The Noir team is progressively adding new cryptographic primitives to the standard library. Reach out for news or if you would be interested in adding more of these calculations in Noir. - -Some methods are available thanks to the Aztec backend, not being performed using Noir. When using other backends, these methods may or may not be supplied. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/schnorr.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/schnorr.mdx deleted file mode 100644 index b59e69c8f07..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/schnorr.mdx +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: Schnorr Signatures -description: Learn how you can verify Schnorr signatures using Noir -keywords: [cryptographic primitives, Noir project, schnorr, signatures] -sidebar_position: 2 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## schnorr::verify_signature - -Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin). -See schnorr::verify_signature_slice for a version that works directly on slices. - -```rust title="schnorr_verify" showLineNumbers -pub fn verify_signature( - public_key_x: Field, - public_key_y: Field, - signature: [u8; 64], - message: [u8; N] -) -> bool -``` -> Source code: noir_stdlib/src/schnorr.nr#L2-L9 - - -where `_signature` can be generated like so using the npm package -[@noir-lang/barretenberg](https://www.npmjs.com/package/@noir-lang/barretenberg) - -```js -const { BarretenbergWasm } = require('@noir-lang/barretenberg/dest/wasm'); -const { Schnorr } = require('@noir-lang/barretenberg/dest/crypto/schnorr'); - -... - -const barretenberg = await BarretenbergWasm.new(); -const schnorr = new Schnorr(barretenberg); -const pubKey = schnorr.computePublicKey(privateKey); -const message = ... -const signature = Array.from( - schnorr.constructSignature(hash, privateKey).toBuffer() -); - -... -``` - - - -## schnorr::verify_signature_slice - -Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin) -where the message is a slice. - -```rust title="schnorr_verify_slice" showLineNumbers -pub fn verify_signature_slice( - public_key_x: Field, - public_key_y: Field, - signature: [u8; 64], - message: [u8] -) -> bool -``` -> Source code: noir_stdlib/src/schnorr.nr#L13-L20 - - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/logging.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/logging.md deleted file mode 100644 index db75ef9f86f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/logging.md +++ /dev/null @@ -1,78 +0,0 @@ ---- -title: Logging -description: - Learn how to use the println statement for debugging in Noir with this tutorial. Understand the - basics of logging in Noir and how to implement it in your code. -keywords: - [ - noir logging, - println statement, - print statement, - debugging in noir, - noir std library, - logging tutorial, - basic logging in noir, - noir logging implementation, - noir debugging techniques, - rust, - ] ---- - -The standard library provides two familiar statements you can use: `println` and `print`. Despite being a limited implementation of rust's `println!` and `print!` macros, these constructs can be useful for debugging. - -You can print the output of both statements in your Noir code by using the `nargo execute` command or the `--show-output` flag when using `nargo test` (provided there are print statements in your tests). - -It is recommended to use `nargo execute` if you want to debug failing constraints with `println` or `print` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). Neither `println`, nor `print` are callable for failed constraints caught at compile time. - -Both `print` and `println` are generic functions which can work on integers, fields, strings, and even structs or expressions. Note however, that slices are currently unsupported. For example: - -```rust -struct Person { - age: Field, - height: Field, -} - -fn main(age: Field, height: Field) { - let person = Person { - age: age, - height: height, - }; - println(person); - println(age + height); - println("Hello world!"); -} -``` - -You can print different types in the same statement (including strings) with a type called `fmtstr`. It can be specified in the same way as a normal string, just prepended with an "f" character: - -```rust - let fmt_str = f"i: {i}, j: {j}"; - println(fmt_str); - - let s = myStruct { y: x, x: y }; - println(s); - - println(f"i: {i}, s: {s}"); - - println(x); - println([x, y]); - - let foo = fooStruct { my_struct: s, foo: 15 }; - println(f"s: {s}, foo: {foo}"); - - println(15); // prints 0x0f, implicit Field - println(-1 as u8); // prints 255 - println(-1 as i8); // prints -1 -``` - -Examples shown above are interchangeable between the two `print` statements: - -```rust -let person = Person { age : age, height : height }; - -println(person); -print(person); - -println("Hello world!"); // Prints with a newline at the end of the input -print("Hello world!"); // Prints the input and keeps cursor on the same line -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/merkle_trees.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/merkle_trees.md deleted file mode 100644 index 6a9ebf72ada..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/merkle_trees.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: Merkle Trees -description: Learn about Merkle Trees in Noir with this tutorial. Explore the basics of computing a merkle root using a proof, with examples. -keywords: - [ - Merkle trees in Noir, - Noir programming language, - check membership, - computing root from leaf, - Noir Merkle tree implementation, - Merkle tree tutorial, - Merkle tree code examples, - Noir libraries, - pedersen hash., - ] ---- - -## compute_merkle_root - -Returns the root of the tree from the provided leaf and its hash path, using a [Pedersen hash](./cryptographic_primitives/hashes.mdx#pedersen_hash). - -```rust -fn compute_merkle_root(leaf : Field, index : Field, hash_path: [Field]) -> Field -``` - -example: - -```rust -/** - // these values are for this example only - index = "0" - priv_key = "0x000000000000000000000000000000000000000000000000000000616c696365" - secret = "0x1929ea3ab8d9106a899386883d9428f8256cfedb3c4f6b66bf4aa4d28a79988f" - note_hash_path = [ - "0x1e61bdae0f027b1b2159e1f9d3f8d00fa668a952dddd822fda80dc745d6f65cc", - "0x0e4223f3925f98934393c74975142bd73079ab0621f4ee133cee050a3c194f1a", - "0x2fd7bb412155bf8693a3bd2a3e7581a679c95c68a052f835dddca85fa1569a40" - ] - */ -fn main(index: Field, priv_key: Field, secret: Field, note_hash_path: [Field; 3]) { - - let pubkey = std::scalar_mul::fixed_base_embedded_curve(priv_key); - let pubkey_x = pubkey[0]; - let pubkey_y = pubkey[1]; - let note_commitment = std::hash::pedersen(&[pubkey_x, pubkey_y, secret]); - - let root = std::merkle::compute_merkle_root(note_commitment[0], index, note_hash_path.as_slice()); - println(root); -} -``` - -To check merkle tree membership: - -1. Include a merkle root as a program input. -2. Compute the merkle root of a given leaf, index and hash path. -3. Assert the merkle roots are equal. - -For more info about merkle trees, see the Wikipedia [page](https://en.wikipedia.org/wiki/Merkle_tree). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/options.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/options.md deleted file mode 100644 index a1bd4e1de5f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/options.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -title: Option Type ---- - -The `Option` type is a way to express that a value might be present (`Some(T))` or absent (`None`). It's a safer way to handle potential absence of values, compared to using nulls in many other languages. - -```rust -struct Option { - None, - Some(T), -} -``` - -The `Option` type, already imported into your Noir program, can be used directly: - -```rust -fn main() { - let none = Option::none(); - let some = Option::some(3); -} -``` - -See [this test](https://github.com/noir-lang/noir/blob/5cbfb9c4a06c8865c98ff2b594464b037d821a5c/crates/nargo_cli/tests/test_data/option/src/main.nr) for a more comprehensive set of examples of each of the methods described below. - -## Methods - -### none - -Constructs a none value. - -### some - -Constructs a some wrapper around a given value. - -### is_none - -Returns true if the Option is None. - -### is_some - -Returns true of the Option is Some. - -### unwrap - -Asserts `self.is_some()` and returns the wrapped value. - -### unwrap_unchecked - -Returns the inner value without asserting `self.is_some()`. This method can be useful within an if condition when we already know that `option.is_some()`. If the option is None, there is no guarantee what value will be returned, only that it will be of type T for an `Option`. - -### unwrap_or - -Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value. - -### unwrap_or_else - -Returns the wrapped value if `self.is_some()`. Otherwise, calls the given function to return a default value. - -### expect - -Asserts `self.is_some()` with a provided custom message and returns the contained `Some` value. The custom message is expected to be a format string. - -### map - -If self is `Some(x)`, this returns `Some(f(x))`. Otherwise, this returns `None`. - -### map_or - -If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns the given default value. - -### map_or_else - -If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns `default()`. - -### and - -Returns None if self is None. Otherwise, this returns `other`. - -### and_then - -If self is None, this returns None. Otherwise, this calls the given function with the Some value contained within self, and returns the result of that call. In some languages this function is called `flat_map` or `bind`. - -### or - -If self is Some, return self. Otherwise, return `other`. - -### or_else - -If self is Some, return self. Otherwise, return `default()`. - -### xor - -If only one of the two Options is Some, return that option. Otherwise, if both options are Some or both are None, None is returned. - -### filter - -Returns `Some(x)` if self is `Some(x)` and `predicate(x)` is true. Otherwise, this returns `None`. - -### flatten - -Flattens an `Option>` into a `Option`. This returns `None` if the outer Option is None. Otherwise, this returns the inner Option. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/recursion.md deleted file mode 100644 index f33c285cf4e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/recursion.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -title: Recursive Proofs -description: Learn about how to write recursive proofs in Noir. -keywords: [recursion, recursive proofs, verification_key, verify_proof] ---- - -Noir supports recursively verifying proofs, meaning you verify the proof of a Noir program in another Noir program. This enables creating proofs of arbitrary size by doing step-wise verification of smaller components of a large proof. - -Read [the explainer on recursion](../../explainers/explainer-recursion.md) to know more about this function and the [guide on how to use it.](../../how_to/how-to-recursion.md) - -## The `#[recursive]` Attribute - -In Noir, the `#[recursive]` attribute is used to indicate that a circuit is designed for recursive proof generation. When applied, it informs the compiler and the tooling that the circuit should be compiled in a way that makes its proofs suitable for recursive verification. This attribute eliminates the need for manual flagging of recursion at the tooling level, streamlining the proof generation process for recursive circuits. - -### Example usage with `#[recursive]` - -```rust -#[recursive] -fn main(x: Field, y: pub Field) { - assert(x == y, "x and y are not equal"); -} - -// This marks the circuit as recursion-friendly and indicates that proofs generated from this circuit -// are intended for recursive verification. -``` - -By incorporating this attribute directly in the circuit's definition, tooling like Nargo and NoirJS can automatically execute recursive-specific duties for Noir programs (e.g. recursive-friendly proof artifact generation) without additional flags or configurations. - -## Verifying Recursive Proofs - -```rust -#[foreign(recursive_aggregation)] -pub fn verify_proof(verification_key: [Field], proof: [Field], public_inputs: [Field], key_hash: Field) {} -``` - -:::info - -This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. - -::: - -## Example usage - -```rust -use dep::std; - -fn main( - verification_key : [Field; 114], - proof : [Field; 93], - public_inputs : [Field; 1], - key_hash : Field, - proof_b : [Field; 93], -) { - std::verify_proof( - verification_key.as_slice(), - proof.as_slice(), - public_inputs.as_slice(), - key_hash - ); - - std::verify_proof( - verification_key.as_slice(), - proof_b.as_slice(), - public_inputs.as_slice(), - key_hash - ); -} -``` - -You can see a full example of recursive proofs in [this example recursion demo repo](https://github.com/noir-lang/noir-examples/tree/master/recursion). - -## Parameters - -### `verification_key` - -The verification key for the zk program that is being verified. - -### `proof` - -The proof for the zk program that is being verified. - -### `public_inputs` - -These represent the public inputs of the proof we are verifying. - -### `key_hash` - -A key hash is used to check the validity of the verification key. The circuit implementing this opcode can use this hash to ensure that the key provided to the circuit matches the key produced by the circuit creator. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/zeroed.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/zeroed.md deleted file mode 100644 index f450fecdd36..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/zeroed.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Zeroed Function -description: - The zeroed function returns a zeroed value of any type. -keywords: - [ - zeroed - ] ---- - -Implements `fn zeroed() -> T` to return a zeroed value of any type. This function is generally unsafe to use as the zeroed bit pattern is not guaranteed to be valid for all types. It can however, be useful in cases when the value is guaranteed not to be used such as in a BoundedVec library implementing a growable vector, up to a certain length, backed by an array. The array can be initialized with zeroed values which are guaranteed to be inaccessible until the vector is pushed to. Similarly, enumerations in noir can be implemented using this method by providing zeroed values for the unused variants. - -You can access the function at `std::unsafe::zeroed`. - -This function currently supports the following types: - -- Field -- Bool -- Uint -- Array -- Slice -- String -- Tuple -- Function - -Using it on other types could result in unexpected behavior. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/.nojekyll deleted file mode 100644 index e2ac6616add..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md deleted file mode 100644 index d7249d24330..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md +++ /dev/null @@ -1,160 +0,0 @@ -# BarretenbergBackend - -## Extends - -- `BarretenbergVerifierBackend` - -## Implements - -- [`Backend`](../index.md#backend) - -## Constructors - -### new BarretenbergBackend(acirCircuit, options) - -```ts -new BarretenbergBackend(acirCircuit, options): BarretenbergBackend -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `acirCircuit` | `CompiledCircuit` | -| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | - -#### Returns - -[`BarretenbergBackend`](BarretenbergBackend.md) - -#### Inherited from - -BarretenbergVerifierBackend.constructor - -## Properties - -| Property | Type | Description | Inheritance | -| :------ | :------ | :------ | :------ | -| `acirComposer` | `any` | - | BarretenbergVerifierBackend.acirComposer | -| `acirUncompressedBytecode` | `Uint8Array` | - | BarretenbergVerifierBackend.acirUncompressedBytecode | -| `api` | `Barretenberg` | - | BarretenbergVerifierBackend.api | -| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | - | BarretenbergVerifierBackend.options | - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Inherited from - -BarretenbergVerifierBackend.destroy - -*** - -### generateProof() - -```ts -generateProof(compressedWitness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `compressedWitness` | `Uint8Array` | - -#### Returns - -`Promise`\<`ProofData`\> - -#### Description - -Generates a proof - -*** - -### generateRecursiveProofArtifacts() - -```ts -generateRecursiveProofArtifacts(proofData, numOfPublicInputs): Promise -``` - -Generates artifacts that will be passed to a circuit that will verify this proof. - -Instead of passing the proof and verification key as a byte array, we pass them -as fields which makes it cheaper to verify in a circuit. - -The proof that is passed here will have been created using a circuit -that has the #[recursive] attribute on its `main` method. - -The number of public inputs denotes how many public inputs are in the inner proof. - -#### Parameters - -| Parameter | Type | Default value | -| :------ | :------ | :------ | -| `proofData` | `ProofData` | `undefined` | -| `numOfPublicInputs` | `number` | `0` | - -#### Returns - -`Promise`\<`object`\> - -#### Example - -```typescript -const artifacts = await backend.generateRecursiveProofArtifacts(proof, numOfPublicInputs); -``` - -*** - -### getVerificationKey() - -```ts -getVerificationKey(): Promise -``` - -#### Returns - -`Promise`\<`Uint8Array`\> - -#### Inherited from - -BarretenbergVerifierBackend.getVerificationKey - -*** - -### verifyProof() - -```ts -verifyProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | `ProofData` | - -#### Returns - -`Promise`\<`boolean`\> - -#### Inherited from - -BarretenbergVerifierBackend.verifyProof - -#### Description - -Verifies a proof - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier.md deleted file mode 100644 index 500276ea748..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier.md +++ /dev/null @@ -1,58 +0,0 @@ -# BarretenbergVerifier - -## Constructors - -### new BarretenbergVerifier(options) - -```ts -new BarretenbergVerifier(options): BarretenbergVerifier -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | - -#### Returns - -[`BarretenbergVerifier`](BarretenbergVerifier.md) - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -*** - -### verifyProof() - -```ts -verifyProof(proofData, verificationKey): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | `ProofData` | -| `verificationKey` | `Uint8Array` | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Verifies a proof - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/index.md deleted file mode 100644 index 64971973196..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/index.md +++ /dev/null @@ -1,59 +0,0 @@ -# backend_barretenberg - -## Exports - -### Classes - -| Class | Description | -| :------ | :------ | -| [BarretenbergBackend](classes/BarretenbergBackend.md) | - | -| [BarretenbergVerifier](classes/BarretenbergVerifier.md) | - | - -### Type Aliases - -| Type alias | Description | -| :------ | :------ | -| [BackendOptions](type-aliases/BackendOptions.md) | - | - -## References - -### CompiledCircuit - -Renames and re-exports [Backend](index.md#backend) - -*** - -### ProofData - -Renames and re-exports [Backend](index.md#backend) - -## Variables - -### Backend - -```ts -Backend: any; -``` - -## Functions - -### publicInputsToWitnessMap() - -```ts -publicInputsToWitnessMap(publicInputs, abi): Backend -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `publicInputs` | `string`[] | -| `abi` | `Abi` | - -#### Returns - -[`Backend`](index.md#backend) - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md deleted file mode 100644 index b49a479f4f4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md +++ /dev/null @@ -1,21 +0,0 @@ -# BackendOptions - -```ts -type BackendOptions: object; -``` - -## Description - -An options object, currently only used to specify the number of threads to use. - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `memory` | `object` | - | -| `memory.maximum` | `number` | - | -| `threads` | `number` | **Description**

Number of threads | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs deleted file mode 100644 index d7d5128f9e3..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend","label":"BarretenbergBackend"},{"type":"doc","id":"reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier","label":"BarretenbergVerifier"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions","label":"BackendOptions"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/.nojekyll deleted file mode 100644 index e2ac6616add..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/classes/Noir.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/classes/Noir.md deleted file mode 100644 index 45dd62ee57e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/classes/Noir.md +++ /dev/null @@ -1,132 +0,0 @@ -# Noir - -## Constructors - -### new Noir(circuit, backend) - -```ts -new Noir(circuit, backend?): Noir -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `circuit` | `CompiledCircuit` | -| `backend`? | `any` | - -#### Returns - -[`Noir`](Noir.md) - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Description - -Destroys the underlying backend instance. - -#### Example - -```typescript -await noir.destroy(); -``` - -*** - -### execute() - -```ts -execute(inputs, foreignCallHandler?): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `inputs` | `InputMap` | -| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | - -#### Returns - -`Promise`\<`object`\> - -#### Description - -Allows to execute a circuit to get its witness and return value. - -#### Example - -```typescript -async execute(inputs) -``` - -*** - -### generateProof() - -```ts -generateProof(inputs, foreignCallHandler?): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `inputs` | `InputMap` | -| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | - -#### Returns - -`Promise`\<`ProofData`\> - -#### Description - -Generates a witness and a proof given an object as input. - -#### Example - -```typescript -async generateProof(input) -``` - -*** - -### verifyProof() - -```ts -verifyProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | `ProofData` | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Instantiates the verification key and verifies a proof. - -#### Example - -```typescript -async verifyProof(proof) -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/and.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/and.md deleted file mode 100644 index c783283e396..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/and.md +++ /dev/null @@ -1,22 +0,0 @@ -# and() - -```ts -and(lhs, rhs): string -``` - -Performs a bitwise AND operation between `lhs` and `rhs` - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `lhs` | `string` | | -| `rhs` | `string` | | - -## Returns - -`string` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/blake2s256.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/blake2s256.md deleted file mode 100644 index 7882d0da8d5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/blake2s256.md +++ /dev/null @@ -1,21 +0,0 @@ -# blake2s256() - -```ts -blake2s256(inputs): Uint8Array -``` - -Calculates the Blake2s256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md deleted file mode 100644 index 5e3cd53e9d3..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md +++ /dev/null @@ -1,28 +0,0 @@ -# ecdsa\_secp256k1\_verify() - -```ts -ecdsa_secp256k1_verify( - hashed_msg, - public_key_x_bytes, - public_key_y_bytes, - signature): boolean -``` - -Verifies a ECDSA signature over the secp256k1 curve. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `hashed_msg` | `Uint8Array` | | -| `public_key_x_bytes` | `Uint8Array` | | -| `public_key_y_bytes` | `Uint8Array` | | -| `signature` | `Uint8Array` | | - -## Returns - -`boolean` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md deleted file mode 100644 index 0b20ff68957..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md +++ /dev/null @@ -1,28 +0,0 @@ -# ecdsa\_secp256r1\_verify() - -```ts -ecdsa_secp256r1_verify( - hashed_msg, - public_key_x_bytes, - public_key_y_bytes, - signature): boolean -``` - -Verifies a ECDSA signature over the secp256r1 curve. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `hashed_msg` | `Uint8Array` | | -| `public_key_x_bytes` | `Uint8Array` | | -| `public_key_y_bytes` | `Uint8Array` | | -| `signature` | `Uint8Array` | | - -## Returns - -`boolean` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/keccak256.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/keccak256.md deleted file mode 100644 index d10f155ce86..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/keccak256.md +++ /dev/null @@ -1,21 +0,0 @@ -# keccak256() - -```ts -keccak256(inputs): Uint8Array -``` - -Calculates the Keccak256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/sha256.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/sha256.md deleted file mode 100644 index 6ba4ecac022..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/sha256.md +++ /dev/null @@ -1,21 +0,0 @@ -# sha256() - -```ts -sha256(inputs): Uint8Array -``` - -Calculates the SHA256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/xor.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/xor.md deleted file mode 100644 index 8d762b895d3..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/xor.md +++ /dev/null @@ -1,22 +0,0 @@ -# xor() - -```ts -xor(lhs, rhs): string -``` - -Performs a bitwise XOR operation between `lhs` and `rhs` - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `lhs` | `string` | | -| `rhs` | `string` | | - -## Returns - -`string` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/index.md deleted file mode 100644 index 40bef8393fc..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/index.md +++ /dev/null @@ -1,55 +0,0 @@ -# noir_js - -## Exports - -### Classes - -| Class | Description | -| :------ | :------ | -| [Noir](classes/Noir.md) | - | - -### Type Aliases - -| Type alias | Description | -| :------ | :------ | -| [ErrorWithPayload](type-aliases/ErrorWithPayload.md) | - | -| [ForeignCallHandler](type-aliases/ForeignCallHandler.md) | A callback which performs an foreign call and returns the response. | -| [ForeignCallInput](type-aliases/ForeignCallInput.md) | - | -| [ForeignCallOutput](type-aliases/ForeignCallOutput.md) | - | -| [WitnessMap](type-aliases/WitnessMap.md) | - | - -### Functions - -| Function | Description | -| :------ | :------ | -| [and](functions/and.md) | Performs a bitwise AND operation between `lhs` and `rhs` | -| [blake2s256](functions/blake2s256.md) | Calculates the Blake2s256 hash of the input bytes | -| [ecdsa\_secp256k1\_verify](functions/ecdsa_secp256k1_verify.md) | Verifies a ECDSA signature over the secp256k1 curve. | -| [ecdsa\_secp256r1\_verify](functions/ecdsa_secp256r1_verify.md) | Verifies a ECDSA signature over the secp256r1 curve. | -| [keccak256](functions/keccak256.md) | Calculates the Keccak256 hash of the input bytes | -| [sha256](functions/sha256.md) | Calculates the SHA256 hash of the input bytes | -| [xor](functions/xor.md) | Performs a bitwise XOR operation between `lhs` and `rhs` | - -## References - -### CompiledCircuit - -Renames and re-exports [InputMap](index.md#inputmap) - -*** - -### ProofData - -Renames and re-exports [InputMap](index.md#inputmap) - -## Variables - -### InputMap - -```ts -InputMap: any; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md deleted file mode 100644 index 812b8b16481..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md +++ /dev/null @@ -1,24 +0,0 @@ -# ForeignCallHandler - -```ts -type ForeignCallHandler: (name, inputs) => Promise; -``` - -A callback which performs an foreign call and returns the response. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `name` | `string` | The identifier for the type of foreign call being performed. | -| `inputs` | [`ForeignCallInput`](ForeignCallInput.md)[] | An array of hex encoded inputs to the foreign call. | - -## Returns - -`Promise`\<[`ForeignCallOutput`](ForeignCallOutput.md)[]\> - -outputs - An array of hex encoded outputs containing the results of the foreign call. - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md deleted file mode 100644 index dd95809186a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md +++ /dev/null @@ -1,9 +0,0 @@ -# ForeignCallInput - -```ts -type ForeignCallInput: string[]; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md deleted file mode 100644 index b71fb78a946..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md +++ /dev/null @@ -1,9 +0,0 @@ -# ForeignCallOutput - -```ts -type ForeignCallOutput: string | string[]; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md deleted file mode 100644 index 258c46f9d0c..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md +++ /dev/null @@ -1,9 +0,0 @@ -# WitnessMap - -```ts -type WitnessMap: Map; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/.nojekyll deleted file mode 100644 index e2ac6616add..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/functions/compile.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/functions/compile.md deleted file mode 100644 index 6faf763b37f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/functions/compile.md +++ /dev/null @@ -1,51 +0,0 @@ -# compile() - -```ts -compile( - fileManager, - projectPath?, - logFn?, -debugLogFn?): Promise -``` - -Compiles a Noir project - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `fileManager` | `FileManager` | The file manager to use | -| `projectPath`? | `string` | The path to the project inside the file manager. Defaults to the root of the file manager | -| `logFn`? | `LogFn` | A logging function. If not provided, console.log will be used | -| `debugLogFn`? | `LogFn` | A debug logging function. If not provided, logFn will be used | - -## Returns - -`Promise`\<[`ProgramCompilationArtifacts`](../index.md#programcompilationartifacts)\> - -## Example - -```typescript -// Node.js - -import { compile_program, createFileManager } from '@noir-lang/noir_wasm'; - -const fm = createFileManager(myProjectPath); -const myCompiledCode = await compile_program(fm); -``` - -```typescript -// Browser - -import { compile_program, createFileManager } from '@noir-lang/noir_wasm'; - -const fm = createFileManager('/'); -for (const path of files) { - await fm.writeFile(path, await getFileAsStream(path)); -} -const myCompiledCode = await compile_program(fm); -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/functions/compile_contract.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/functions/compile_contract.md deleted file mode 100644 index 7d0b39a43ef..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/functions/compile_contract.md +++ /dev/null @@ -1,51 +0,0 @@ -# compile\_contract() - -```ts -compile_contract( - fileManager, - projectPath?, - logFn?, -debugLogFn?): Promise -``` - -Compiles a Noir project - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `fileManager` | `FileManager` | The file manager to use | -| `projectPath`? | `string` | The path to the project inside the file manager. Defaults to the root of the file manager | -| `logFn`? | `LogFn` | A logging function. If not provided, console.log will be used | -| `debugLogFn`? | `LogFn` | A debug logging function. If not provided, logFn will be used | - -## Returns - -`Promise`\<[`ContractCompilationArtifacts`](../index.md#contractcompilationartifacts)\> - -## Example - -```typescript -// Node.js - -import { compile_contract, createFileManager } from '@noir-lang/noir_wasm'; - -const fm = createFileManager(myProjectPath); -const myCompiledCode = await compile_contract(fm); -``` - -```typescript -// Browser - -import { compile_contract, createFileManager } from '@noir-lang/noir_wasm'; - -const fm = createFileManager('/'); -for (const path of files) { - await fm.writeFile(path, await getFileAsStream(path)); -} -const myCompiledCode = await compile_contract(fm); -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/functions/createFileManager.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/functions/createFileManager.md deleted file mode 100644 index 7e65c1d69c7..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/functions/createFileManager.md +++ /dev/null @@ -1,21 +0,0 @@ -# createFileManager() - -```ts -createFileManager(dataDir): FileManager -``` - -Creates a new FileManager instance based on fs in node and memfs in the browser (via webpack alias) - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `dataDir` | `string` | root of the file system | - -## Returns - -`FileManager` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md deleted file mode 100644 index fcea9275341..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md +++ /dev/null @@ -1,21 +0,0 @@ -# inflateDebugSymbols() - -```ts -inflateDebugSymbols(debugSymbols): any -``` - -Decompresses and decodes the debug symbols - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `debugSymbols` | `string` | The base64 encoded debug symbols | - -## Returns - -`any` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/index.md deleted file mode 100644 index b6e0f9d1bc0..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/index.md +++ /dev/null @@ -1,49 +0,0 @@ -# noir_wasm - -## Exports - -### Functions - -| Function | Description | -| :------ | :------ | -| [compile](functions/compile.md) | Compiles a Noir project | -| [compile\_contract](functions/compile_contract.md) | Compiles a Noir project | -| [createFileManager](functions/createFileManager.md) | Creates a new FileManager instance based on fs in node and memfs in the browser (via webpack alias) | -| [inflateDebugSymbols](functions/inflateDebugSymbols.md) | Decompresses and decodes the debug symbols | - -## References - -### compile\_program - -Renames and re-exports [compile](functions/compile.md) - -## Interfaces - -### ContractCompilationArtifacts - -The compilation artifacts of a given contract. - -#### Properties - -| Property | Type | Description | -| :------ | :------ | :------ | -| `contract` | `ContractArtifact` | The compiled contract. | -| `warnings` | `unknown`[] | Compilation warnings. | - -*** - -### ProgramCompilationArtifacts - -The compilation artifacts of a given program. - -#### Properties - -| Property | Type | Description | -| :------ | :------ | :------ | -| `name` | `string` | not part of the compilation output, injected later | -| `program` | `ProgramArtifact` | The compiled contract. | -| `warnings` | `unknown`[] | Compilation warnings. | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs deleted file mode 100644 index e0870710349..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"doc","id":"reference/NoirJS/noir_wasm/index","label":"API"},{"type":"category","label":"Functions","items":[{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/compile","label":"compile"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/compile_contract","label":"compile_contract"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/createFileManager","label":"createFileManager"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/inflateDebugSymbols","label":"inflateDebugSymbols"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/_category_.json deleted file mode 100644 index 5b6a20a609a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 4, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/debugger/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/debugger/_category_.json deleted file mode 100644 index 27869205ad3..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/debugger/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Debugger", - "position": 1, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/debugger/debugger_known_limitations.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/debugger/debugger_known_limitations.md deleted file mode 100644 index 936d416ac4b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/debugger/debugger_known_limitations.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: Known limitations -description: - An overview of known limitations of the current version of the Noir debugger -keywords: - [ - Nargo, - Noir Debugger, - VS Code, - ] -sidebar_position: 2 ---- - -# Debugger Known Limitations - -There are currently some limits to what the debugger can observe. - -## Mutable references - -The debugger is currently blind to any state mutated via a mutable reference. For example, in: - -``` -let mut x = 1; -let y = &mut x; -*y = 2; -``` - -The update on `x` will not be observed by the debugger. That means, when running `vars` from the debugger REPL, or inspecting the _local variables_ pane in the VS Code debugger, `x` will appear with value 1 despite having executed `*y = 2;`. - -## Variables of type function or mutable references are opaque - -When inspecting variables, any variable of type `Function` or `MutableReference` will render its value as `<>` or `<>`. - -## Debugger instrumentation affects resulting ACIR - -In order to make the state of local variables observable, the debugger compiles Noir circuits interleaving foreign calls that track any mutations to them. While this works (except in the cases described above) and doesn't introduce any behavior changes, it does as a side effect produce bigger bytecode. In particular, when running the command `opcodes` on the REPL debugger, you will notice Unconstrained VM blocks that look like this: - -``` -... -5 BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [], q_c: 2 }), Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(2))], q_c: 0 })] - | outputs=[] - 5.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } - 5.1 | Mov { destination: RegisterIndex(3), source: RegisterIndex(1) } - 5.2 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } - 5.3 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } - 5.4 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } - 5.5 | Mov { destination: RegisterIndex(3), source: RegisterIndex(3) } - 5.6 | Call { location: 8 } - 5.7 | Stop - 5.8 | ForeignCall { function: "__debug_var_assign", destinations: [], inputs: [RegisterIndex(RegisterIndex(2)), RegisterIndex(RegisterIndex(3))] } -... -``` - -If you are interested in debugging/inspecting compiled ACIR without these synthetic changes, you can invoke the REPL debugger with the `--skip-instrumentation` flag or launch the VS Code debugger with the `skipConfiguration` property set to true in its launch configuration. You can find more details about those in the [Debugger REPL reference](debugger_repl.md) and the [VS Code Debugger reference](debugger_vscode.md). - -:::note -Skipping debugger instrumentation means you won't be able to inspect values of local variables. -::: - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/debugger/debugger_repl.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/debugger/debugger_repl.md deleted file mode 100644 index 46e2011304e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/debugger/debugger_repl.md +++ /dev/null @@ -1,360 +0,0 @@ ---- -title: REPL Debugger -description: - Noir Debugger REPL options and commands. -keywords: - [ - Nargo, - Noir CLI, - Noir Debugger, - REPL, - ] -sidebar_position: 1 ---- - -## Running the REPL debugger - -`nargo debug [OPTIONS] [WITNESS_NAME]` - -Runs the Noir REPL debugger. If a `WITNESS_NAME` is provided the debugger writes the resulting execution witness to a `WITNESS_NAME` file. - -### Options - -| Option | Description | -| --------------------- | ------------------------------------------------------------ | -| `-p, --prover-name ` | The name of the toml file which contains the inputs for the prover [default: Prover]| -| `--package ` | The name of the package to debug | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -None of these options are required. - -:::note -Since the debugger starts by compiling the target package, all Noir compiler options are also available. Check out the [compiler reference](../nargo_commands.md#nargo-compile) to learn more about the compiler options. -::: - -## REPL commands - -Once the debugger is running, it accepts the following commands. - -#### `help` (h) - -Displays the menu of available commands. - -``` -> help -Available commands: - - opcodes display ACIR opcodes - into step into to the next opcode - next step until a new source location is reached - out step until a new source location is reached - and the current stack frame is finished - break LOCATION:OpcodeLocation add a breakpoint at an opcode location - over step until a new source location is reached - without diving into function calls - restart restart the debugging session - delete LOCATION:OpcodeLocation delete breakpoint at an opcode location - witness show witness map - witness index:u32 display a single witness from the witness map - witness index:u32 value:String update a witness with the given value - memset index:usize value:String update a memory cell with the given - value - continue continue execution until the end of the - program - vars show variable values available at this point - in execution - stacktrace display the current stack trace - memory show memory (valid when executing unconstrained code) value - step step to the next ACIR opcode - -Other commands: - - help Show this help message - quit Quit repl - -``` - -### Stepping through programs - -#### `next` (n) - -Step until the next Noir source code location. While other commands, such as [`into`](#into-i) and [`step`](#step-s), allow for finer grained control of the program's execution at the opcode level, `next` is source code centric. For example: - -``` -3 ... -4 fn main(x: u32) { -5 assert(entry_point(x) == 2); -6 swap_entry_point(x, x + 1); -7 -> assert(deep_entry_point(x) == 4); -8 multiple_values_entry_point(x); -9 } -``` - - -Using `next` here would cause the debugger to jump to the definition of `deep_entry_point` (if available). - -If you want to step over `deep_entry_point` and go straight to line 8, use [the `over` command](#over) instead. - -#### `over` - -Step until the next source code location, without diving into function calls. For example: - -``` -3 ... -4 fn main(x: u32) { -5 assert(entry_point(x) == 2); -6 swap_entry_point(x, x + 1); -7 -> assert(deep_entry_point(x) == 4); -8 multiple_values_entry_point(x); -9 } -``` - - -Using `over` here would cause the debugger to execute until line 8 (`multiple_values_entry_point(x);`). - -If you want to step into `deep_entry_point` instead, use [the `next` command](#next-n). - -#### `out` - -Step until the end of the current function call. For example: - -``` - 3 ... - 4 fn main(x: u32) { - 5 assert(entry_point(x) == 2); - 6 swap_entry_point(x, x + 1); - 7 -> assert(deep_entry_point(x) == 4); - 8 multiple_values_entry_point(x); - 9 } - 10 - 11 unconstrained fn returns_multiple_values(x: u32) -> (u32, u32, u32, u32) { - 12 ... - ... - 55 - 56 unconstrained fn deep_entry_point(x: u32) -> u32 { - 57 -> level_1(x + 1) - 58 } - -``` - -Running `out` here will resume execution until line 8. - -#### `step` (s) - -Skips to the next ACIR code. A compiled Noir program is a sequence of ACIR opcodes. However, an unconstrained VM opcode denotes the start of an unconstrained code block, to be executed by the unconstrained VM. For example (redacted for brevity): - -``` -0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] -1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] - 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } - 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } - 1.2 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } - 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } - 1.4 | Call { location: 7 } - ... - 1.43 | Return -2 EXPR [ (1, _1) -2 ] -``` - -The `->` here shows the debugger paused at an ACIR opcode: `BRILLIG`, at index 1, which denotes an unconstrained code block is about to start. - -Using the `step` command at this point would result in the debugger stopping at ACIR opcode 2, `EXPR`, skipping unconstrained computation steps. - -Use [the `into` command](#into-i) instead if you want to follow unconstrained computation step by step. - -#### `into` (i) - -Steps into the next opcode. A compiled Noir program is a sequence of ACIR opcodes. However, a BRILLIG opcode denotes the start of an unconstrained code block, to be executed by the unconstrained VM. For example (redacted for brevity): - -``` -0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] -1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] - 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } - 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } - 1.2 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } - 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } - 1.4 | Call { location: 7 } - ... - 1.43 | Return -2 EXPR [ (1, _1) -2 ] -``` - -The `->` here shows the debugger paused at an ACIR opcode: `BRILLIG`, at index 1, which denotes an unconstrained code block is about to start. - -Using the `into` command at this point would result in the debugger stopping at opcode 1.0, `Mov ...`, allowing the debugger user to follow unconstrained computation step by step. - -Use [the `step` command](#step-s) instead if you want to skip to the next ACIR code directly. - -#### `continue` (c) - -Continues execution until the next breakpoint, or the end of the program. - -#### `restart` (res) - -Interrupts execution, and restarts a new debugging session from scratch. - -#### `opcodes` (o) - -Display the program's ACIR opcode sequence. For example: - -``` -0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] -1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] - 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } - 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } - 1.2 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } - 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } - 1.4 | Call { location: 7 } - ... - 1.43 | Return -2 EXPR [ (1, _1) -2 ] -``` - -### Breakpoints - -#### `break [Opcode]` (or shorthand `b [Opcode]`) - -Sets a breakpoint on the specified opcode index. To get a list of the program opcode numbers, see [the `opcode` command](#opcodes-o). For example: - -``` -0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] -1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] - 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } - 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } - 1.2 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } - 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } - 1.4 | Call { location: 7 } - ... - 1.43 | Return -2 EXPR [ (1, _1) -2 ] -``` - -In this example, issuing a `break 1.2` command adds break on opcode 1.2, as denoted by the `*` character: - -``` -0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] -1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] - 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } - 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } - 1.2 | * Const { destination: RegisterIndex(1), value: Value { inner: 0 } } - 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } - 1.4 | Call { location: 7 } - ... - 1.43 | Return -2 EXPR [ (1, _1) -2 ] -``` - -Running [the `continue` command](#continue-c) at this point would cause the debugger to execute the program until opcode 1.2. - -#### `delete [Opcode]` (or shorthand `d [Opcode]`) - -Deletes a breakpoint at an opcode location. Usage is analogous to [the `break` command](#). - -### Variable inspection - -#### vars - -Show variable values available at this point in execution. - -:::note -The ability to inspect variable values from the debugger depends on compilation to be run in a special debug instrumentation mode. This instrumentation weaves variable tracing code with the original source code. - -So variable value inspection comes at the expense of making the resulting ACIR bytecode bigger and harder to understand and optimize. - -If you find this compromise unacceptable, you can run the debugger with the flag `--skip-debug-instrumentation`. This will compile your circuit without any additional debug information, so the resulting ACIR bytecode will be identical to the one produced by standard Noir compilation. However, if you opt for this, the `vars` command will not be available while debugging. -::: - - -### Stacktrace - -#### `stacktrace` - -Displays the current stack trace. - - -### Witness map - -#### `witness` (w) - -Show witness map. For example: - -``` -_0 = 0 -_1 = 2 -_2 = 1 -``` - -#### `witness [Witness Index]` - -Display a single witness from the witness map. For example: - -``` -> witness 1 -_1 = 2 -``` - -#### `witness [Witness Index] [New value]` - -Overwrite the given index with a new value. For example: - -``` -> witness 1 3 -_1 = 3 -``` - - -### Unconstrained VM memory - -#### `memory` - -Show unconstrained VM memory state. For example: - -``` -> memory -At opcode 1.13: Store { destination_pointer: RegisterIndex(0), source: RegisterIndex(3) } -... -> registers -0 = 0 -1 = 10 -2 = 0 -3 = 1 -4 = 1 -5 = 2³² -6 = 1 -> into -At opcode 1.14: Const { destination: RegisterIndex(5), value: Value { inner: 1 } } -... -> memory -0 = 1 -> -``` - -In the example above: we start with clean memory, then step through a `Store` opcode which stores the value of register 3 (1) into the memory address stored in register 0 (0). Thus now `memory` shows memory address 0 contains value 1. - -:::note -This command is only functional while the debugger is executing unconstrained code. -::: - -#### `memset [Memory address] [New value]` - -Update a memory cell with the given value. For example: - -``` -> memory -0 = 1 -> memset 0 2 -> memory -0 = 2 -> memset 1 4 -> memory -0 = 2 -1 = 4 -> -``` - -:::note -This command is only functional while the debugger is executing unconstrained code. -::: \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/debugger/debugger_vscode.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/debugger/debugger_vscode.md deleted file mode 100644 index c027332b3b0..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/debugger/debugger_vscode.md +++ /dev/null @@ -1,82 +0,0 @@ ---- -title: VS Code Debugger -description: - VS Code Debugger configuration and features. -keywords: - [ - Nargo, - Noir CLI, - Noir Debugger, - VS Code, - IDE, - ] -sidebar_position: 0 ---- - -# VS Code Noir Debugger Reference - -The Noir debugger enabled by the vscode-noir extension ships with default settings such that the most common scenario should run without any additional configuration steps. - -These defaults can nevertheless be overridden by defining a launch configuration file. This page provides a reference for the properties you can override via a launch configuration file, as well as documenting the Nargo `dap` command, which is a dependency of the VS Code Noir debugger. - - -## Creating and editing launch configuration files - -To create a launch configuration file from VS Code, open the _debug pane_, and click on _create a launch.json file_. - -![Creating a launch configuration file](@site/static/img/debugger/ref1-create-launch.png) - -A `launch.json` file will be created, populated with basic defaults. - -### Noir Debugger launch.json properties - -#### projectFolder - -_String, optional._ - -Absolute path to the Nargo project to debug. By default, it is dynamically determined by looking for the nearest `Nargo.toml` file to the active file at the moment of launching the debugger. - -#### proverName - -_String, optional._ - -Name of the prover input to use. Defaults to `Prover`, which looks for a file named `Prover.toml` at the `projectFolder`. - -#### generateAcir - -_Boolean, optional._ - -If true, generate ACIR opcodes instead of unconstrained opcodes which will be closer to release binaries but less convenient for debugging. Defaults to `false`. - -#### skipInstrumentation - -_Boolean, optional._ - -Skips variables debugging instrumentation of code, making debugging less convenient but the resulting binary smaller and closer to production. Defaults to `false`. - -:::note -Skipping instrumentation causes the debugger to be unable to inspect local variables. -::: - -## `nargo dap [OPTIONS]` - -When run without any option flags, it starts the Nargo Debug Adapter Protocol server, which acts as the debugging backend for the VS Code Noir Debugger. - -All option flags are related to preflight checks. The Debug Adapter Protocol specifies how errors are to be informed from a running DAP server, but it doesn't specify mechanisms to communicate server initialization errors between the DAP server and its client IDE. - -Thus `nargo dap` ships with a _preflight check_ mode. If flag `--preflight-check` and the rest of the `--preflight-*` flags are provided, Nargo will run the same initialization routine except it will not start the DAP server. - -`vscode-noir` will then run `nargo dap` in preflight check mode first before a debugging session starts. If the preflight check ends in error, vscode-noir will present stderr and stdout output from this process through its own Output pane in VS Code. This makes it possible for users to diagnose what pieces of configuration might be wrong or missing in case of initialization errors. - -If the preflight check succeeds, `vscode-noir` proceeds to start the DAP server normally but running `nargo dap` without any additional flags. - -### Options - -| Option | Description | -| --------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | -| `--preflight-check` | If present, dap runs in preflight check mode. | -| `--preflight-project-folder ` | Absolute path to the project to debug for preflight check. | -| `--preflight-prover-name ` | Name of prover file to use for preflight check | -| `--preflight-generate-acir` | Optional. If present, compile in ACIR mode while running preflight check. | -| `--preflight-skip-instrumentation` | Optional. If present, compile without introducing debug instrumentation while running preflight check. | -| `-h, --help` | Print help. | diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/nargo_commands.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/nargo_commands.md deleted file mode 100644 index 519e3dbddc2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/nargo_commands.md +++ /dev/null @@ -1,397 +0,0 @@ ---- -title: Nargo -description: - Noir CLI Commands for Noir Prover and Verifier to create, execute, prove and verify programs, - generate Solidity verifier smart contract and compile into JSON file containing ACIR - representation and ABI of circuit. -keywords: - [ - Nargo, - Noir CLI, - Noir Prover, - Noir Verifier, - generate Solidity verifier, - compile JSON file, - ACIR representation, - ABI of circuit, - TypeScript, - ] -sidebar_position: 0 ---- - -# Command-Line Help for `nargo` - -This document contains the help content for the `nargo` command-line program. - -**Command Overview:** - -* [`nargo`↴](#nargo) -* [`nargo backend`↴](#nargo-backend) -* [`nargo backend current`↴](#nargo-backend-current) -* [`nargo backend ls`↴](#nargo-backend-ls) -* [`nargo backend use`↴](#nargo-backend-use) -* [`nargo backend install`↴](#nargo-backend-install) -* [`nargo backend uninstall`↴](#nargo-backend-uninstall) -* [`nargo check`↴](#nargo-check) -* [`nargo fmt`↴](#nargo-fmt) -* [`nargo codegen-verifier`↴](#nargo-codegen-verifier) -* [`nargo compile`↴](#nargo-compile) -* [`nargo new`↴](#nargo-new) -* [`nargo init`↴](#nargo-init) -* [`nargo execute`↴](#nargo-execute) -* [`nargo prove`↴](#nargo-prove) -* [`nargo verify`↴](#nargo-verify) -* [`nargo test`↴](#nargo-test) -* [`nargo info`↴](#nargo-info) -* [`nargo lsp`↴](#nargo-lsp) - -## `nargo` - -Noir's package manager - -**Usage:** `nargo ` - -###### **Subcommands:** - -* `backend` — Install and select custom backends used to generate and verify proofs -* `check` — Checks the constraint system for errors -* `fmt` — Format the Noir files in a workspace -* `codegen-verifier` — Generates a Solidity verifier smart contract for the program -* `compile` — Compile the program and its secret execution trace into ACIR format -* `new` — Create a Noir project in a new directory -* `init` — Create a Noir project in the current directory -* `execute` — Executes a circuit to calculate its return value -* `prove` — Create proof for this program. The proof is returned as a hex encoded string -* `verify` — Given a proof and a program, verify whether the proof is valid -* `test` — Run the tests for this program -* `info` — Provides detailed information on each of a program's function (represented by a single circuit) -* `lsp` — Starts the Noir LSP server - -###### **Options:** - - - - -## `nargo backend` - -Install and select custom backends used to generate and verify proofs - -**Usage:** `nargo backend ` - -###### **Subcommands:** - -* `current` — Prints the name of the currently active backend -* `ls` — Prints the list of currently installed backends -* `use` — Select the backend to use -* `install` — Install a new backend from a URL -* `uninstall` — Uninstalls a backend - - - -## `nargo backend current` - -Prints the name of the currently active backend - -**Usage:** `nargo backend current` - - - -## `nargo backend ls` - -Prints the list of currently installed backends - -**Usage:** `nargo backend ls` - - - -## `nargo backend use` - -Select the backend to use - -**Usage:** `nargo backend use ` - -###### **Arguments:** - -* `` - - - -## `nargo backend install` - -Install a new backend from a URL - -**Usage:** `nargo backend install ` - -###### **Arguments:** - -* `` — The name of the backend to install -* `` — The URL from which to download the backend - - - -## `nargo backend uninstall` - -Uninstalls a backend - -**Usage:** `nargo backend uninstall ` - -###### **Arguments:** - -* `` — The name of the backend to uninstall - - - -## `nargo check` - -Checks the constraint system for errors - -**Usage:** `nargo check [OPTIONS]` - -###### **Options:** - -* `--package ` — The name of the package to check -* `--workspace` — Check all packages in the workspace -* `--overwrite` — Force overwrite of existing files -* `--expression-width ` — Override the expression width requested by the backend - - Default value: `4` -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings - - - -## `nargo fmt` - -Format the Noir files in a workspace - -**Usage:** `nargo fmt [OPTIONS]` - -###### **Options:** - -* `--check` — Run noirfmt in check mode - - - -## `nargo codegen-verifier` - -Generates a Solidity verifier smart contract for the program - -**Usage:** `nargo codegen-verifier [OPTIONS]` - -###### **Options:** - -* `--package ` — The name of the package to codegen -* `--workspace` — Codegen all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend - - Default value: `4` -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings - - - -## `nargo compile` - -Compile the program and its secret execution trace into ACIR format - -**Usage:** `nargo compile [OPTIONS]` - -###### **Options:** - -* `--package ` — The name of the package to compile -* `--workspace` — Compile all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend - - Default value: `4` -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings - - - -## `nargo new` - -Create a Noir project in a new directory - -**Usage:** `nargo new [OPTIONS] ` - -###### **Arguments:** - -* `` — The path to save the new project - -###### **Options:** - -* `--name ` — Name of the package [default: package directory name] -* `--lib` — Use a library template -* `--bin` — Use a binary template [default] -* `--contract` — Use a contract template - - - -## `nargo init` - -Create a Noir project in the current directory - -**Usage:** `nargo init [OPTIONS]` - -###### **Options:** - -* `--name ` — Name of the package [default: current directory name] -* `--lib` — Use a library template -* `--bin` — Use a binary template [default] -* `--contract` — Use a contract template - - - -## `nargo execute` - -Executes a circuit to calculate its return value - -**Usage:** `nargo execute [OPTIONS] [WITNESS_NAME]` - -###### **Arguments:** - -* `` — Write the execution witness to named file - -###### **Options:** - -* `-p`, `--prover-name ` — The name of the toml file which contains the inputs for the prover - - Default value: `Prover` -* `--package ` — The name of the package to execute -* `--workspace` — Execute all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend - - Default value: `4` -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings -* `--oracle-resolver ` — JSON RPC url to solve oracle calls - - - -## `nargo prove` - -Create proof for this program. The proof is returned as a hex encoded string - -**Usage:** `nargo prove [OPTIONS]` - -###### **Options:** - -* `-p`, `--prover-name ` — The name of the toml file which contains the inputs for the prover - - Default value: `Prover` -* `-v`, `--verifier-name ` — The name of the toml file which contains the inputs for the verifier - - Default value: `Verifier` -* `--verify` — Verify proof after proving -* `--package ` — The name of the package to prove -* `--workspace` — Prove all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend - - Default value: `4` -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings -* `--oracle-resolver ` — JSON RPC url to solve oracle calls - - - -## `nargo verify` - -Given a proof and a program, verify whether the proof is valid - -**Usage:** `nargo verify [OPTIONS]` - -###### **Options:** - -* `-v`, `--verifier-name ` — The name of the toml file which contains the inputs for the verifier - - Default value: `Verifier` -* `--package ` — The name of the package verify -* `--workspace` — Verify all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend - - Default value: `4` -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings - - - -## `nargo test` - -Run the tests for this program - -**Usage:** `nargo test [OPTIONS] [TEST_NAME]` - -###### **Arguments:** - -* `` — If given, only tests with names containing this string will be run - -###### **Options:** - -* `--show-output` — Display output of `println` statements -* `--exact` — Only run tests that match exactly -* `--package ` — The name of the package to test -* `--workspace` — Test all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend - - Default value: `4` -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings -* `--oracle-resolver ` — JSON RPC url to solve oracle calls - - - -## `nargo info` - -Provides detailed information on each of a program's function (represented by a single circuit) - -Current information provided per circuit: 1. The number of ACIR opcodes 2. Counts the final number gates in the circuit used by a backend - -**Usage:** `nargo info [OPTIONS]` - -###### **Options:** - -* `--package ` — The name of the package to detail -* `--workspace` — Detail all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend - - Default value: `4` -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings - - - -## `nargo lsp` - -Starts the Noir LSP server - -Starts an LSP server which allows IDEs such as VS Code to display diagnostics in Noir source. - -VS Code Noir Language Support: https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir - -**Usage:** `nargo lsp` - - - -
- - - This document was generated automatically by - clap-markdown. - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/tooling/debugger.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/tooling/debugger.md deleted file mode 100644 index 9b7565ba9ff..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/tooling/debugger.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Debugger -description: Learn about the Noir Debugger, in its REPL or VS Code versions. -keywords: [Nargo, VSCode, Visual Studio Code, REPL, Debugger] -sidebar_position: 2 ---- - -# Noir Debugger - -There are currently two ways of debugging Noir programs: - -1. From VS Code, via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). -2. Via the REPL debugger, which ships with Nargo. - -In order to use either version of the debugger, you will need to install recent enough versions of Noir, [Nargo](../getting_started/installation/index.md) and vscode-noir: - -- Noir & Nargo ≥0.28.0 -- Noir's VS Code extension ≥0.0.11 - -:::info -At the moment, the debugger supports debugging binary projects, but not contracts. -::: - -We cover the VS Code Noir debugger more in depth in [its VS Code debugger how-to guide](../how_to/debugger/debugging_with_vs_code.md) and [the reference](../reference/debugger/debugger_vscode.md). - -The REPL debugger is discussed at length in [the REPL debugger how-to guide](../how_to/debugger/debugging_with_the_repl.md) and [the reference](../reference/debugger/debugger_repl.md). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/tooling/language_server.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/tooling/language_server.md deleted file mode 100644 index 81e0356ef8a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/tooling/language_server.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Language Server -description: Learn about the Noir Language Server, how to install the components, and configuration that may be required. -keywords: [Nargo, Language Server, LSP, VSCode, Visual Studio Code] -sidebar_position: 0 ---- - -This section helps you install and configure the Noir Language Server. - -The Language Server Protocol (LSP) has two components, the [Server](#language-server) and the [Client](#language-client). Below we describe each in the context of Noir. - -## Language Server - -The Server component is provided by the Nargo command line tool that you installed at the beginning of this guide. -As long as Nargo is installed and you've used it to run other commands in this guide, it should be good to go! - -If you'd like to verify that the `nargo lsp` command is available, you can run `nargo --help` and look for `lsp` in the list of commands. If you see it, you're using a version of Noir with LSP support. - -## Language Client - -The Client component is usually an editor plugin that launches the Server. It communicates LSP messages between the editor and the Server. For example, when you save a file, the Client will alert the Server, so it can try to compile the project and report any errors. - -Currently, Noir provides a Language Client for Visual Studio Code via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). - -> **Note:** Noir's Language Server Protocol support currently assumes users' VSCode workspace root to be the same as users' Noir project root (i.e. where Nargo.toml lies). -> -> If LSP features seem to be missing / malfunctioning, make sure you are opening your Noir project directly (instead of as a sub-folder) in your VSCode instance. - -When your language server is running correctly and the VSCode plugin is installed, you should see handy codelens buttons for compilation, measuring circuit size, execution, and tests: - -![Compile and Execute](@site/static/img/codelens_compile_execute.png) -![Run test](@site/static/img/codelens_run_test.png) - -You should also see your tests in the `testing` panel: - -![Testing panel](@site/static/img/codelens_testing_panel.png) - -### Configuration - -- **Noir: Enable LSP** - If checked, the extension will launch the Language Server via `nargo lsp` and communicate with it. -- **Noir: Nargo Flags** - Additional flags may be specified if you require them to be added when the extension calls `nargo lsp`. -- **Noir: Nargo Path** - An absolute path to a Nargo binary with the `lsp` command. This may be useful if Nargo is not within the `PATH` of your editor. -- **Noir > Trace: Server** - Setting this to `"messages"` or `"verbose"` will log LSP messages between the Client and Server. Useful for debugging. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/tooling/testing.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/tooling/testing.md deleted file mode 100644 index d3e0c522473..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/tooling/testing.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -title: Testing in Noir -description: Learn how to use Nargo to test your Noir program in a quick and easy way -keywords: [Nargo, testing, Noir, compile, test] -sidebar_position: 1 ---- - -You can test your Noir programs using Noir circuits. - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. - -For example if you have a program like: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test] -fn test_add() { - assert(add(2,2) == 4); - assert(add(0,1) == 1); - assert(add(1,0) == 1); -} -``` - -Running `nargo test` will test that the `test_add` function can be executed while satisfying all -the constraints which allows you to test that add returns the expected values. Test functions can't -have any arguments currently. - -### Test fail - -You can write tests that are expected to fail by using the decorator `#[test(should_fail)]`. For example: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test(should_fail)] -fn test_add() { - assert(add(2,2) == 5); -} -``` - -You can be more specific and make it fail with a specific reason by using `should_fail_with = "`: - -```rust -fn main(african_swallow_avg_speed : Field) { - assert(african_swallow_avg_speed == 65, "What is the airspeed velocity of an unladen swallow"); -} - -#[test] -fn test_king_arthur() { - main(65); -} - -#[test(should_fail_with = "What is the airspeed velocity of an unladen swallow")] -fn test_bridgekeeper() { - main(32); -} - -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/tutorials/noirjs_app.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/tutorials/noirjs_app.md deleted file mode 100644 index 3dd9fe7d2b0..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/tutorials/noirjs_app.md +++ /dev/null @@ -1,326 +0,0 @@ ---- -title: Building a web app with NoirJS -description: Learn how to setup a new app that uses Noir to generate and verify zero-knowledge SNARK proofs in a typescript or javascript environment. -keywords: [how to, guide, javascript, typescript, noir, barretenberg, zero-knowledge, proofs, app] -sidebar_position: 0 -pagination_next: noir/concepts/data_types/index ---- - -NoirJS is a set of packages meant to work both in a browser and a server environment. In this tutorial, we will build a simple web app using them. From here, you should get an idea on how to proceed with your own Noir projects! - -You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). - -## Setup - -:::note - -Feel free to use whatever versions, just keep in mind that Nargo and the NoirJS packages are meant to be in sync. For example, Nargo 0.27.x matches `noir_js@0.27.x`, etc. - -In this guide, we will be pinned to 0.27.0. - -::: - -Before we start, we want to make sure we have Node and Nargo installed. - -We start by opening a terminal and executing `node --version`. If we don't get an output like `v20.10.0`, that means node is not installed. Let's do that by following the handy [nvm guide](https://github.com/nvm-sh/nvm?tab=readme-ov-file#install--update-script). - -As for `Nargo`, we can follow the [Nargo guide](../getting_started/installation/index.md) to install it. If you're lazy, just paste this on a terminal and run `noirup`: - -```sh -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -Easy enough. Onwards! - -## Our project - -ZK is a powerful technology. An app that doesn't reveal one of the inputs to _anyone_ is almost unbelievable, yet Noir makes it as easy as a single line of code. - -In fact, it's so simple that it comes nicely packaged in `nargo`. Let's do that! - -### Nargo - -Run: - -`nargo new circuit` - -And... That's about it. Your program is ready to be compiled and run. - -To compile, let's `cd` into the `circuit` folder to enter our project, and call: - -`nargo compile` - -This compiles our circuit into `json` format and add it to a new `target` folder. - -:::info - -At this point in the tutorial, your folder structure should look like this: - -```tree -. -└── circuit <---- our working directory - ├── Nargo.toml - ├── src - │ └── main.nr - └── target - └── circuit.json -``` - -::: - -### Node and Vite - -If you want to explore Nargo, feel free to go on a side-quest now and follow the steps in the -[getting started](../getting_started/hello_noir/index.md) guide. However, we want our app to run on the browser, so we need Vite. - -Vite is a powerful tool to generate static websites. While it provides all kinds of features, let's just go barebones with some good old vanilla JS. - -To do this this, go back to the previous folder (`cd ..`) and create a new vite project by running `npm create vite` and choosing "Vanilla" and "Javascript". - -A wild `vite-project` directory should now appear in your root folder! Let's not waste any time and dive right in: - -```bash -cd vite-project -``` - -### Setting Up Vite and Configuring the Project - -Before we proceed with any coding, let's get our environment tailored for Noir. We'll start by laying down the foundations with a `vite.config.js` file. This little piece of configuration is our secret sauce for making sure everything meshes well with the NoirJS libraries and other special setups we might need, like handling WebAssembly modules. Here’s how you get that going: - -#### Creating the vite.config.js - -In your freshly minted `vite-project` folder, create a new file named `vite.config.js` and open it in your code editor. Paste the following to set the stage: - -```javascript -import { defineConfig } from "vite"; -import copy from "rollup-plugin-copy"; - -export default defineConfig({ - esbuild: { - target: "esnext", - }, - optimizeDeps: { - esbuildOptions: { - target: "esnext", - }, - }, - plugins: [ - copy({ - targets: [ - { src: "node_modules/**/*.wasm", dest: "node_modules/.vite/dist" }, - ], - copySync: true, - hook: "buildStart", - }), - ], - server: { - port: 3000, - }, -}); -``` - -#### Install Dependencies - -Now that our stage is set, install the necessary NoirJS packages along with our other dependencies: - -```bash -npm install && npm install @noir-lang/backend_barretenberg@0.27.0 @noir-lang/noir_js@0.27.0 -npm install rollup-plugin-copy --save-dev -``` - -:::info - -At this point in the tutorial, your folder structure should look like this: - -```tree -. -└── circuit - └── ...etc... -└── vite-project <---- our working directory - └── ...etc... -``` - -::: - -#### Some cleanup - -`npx create vite` is amazing but it creates a bunch of files we don't really need for our simple example. Actually, let's just delete everything except for `vite.config.js`, `index.html`, `main.js` and `package.json`. I feel lighter already. - -![my heart is ready for you, noir.js](@site/static/img/memes/titanic.jpeg) - -## HTML - -Our app won't run like this, of course. We need some working HTML, at least. Let's open our broken-hearted `index.html` and replace everything with this code snippet: - -```html - - - - - - -

Noir app

-
- - -
-
-

Logs

-

Proof

-
- - -``` - -It _could_ be a beautiful UI... Depending on which universe you live in. - -## Some good old vanilla Javascript - -Our love for Noir needs undivided attention, so let's just open `main.js` and delete everything (this is where the romantic scenery becomes a bit creepy). - -Start by pasting in this boilerplate code: - -```js -const setup = async () => { - await Promise.all([ - import('@noir-lang/noirc_abi').then((module) => - module.default(new URL('@noir-lang/noirc_abi/web/noirc_abi_wasm_bg.wasm', import.meta.url).toString()), - ), - import('@noir-lang/acvm_js').then((module) => - module.default(new URL('@noir-lang/acvm_js/web/acvm_js_bg.wasm', import.meta.url).toString()), - ), - ]); -}; - -function display(container, msg) { - const c = document.getElementById(container); - const p = document.createElement('p'); - p.textContent = msg; - c.appendChild(p); -} - -document.getElementById('submitGuess').addEventListener('click', async () => { - try { - // here's where love happens - } catch (err) { - display('logs', 'Oh 💔 Wrong guess'); - } -}); -``` - -The display function doesn't do much. We're simply manipulating our website to see stuff happening. For example, if the proof fails, it will simply log a broken heart 😢 - -As for the `setup` function, it's just a sad reminder that dealing with `wasm` on the browser is not as easy as it should. Just copy, paste, and forget. - -:::info - -At this point in the tutorial, your folder structure should look like this: - -```tree -. -└── circuit - └── ...same as above -└── vite-project - ├── vite.config.js - ├── main.js - ├── package.json - └── index.html -``` - -You'll see other files and folders showing up (like `package-lock.json`, `node_modules`) but you shouldn't have to care about those. - -::: - -## Some NoirJS - -We're starting with the good stuff now. If you've compiled the circuit as described above, you should have a `json` file we want to import at the very top of our `main.js` file: - -```ts -import circuit from '../circuit/target/circuit.json'; -``` - -[Noir is backend-agnostic](../index.mdx#whats-new-about-noir). We write Noir, but we also need a proving backend. That's why we need to import and instantiate the two dependencies we installed above: `BarretenbergBackend` and `Noir`. Let's import them right below: - -```js -import { BarretenbergBackend, BarretenbergVerifier as Verifier } from '@noir-lang/backend_barretenberg'; -import { Noir } from '@noir-lang/noir_js'; -``` - -And instantiate them inside our try-catch block: - -```ts -// try { -const backend = new BarretenbergBackend(circuit); -const noir = new Noir(circuit, backend); -// } -``` - -:::note - -For the remainder of the tutorial, everything will be happening inside the `try` block - -::: - -## Our app - -Now for the app itself. We're capturing whatever is in the input when people press the submit button. Just add this: - -```js -const x = parseInt(document.getElementById('guessInput').value); -const input = { x, y: 2 }; -``` - -Now we're ready to prove stuff! Let's feed some inputs to our circuit and calculate the proof: - -```js -await setup(); // let's squeeze our wasm inits here - -display('logs', 'Generating proof... ⌛'); -const proof = await noir.generateProof(input); -display('logs', 'Generating proof... ✅'); -display('results', proof.proof); -``` - -You're probably eager to see stuff happening, so go and run your app now! - -From your terminal, run `npm run dev`. If it doesn't open a browser for you, just visit `localhost:5173`. You should now see the worst UI ever, with an ugly input. - -![Getting Started 0](@site/static/img/noir_getting_started_1.png) - -Now, our circuit says `fn main(x: Field, y: pub Field)`. This means only the `y` value is public, and it's hardcoded above: `input = { x, y: 2 }`. In other words, you won't need to send your secret`x` to the verifier! - -By inputting any number other than 2 in the input box and clicking "submit", you should get a valid proof. Otherwise the proof won't even generate correctly. By the way, if you're human, you shouldn't be able to understand anything on the "proof" box. That's OK. We like you, human ❤️. - -## Verifying - -Time to celebrate, yes! But we shouldn't trust machines so blindly. Let's add these lines to see our proof being verified: - -```js -display('logs', 'Verifying proof... ⌛'); -const verificationKey = await backend.getVerificationKey(); -const verifier = new Verifier(); -const isValid = await verifier.verifyProof(proof, verificationKey); -if (isValid) display('logs', 'Verifying proof... ✅'); -``` - -You have successfully generated a client-side Noir web app! - -![coded app without math knowledge](@site/static/img/memes/flextape.jpeg) - -## Further Reading - -You can see how noirjs is used in a full stack Next.js hardhat application in the [noir-starter repo here](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat). The example shows how to calculate a proof in the browser and verify it with a deployed Solidity verifier contract from noirjs. - -You should also check out the more advanced examples in the [noir-examples repo](https://github.com/noir-lang/noir-examples), where you'll find reference usage for some cool apps. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/explainers/explainer-oracle.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/explainers/explainer-oracle.md deleted file mode 100644 index b84ca5dd986..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/explainers/explainer-oracle.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: Oracles -description: This guide provides an in-depth understanding of how Oracles work in Noir programming. Learn how to use outside calculations in your programs, constrain oracles, and understand their uses and limitations. -keywords: - - Noir Programming - - Oracles - - JSON-RPC - - Foreign Call Handlers - - Constrained Functions - - Blockchain Programming -sidebar_position: 1 ---- - -If you've seen "The Matrix" you may recall "The Oracle" as Gloria Foster smoking cigarettes and baking cookies. While she appears to "know things", she is actually providing a calculation of a pre-determined future. Noir Oracles are similar, in a way. They don't calculate the future (yet), but they allow you to use outside calculations in your programs. - -![matrix oracle prediction](@site/static/img/memes/matrix_oracle.jpeg) - -A Noir program is usually self-contained. You can pass certain inputs to it, and it will generate a deterministic output for those inputs. But what if you wanted to defer some calculation to an outside process or source? - -Oracles are functions that provide this feature. - -## Use cases - -An example usage for Oracles is proving something on-chain. For example, proving that the ETH-USDC quote was below a certain target at a certain block time. Or even making more complex proofs like proving the ownership of an NFT as an anonymous login method. - -Another interesting use case is to defer expensive calculations to be made outside of the Noir program, and then constraining the result; similar to the use of [unconstrained functions](../noir/concepts//unconstrained.md). - -In short, anything that can be constrained in a Noir program but needs to be fetched from an external source is a great candidate to be used in oracles. - -## Constraining oracles - -Just like in The Matrix, Oracles are powerful. But with great power, comes great responsibility. Just because you're using them in a Noir program doesn't mean they're true. Noir has no superpowers. If you want to prove that Portugal won the Euro Cup 2016, you're still relying on potentially untrusted information. - -To give a concrete example, Alice wants to login to the [NounsDAO](https://nouns.wtf/) forum with her username "noir_nouner" by proving she owns a noun without revealing her ethereum address. Her Noir program could have a oracle call like this: - -```rust -#[oracle(getNoun)] -unconstrained fn get_noun(address: Field) -> Field -``` - -This oracle could naively resolve with the number of Nouns she possesses. However, it is useless as a trusted source, as the oracle could resolve to anything Alice wants. In order to make this oracle call actually useful, Alice would need to constrain the response from the oracle, by proving her address and the noun count belongs to the state tree of the contract. - -In short, **Oracles don't prove anything. Your Noir program does.** - -:::danger - -If you don't constrain the return of your oracle, you could be clearly opening an attack vector on your Noir program. Make double-triple sure that the return of an oracle call is constrained! - -::: - -## How to use Oracles - -On CLI, Nargo resolves oracles by making JSON RPC calls, which means it would require an RPC node to be running. - -In JavaScript, NoirJS accepts and resolves arbitrary call handlers (that is, not limited to JSON) as long as they matches the expected types the developer defines. Refer to [Foreign Call Handler](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) to learn more about NoirJS's call handling. - -If you want to build using oracles, follow through to the [oracle guide](../how_to/how-to-oracles.md) for a simple example on how to do that. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/explainers/explainer-recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/explainers/explainer-recursion.md deleted file mode 100644 index 18846176ca7..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/explainers/explainer-recursion.md +++ /dev/null @@ -1,176 +0,0 @@ ---- -title: Recursive proofs -description: Explore the concept of recursive proofs in Zero-Knowledge programming. Understand how recursion works in Noir, a language for writing smart contracts on the EVM blockchain. Learn through practical examples like Alice and Bob's guessing game, Charlie's recursive merkle tree, and Daniel's reusable components. Discover how to use recursive proofs to optimize computational resources and improve efficiency. - -keywords: - [ - "Recursive Proofs", - "Zero-Knowledge Programming", - "Noir", - "EVM Blockchain", - "Smart Contracts", - "Recursion in Noir", - "Alice and Bob Guessing Game", - "Recursive Merkle Tree", - "Reusable Components", - "Optimizing Computational Resources", - "Improving Efficiency", - "Verification Key", - "Aggregation", - "Recursive zkSNARK schemes", - "PLONK", - "Proving and Verification Keys" - ] -sidebar_position: 1 -pagination_next: how_to/how-to-recursion ---- - -In programming, we tend to think of recursion as something calling itself. A classic example would be the calculation of the factorial of a number: - -```js -function factorial(n) { - if (n === 0 || n === 1) { - return 1; - } else { - return n * factorial(n - 1); - } -} -``` - -In this case, while `n` is not `1`, this function will keep calling itself until it hits the base case, bubbling up the result on the call stack: - -```md - Is `n` 1? <--------- - /\ / - / \ n = n -1 - / \ / - Yes No -------- -``` - -In Zero-Knowledge, recursion has some similarities. - -It is not a Noir function calling itself, but a proof being used as an input to another circuit. In short, you verify one proof *inside* another proof, returning the proof that both proofs are valid. - -This means that, given enough computational resources, you can prove the correctness of any arbitrary number of proofs in a single proof. This could be useful to design state channels (for which a common example would be [Bitcoin's Lightning Network](https://en.wikipedia.org/wiki/Lightning_Network)), to save on gas costs by settling one proof on-chain, or simply to make business logic less dependent on a consensus mechanism. - -## Examples - -Let us look at some of these examples - -### Alice and Bob - Guessing game - -Alice and Bob are friends, and they like guessing games. They want to play a guessing game online, but for that, they need a trusted third-party that knows both of their secrets and finishes the game once someone wins. - -So, they use zero-knowledge proofs. Alice tries to guess Bob's number, and Bob will generate a ZK proof stating whether she succeeded or failed. - -This ZK proof can go on a smart contract, revealing the winner and even giving prizes. However, this means every turn needs to be verified on-chain. This incurs some cost and waiting time that may simply make the game too expensive or time-consuming to be worth it. - -As a solution, Alice proposes the following: "what if Bob generates his proof, and instead of sending it on-chain, I verify it *within* my own proof before playing my own turn?". - -She can then generate a proof that she verified his proof, and so on. - -```md - Did you fail? <-------------------------- - / \ / - / \ n = n -1 - / \ / - Yes No / - | | / - | | / - | You win / - | / - | / -Generate proof of that / - + / - my own guess ---------------- -``` - -### Charlie - Recursive merkle tree - -Charlie is a concerned citizen, and wants to be sure his vote in an election is accounted for. He votes with a ZK proof, but he has no way of knowing that his ZK proof was included in the total vote count! - -If the vote collector puts all of the votes into a [Merkle tree](https://en.wikipedia.org/wiki/Merkle_tree), everyone can prove the verification of two proofs within one proof, as such: - -```md - abcd - __________|______________ - | | - ab cd - _____|_____ ______|______ - | | | | - alice bob charlie daniel -``` - -Doing this recursively allows us to arrive on a final proof `abcd` which if true, verifies the correctness of all the votes. - -### Daniel - Reusable components - -Daniel has a big circuit and a big headache. A part of his circuit is a setup phase that finishes with some assertions that need to be made. But that section alone takes most of the proving time, and is largely independent of the rest of the circuit. - -He might find it more efficient to generate a proof for that setup phase separately, and verify that proof recursively in the actual business logic section of his circuit. This will allow for parallelization of both proofs, which results in a considerable speedup. - -## What params do I need - -As you can see in the [recursion reference](noir/standard_library/recursion.md), a simple recursive proof requires: - -- The proof to verify -- The Verification Key of the circuit that generated the proof -- A hash of this verification key, as it's needed for some backends -- The public inputs for the proof - -:::info - -Recursive zkSNARK schemes do not necessarily "verify a proof" in the sense that you expect a true or false to be spit out by the verifier. Rather an aggregation object is built over the public inputs. - -So, taking the example of Alice and Bob and their guessing game: - -- Alice makes her guess. Her proof is *not* recursive: it doesn't verify any proof within it! It's just a standard `assert(x != y)` circuit -- Bob verifies Alice's proof and makes his own guess. In this circuit, he doesn't exactly *prove* the verification of Alice's proof. Instead, he *aggregates* his proof to Alice's proof. The actual verification is done when the full proof is verified, for example when using `nargo verify` or through the verifier smart contract. - -We can imagine recursive proofs a [relay race](https://en.wikipedia.org/wiki/Relay_race). The first runner doesn't have to receive the baton from anyone else, as he/she already starts with it. But when his/her turn is over, the next runner needs to receive it, run a bit more, and pass it along. Even though every runner could theoretically verify the baton mid-run (why not? 🏃🔍), only at the end of the race does the referee verify that the whole race is valid. - -::: - -## Some architecture - -As with everything in computer science, there's no one-size-fits all. But there are some patterns that could help understanding and implementing them. To give three examples: - -### Adding some logic to a proof verification - -This would be an approach for something like our guessing game, where proofs are sent back and forth and are verified by each opponent. This circuit would be divided in two sections: - -- A `recursive verification` section, which would be just the call to `std::verify_proof`, and that would be skipped on the first move (since there's no proof to verify) -- A `guessing` section, which is basically the logic part where the actual guessing happens - -In such a situation, and assuming Alice is first, she would skip the first part and try to guess Bob's number. Bob would then verify her proof on the first section of his run, and try to guess Alice's number on the second part, and so on. - -### Aggregating proofs - -In some one-way interaction situations, recursion would allow for aggregation of simple proofs that don't need to be immediately verified on-chain or elsewhere. - -To give a practical example, a barman wouldn't need to verify a "proof-of-age" on-chain every time he serves alcohol to a customer. Instead, the architecture would comprise two circuits: - -- A `main`, non-recursive circuit with some logic -- A `recursive` circuit meant to verify two proofs in one proof - -The customer's proofs would be intermediate, and made on their phones, and the barman could just verify them locally. He would then aggregate them into a final proof sent on-chain (or elsewhere) at the end of the day. - -### Recursively verifying different circuits - -Nothing prevents you from verifying different circuits in a recursive proof, for example: - -- A `circuit1` circuit -- A `circuit2` circuit -- A `recursive` circuit - -In this example, a regulator could verify that taxes were paid for a specific purchase by aggregating both a `payer` circuit (proving that a purchase was made and taxes were paid), and a `receipt` circuit (proving that the payment was received) - -## How fast is it - -At the time of writing, verifying recursive proofs is surprisingly fast. This is because most of the time is spent on generating the verification key that will be used to generate the next proof. So you are able to cache the verification key and reuse it later. - -Currently, Noir JS packages don't expose the functionality of loading proving and verification keys, but that feature exists in the underlying `bb.js` package. - -## How can I try it - -Learn more about using recursion in Nargo and NoirJS in the [how-to guide](../how_to/how-to-recursion.md) and see a full example in [noir-examples](https://github.com/noir-lang/noir-examples). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/_category_.json deleted file mode 100644 index 5d694210bbf..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 0, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/installation/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/installation/_category_.json deleted file mode 100644 index 0c02fb5d4d7..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/installation/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "position": 0, - "label": "Install Nargo", - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/installation/other_install_methods.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/installation/other_install_methods.md deleted file mode 100644 index 3634723562b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/installation/other_install_methods.md +++ /dev/null @@ -1,102 +0,0 @@ ---- -title: Alternative Installations -description: There are different ways to install Nargo, the one-stop shop and command-line tool for developing Noir programs. This guide explains how to specify which version to install when using noirup, and using WSL for windows. -keywords: [ - Installation - Nargo - Noirup - Binaries - Compiling from Source - WSL for Windows - macOS - Linux - Nix - Direnv - Uninstalling Nargo - ] -sidebar_position: 1 ---- - -## Encouraged Installation Method: Noirup - -Noirup is the endorsed method for installing Nargo, streamlining the process of fetching binaries or compiling from source. It supports a range of options to cater to your specific needs, from nightly builds and specific versions to compiling from various sources. - -### Installing Noirup - -First, ensure you have `noirup` installed: - -```sh -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -### Fetching Binaries - -With `noirup`, you can easily switch between different Nargo versions, including nightly builds: - -- **Nightly Version**: Install the latest nightly build. - - ```sh - noirup --version nightly - ``` - -- **Specific Version**: Install a specific version of Nargo. - ```sh - noirup --version - ``` - -### Compiling from Source - -`noirup` also enables compiling Nargo from various sources: - -- **From a Specific Branch**: Install from the latest commit on a branch. - - ```sh - noirup --branch - ``` - -- **From a Fork**: Install from the main branch of a fork. - - ```sh - noirup --repo - ``` - -- **From a Specific Branch in a Fork**: Install from a specific branch in a fork. - - ```sh - noirup --repo --branch - ``` - -- **From a Specific Pull Request**: Install from a specific PR. - - ```sh - noirup --pr - ``` - -- **From a Specific Commit**: Install from a specific commit. - - ```sh - noirup -C - ``` - -- **From Local Source**: Compile and install from a local directory. - ```sh - noirup --path ./path/to/local/source - ``` - -## Installation on Windows - -The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed natively. However, it is available by using Windows Subsystem for Linux (WSL). - -Step 1: Follow the instructions [here](https://learn.microsoft.com/en-us/windows/wsl/install) to install and run WSL. - -step 2: Follow the [Noirup instructions](#encouraged-installation-method-noirup). - -## Uninstalling Nargo - -If you installed Nargo with `noirup`, you can uninstall Nargo by removing the files in `~/.nargo`, `~/nargo`, and `~/noir_cache`. This ensures that all installed binaries, configurations, and cache related to Nargo are fully removed from your system. - -```bash -rm -r ~/.nargo -rm -r ~/nargo -rm -r ~/noir_cache -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/_category_.json deleted file mode 100644 index 23b560f610b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 1, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/debugger/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/debugger/_category_.json deleted file mode 100644 index cc2cbb1c253..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/debugger/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Debugging", - "position": 5, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/debugger/debugging_with_the_repl.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/debugger/debugging_with_the_repl.md deleted file mode 100644 index 09e5bae68ad..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/debugger/debugging_with_the_repl.md +++ /dev/null @@ -1,164 +0,0 @@ ---- -title: Using the REPL Debugger -description: - Step by step guide on how to debug your Noir circuits with the REPL Debugger. -keywords: - [ - Nargo, - Noir CLI, - Noir Debugger, - REPL, - ] -sidebar_position: 1 ---- - -#### Pre-requisites - -In order to use the REPL debugger, first you need to install recent enough versions of Nargo and vscode-noir. - -## Debugging a simple circuit - -Let's debug a simple circuit: - -```rust -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` - -To start the REPL debugger, using a terminal, go to a Noir circuit's home directory. Then: - -`$ nargo debug` - -You should be seeing this in your terminal: - -``` -[main] Starting debugger -At ~/noir-examples/recursion/circuits/main/src/main.nr:1:9 - 1 -> fn main(x : Field, y : pub Field) { - 2 assert(x != y); - 3 } -> -``` - -The debugger displays the current Noir code location, and it is now waiting for us to drive it. - -Let's first take a look at the available commands. For that we'll use the `help` command. - -``` -> help -Available commands: - - opcodes display ACIR opcodes - into step into to the next opcode - next step until a new source location is reached - out step until a new source location is reached - and the current stack frame is finished - break LOCATION:OpcodeLocation add a breakpoint at an opcode location - over step until a new source location is reached - without diving into function calls - restart restart the debugging session - delete LOCATION:OpcodeLocation delete breakpoint at an opcode location - witness show witness map - witness index:u32 display a single witness from the witness map - witness index:u32 value:String update a witness with the given value - memset index:usize value:String update a memory cell with the given - value - continue continue execution until the end of the - program - vars show variable values available at this point - in execution - stacktrace display the current stack trace - memory show memory (valid when executing unconstrained code) - step step to the next ACIR opcode - -Other commands: - - help Show this help message - quit Quit repl - -``` - -Some commands operate only for unconstrained functions, such as `memory` and `memset`. If you try to use them while execution is paused at an ACIR opcode, the debugger will simply inform you that you are not executing unconstrained code: - -``` -> memory -Unconstrained VM memory not available -> -``` - -Before continuing, we can take a look at the initial witness map: - -``` -> witness -_0 = 1 -_1 = 2 -> -``` - -Cool, since `x==1`, `y==2`, and we want to check that `x != y`, our circuit should succeed. At this point we could intervene and use the witness setter command to change one of the witnesses. Let's set `y=3`, then back to 2, so we don't affect the expected result: - -``` -> witness -_0 = 1 -_1 = 2 -> witness 1 3 -_1 = 3 -> witness -_0 = 1 -_1 = 3 -> witness 1 2 -_1 = 2 -> witness -_0 = 1 -_1 = 2 -> -``` - -Now we can inspect the current state of local variables. For that we use the `vars` command. - -``` -> vars -> -``` - -We currently have no vars in context, since we are at the entry point of the program. Let's use `next` to execute until the next point in the program. - -``` -> vars -> next -At ~/noir-examples/recursion/circuits/main/src/main.nr:1:20 - 1 -> fn main(x : Field, y : pub Field) { - 2 assert(x != y); - 3 } -> vars -x:Field = 0x01 -``` - -As a result of stepping, the variable `x`, whose initial value comes from the witness map, is now in context and returned by `vars`. - -``` -> next - 1 fn main(x : Field, y : pub Field) { - 2 -> assert(x != y); - 3 } -> vars -y:Field = 0x02 -x:Field = 0x01 -``` - -Stepping again we can finally see both variables and their values. And now we can see that the next assertion should succeed. - -Let's continue to the end: - -``` -> continue -(Continuing execution...) -Finished execution -> q -[main] Circuit witness successfully solved -``` - -Upon quitting the debugger after a solved circuit, the resulting circuit witness gets saved, equivalent to what would happen if we had run the same circuit with `nargo execute`. - -We just went through the basics of debugging using Noir REPL debugger. For a comprehensive reference, check out [the reference page](../../reference/debugger/debugger_repl.md). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/debugger/debugging_with_vs_code.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/debugger/debugging_with_vs_code.md deleted file mode 100644 index a5858c1a5eb..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/debugger/debugging_with_vs_code.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -title: Using the VS Code Debugger -description: - Step by step guide on how to debug your Noir circuits with the VS Code Debugger configuration and features. -keywords: - [ - Nargo, - Noir CLI, - Noir Debugger, - VS Code, - IDE, - ] -sidebar_position: 0 ---- - -This guide will show you how to use VS Code with the vscode-noir extension to debug a Noir project. - -#### Pre-requisites - -- Nargo -- vscode-noir -- A Noir project with a `Nargo.toml`, `Prover.toml` and at least one Noir (`.nr`) containing an entry point function (typically `main`). - -## Running the debugger - -The easiest way to start debugging is to open the file you want to debug, and press `F5`. This will cause the debugger to launch, using your `Prover.toml` file as input. - -You should see something like this: - -![Debugger launched](@site/static/img/debugger/1-started.png) - -Let's inspect the state of the program. For that, we open VS Code's _Debug pane_. Look for this icon: - -![Debug pane icon](@site/static/img/debugger/2-icon.png) - -You will now see two categories of variables: Locals and Witness Map. - -![Debug pane expanded](@site/static/img/debugger/3-debug-pane.png) - -1. **Locals**: variables of your program. At this point in execution this section is empty, but as we step through the code it will get populated by `x`, `result`, `digest`, etc. - -2. **Witness map**: these are initially populated from your project's `Prover.toml` file. In this example, they will be used to populate `x` and `result` at the beginning of the `main` function. - -Most of the time you will probably be focusing mostly on locals, as they represent the high level state of your program. - -You might be interested in inspecting the witness map in case you are trying to solve a really low level issue in the compiler or runtime itself, so this concerns mostly advanced or niche users. - -Let's step through the program, by using the debugger buttons or their corresponding keyboard shortcuts. - -![Debugger buttons](@site/static/img/debugger/4-debugger-buttons.png) - -Now we can see in the variables pane that there's values for `digest`, `result` and `x`. - -![Inspecting locals](@site/static/img/debugger/5-assert.png) - -We can also inspect the values of variables by directly hovering on them on the code. - -![Hover locals](@site/static/img/debugger/6-hover.png) - -Let's set a break point at the `keccak256` function, so we can continue execution up to the point when it's first invoked without having to go one step at a time. - -We just need to click the to the right of the line number 18. Once the breakpoint appears, we can click the `continue` button or use its corresponding keyboard shortcut (`F5` by default). - -![Breakpoint](@site/static/img/debugger/7-break.png) - -Now we are debugging the `keccak256` function, notice the _Call Stack pane_ at the lower right. This lets us inspect the current call stack of our process. - -That covers most of the current debugger functionalities. Check out [the reference](../../reference/debugger/debugger_vscode.md) for more details on how to configure the debugger. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/using-devcontainers.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/using-devcontainers.mdx deleted file mode 100644 index 727ec6ca667..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/using-devcontainers.mdx +++ /dev/null @@ -1,110 +0,0 @@ ---- -title: Developer Containers and Codespaces -description: "Learn how to set up a devcontainer in your GitHub repository for a seamless coding experience with Codespaces. Follow our easy 8-step guide to create your own Noir environment without installing Nargo locally." -keywords: ["Devcontainer", "Codespaces", "GitHub", "Noir Environment", "Docker Image", "Development Environment", "Remote Coding", "GitHub Codespaces", "Noir Programming", "Nargo", "VSCode Extensions", "Noirup"] -sidebar_position: 1 ---- - -Adding a developer container configuration file to your Noir project is one of the easiest way to unlock coding in browser. - -## What's a devcontainer after all? - -A [Developer Container](https://containers.dev/) (devcontainer for short) is a Docker image that comes preloaded with tools, extensions, and other tools you need to quickly get started or continue a project, without having to install Nargo locally. Think of it as a development environment in a box. - -There are many advantages to this: - -- It's platform and architecture agnostic -- You don't need to have an IDE installed, or Nargo, or use a terminal at all -- It's safer for using on a public machine or public network - -One of the best ways of using devcontainers is... not using your machine at all, for maximum control, performance, and ease of use. -Enter Codespaces. - -## Codespaces - -If a devcontainer is just a Docker image, then what stops you from provisioning a `p3dn.24xlarge` AWS EC2 instance with 92 vCPUs and 768 GiB RAM and using it to prove your 10-gate SNARK proof? - -Nothing! Except perhaps the 30-40$ per hour it will cost you. - -The problem is that provisioning takes time, and I bet you don't want to see the AWS console every time you want to code something real quick. - -Fortunately, there's an easy and free way to get a decent remote machine ready and loaded in less than 2 minutes: Codespaces. [Codespaces is a Github feature](https://github.com/features/codespaces) that allows you to code in a remote machine by using devcontainers, and it's pretty cool: - -- You can start coding Noir in less than a minute -- It uses the resources of a remote machine, so you can code on your grandma's phone if needed be -- It makes it easy to share work with your frens -- It's fully reusable, you can stop and restart whenever you need to - -:::info - -Don't take out your wallet just yet. Free GitHub accounts get about [15-60 hours of coding](https://github.com/features/codespaces) for free per month, depending on the size of your provisioned machine. - -::: - -## Tell me it's _actually_ easy - -It is! - -Github comes with a default codespace and you can use it to code your own devcontainer. That's exactly what we will be doing in this guide. - - - -8 simple steps: - -#### 1. Create a new repository on GitHub. - -#### 2. Click "Start coding with Codespaces". This will use the default image. - -#### 3. Create a folder called `.devcontainer` in the root of your repository. - -#### 4. Create a Dockerfile in that folder, and paste the following code: - -```docker -FROM --platform=linux/amd64 node:lts-bookworm-slim -SHELL ["/bin/bash", "-c"] -RUN apt update && apt install -y curl bash git tar gzip libc++-dev -RUN curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -ENV PATH="/root/.nargo/bin:$PATH" -RUN noirup -ENTRYPOINT ["nargo"] -``` -#### 5. Create a file called `devcontainer.json` in the same folder, and paste the following code: - -```json -{ - "name": "Noir on Codespaces", - "build": { - "context": ".", - "dockerfile": "Dockerfile" - }, - "customizations": { - "vscode": { - "extensions": ["noir-lang.vscode-noir"] - } - } -} -``` -#### 6. Commit and push your changes - -This will pull the new image and build it, so it could take a minute or so - -#### 8. Done! -Just wait for the build to finish, and there's your easy Noir environment. - - -Refer to [noir-starter](https://github.com/noir-lang/noir-starter/) as an example of how devcontainers can be used together with codespaces. - - - -## How do I use it? - -Using the codespace is obviously much easier than setting it up. -Just navigate to your repository and click "Code" -> "Open with Codespaces". It should take a few seconds to load, and you're ready to go. - -:::info - -If you really like the experience, you can add a badge to your readme, links to existing codespaces, and more. -Check out the [official docs](https://docs.github.com/en/codespaces/setting-up-your-project-for-codespaces/setting-up-your-repository/facilitating-quick-creation-and-resumption-of-codespaces) for more info. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/migration_notes.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/migration_notes.md deleted file mode 100644 index 6bd740024e5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/migration_notes.md +++ /dev/null @@ -1,105 +0,0 @@ ---- -title: Migration notes -description: Read about migration notes from previous versions, which could solve problems while updating -keywords: [Noir, notes, migration, updating, upgrading] ---- - -Noir is in full-speed development. Things break fast, wild, and often. This page attempts to leave some notes on errors you might encounter when upgrading and how to resolve them until proper patches are built. - -### `backend encountered an error: libc++.so.1` - -Depending on your OS, you may encounter the following error when running `nargo prove` for the first time: - -```text -The backend encountered an error: "/home/codespace/.nargo/backends/acvm-backend-barretenberg/backend_binary: error while loading shared libraries: libc++.so.1: cannot open shared object file: No such file or directory\n" -``` - -Install the `libc++-dev` library with: - -```bash -sudo apt install libc++-dev -``` - -## ≥0.19 - -### Enforcing `compiler_version` - -From this version on, the compiler will check for the `compiler_version` field in `Nargo.toml`, and will error if it doesn't match the current Nargo version in use. - -To update, please make sure this field in `Nargo.toml` matches the output of `nargo --version`. - -## ≥0.14 - -The index of the [for loops](noir/concepts/control_flow.md#loops) is now of type `u64` instead of `Field`. An example refactor would be: - -```rust -for i in 0..10 { - let i = i as Field; -} -``` - -## ≥v0.11.0 and Nargo backend - -From this version onwards, Nargo starts managing backends through the `nargo backend` command. Upgrading to the versions per usual steps might lead to: - -### `backend encountered an error` - -This is likely due to the existing locally installed version of proving backend (e.g. barretenberg) is incompatible with the version of Nargo in use. - -To fix the issue: - -1. Uninstall the existing backend - -```bash -nargo backend uninstall acvm-backend-barretenberg -``` - -You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. - -2. Reinstall a compatible version of the proving backend. - -If you are using the default barretenberg backend, simply run: - -``` -nargo prove -``` - -with your Noir program. - -This will trigger the download and installation of the latest version of barretenberg compatible with your Nargo in use. - -### `backend encountered an error: illegal instruction` - -On certain Intel-based systems, an `illegal instruction` error may arise due to incompatibility of barretenberg with certain CPU instructions. - -To fix the issue: - -1. Uninstall the existing backend - -```bash -nargo backend uninstall acvm-backend-barretenberg -``` - -You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. - -2. Reinstall a compatible version of the proving backend. - -If you are using the default barretenberg backend, simply run: - -``` -nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/barretenberg-js-binary/raw/master/run-bb.tar.gz -``` - -This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. - -The gzipped file is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. - -Then run: - -``` -DESIRED_BINARY_VERSION=0.8.1 nargo info -``` - -This overrides the bb native binary with a bb.js node application instead, which should be compatible with most if not all hardware. This does come with the drawback of being generally slower than native binary. - -0.8.1 indicates bb.js version 0.8.1, so if you change that it will update to a different version or the default version in the script if none was supplied. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/_category_.json deleted file mode 100644 index 7da08f8a8c5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Concepts", - "position": 0, - "collapsible": true, - "collapsed": true -} \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/assert.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/assert.md deleted file mode 100644 index bcff613a695..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/assert.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Assert Function -description: - Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or - comparison expression that follows to be true, and what happens if the expression is false at - runtime. -keywords: [Noir programming language, assert statement, predicate expression, comparison expression] -sidebar_position: 4 ---- - -Noir includes a special `assert` function which will explicitly constrain the predicate/comparison -expression that follows to be true. If this expression is false at runtime, the program will fail to -be proven. Example: - -```rust -fn main(x : Field, y : Field) { - assert(x == y); -} -``` - -> Assertions only work for predicate operations, such as `==`. If there's any ambiguity on the operation, the program will fail to compile. For example, it is unclear if `assert(x + y)` would check for `x + y == 0` or simply would return `true`. - -You can optionally provide a message to be logged when the assertion fails: - -```rust -assert(x == y, "x and y are not equal"); -``` - -Aside string literals, the optional message can be a format string or any other type supported as input for Noir's [print](../standard_library/logging.md) functions. This feature lets you incorporate runtime variables into your failed assertion logs: - -```rust -assert(x == y, f"Expected x == y, but got {x} == {y}"); -``` - -Using a variable as an assertion message directly: - -```rust -struct myStruct { - myField: Field -} - -let s = myStruct { myField: y }; -assert(s.myField == x, s); -``` - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/comments.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/comments.md deleted file mode 100644 index b51a85f5c94..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/comments.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Comments -description: - Learn how to write comments in Noir programming language. A comment is a line of code that is - ignored by the compiler, but it can be read by programmers. Single-line and multi-line comments - are supported in Noir. -keywords: [Noir programming language, comments, single-line comments, multi-line comments] -sidebar_position: 10 ---- - -A comment is a line in your codebase which the compiler ignores, however it can be read by -programmers. - -Here is a single line comment: - -```rust -// This is a comment and is ignored -``` - -`//` is used to tell the compiler to ignore the rest of the line. - -Noir also supports multi-line block comments. Start a block comment with `/*` and end the block with `*/`. - -Noir does not natively support doc comments. You may be able to use [Rust doc comments](https://doc.rust-lang.org/reference/comments.html) in your code to leverage some Rust documentation build tools with Noir code. - -```rust -/* - This is a block comment describing a complex function. -*/ -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/control_flow.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/control_flow.md deleted file mode 100644 index 045d3c3a5f5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/control_flow.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -title: Control Flow -description: - Learn how to use loops and if expressions in the Noir programming language. Discover the syntax - and examples for for loops and if-else statements. -keywords: [Noir programming language, loops, for loop, if-else statements, Rust syntax] -sidebar_position: 2 ---- - -## If Expressions - -Noir supports `if-else` statements. The syntax is most similar to Rust's where it is not required -for the statement's conditional to be surrounded by parentheses. - -```rust -let a = 0; -let mut x: u32 = 0; - -if a == 0 { - if a != 0 { - x = 6; - } else { - x = 2; - } -} else { - x = 5; - assert(x == 5); -} -assert(x == 2); -``` - -## Loops - -Noir has one kind of loop: the `for` loop. `for` loops allow you to repeat a block of code multiple -times. - -The following block of code between the braces is run 10 times. - -```rust -for i in 0..10 { - // do something -} -``` - -The index for loops is of type `u64`. - -### Break and Continue - -In unconstrained code, `break` and `continue` are also allowed in `for` loops. These are only allowed -in unconstrained code since normal constrained code requires that Noir knows exactly how many iterations -a loop may have. `break` and `continue` can be used like so: - -```rust -for i in 0 .. 10 { - println("Iteration start") - - if i == 2 { - continue; - } - - if i == 5 { - break; - } - - println(i); -} -println("Loop end") -``` - -When used, `break` will end the current loop early and jump to the statement after the for loop. In the example -above, the `break` will stop the loop and jump to the `println("Loop end")`. - -`continue` will stop the current iteration of the loop, and jump to the start of the next iteration. In the example -above, `continue` will jump to `println("Iteration start")` when used. Note that the loop continues as normal after this. -The iteration variable `i` is still increased by one as normal when `continue` is used. - -`break` and `continue` cannot currently be used to jump out of more than a single loop at a time. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_bus.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_bus.md deleted file mode 100644 index e54fc861257..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_bus.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: Data Bus -sidebar_position: 13 ---- -**Disclaimer** this feature is experimental, do not use it! - -The data bus is an optimization that the backend can use to make recursion more efficient. -In order to use it, you must define some inputs of the program entry points (usually the `main()` -function) with the `call_data` modifier, and the return values with the `return_data` modifier. -These modifiers are incompatible with `pub` and `mut` modifiers. - -## Example - -```rust -fn main(mut x: u32, y: call_data u32, z: call_data [u32;4] ) -> return_data u32 { - let a = z[x]; - a+y -} -``` - -As a result, both call_data and return_data will be treated as private inputs and encapsulated into a read-only array each, for the backend to process. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/_category_.json deleted file mode 100644 index 5d694210bbf..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 0, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/arrays.md deleted file mode 100644 index 9b02d52e8a8..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/arrays.md +++ /dev/null @@ -1,253 +0,0 @@ ---- -title: Arrays -description: - Dive into the Array data type in Noir. Grasp its methods, practical examples, and best practices for efficiently using Arrays in your Noir code. -keywords: - [ - noir, - array type, - methods, - examples, - indexing, - ] -sidebar_position: 4 ---- - -An array is one way of grouping together values into one compound type. Array types can be inferred -or explicitly specified via the syntax `[; ]`: - -```rust -fn main(x : Field, y : Field) { - let my_arr = [x, y]; - let your_arr: [Field; 2] = [x, y]; -} -``` - -Here, both `my_arr` and `your_arr` are instantiated as an array containing two `Field` elements. - -Array elements can be accessed using indexing: - -```rust -fn main() { - let a = [1, 2, 3, 4, 5]; - - let first = a[0]; - let second = a[1]; -} -``` - -All elements in an array must be of the same type (i.e. homogeneous). That is, an array cannot group -a `Field` value and a `u8` value together for example. - -You can write mutable arrays, like: - -```rust -fn main() { - let mut arr = [1, 2, 3, 4, 5]; - assert(arr[0] == 1); - - arr[0] = 42; - assert(arr[0] == 42); -} -``` - -You can instantiate a new array of a fixed size with the same value repeated for each element. The following example instantiates an array of length 32 where each element is of type Field and has the value 0. - -```rust -let array: [Field; 32] = [0; 32]; -``` - -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: - -```rust -let array: [Field; 32] = [0; 32]; -let sl = array.as_slice() -``` - -You can define multidimensional arrays: - -```rust -let array : [[Field; 2]; 2]; -let element = array[0][0]; -``` - -However, multidimensional slices are not supported. For example, the following code will error at compile time: - -```rust -let slice : [[Field]] = &[]; -``` - -## Types - -You can create arrays of primitive types or structs. There is not yet support for nested arrays -(arrays of arrays) or arrays of structs that contain arrays. - -## Methods - -For convenience, the STD provides some ready-to-use, common methods for arrays. -Each of these functions are located within the generic impl `impl [T; N] {`. -So anywhere `self` appears, it refers to the variable `self: [T; N]`. - -### len - -Returns the length of an array - -```rust -fn len(self) -> Field -``` - -example - -```rust -fn main() { - let array = [42, 42]; - assert(array.len() == 2); -} -``` - -### sort - -Returns a new sorted array. The original array remains untouched. Notice that this function will -only work for arrays of fields or integers, not for any arbitrary type. This is because the sorting -logic it uses internally is optimized specifically for these values. If you need a sort function to -sort any type, you should use the function `sort_via` described below. - -```rust -fn sort(self) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32]; - let sorted = arr.sort(); - assert(sorted == [32, 42]); -} -``` - -### sort_via - -Sorts the array with a custom comparison function - -```rust -fn sort_via(self, ordering: fn(T, T) -> bool) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32] - let sorted_ascending = arr.sort_via(|a, b| a <= b); - assert(sorted_ascending == [32, 42]); // verifies - - let sorted_descending = arr.sort_via(|a, b| a >= b); - assert(sorted_descending == [32, 42]); // does not verify -} -``` - -### map - -Applies a function to each element of the array, returning a new array containing the mapped elements. - -```rust -fn map(self, f: fn(T) -> U) -> [U; N] -``` - -example - -```rust -let a = [1, 2, 3]; -let b = a.map(|a| a * 2); // b is now [2, 4, 6] -``` - -### fold - -Applies a function to each element of the array, returning the final accumulated value. The first -parameter is the initial value. - -```rust -fn fold(self, mut accumulator: U, f: fn(U, T) -> U) -> U -``` - -This is a left fold, so the given function will be applied to the accumulator and first element of -the array, then the second, and so on. For a given call the expected result would be equivalent to: - -```rust -let a1 = [1]; -let a2 = [1, 2]; -let a3 = [1, 2, 3]; - -let f = |a, b| a - b; -a1.fold(10, f) //=> f(10, 1) -a2.fold(10, f) //=> f(f(10, 1), 2) -a3.fold(10, f) //=> f(f(f(10, 1), 2), 3) -``` - -example: - -```rust - -fn main() { - let arr = [2, 2, 2, 2, 2]; - let folded = arr.fold(0, |a, b| a + b); - assert(folded == 10); -} - -``` - -### reduce - -Same as fold, but uses the first element as starting element. - -```rust -fn reduce(self, f: fn(T, T) -> T) -> T -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let reduced = arr.reduce(|a, b| a + b); - assert(reduced == 10); -} -``` - -### all - -Returns true if all the elements satisfy the given predicate - -```rust -fn all(self, predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let all = arr.all(|a| a == 2); - assert(all); -} -``` - -### any - -Returns true if any of the elements satisfy the given predicate - -```rust -fn any(self, predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 5]; - let any = arr.any(|a| a == 5); - assert(any); -} - -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/fields.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/fields.md deleted file mode 100644 index a10a4810788..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/fields.md +++ /dev/null @@ -1,192 +0,0 @@ ---- -title: Fields -description: - Dive deep into the Field data type in Noir. Understand its methods, practical examples, and best practices to effectively use Fields in your Noir programs. -keywords: - [ - noir, - field type, - methods, - examples, - best practices, - ] -sidebar_position: 0 ---- - -The field type corresponds to the native field type of the proving backend. - -The size of a Noir field depends on the elliptic curve's finite field for the proving backend -adopted. For example, a field would be a 254-bit integer when paired with the default backend that -spans the Grumpkin curve. - -Fields support integer arithmetic and are often used as the default numeric type in Noir: - -```rust -fn main(x : Field, y : Field) { - let z = x + y; -} -``` - -`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new -private value `z` constrained to be equal to `x + y`. - -If proving efficiency is of priority, fields should be used as a default for solving problems. -Smaller integer types (e.g. `u64`) incur extra range constraints. - -## Methods - -After declaring a Field, you can use these common methods on it: - -### to_le_bits - -Transforms the field into an array of bits, Little Endian. - -```rust -fn to_le_bits(_x : Field, _bit_size: u32) -> [u1] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_le_bits(32); -} -``` - -### to_be_bits - -Transforms the field into an array of bits, Big Endian. - -```rust -fn to_be_bits(_x : Field, _bit_size: u32) -> [u1] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_be_bits(32); -} -``` - -### to_le_bytes - -Transforms into an array of bytes, Little Endian - -```rust -fn to_le_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_le_bytes(4); -} -``` - -### to_be_bytes - -Transforms into an array of bytes, Big Endian - -```rust -fn to_be_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_be_bytes(4); -} -``` - -### to_le_radix - -Decomposes into a vector over the specified base, Little Endian - -```rust -fn to_le_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_le_radix(256, 4); -} -``` - -### to_be_radix - -Decomposes into a vector over the specified base, Big Endian - -```rust -fn to_be_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_be_radix(256, 4); -} -``` - -### pow_32 - -Returns the value to the power of the specified exponent - -```rust -fn pow_32(self, exponent: Field) -> Field -``` - -example: - -```rust -fn main() { - let field = 2 - let pow = field.pow_32(4); - assert(pow == 16); -} -``` - -### assert_max_bit_size - -Adds a constraint to specify that the field can be represented with `bit_size` number of bits - -```rust -fn assert_max_bit_size(self, bit_size: u32) -``` - -example: - -```rust -fn main() { - let field = 2 - field.assert_max_bit_size(32); -} -``` - -### sgn0 - -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. - -```rust -fn sgn0(self) -> u1 -``` - - -### lt - -Returns true if the field is less than the other field - -```rust -pub fn lt(self, another: Field) -> bool -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/function_types.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/function_types.md deleted file mode 100644 index f6121af17e2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/function_types.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Function types -sidebar_position: 10 ---- - -Noir supports higher-order functions. The syntax for a function type is as follows: - -```rust -fn(arg1_type, arg2_type, ...) -> return_type -``` - -Example: - -```rust -fn assert_returns_100(f: fn() -> Field) { // f takes no args and returns a Field - assert(f() == 100); -} - -fn main() { - assert_returns_100(|| 100); // ok - assert_returns_100(|| 150); // fails -} -``` - -A function type also has an optional capture environment - this is necessary to support closures. -See [Lambdas](../lambdas.md) for more details. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/index.md deleted file mode 100644 index 357813c147a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/index.md +++ /dev/null @@ -1,110 +0,0 @@ ---- -title: Data Types -description: - Get a clear understanding of the two categories of Noir data types - primitive types and compound - types. Learn about their characteristics, differences, and how to use them in your Noir - programming. -keywords: - [ - noir, - data types, - primitive types, - compound types, - private types, - public types, - ] ---- - -Every value in Noir has a type, which determines which operations are valid for it. - -All values in Noir are fundamentally composed of `Field` elements. For a more approachable -developing experience, abstractions are added on top to introduce different data types in Noir. - -Noir has two category of data types: primitive types (e.g. `Field`, integers, `bool`) and compound -types that group primitive types (e.g. arrays, tuples, structs). Each value can either be private or -public. - -## Private & Public Types - -A **private value** is known only to the Prover, while a **public value** is known by both the -Prover and Verifier. Mark values as `private` when the value should only be known to the prover. All -primitive types (including individual fields of compound types) in Noir are private by default, and -can be marked public when certain values are intended to be revealed to the Verifier. - -> **Note:** For public values defined in Noir programs paired with smart contract verifiers, once -> the proofs are verified on-chain the values can be considered known to everyone that has access to -> that blockchain. - -Public data types are treated no differently to private types apart from the fact that their values -will be revealed in proofs generated. Simply changing the value of a public type will not change the -circuit (where the same goes for changing values of private types as well). - -_Private values_ are also referred to as _witnesses_ sometimes. - -> **Note:** The terms private and public when applied to a type (e.g. `pub Field`) have a different -> meaning than when applied to a function (e.g. `pub fn foo() {}`). -> -> The former is a visibility modifier for the Prover to interpret if a value should be made known to -> the Verifier, while the latter is a visibility modifier for the compiler to interpret if a -> function should be made accessible to external Noir programs like in other languages. - -### pub Modifier - -All data types in Noir are private by default. Types are explicitly declared as public using the -`pub` modifier: - -```rust -fn main(x : Field, y : pub Field) -> pub Field { - x + y -} -``` - -In this example, `x` is **private** while `y` and `x + y` (the return value) are **public**. Note -that visibility is handled **per variable**, so it is perfectly valid to have one input that is -private and another that is public. - -> **Note:** Public types can only be declared through parameters on `main`. - -## Type Aliases - -A type alias is a new name for an existing type. Type aliases are declared with the keyword `type`: - -```rust -type Id = u8; - -fn main() { - let id: Id = 1; - let zero: u8 = 0; - assert(zero + 1 == id); -} -``` - -Type aliases can also be used with [generics](../generics.md): - -```rust -type Id = Size; - -fn main() { - let id: Id = 1; - let zero: u32 = 0; - assert(zero + 1 == id); -} -``` - -Type aliases can even refer to other aliases. An error will be issued if they form a cycle: - -```rust -// Ok! -type A = B; -type B = Field; - -type Bad1 = Bad2; - -// error: Dependency cycle found -type Bad2 = Bad1; -// ^^^^^^^^^^^ 'Bad2' recursively depends on itself: Bad2 -> Bad1 -> Bad2 -``` - -### BigInt - -You can achieve BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/references.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/references.md deleted file mode 100644 index a5293d11cfb..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/references.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: References -sidebar_position: 9 ---- - -Noir supports first-class references. References are a bit like pointers: they point to a specific address that can be followed to access the data stored at that address. You can use Rust-like syntax to use pointers in Noir: the `&` operator references the variable, the `*` operator dereferences it. - -Example: - -```rust -fn main() { - let mut x = 2; - - // you can reference x as &mut and pass it to multiplyBy2 - multiplyBy2(&mut x); -} - -// you can access &mut here -fn multiplyBy2(x: &mut Field) { - // and dereference it with * - *x = *x * 2; -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/structs.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/structs.md deleted file mode 100644 index dbf68c99813..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/structs.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -title: Structs -description: - Explore the Struct data type in Noir. Learn about its methods, see real-world examples, and grasp how to effectively define and use Structs in your Noir programs. -keywords: - [ - noir, - struct type, - methods, - examples, - data structures, - ] -sidebar_position: 8 ---- - -A struct also allows for grouping multiple values of different types. Unlike tuples, we can also -name each field. - -> **Note:** The usage of _field_ here refers to each element of the struct and is unrelated to the -> field type of Noir. - -Defining a struct requires giving it a name and listing each field within as `: ` pairs: - -```rust -struct Animal { - hands: Field, - legs: Field, - eyes: u8, -} -``` - -An instance of a struct can then be created with actual values in `: ` pairs in any -order. Struct fields are accessible using their given names: - -```rust -fn main() { - let legs = 4; - - let dog = Animal { - eyes: 2, - hands: 0, - legs, - }; - - let zero = dog.hands; -} -``` - -Structs can also be destructured in a pattern, binding each field to a new variable: - -```rust -fn main() { - let Animal { hands, legs: feet, eyes } = get_octopus(); - - let ten = hands + feet + eyes as u8; -} - -fn get_octopus() -> Animal { - let octopus = Animal { - hands: 0, - legs: 8, - eyes: 2, - }; - - octopus -} -``` - -The new variables can be bound with names different from the original struct field names, as -showcased in the `legs --> feet` binding in the example above. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/tuples.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/tuples.md deleted file mode 100644 index 2ec5c9c4113..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/tuples.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Tuples -description: - Dive into the Tuple data type in Noir. Understand its methods, practical examples, and best practices for efficiently using Tuples in your Noir code. -keywords: - [ - noir, - tuple type, - methods, - examples, - multi-value containers, - ] -sidebar_position: 7 ---- - -A tuple collects multiple values like an array, but with the added ability to collect values of -different types: - -```rust -fn main() { - let tup: (u8, u64, Field) = (255, 500, 1000); -} -``` - -One way to access tuple elements is via destructuring using pattern matching: - -```rust -fn main() { - let tup = (1, 2); - - let (one, two) = tup; - - let three = one + two; -} -``` - -Another way to access tuple elements is via direct member access, using a period (`.`) followed by -the index of the element we want to access. Index `0` corresponds to the first tuple element, `1` to -the second and so on: - -```rust -fn main() { - let tup = (5, 6, 7, 8); - - let five = tup.0; - let eight = tup.3; -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/functions.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/functions.md deleted file mode 100644 index f656cdfd97a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/functions.md +++ /dev/null @@ -1,226 +0,0 @@ ---- -title: Functions -description: - Learn how to declare functions and methods in Noir, a programming language with Rust semantics. - This guide covers parameter declaration, return types, call expressions, and more. -keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] -sidebar_position: 1 ---- - -Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. - -To declare a function the `fn` keyword is used. - -```rust -fn foo() {} -``` - -By default, functions are visible only within the package they are defined. To make them visible outside of that package (for example, as part of a [library](../modules_packages_crates/crates_and_packages.md#libraries)), you should mark them as `pub`: - -```rust -pub fn foo() {} -``` - -You can also restrict the visibility of the function to only the crate it was defined in, by specifying `pub(crate)`: - -```rust -pub(crate) fn foo() {} //foo can only be called within its crate -``` - -All parameters in a function must have a type and all types are known at compile time. The parameter -is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. - -```rust -fn foo(x : Field, y : Field){} -``` - -The return type of a function can be stated by using the `->` arrow notation. The function below -states that the foo function must return a `Field`. If the function returns no value, then the arrow -is omitted. - -```rust -fn foo(x : Field, y : Field) -> Field { - x + y -} -``` - -Note that a `return` keyword is unneeded in this case - the last expression in a function's body is -returned. - -## Main function - -If you're writing a binary, the `main` function is the starting point of your program. You can pass all types of expressions to it, as long as they have a fixed size at compile time: - -```rust -fn main(x : Field) // this is fine: passing a Field -fn main(x : [Field; 2]) // this is also fine: passing a Field with known size at compile-time -fn main(x : (Field, bool)) // 👌: passing a (Field, bool) tuple means size 2 -fn main(x : str<5>) // this is fine, as long as you pass a string of size 5 - -fn main(x : Vec) // can't compile, has variable size -fn main(x : [Field]) // can't compile, has variable size -fn main(....// i think you got it by now -``` - -Keep in mind [tests](../../tooling/testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: - -```rust -fn main(x : [Field]) { - assert(x[0] == 1); -} - -#[test] -fn test_one() { - main(&[1, 2]); -} -``` - -```bash -$ nargo test -[testing] Running 1 test functions -[testing] Testing test_one... ok -[testing] All tests passed - -$ nargo check -The application panicked (crashed). -Message: Cannot have variable sized arrays as a parameter to main -``` - -## Call Expressions - -Calling a function in Noir is executed by using the function name and passing in the necessary -arguments. - -Below we show how to call the `foo` function from the `main` function using a call expression: - -```rust -fn main(x : Field, y : Field) { - let z = foo(x); -} - -fn foo(x : Field) -> Field { - x + x -} -``` - -## Methods - -You can define methods in Noir on any struct type in scope. - -```rust -struct MyStruct { - foo: Field, - bar: Field, -} - -impl MyStruct { - fn new(foo: Field) -> MyStruct { - MyStruct { - foo, - bar: 2, - } - } - - fn sum(self) -> Field { - self.foo + self.bar - } -} - -fn main() { - let s = MyStruct::new(40); - assert(s.sum() == 42); -} -``` - -Methods are just syntactic sugar for functions, so if we wanted to we could also call `sum` as -follows: - -```rust -assert(MyStruct::sum(s) == 42); -``` - -It is also possible to specialize which method is chosen depending on the [generic](./generics.md) type that is used. In this example, the `foo` function returns different values depending on its type: - -```rust -struct Foo {} - -impl Foo { - fn foo(self) -> Field { 1 } -} - -impl Foo { - fn foo(self) -> Field { 2 } -} - -fn main() { - let f1: Foo = Foo{}; - let f2: Foo = Foo{}; - assert(f1.foo() + f2.foo() == 3); -} -``` - -Also note that impls with the same method name defined in them cannot overlap. For example, if we already have `foo` defined for `Foo` and `Foo` like we do above, we cannot also define `foo` in an `impl Foo` since it would be ambiguous which version of `foo` to choose. - -```rust -// Including this impl in the same project as the above snippet would -// cause an overlapping impls error -impl Foo { - fn foo(self) -> Field { 3 } -} -``` - -## Lambdas - -Lambdas are anonymous functions. They follow the syntax of Rust - `|arg1, arg2, ..., argN| return_expression`. - -```rust -let add_50 = |val| val + 50; -assert(add_50(100) == 150); -``` - -See [Lambdas](./lambdas.md) for more details. - -## Attributes - -Attributes are metadata that can be applied to a function, using the following syntax: `#[attribute(value)]`. - -Supported attributes include: - -- **builtin**: the function is implemented by the compiler, for efficiency purposes. -- **deprecated**: mark the function as _deprecated_. Calling the function will generate a warning: `warning: use of deprecated function` -- **field**: Used to enable conditional compilation of code depending on the field size. See below for more details -- **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./unconstrained.md) and [NoirJS](../../reference/NoirJS/noir_js/index.md) for more details. -- **test**: mark the function as unit tests. See [Tests](../../tooling/testing.md) for more details - -### Field Attribute - -The field attribute defines which field the function is compatible for. The function is conditionally compiled, under the condition that the field attribute matches the Noir native field. -The field can be defined implicitly, by using the name of the elliptic curve usually associated to it - for instance bn254, bls12_381 - or explicitly by using the field (prime) order, in decimal or hexadecimal form. -As a result, it is possible to define multiple versions of a function with each version specialized for a different field attribute. This can be useful when a function requires different parameters depending on the underlying elliptic curve. - -Example: we define the function `foo()` three times below. Once for the default Noir bn254 curve, once for the field $\mathbb F_{23}$, which will normally never be used by Noir, and once again for the bls12_381 curve. - -```rust -#[field(bn254)] -fn foo() -> u32 { - 1 -} - -#[field(23)] -fn foo() -> u32 { - 2 -} - -// This commented code would not compile as foo would be defined twice because it is the same field as bn254 -// #[field(21888242871839275222246405745257275088548364400416034343698204186575808495617)] -// fn foo() -> u32 { -// 2 -// } - -#[field(bls12_381)] -fn foo() -> u32 { - 3 -} -``` - -If the field name is not known to Noir, it will discard the function. Field names are case insensitive. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/generics.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/generics.md deleted file mode 100644 index 0c1c27a2221..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/generics.md +++ /dev/null @@ -1,106 +0,0 @@ ---- -title: Generics -description: Learn how to use Generics in Noir -keywords: [Noir, Rust, generics, functions, structs] -sidebar_position: 7 ---- - -Generics allow you to use the same functions with multiple different concrete data types. You can -read more about the concept of generics in the Rust documentation -[here](https://doc.rust-lang.org/book/ch10-01-syntax.html). - -Here is a trivial example showing the identity function that supports any type. In Rust, it is -common to refer to the most general type as `T`. We follow the same convention in Noir. - -```rust -fn id(x: T) -> T { - x -} -``` - -## In Structs - -Generics are useful for specifying types in structs. For example, we can specify that a field in a -struct will be of a certain generic type. In this case `value` is of type `T`. - -```rust -struct RepeatedValue { - value: T, - count: Field, -} - -impl RepeatedValue { - fn print(self) { - for _i in 0 .. self.count { - println(self.value); - } - } -} - -fn main() { - let repeated = RepeatedValue { value: "Hello!", count: 2 }; - repeated.print(); -} -``` - -The `print` function will print `Hello!` an arbitrary number of times, twice in this case. - -If we want to be generic over array lengths (which are type-level integers), we can use numeric -generics. Using these looks just like using regular generics, but these generics can resolve to -integers at compile-time, rather than resolving to types. Here's an example of a struct that is -generic over the size of the array it contains internally: - -```rust -struct BigInt { - limbs: [u32; N], -} - -impl BigInt { - // `N` is in scope of all methods in the impl - fn first(first: BigInt, second: BigInt) -> Self { - assert(first.limbs != second.limbs); - first - - fn second(first: BigInt, second: Self) -> Self { - assert(first.limbs != second.limbs); - second - } -} -``` - -## Calling functions on generic parameters - -Since a generic type `T` can represent any type, how can we call functions on the underlying type? -In other words, how can we go from "any type `T`" to "any type `T` that has certain methods available?" - -This is what [traits](../concepts/traits.md) are for in Noir. Here's an example of a function generic over -any type `T` that implements the `Eq` trait for equality: - -```rust -fn first_element_is_equal(array1: [T; N], array2: [T; N]) -> bool - where T: Eq -{ - if (array1.len() == 0) | (array2.len() == 0) { - true - } else { - array1[0] == array2[0] - } -} - -fn main() { - assert(first_element_is_equal([1, 2, 3], [1, 5, 6])); - - // We can use first_element_is_equal for arrays of any type - // as long as we have an Eq impl for the types we pass in - let array = [MyStruct::new(), MyStruct::new()]; - assert(array_eq(array, array, MyStruct::eq)); -} - -impl Eq for MyStruct { - fn eq(self, other: MyStruct) -> bool { - self.foo == other.foo - } -} -``` - -You can find more details on traits and trait implementations on the [traits page](../concepts/traits.md). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/globals.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/globals.md deleted file mode 100644 index 063a3d89248..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/globals.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -title: Global Variables -description: - Learn about global variables in Noir. Discover how - to declare, modify, and use them in your programs. -keywords: [noir programming language, globals, global variables, constants] -sidebar_position: 8 ---- - -## Globals - - -Noir supports global variables. The global's type can be inferred by the compiler entirely: - -```rust -global N = 5; // Same as `global N: Field = 5` - -global TUPLE = (3, 2); - -fn main() { - assert(N == 5); - assert(N == TUPLE.0 + TUPLE.1); -} -``` - -:::info - -Globals can be defined as any expression, so long as they don't depend on themselves - otherwise there would be a dependency cycle! For example: - -```rust -global T = foo(T); // dependency error -``` - -::: - - -If they are initialized to a literal integer, globals can be used to specify an array's length: - -```rust -global N: Field = 2; - -fn main(y : [Field; N]) { - assert(y[0] == y[1]) -} -``` - -A global from another module can be imported or referenced externally like any other name: - -```rust -global N = 20; - -fn main() { - assert(my_submodule::N != N); -} - -mod my_submodule { - global N: Field = 10; -} -``` - -When a global is used, Noir replaces the name with its definition on each occurrence. -This means globals defined using function calls will repeat the call each time they're used: - -```rust -global RESULT = foo(); - -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. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/lambdas.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/lambdas.md deleted file mode 100644 index be3c7e0b5ca..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/lambdas.md +++ /dev/null @@ -1,81 +0,0 @@ ---- -title: Lambdas -description: Learn how to use anonymous functions in Noir programming language. -keywords: [Noir programming language, lambda, closure, function, anonymous function] -sidebar_position: 9 ---- - -## Introduction - -Lambdas are anonymous functions. The syntax is `|arg1, arg2, ..., argN| return_expression`. - -```rust -let add_50 = |val| val + 50; -assert(add_50(100) == 150); -``` - -A block can be used as the body of a lambda, allowing you to declare local variables inside it: - -```rust -let cool = || { - let x = 100; - let y = 100; - x + y -} - -assert(cool() == 200); -``` - -## Closures - -Inside the body of a lambda, you can use variables defined in the enclosing function. Such lambdas are called **closures**. In this example `x` is defined inside `main` and is accessed from within the lambda: - -```rust -fn main() { - let x = 100; - let closure = || x + 150; - assert(closure() == 250); -} -``` - -## Passing closures to higher-order functions - -It may catch you by surprise that the following code fails to compile: - -```rust -fn foo(f: fn () -> Field) -> Field { - f() -} - -fn main() { - let (x, y) = (50, 50); - assert(foo(|| x + y) == 100); // error :( -} -``` - -The reason is that the closure's capture environment affects its type - we have a closure that captures two Fields and `foo` -expects a regular function as an argument - those are incompatible. -:::note - -Variables contained within the `||` are the closure's parameters, and the expression that follows it is the closure's body. The capture environment is comprised of any variables used in the closure's body that are not parameters. - -E.g. in |x| x + y, y would be a captured variable, but x would not be, since it is a parameter of the closure. - -::: -The syntax for the type of a closure is `fn[env](args) -> ret_type`, where `env` is the capture environment of the closure - -in this example that's `(Field, Field)`. - -The best solution in our case is to make `foo` generic over the environment type of its parameter, so that it can be called -with closures with any environment, as well as with regular functions: - -```rust -fn foo(f: fn[Env]() -> Field) -> Field { - f() -} - -fn main() { - let (x, y) = (50, 50); - assert(foo(|| x + y) == 100); // compiles fine - assert(foo(|| 60) == 60); // compiles fine -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/mutability.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/mutability.md deleted file mode 100644 index fdeef6a87c5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/mutability.md +++ /dev/null @@ -1,121 +0,0 @@ ---- -title: Mutability -description: - Learn about mutable variables in Noir. Discover how - to declare, modify, and use them in your programs. -keywords: [noir programming language, mutability in noir, mutable variables] -sidebar_position: 8 ---- - -Variables in noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned -to via an assignment expression. - -```rust -let x = 2; -x = 3; // error: x must be mutable to be assigned to - -let mut y = 3; -let y = 4; // OK -``` - -The `mut` modifier can also apply to patterns: - -```rust -let (a, mut b) = (1, 2); -a = 11; // error: a must be mutable to be assigned to -b = 12; // OK - -let mut (c, d) = (3, 4); -c = 13; // OK -d = 14; // OK - -// etc. -let MyStruct { x: mut y } = MyStruct { x: a }; -// y is now in scope -``` - -Note that mutability in noir is local and everything is passed by value, so if a called function -mutates its parameters then the parent function will keep the old value of the parameters. - -```rust -fn main() -> pub Field { - let x = 3; - helper(x); - x // x is still 3 -} - -fn helper(mut x: i32) { - x = 4; -} -``` - -## Non-local mutability - -Non-local mutability can be achieved through the mutable reference type `&mut T`: - -```rust -fn set_to_zero(x: &mut Field) { - *x = 0; -} - -fn main() { - let mut y = 42; - set_to_zero(&mut y); - assert(*y == 0); -} -``` - -When creating a mutable reference, the original variable being referred to (`y` in this -example) must also be mutable. Since mutable references are a reference type, they must -be explicitly dereferenced via `*` to retrieve the underlying value. Note that this yields -a copy of the value, so mutating this copy will not change the original value behind the -reference: - -```rust -fn main() { - let mut x = 1; - let x_ref = &mut x; - - let mut y = *x_ref; - let y_ref = &mut y; - - x = 2; - *x_ref = 3; - - y = 4; - *y_ref = 5; - - assert(x == 3); - assert(*x_ref == 3); - assert(y == 5); - assert(*y_ref == 5); -} -``` - -Note that types in Noir are actually deeply immutable so the copy that occurs when -dereferencing is only a conceptual copy - no additional constraints will occur. - -Mutable references can also be stored within structs. Note that there is also -no lifetime parameter on these unlike rust. This is because the allocated memory -always lasts the entire program - as if it were an array of one element. - -```rust -struct Foo { - x: &mut Field -} - -impl Foo { - fn incr(mut self) { - *self.x += 1; - } -} - -fn main() { - let foo = Foo { x: &mut 0 }; - foo.incr(); - assert(*foo.x == 1); -} -``` - -In general, you should avoid non-local & shared mutability unless it is needed. Sticking -to only local mutability will improve readability and potentially improve compiler optimizations as well. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/ops.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/ops.md deleted file mode 100644 index c35c36c38a9..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/ops.md +++ /dev/null @@ -1,98 +0,0 @@ ---- -title: Logical Operations -description: - Learn about the supported arithmetic and logical operations in the Noir programming language. - Discover how to perform operations on private input types, integers, and booleans. -keywords: - [ - Noir programming language, - supported operations, - arithmetic operations, - logical operations, - predicate operators, - bitwise operations, - short-circuiting, - backend, - ] -sidebar_position: 3 ---- - -# Operations - -## Table of Supported Operations - -| Operation | Description | Requirements | -| :-------- | :------------------------------------------------------------: | -------------------------------------: | -| + | Adds two private input types together | Types must be private input | -| - | Subtracts two private input types together | Types must be private input | -| \* | Multiplies two private input types together | Types must be private input | -| / | Divides two private input types together | Types must be private input | -| ^ | XOR two private input types together | Types must be integer | -| & | AND two private input types together | Types must be integer | -| \| | OR two private input types together | Types must be integer | -| \<\< | Left shift an integer by another integer amount | Types must be integer, shift must be u8 | -| >> | Right shift an integer by another integer amount | Types must be integer, shift must be u8 | -| ! | Bitwise not of a value | Type must be integer or boolean | -| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | -| > | returns a bool if one value is more than the other | Upper bound must have a known bit size | -| >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | -| == | returns a bool if one value is equal to the other | Both types must not be constants | -| != | returns a bool if one value is not equal to the other | Both types must not be constants | - -### Predicate Operators - -`<,<=, !=, == , >, >=` are known as predicate/comparison operations because they compare two values. -This differs from the operations such as `+` where the operands are used in _computation_. - -### Bitwise Operations Example - -```rust -fn main(x : Field) { - let y = x as u32; - let z = y & y; -} -``` - -`z` is implicitly constrained to be the result of `y & y`. The `&` operand is used to denote bitwise -`&`. - -> `x & x` would not compile as `x` is a `Field` and not an integer type. - -### Logical Operators - -Noir has no support for the logical operators `||` and `&&`. This is because encoding the -short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can -use the bitwise operators `|` and `&` which operate identically for booleans, just without the -short-circuiting. - -```rust -let my_val = 5; - -let mut flag = 1; -if (my_val > 6) | (my_val == 0) { - flag = 0; -} -assert(flag == 1); - -if (my_val != 10) & (my_val < 50) { - flag = 0; -} -assert(flag == 0); -``` - -### Shorthand operators - -Noir shorthand operators for most of the above operators, namely `+=, -=, *=, /=, %=, &=, |=, ^=, <<=`, and `>>=`. These allow for more concise syntax. For example: - -```rust -let mut i = 0; -i = i + 1; -``` - -could be written as: - -```rust -let mut i = 0; -i += 1; -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/oracles.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/oracles.md deleted file mode 100644 index aa380b5f7b8..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/oracles.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Oracles -description: Dive into how Noir supports Oracles via RPC calls, and learn how to declare an Oracle in Noir with our comprehensive guide. -keywords: - - Noir - - Oracles - - RPC Calls - - Unconstrained Functions - - Programming - - Blockchain -sidebar_position: 6 ---- - -:::note - -This is an experimental feature that is not fully documented. If you notice any outdated information or potential improvements to this page, pull request contributions are very welcome: https://github.com/noir-lang/noir - -::: - -Noir has support for Oracles via RPC calls. This means Noir will make an RPC call and use the return value for proof generation. - -Since Oracles are not resolved by Noir, they are [`unconstrained` functions](./unconstrained.md) - -You can declare an Oracle through the `#[oracle()]` flag. Example: - -```rust -#[oracle(get_number_sequence)] -unconstrained fn get_number_sequence(_size: Field) -> [Field] {} -``` - -The timeout for when using an external RPC oracle resolver can be set with the `NARGO_FOREIGN_CALL_TIMEOUT` environment variable. This timeout is in units of milliseconds. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/shadowing.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/shadowing.md deleted file mode 100644 index 5ce6130d201..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/shadowing.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Shadowing -sidebar_position: 12 ---- - -Noir allows for inheriting variables' values and re-declaring them with the same name similar to Rust, known as shadowing. - -For example, the following function is valid in Noir: - -```rust -fn main() { - let x = 5; - - { - let x = x * 2; - assert (x == 10); - } - - assert (x == 5); -} -``` - -In this example, a variable x is first defined with the value 5. - -The local scope that follows shadows the original x, i.e. creates a local mutable x based on the value of the original x. It is given a value of 2 times the original x. - -When we return to the main scope, x once again refers to just the original x, which stays at the value of 5. - -## Temporal mutability - -One way that shadowing is useful, in addition to ergonomics across scopes, is for temporarily mutating variables. - -```rust -fn main() { - let age = 30; - // age = age + 5; // Would error as `age` is immutable by default. - - let mut age = age + 5; // Temporarily mutates `age` with a new value. - - let age = age; // Locks `age`'s mutability again. - - assert (age == 35); -} -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/unconstrained.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/unconstrained.md deleted file mode 100644 index 96f824c5e42..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/unconstrained.md +++ /dev/null @@ -1,99 +0,0 @@ ---- -title: Unconstrained Functions -description: "Learn about what unconstrained functions in Noir are, how to use them and when you'd want to." - -keywords: [Noir programming language, unconstrained, open] -sidebar_position: 5 ---- - -Unconstrained functions are functions which do not constrain any of the included computation and allow for non-deterministic computation. - -## Why? - -Zero-knowledge (ZK) domain-specific languages (DSL) enable developers to generate ZK proofs from their programs by compiling code down to the constraints of an NP complete language (such as R1CS or PLONKish languages). However, the hard bounds of a constraint system can be very limiting to the functionality of a ZK DSL. - -Enabling a circuit language to perform unconstrained execution is a powerful tool. Said another way, unconstrained execution lets developers generate witnesses from code that does not generate any constraints. Being able to execute logic outside of a circuit is critical for both circuit performance and constructing proofs on information that is external to a circuit. - -Fetching information from somewhere external to a circuit can also be used to enable developers to improve circuit efficiency. - -A ZK DSL does not just prove computation, but proves that some computation was handled correctly. Thus, it is necessary that when we switch from performing some operation directly inside of a circuit to inside of an unconstrained environment that the appropriate constraints are still laid down elsewhere in the circuit. - -## Example - -An in depth example might help drive the point home. This example comes from the excellent [post](https://discord.com/channels/1113924620781883405/1124022445054111926/1128747641853972590) by Tom in the Noir Discord. - -Let's look at how we can optimize a function to turn a `u72` into an array of `u8`s. - -```rust -fn main(num: u72) -> pub [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8)) as u72 & 0xff) as u8; - } - - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 91 -Backend circuit size: 3619 -``` - -A lot of the operations in this function are optimized away by the compiler (all the bit-shifts turn into divisions by constants). However we can save a bunch of gates by casting to u8 a bit earlier. This automatically truncates the bit-shifted value to fit in a u8 which allows us to remove the AND against 0xff. This saves us ~480 gates in total. - -```rust -fn main(num: u72) -> pub [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8)) as u8; - } - - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 75 -Backend circuit size: 3143 -``` - -Those are some nice savings already but we can do better. This code is all constrained so we're proving every step of calculating out using num, but we don't actually care about how we calculate this, just that it's correct. This is where brillig comes in. - -It turns out that truncating a u72 into a u8 is hard to do inside a snark, each time we do as u8 we lay down 4 ACIR opcodes which get converted into multiple gates. It's actually much easier to calculate num from out than the other way around. All we need to do is multiply each element of out by a constant and add them all together, both relatively easy operations inside a snark. - -We can then run u72_to_u8 as unconstrained brillig code in order to calculate out, then use that result in our constrained function and assert that if we were to do the reverse calculation we'd get back num. This looks a little like the below: - -```rust -fn main(num: u72) -> pub [u8; 8] { - let out = u72_to_u8(num); - - let mut reconstructed_num: u72 = 0; - for i in 0..8 { - reconstructed_num += (out[i] as u72 << (56 - (8 * i))); - } - assert(num == reconstructed_num); - out -} - -unconstrained fn u72_to_u8(num: u72) -> [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8))) as u8; - } - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 78 -Backend circuit size: 2902 -``` - -This ends up taking off another ~250 gates from our circuit! We've ended up with more ACIR opcodes than before but they're easier for the backend to prove (resulting in fewer gates). - -Generally we want to use brillig whenever there's something that's easy to verify but hard to compute within the circuit. For example, if you wanted to calculate a square root of a number it'll be a much better idea to calculate this in brillig and then assert that if you square the result you get back your number. - -## Break and Continue - -In addition to loops over runtime bounds, `break` and `continue` are also available in unconstrained code. See [break and continue](../concepts/control_flow.md#break-and-continue) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/_category_.json deleted file mode 100644 index 1debcfe7675..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Modules, Packages and Crates", - "position": 2, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/crates_and_packages.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/crates_and_packages.md deleted file mode 100644 index 95ee9f52ab2..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/crates_and_packages.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Crates and Packages -description: Learn how to use Crates and Packages in your Noir project -keywords: [Nargo, dependencies, package management, crates, package] -sidebar_position: 0 ---- - -## Crates - -A crate is the smallest amount of code that the Noir compiler considers at a time. -Crates can contain modules, and the modules may be defined in other files that get compiled with the crate, as we’ll see in the coming sections. - -### Crate Types - -A Noir crate can come in several forms: binaries, libraries or contracts. - -#### Binaries - -_Binary crates_ are programs which you can compile to an ACIR circuit which you can then create proofs against. Each must have a function called `main` that defines the ACIR circuit which is to be proved. - -#### Libraries - -_Library crates_ don't have a `main` function and they don't compile down to ACIR. Instead they define functionality intended to be shared with multiple projects, and eventually included in a binary crate. - -#### Contracts - -Contract crates are similar to binary crates in that they compile to ACIR which you can create proofs against. They are different in that they do not have a single `main` function, but are a collection of functions to be deployed to the [Aztec network](https://aztec.network). You can learn more about the technical details of Aztec in the [monorepo](https://github.com/AztecProtocol/aztec-packages) or contract [examples](https://github.com/AztecProtocol/aztec-packages/tree/master/noir-projects/noir-contracts/contracts). - -### Crate Root - -Every crate has a root, which is the source file that the compiler starts, this is also known as the root module. The Noir compiler does not enforce any conditions on the name of the file which is the crate root, however if you are compiling via Nargo the crate root must be called `lib.nr` or `main.nr` for library or binary crates respectively. - -## Packages - -A Nargo _package_ is a collection of one of more crates that provides a set of functionality. A package must include a Nargo.toml file. - -A package _must_ contain either a library or a binary crate, but not both. - -### Differences from Cargo Packages - -One notable difference between Rust's Cargo and Noir's Nargo is that while Cargo allows a package to contain an unlimited number of binary crates and a single library crate, Nargo currently only allows a package to contain a single crate. - -In future this restriction may be lifted to allow a Nargo package to contain both a binary and library crate or multiple binary crates. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/modules.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/modules.md deleted file mode 100644 index ae822a1cff4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/modules.md +++ /dev/null @@ -1,105 +0,0 @@ ---- -title: Modules -description: - Learn how to organize your files using modules in Noir, following the same convention as Rust's - module system. Examples included. -keywords: [Noir, Rust, modules, organizing files, sub-modules] -sidebar_position: 2 ---- - -Noir's module system follows the same convention as the _newer_ version of Rust's module system. - -## Purpose of Modules - -Modules are used to organize files. Without modules all of your code would need to live in a single -file. In Noir, the compiler does not automatically scan all of your files to detect modules. This -must be done explicitly by the developer. - -## Examples - -### Importing a module in the crate root - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::hello_world(); -} -``` - -Filename : `src/foo.nr` - -```rust -fn from_foo() {} -``` - -In the above snippet, the crate root is the `src/main.nr` file. The compiler sees the module -declaration `mod foo` which prompts it to look for a foo.nr file. - -Visually this module hierarchy looks like the following : - -``` -crate - ├── main - │ - └── foo - └── from_foo - -``` - -### Importing a module throughout the tree - -All modules are accessible from the `crate::` namespace. - -``` -crate - ├── bar - ├── foo - └── main - -``` - -In the above snippet, if `bar` would like to use functions in `foo`, it can do so by `use crate::foo::function_name`. - -### Sub-modules - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::from_foo(); -} -``` - -Filename : `src/foo.nr` - -```rust -mod bar; -fn from_foo() {} -``` - -Filename : `src/foo/bar.nr` - -```rust -fn from_bar() {} -``` - -In the above snippet, we have added an extra module to the module tree; `bar`. `bar` is a submodule -of `foo` hence we declare bar in `foo.nr` with `mod bar`. Since `foo` is not the crate root, the -compiler looks for the file associated with the `bar` module in `src/foo/bar.nr` - -Visually the module hierarchy looks as follows: - -``` -crate - ├── main - │ - └── foo - ├── from_foo - └── bar - └── from_bar -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/workspaces.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/workspaces.md deleted file mode 100644 index 513497f12bf..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/workspaces.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Workspaces -sidebar_position: 3 ---- - -Workspaces are a feature of nargo that allow you to manage multiple related Noir packages in a single repository. A workspace is essentially a group of related projects that share common build output directories and configurations. - -Each Noir project (with it's own Nargo.toml file) can be thought of as a package. Each package is expected to contain exactly one "named circuit", being the "name" defined in Nargo.toml with the program logic defined in `./src/main.nr`. - -For a project with the following structure: - -```tree -├── crates -│ ├── a -│ │ ├── Nargo.toml -│ │ └── Prover.toml -│ │ └── src -│ │ └── main.nr -│ └── b -│ ├── Nargo.toml -│ └── Prover.toml -│ └── src -│ └── main.nr -│ -└── Nargo.toml -``` - -You can define a workspace in Nargo.toml like so: - -```toml -[workspace] -members = ["crates/a", "crates/b"] -default-member = "crates/a" -``` - -`members` indicates which packages are included in the workspace. As such, all member packages of a workspace will be processed when the `--workspace` flag is used with various commands or if a `default-member` is not specified. - -`default-member` indicates which package various commands process by default. - -Libraries can be defined in a workspace. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. - -Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/_category_.json deleted file mode 100644 index af04c0933fd..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Standard Library", - "position": 1, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/bigint.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/bigint.md deleted file mode 100644 index 2bfdeec6631..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/bigint.md +++ /dev/null @@ -1,122 +0,0 @@ ---- -title: Big Integers -description: How to use big integers from Noir standard library -keywords: - [ - Big Integer, - Noir programming language, - Noir libraries, - ] ---- - -The BigInt module in the standard library exposes some class of integers which do not fit (well) into a Noir native field. It implements modulo arithmetic, modulo a 'big' prime number. - -:::note - -The module can currently be considered as `Field`s with fixed modulo sizes used by a set of elliptic curves, in addition to just the native curve. [More work](https://github.com/noir-lang/noir/issues/510) is needed to achieve arbitrarily sized big integers. - -::: - -Currently 6 classes of integers (i.e 'big' prime numbers) are available in the module, namely: - -- BN254 Fq: Bn254Fq -- BN254 Fr: Bn254Fr -- Secp256k1 Fq: Secpk1Fq -- Secp256k1 Fr: Secpk1Fr -- Secp256r1 Fr: Secpr1Fr -- Secp256r1 Fq: Secpr1Fq - -Where XXX Fq and XXX Fr denote respectively the order of the base and scalar field of the (usual) elliptic curve XXX. -For instance the big integer 'Secpk1Fq' in the standard library refers to integers modulo $2^{256}-2^{32}-977$. - -Feel free to explore the source code for the other primes: - -```rust title="big_int_definition" showLineNumbers -struct BigInt { - pointer: u32, - modulus: u32, -} -``` -> Source code: noir_stdlib/src/bigint.nr#L14-L19 - - -## Example usage - -A common use-case is when constructing a big integer from its bytes representation, and performing arithmetic operations on it: - -```rust title="big_int_example" showLineNumbers -fn big_int_example(x: u8, y: u8) { - let a = Secpk1Fq::from_le_bytes(&[x, y, 0, 45, 2]); - let b = Secpk1Fq::from_le_bytes(&[y, x, 9]); - let c = (a + b) * b / a; - let d = c.to_le_bytes(); - println(d[0]); -} -``` -> Source code: test_programs/execution_success/bigint/src/main.nr#L70-L78 - - -## Methods - -The available operations for each big integer are: - -### from_le_bytes - -Construct a big integer from its little-endian bytes representation. Example: - -```rust - // Construct a big integer from a slice of bytes - let a = Secpk1Fq::from_le_bytes(&[x, y, 0, 45, 2]); - // Construct a big integer from an array of 32 bytes - let a = Secpk1Fq::from_le_bytes_32([1;32]); - ``` - -Sure, here's the formatted version of the remaining methods: - -### to_le_bytes - -Return the little-endian bytes representation of a big integer. Example: - -```rust -let bytes = a.to_le_bytes(); -``` - -### add - -Add two big integers. Example: - -```rust -let sum = a + b; -``` - -### sub - -Subtract two big integers. Example: - -```rust -let difference = a - b; -``` - -### mul - -Multiply two big integers. Example: - -```rust -let product = a * b; -``` - -### div - -Divide two big integers. Note that division is field division and not euclidean division. Example: - -```rust -let quotient = a / b; -``` - -### eq - -Compare two big integers. Example: - -```rust -let are_equal = a == b; -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/black_box_fns.md deleted file mode 100644 index d5694250f05..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/black_box_fns.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: Black Box Functions -description: Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. -keywords: [noir, black box functions] ---- - -Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. This makes certain zk-snark unfriendly computations cheaper than if they were implemented in Noir. - -The ACVM spec defines a set of blackbox functions which backends will be expected to implement. This allows backends to use optimized implementations of these constraints if they have them, however they may also fallback to less efficient naive implementations if not. - -## Function list - -Here is a list of the current black box functions: - -- [AES128](./cryptographic_primitives/ciphers.mdx#aes128) -- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) -- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) -- [Blake3](./cryptographic_primitives/hashes.mdx#blake3) -- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash) -- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) -- [Embedded curve operations (MSM, addition, ...)](./cryptographic_primitives/embedded_curve_ops.mdx) -- AND -- XOR -- RANGE -- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion.md) - -Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. - -You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/noir/blob/master/acvm-repo/acir/src/circuit/black_box_functions.rs). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/bn254.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/bn254.md deleted file mode 100644 index 3294f005dbb..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/bn254.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: Bn254 Field Library ---- - -Noir provides a module in standard library with some optimized functions for bn254 Fr in `std::field::bn254`. - -## decompose - -```rust -fn decompose(x: Field) -> (Field, Field) {} -``` - -Decomposes a single field into two fields, low and high. The low field contains the lower 16 bytes of the input field and the high field contains the upper 16 bytes of the input field. Both field results are range checked to 128 bits. - - -## assert_gt - -```rust -fn assert_gt(a: Field, b: Field) {} -``` - -Asserts that a > b. This will generate less constraints than using `assert(gt(a, b))`. - -## assert_lt - -```rust -fn assert_lt(a: Field, b: Field) {} -``` - -Asserts that a < b. This will generate less constraints than using `assert(lt(a, b))`. - -## gt - -```rust -fn gt(a: Field, b: Field) -> bool {} -``` - -Returns true if a > b. - -## lt - -```rust -fn lt(a: Field, b: Field) -> bool {} -``` - -Returns true if a < b. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/containers/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/containers/index.md deleted file mode 100644 index ea84c6d5c21..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/containers/index.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Containers -description: Container types provided by Noir's standard library for storing and retrieving data -keywords: [containers, data types, vec, hashmap] ---- diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/_category_.json deleted file mode 100644 index 5d694210bbf..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 0, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/ciphers.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/ciphers.mdx deleted file mode 100644 index e83e26efb97..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/ciphers.mdx +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: Ciphers -description: - Learn about the implemented ciphers ready to use for any Noir project -keywords: - [ciphers, Noir project, aes128, encrypt] -sidebar_position: 0 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## aes128 - -Given a plaintext as an array of bytes, returns the corresponding aes128 ciphertext (CBC mode). Input padding is automatically performed using PKCS#7, so that the output length is `input.len() + (16 - input.len() % 16)`. - -```rust title="aes128" showLineNumbers -pub fn aes128_encrypt(input: [u8; N], iv: [u8; 16], key: [u8; 16]) -> [u8] {} -``` -> Source code: noir_stdlib/src/aes128.nr#L2-L4 - - -```rust -fn main() { - let input: [u8; 4] = [0, 12, 3, 15] // Random bytes, will be padded to 16 bytes. - let iv: [u8; 16] = [0; 16]; // Initialisation vector - let key: [u8; 16] = [0; 16] // AES key - let ciphertext = std::aes128::aes128_encrypt(inputs.as_bytes(), iv.as_bytes(), key.as_bytes()); // In this case, the output length will be 16 bytes. -} -``` - - - \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx deleted file mode 100644 index 4394b48f907..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx +++ /dev/null @@ -1,98 +0,0 @@ ---- -title: ECDSA Signature Verification -description: Learn about the cryptographic primitives regarding ECDSA over the secp256k1 and secp256r1 curves -keywords: [cryptographic primitives, Noir project, ecdsa, secp256k1, secp256r1, signatures] -sidebar_position: 3 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -Noir supports ECDSA signatures verification over the secp256k1 and secp256r1 curves. - -## ecdsa_secp256k1::verify_signature - -Verifier for ECDSA Secp256k1 signatures. -See ecdsa_secp256k1::verify_signature_slice for a version that accepts slices directly. - -```rust title="ecdsa_secp256k1" showLineNumbers -pub fn verify_signature( - public_key_x: [u8; 32], - public_key_y: [u8; 32], - signature: [u8; 64], - message_hash: [u8; N] -) -> bool -``` -> Source code: noir_stdlib/src/ecdsa_secp256k1.nr#L2-L9 - - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - - - -## ecdsa_secp256k1::verify_signature_slice - -Verifier for ECDSA Secp256k1 signatures where the message is a slice. - -```rust title="ecdsa_secp256k1_slice" showLineNumbers -pub fn verify_signature_slice( - public_key_x: [u8; 32], - public_key_y: [u8; 32], - signature: [u8; 64], - message_hash: [u8] -) -> bool -``` -> Source code: noir_stdlib/src/ecdsa_secp256k1.nr#L13-L20 - - - - -## ecdsa_secp256r1::verify_signature - -Verifier for ECDSA Secp256r1 signatures. -See ecdsa_secp256r1::verify_signature_slice for a version that accepts slices directly. - -```rust title="ecdsa_secp256r1" showLineNumbers -pub fn verify_signature( - public_key_x: [u8; 32], - public_key_y: [u8; 32], - signature: [u8; 64], - message_hash: [u8; N] -) -> bool -``` -> Source code: noir_stdlib/src/ecdsa_secp256r1.nr#L2-L9 - - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - - - -## ecdsa_secp256r1::verify_signature - -Verifier for ECDSA Secp256r1 signatures where the message is a slice. - -```rust title="ecdsa_secp256r1_slice" showLineNumbers -pub fn verify_signature_slice( - public_key_x: [u8; 32], - public_key_y: [u8; 32], - signature: [u8; 64], - message_hash: [u8] -) -> bool -``` -> Source code: noir_stdlib/src/ecdsa_secp256r1.nr#L13-L20 - - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/index.md deleted file mode 100644 index 650f30165d5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/index.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Cryptographic Primitives -description: - Learn about the cryptographic primitives ready to use for any Noir project -keywords: - [ - cryptographic primitives, - Noir project, - ] ---- - -The Noir team is progressively adding new cryptographic primitives to the standard library. Reach out for news or if you would be interested in adding more of these calculations in Noir. - -Some methods are available thanks to the Aztec backend, not being performed using Noir. When using other backends, these methods may or may not be supplied. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/schnorr.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/schnorr.mdx deleted file mode 100644 index b59e69c8f07..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/schnorr.mdx +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: Schnorr Signatures -description: Learn how you can verify Schnorr signatures using Noir -keywords: [cryptographic primitives, Noir project, schnorr, signatures] -sidebar_position: 2 ---- - -import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; - -## schnorr::verify_signature - -Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin). -See schnorr::verify_signature_slice for a version that works directly on slices. - -```rust title="schnorr_verify" showLineNumbers -pub fn verify_signature( - public_key_x: Field, - public_key_y: Field, - signature: [u8; 64], - message: [u8; N] -) -> bool -``` -> Source code: noir_stdlib/src/schnorr.nr#L2-L9 - - -where `_signature` can be generated like so using the npm package -[@noir-lang/barretenberg](https://www.npmjs.com/package/@noir-lang/barretenberg) - -```js -const { BarretenbergWasm } = require('@noir-lang/barretenberg/dest/wasm'); -const { Schnorr } = require('@noir-lang/barretenberg/dest/crypto/schnorr'); - -... - -const barretenberg = await BarretenbergWasm.new(); -const schnorr = new Schnorr(barretenberg); -const pubKey = schnorr.computePublicKey(privateKey); -const message = ... -const signature = Array.from( - schnorr.constructSignature(hash, privateKey).toBuffer() -); - -... -``` - - - -## schnorr::verify_signature_slice - -Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin) -where the message is a slice. - -```rust title="schnorr_verify_slice" showLineNumbers -pub fn verify_signature_slice( - public_key_x: Field, - public_key_y: Field, - signature: [u8; 64], - message: [u8] -) -> bool -``` -> Source code: noir_stdlib/src/schnorr.nr#L13-L20 - - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/logging.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/logging.md deleted file mode 100644 index db75ef9f86f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/logging.md +++ /dev/null @@ -1,78 +0,0 @@ ---- -title: Logging -description: - Learn how to use the println statement for debugging in Noir with this tutorial. Understand the - basics of logging in Noir and how to implement it in your code. -keywords: - [ - noir logging, - println statement, - print statement, - debugging in noir, - noir std library, - logging tutorial, - basic logging in noir, - noir logging implementation, - noir debugging techniques, - rust, - ] ---- - -The standard library provides two familiar statements you can use: `println` and `print`. Despite being a limited implementation of rust's `println!` and `print!` macros, these constructs can be useful for debugging. - -You can print the output of both statements in your Noir code by using the `nargo execute` command or the `--show-output` flag when using `nargo test` (provided there are print statements in your tests). - -It is recommended to use `nargo execute` if you want to debug failing constraints with `println` or `print` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). Neither `println`, nor `print` are callable for failed constraints caught at compile time. - -Both `print` and `println` are generic functions which can work on integers, fields, strings, and even structs or expressions. Note however, that slices are currently unsupported. For example: - -```rust -struct Person { - age: Field, - height: Field, -} - -fn main(age: Field, height: Field) { - let person = Person { - age: age, - height: height, - }; - println(person); - println(age + height); - println("Hello world!"); -} -``` - -You can print different types in the same statement (including strings) with a type called `fmtstr`. It can be specified in the same way as a normal string, just prepended with an "f" character: - -```rust - let fmt_str = f"i: {i}, j: {j}"; - println(fmt_str); - - let s = myStruct { y: x, x: y }; - println(s); - - println(f"i: {i}, s: {s}"); - - println(x); - println([x, y]); - - let foo = fooStruct { my_struct: s, foo: 15 }; - println(f"s: {s}, foo: {foo}"); - - println(15); // prints 0x0f, implicit Field - println(-1 as u8); // prints 255 - println(-1 as i8); // prints -1 -``` - -Examples shown above are interchangeable between the two `print` statements: - -```rust -let person = Person { age : age, height : height }; - -println(person); -print(person); - -println("Hello world!"); // Prints with a newline at the end of the input -print("Hello world!"); // Prints the input and keeps cursor on the same line -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/merkle_trees.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/merkle_trees.md deleted file mode 100644 index 6a9ebf72ada..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/merkle_trees.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: Merkle Trees -description: Learn about Merkle Trees in Noir with this tutorial. Explore the basics of computing a merkle root using a proof, with examples. -keywords: - [ - Merkle trees in Noir, - Noir programming language, - check membership, - computing root from leaf, - Noir Merkle tree implementation, - Merkle tree tutorial, - Merkle tree code examples, - Noir libraries, - pedersen hash., - ] ---- - -## compute_merkle_root - -Returns the root of the tree from the provided leaf and its hash path, using a [Pedersen hash](./cryptographic_primitives/hashes.mdx#pedersen_hash). - -```rust -fn compute_merkle_root(leaf : Field, index : Field, hash_path: [Field]) -> Field -``` - -example: - -```rust -/** - // these values are for this example only - index = "0" - priv_key = "0x000000000000000000000000000000000000000000000000000000616c696365" - secret = "0x1929ea3ab8d9106a899386883d9428f8256cfedb3c4f6b66bf4aa4d28a79988f" - note_hash_path = [ - "0x1e61bdae0f027b1b2159e1f9d3f8d00fa668a952dddd822fda80dc745d6f65cc", - "0x0e4223f3925f98934393c74975142bd73079ab0621f4ee133cee050a3c194f1a", - "0x2fd7bb412155bf8693a3bd2a3e7581a679c95c68a052f835dddca85fa1569a40" - ] - */ -fn main(index: Field, priv_key: Field, secret: Field, note_hash_path: [Field; 3]) { - - let pubkey = std::scalar_mul::fixed_base_embedded_curve(priv_key); - let pubkey_x = pubkey[0]; - let pubkey_y = pubkey[1]; - let note_commitment = std::hash::pedersen(&[pubkey_x, pubkey_y, secret]); - - let root = std::merkle::compute_merkle_root(note_commitment[0], index, note_hash_path.as_slice()); - println(root); -} -``` - -To check merkle tree membership: - -1. Include a merkle root as a program input. -2. Compute the merkle root of a given leaf, index and hash path. -3. Assert the merkle roots are equal. - -For more info about merkle trees, see the Wikipedia [page](https://en.wikipedia.org/wiki/Merkle_tree). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/options.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/options.md deleted file mode 100644 index a1bd4e1de5f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/options.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -title: Option Type ---- - -The `Option` type is a way to express that a value might be present (`Some(T))` or absent (`None`). It's a safer way to handle potential absence of values, compared to using nulls in many other languages. - -```rust -struct Option { - None, - Some(T), -} -``` - -The `Option` type, already imported into your Noir program, can be used directly: - -```rust -fn main() { - let none = Option::none(); - let some = Option::some(3); -} -``` - -See [this test](https://github.com/noir-lang/noir/blob/5cbfb9c4a06c8865c98ff2b594464b037d821a5c/crates/nargo_cli/tests/test_data/option/src/main.nr) for a more comprehensive set of examples of each of the methods described below. - -## Methods - -### none - -Constructs a none value. - -### some - -Constructs a some wrapper around a given value. - -### is_none - -Returns true if the Option is None. - -### is_some - -Returns true of the Option is Some. - -### unwrap - -Asserts `self.is_some()` and returns the wrapped value. - -### unwrap_unchecked - -Returns the inner value without asserting `self.is_some()`. This method can be useful within an if condition when we already know that `option.is_some()`. If the option is None, there is no guarantee what value will be returned, only that it will be of type T for an `Option`. - -### unwrap_or - -Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value. - -### unwrap_or_else - -Returns the wrapped value if `self.is_some()`. Otherwise, calls the given function to return a default value. - -### expect - -Asserts `self.is_some()` with a provided custom message and returns the contained `Some` value. The custom message is expected to be a format string. - -### map - -If self is `Some(x)`, this returns `Some(f(x))`. Otherwise, this returns `None`. - -### map_or - -If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns the given default value. - -### map_or_else - -If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns `default()`. - -### and - -Returns None if self is None. Otherwise, this returns `other`. - -### and_then - -If self is None, this returns None. Otherwise, this calls the given function with the Some value contained within self, and returns the result of that call. In some languages this function is called `flat_map` or `bind`. - -### or - -If self is Some, return self. Otherwise, return `other`. - -### or_else - -If self is Some, return self. Otherwise, return `default()`. - -### xor - -If only one of the two Options is Some, return that option. Otherwise, if both options are Some or both are None, None is returned. - -### filter - -Returns `Some(x)` if self is `Some(x)` and `predicate(x)` is true. Otherwise, this returns `None`. - -### flatten - -Flattens an `Option>` into a `Option`. This returns `None` if the outer Option is None. Otherwise, this returns the inner Option. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/traits.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/traits.md deleted file mode 100644 index a14312d2792..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/traits.md +++ /dev/null @@ -1,464 +0,0 @@ ---- -title: Traits -description: Noir's stdlib provides a few commonly used traits. -keywords: [traits, trait, interface, protocol, default, add, eq] ---- - -## `std::default` - -### `std::default::Default` - -```rust title="default-trait" showLineNumbers -trait Default { - fn default() -> Self; -} -``` -> Source code: noir_stdlib/src/default.nr#L1-L5 - - -Constructs a default value of a type. - -Implementations: -```rust -impl Default for Field { .. } - -impl Default for i8 { .. } -impl Default for i16 { .. } -impl Default for i32 { .. } -impl Default for i64 { .. } - -impl Default for u8 { .. } -impl Default for u16 { .. } -impl Default for u32 { .. } -impl Default for u64 { .. } - -impl Default for () { .. } -impl Default for bool { .. } - -impl Default for [T; N] - where T: Default { .. } - -impl Default for [T] { .. } - -impl Default for (A, B) - where A: Default, B: Default { .. } - -impl Default for (A, B, C) - where A: Default, B: Default, C: Default { .. } - -impl Default for (A, B, C, D) - where A: Default, B: Default, C: Default, D: Default { .. } - -impl Default for (A, B, C, D, E) - where A: Default, B: Default, C: Default, D: Default, E: Default { .. } -``` - -For primitive integer types, the return value of `default` is `0`. Container -types such as arrays are filled with default values of their element type, -except slices whose length is unknown and thus defaulted to zero. - - -## `std::convert` - -### `std::convert::From` - -```rust title="from-trait" showLineNumbers -trait From { - fn from(input: T) -> Self; -} -``` -> Source code: noir_stdlib/src/convert.nr#L1-L5 - - -The `From` trait defines how to convert from a given type `T` to the type on which the trait is implemented. - -The Noir standard library provides a number of implementations of `From` between primitive types. -```rust title="from-impls" showLineNumbers -// Unsigned integers - -impl From for u32 { fn from(value: u8) -> u32 { value as u32 } } - -impl From for u64 { fn from(value: u8) -> u64 { value as u64 } } -impl From for u64 { fn from(value: u32) -> u64 { value as u64 } } - -impl From for Field { fn from(value: u8) -> Field { value as Field } } -impl From for Field { fn from(value: u32) -> Field { value as Field } } -impl From for Field { fn from(value: u64) -> Field { value as Field } } - -// Signed integers - -impl From for i32 { fn from(value: i8) -> i32 { value as i32 } } - -impl From for i64 { fn from(value: i8) -> i64 { value as i64 } } -impl From for i64 { fn from(value: i32) -> i64 { value as i64 } } - -// Booleans -impl From for u8 { fn from(value: bool) -> u8 { value as u8 } } -impl From for u32 { fn from(value: bool) -> u32 { value as u32 } } -impl From for u64 { fn from(value: bool) -> u64 { value as u64 } } -impl From for i8 { fn from(value: bool) -> i8 { value as i8 } } -impl From for i32 { fn from(value: bool) -> i32 { value as i32 } } -impl From for i64 { fn from(value: bool) -> i64 { value as i64 } } -impl From for Field { fn from(value: bool) -> Field { value as Field } } -``` -> Source code: noir_stdlib/src/convert.nr#L25-L52 - - -#### When to implement `From` - -As a general rule of thumb, `From` may be implemented in the [situations where it would be suitable in Rust](https://doc.rust-lang.org/std/convert/trait.From.html#when-to-implement-from): - -- The conversion is *infallible*: Noir does not provide an equivalent to Rust's `TryFrom`, if the conversion can fail then provide a named method instead. -- The conversion is *lossless*: semantically, it should not lose or discard information. For example, `u32: From` can losslessly convert any `u16` into a valid `u32` such that the original `u16` can be recovered. On the other hand, `u16: From` should not be implemented as `2**16` is a `u32` which cannot be losslessly converted into a `u16`. -- The conversion is *value-preserving*: the conceptual kind and meaning of the resulting value is the same, even though the Noir type and technical representation might be different. While it's possible to infallibly and losslessly convert a `u8` into a `str<2>` hex representation, `4u8` and `"04"` are too different for `str<2>: From` to be implemented. -- The conversion is *obvious*: it's the only reasonable conversion between the two types. If there's ambiguity on how to convert between them such that the same input could potentially map to two different values then a named method should be used. For instance rather than implementing `U128: From<[u8; 16]>`, the methods `U128::from_le_bytes` and `U128::from_be_bytes` are used as otherwise the endianness of the array would be ambiguous, resulting in two potential values of `U128` from the same byte array. - -One additional recommendation specific to Noir is: -- The conversion is *efficient*: it's relatively cheap to convert between the two types. Due to being a ZK DSL, it's more important to avoid unnecessary computation compared to Rust. If the implementation of `From` would encourage users to perform unnecessary conversion, resulting in additional proving time, then it may be preferable to expose functionality such that this conversion may be avoided. - -### `std::convert::Into` - -The `Into` trait is defined as the reciprocal of `From`. It should be easy to convince yourself that if we can convert to type `A` from type `B`, then it's possible to convert type `B` into type `A`. - -For this reason, implementing `From` on a type will automatically generate a matching `Into` implementation. One should always prefer implementing `From` over `Into` as implementing `Into` will not generate a matching `From` implementation. - -```rust title="into-trait" showLineNumbers -trait Into { - fn into(self) -> T; -} - -impl Into for U where T: From { - fn into(self) -> T { - T::from(self) - } -} -``` -> Source code: noir_stdlib/src/convert.nr#L13-L23 - - -`Into` is most useful when passing function arguments where the types don't quite match up with what the function expects. In this case, the compiler has enough type information to perform the necessary conversion by just appending `.into()` onto the arguments in question. - - -## `std::cmp` - -### `std::cmp::Eq` - -```rust title="eq-trait" showLineNumbers -trait Eq { - fn eq(self, other: Self) -> bool; -} -``` -> Source code: noir_stdlib/src/cmp.nr#L1-L5 - - -Returns `true` if `self` is equal to `other`. Implementing this trait on a type -allows the type to be used with `==` and `!=`. - -Implementations: -```rust -impl Eq for Field { .. } - -impl Eq for i8 { .. } -impl Eq for i16 { .. } -impl Eq for i32 { .. } -impl Eq for i64 { .. } - -impl Eq for u8 { .. } -impl Eq for u16 { .. } -impl Eq for u32 { .. } -impl Eq for u64 { .. } - -impl Eq for () { .. } -impl Eq for bool { .. } - -impl Eq for [T; N] - where T: Eq { .. } - -impl Eq for [T] - where T: Eq { .. } - -impl Eq for (A, B) - where A: Eq, B: Eq { .. } - -impl Eq for (A, B, C) - where A: Eq, B: Eq, C: Eq { .. } - -impl Eq for (A, B, C, D) - where A: Eq, B: Eq, C: Eq, D: Eq { .. } - -impl Eq for (A, B, C, D, E) - where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq { .. } -``` - -### `std::cmp::Ord` - -```rust title="ord-trait" showLineNumbers -trait Ord { - fn cmp(self, other: Self) -> Ordering; -} -``` -> Source code: noir_stdlib/src/cmp.nr#L102-L106 - - -`a.cmp(b)` compares two values returning `Ordering::less()` if `a < b`, -`Ordering::equal()` if `a == b`, or `Ordering::greater()` if `a > b`. -Implementing this trait on a type allows `<`, `<=`, `>`, and `>=` to be -used on values of the type. - -`std::cmp` also provides `max` and `min` functions for any type which implements the `Ord` trait. - -Implementations: - -```rust -impl Ord for u8 { .. } -impl Ord for u16 { .. } -impl Ord for u32 { .. } -impl Ord for u64 { .. } - -impl Ord for i8 { .. } -impl Ord for i16 { .. } -impl Ord for i32 { .. } - -impl Ord for i64 { .. } - -impl Ord for () { .. } -impl Ord for bool { .. } - -impl Ord for [T; N] - where T: Ord { .. } - -impl Ord for [T] - where T: Ord { .. } - -impl Ord for (A, B) - where A: Ord, B: Ord { .. } - -impl Ord for (A, B, C) - where A: Ord, B: Ord, C: Ord { .. } - -impl Ord for (A, B, C, D) - where A: Ord, B: Ord, C: Ord, D: Ord { .. } - -impl Ord for (A, B, C, D, E) - where A: Ord, B: Ord, C: Ord, D: Ord, E: Ord { .. } -``` - -## `std::ops` - -### `std::ops::Add`, `std::ops::Sub`, `std::ops::Mul`, and `std::ops::Div` - -These traits abstract over addition, subtraction, multiplication, and division respectively. -Implementing these traits for a given type will also allow that type to be used with the corresponding operator -for that trait (`+` for Add, etc) in addition to the normal method names. - -```rust title="add-trait" showLineNumbers -trait Add { - fn add(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops/arith.nr#L1-L5 - -```rust title="sub-trait" showLineNumbers -trait Sub { - fn sub(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops/arith.nr#L19-L23 - -```rust title="mul-trait" showLineNumbers -trait Mul { - fn mul(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops/arith.nr#L37-L41 - -```rust title="div-trait" showLineNumbers -trait Div { - fn div(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops/arith.nr#L55-L59 - - -The implementations block below is given for the `Add` trait, but the same types that implement -`Add` also implement `Sub`, `Mul`, and `Div`. - -Implementations: -```rust -impl Add for Field { .. } - -impl Add for i8 { .. } -impl Add for i16 { .. } -impl Add for i32 { .. } -impl Add for i64 { .. } - -impl Add for u8 { .. } -impl Add for u16 { .. } -impl Add for u32 { .. } -impl Add for u64 { .. } -``` - -### `std::ops::Rem` - -```rust title="rem-trait" showLineNumbers -trait Rem{ - fn rem(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops/arith.nr#L73-L77 - - -`Rem::rem(a, b)` is the remainder function returning the result of what is -left after dividing `a` and `b`. Implementing `Rem` allows the `%` operator -to be used with the implementation type. - -Unlike other numeric traits, `Rem` is not implemented for `Field`. - -Implementations: -```rust -impl Rem for u8 { fn rem(self, other: u8) -> u8 { self % other } } -impl Rem for u16 { fn rem(self, other: u16) -> u16 { self % other } } -impl Rem for u32 { fn rem(self, other: u32) -> u32 { self % other } } -impl Rem for u64 { fn rem(self, other: u64) -> u64 { self % other } } - -impl Rem for i8 { fn rem(self, other: i8) -> i8 { self % other } } -impl Rem for i16 { fn rem(self, other: i16) -> i16 { self % other } } -impl Rem for i32 { fn rem(self, other: i32) -> i32 { self % other } } -impl Rem for i64 { fn rem(self, other: i64) -> i64 { self % other } } -``` - -### `std::ops::Neg` - -```rust title="neg-trait" showLineNumbers -trait Neg { - fn neg(self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops/arith.nr#L89-L93 - - -`Neg::neg` is equivalent to the unary negation operator `-`. - -Implementations: -```rust title="neg-trait-impls" showLineNumbers -impl Neg for Field { fn neg(self) -> Field { -self } } - -impl Neg for i8 { fn neg(self) -> i8 { -self } } -impl Neg for i16 { fn neg(self) -> i16 { -self } } -impl Neg for i32 { fn neg(self) -> i32 { -self } } -impl Neg for i64 { fn neg(self) -> i64 { -self } } -``` -> Source code: noir_stdlib/src/ops/arith.nr#L95-L102 - - -### `std::ops::Not` - -```rust title="not-trait" showLineNumbers -trait Not { - fn not(self: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops/bit.nr#L1-L5 - - -`Not::not` is equivalent to the unary bitwise NOT operator `!`. - -Implementations: -```rust title="not-trait-impls" showLineNumbers -impl Not for bool { fn not(self) -> bool { !self } } - -impl Not for u64 { fn not(self) -> u64 { !self } } -impl Not for u32 { fn not(self) -> u32 { !self } } -impl Not for u16 { fn not(self) -> u16 { !self } } -impl Not for u8 { fn not(self) -> u8 { !self } } -impl Not for u1 { fn not(self) -> u1 { !self } } - -impl Not for i8 { fn not(self) -> i8 { !self } } -impl Not for i16 { fn not(self) -> i16 { !self } } -impl Not for i32 { fn not(self) -> i32 { !self } } -impl Not for i64 { fn not(self) -> i64 { !self } } -``` -> Source code: noir_stdlib/src/ops/bit.nr#L7-L20 - - -### `std::ops::{ BitOr, BitAnd, BitXor }` - -```rust title="bitor-trait" showLineNumbers -trait BitOr { - fn bitor(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops/bit.nr#L22-L26 - -```rust title="bitand-trait" showLineNumbers -trait BitAnd { - fn bitand(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops/bit.nr#L40-L44 - -```rust title="bitxor-trait" showLineNumbers -trait BitXor { - fn bitxor(self, other: Self) -> Self; -} -``` -> Source code: noir_stdlib/src/ops/bit.nr#L58-L62 - - -Traits for the bitwise operations `|`, `&`, and `^`. - -Implementing `BitOr`, `BitAnd` or `BitXor` for a type allows the `|`, `&`, or `^` operator respectively -to be used with the type. - -The implementations block below is given for the `BitOr` trait, but the same types that implement -`BitOr` also implement `BitAnd` and `BitXor`. - -Implementations: -```rust -impl BitOr for bool { fn bitor(self, other: bool) -> bool { self | other } } - -impl BitOr for u8 { fn bitor(self, other: u8) -> u8 { self | other } } -impl BitOr for u16 { fn bitor(self, other: u16) -> u16 { self | other } } -impl BitOr for u32 { fn bitor(self, other: u32) -> u32 { self | other } } -impl BitOr for u64 { fn bitor(self, other: u64) -> u64 { self | other } } - -impl BitOr for i8 { fn bitor(self, other: i8) -> i8 { self | other } } -impl BitOr for i16 { fn bitor(self, other: i16) -> i16 { self | other } } -impl BitOr for i32 { fn bitor(self, other: i32) -> i32 { self | other } } -impl BitOr for i64 { fn bitor(self, other: i64) -> i64 { self | other } } -``` - -### `std::ops::{ Shl, Shr }` - -```rust title="shl-trait" showLineNumbers -trait Shl { - fn shl(self, other: u8) -> Self; -} -``` -> Source code: noir_stdlib/src/ops/bit.nr#L76-L80 - -```rust title="shr-trait" showLineNumbers -trait Shr { - fn shr(self, other: u8) -> Self; -} -``` -> Source code: noir_stdlib/src/ops/bit.nr#L93-L97 - - -Traits for a bit shift left and bit shift right. - -Implementing `Shl` for a type allows the left shift operator (`<<`) to be used with the implementation type. -Similarly, implementing `Shr` allows the right shift operator (`>>`) to be used with the type. - -Note that bit shifting is not currently implemented for signed types. - -The implementations block below is given for the `Shl` trait, but the same types that implement -`Shl` also implement `Shr`. - -Implementations: -```rust -impl Shl for u8 { fn shl(self, other: u8) -> u8 { self << other } } -impl Shl for u16 { fn shl(self, other: u16) -> u16 { self << other } } -impl Shl for u32 { fn shl(self, other: u32) -> u32 { self << other } } -impl Shl for u64 { fn shl(self, other: u64) -> u64 { self << other } } -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/zeroed.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/zeroed.md deleted file mode 100644 index f450fecdd36..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/zeroed.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Zeroed Function -description: - The zeroed function returns a zeroed value of any type. -keywords: - [ - zeroed - ] ---- - -Implements `fn zeroed() -> T` to return a zeroed value of any type. This function is generally unsafe to use as the zeroed bit pattern is not guaranteed to be valid for all types. It can however, be useful in cases when the value is guaranteed not to be used such as in a BoundedVec library implementing a growable vector, up to a certain length, backed by an array. The array can be initialized with zeroed values which are guaranteed to be inaccessible until the vector is pushed to. Similarly, enumerations in noir can be implemented using this method by providing zeroed values for the unused variants. - -You can access the function at `std::unsafe::zeroed`. - -This function currently supports the following types: - -- Field -- Bool -- Uint -- Array -- Slice -- String -- Tuple -- Function - -Using it on other types could result in unexpected behavior. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/.nojekyll deleted file mode 100644 index e2ac6616add..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md deleted file mode 100644 index d7249d24330..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md +++ /dev/null @@ -1,160 +0,0 @@ -# BarretenbergBackend - -## Extends - -- `BarretenbergVerifierBackend` - -## Implements - -- [`Backend`](../index.md#backend) - -## Constructors - -### new BarretenbergBackend(acirCircuit, options) - -```ts -new BarretenbergBackend(acirCircuit, options): BarretenbergBackend -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `acirCircuit` | `CompiledCircuit` | -| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | - -#### Returns - -[`BarretenbergBackend`](BarretenbergBackend.md) - -#### Inherited from - -BarretenbergVerifierBackend.constructor - -## Properties - -| Property | Type | Description | Inheritance | -| :------ | :------ | :------ | :------ | -| `acirComposer` | `any` | - | BarretenbergVerifierBackend.acirComposer | -| `acirUncompressedBytecode` | `Uint8Array` | - | BarretenbergVerifierBackend.acirUncompressedBytecode | -| `api` | `Barretenberg` | - | BarretenbergVerifierBackend.api | -| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | - | BarretenbergVerifierBackend.options | - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Inherited from - -BarretenbergVerifierBackend.destroy - -*** - -### generateProof() - -```ts -generateProof(compressedWitness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `compressedWitness` | `Uint8Array` | - -#### Returns - -`Promise`\<`ProofData`\> - -#### Description - -Generates a proof - -*** - -### generateRecursiveProofArtifacts() - -```ts -generateRecursiveProofArtifacts(proofData, numOfPublicInputs): Promise -``` - -Generates artifacts that will be passed to a circuit that will verify this proof. - -Instead of passing the proof and verification key as a byte array, we pass them -as fields which makes it cheaper to verify in a circuit. - -The proof that is passed here will have been created using a circuit -that has the #[recursive] attribute on its `main` method. - -The number of public inputs denotes how many public inputs are in the inner proof. - -#### Parameters - -| Parameter | Type | Default value | -| :------ | :------ | :------ | -| `proofData` | `ProofData` | `undefined` | -| `numOfPublicInputs` | `number` | `0` | - -#### Returns - -`Promise`\<`object`\> - -#### Example - -```typescript -const artifacts = await backend.generateRecursiveProofArtifacts(proof, numOfPublicInputs); -``` - -*** - -### getVerificationKey() - -```ts -getVerificationKey(): Promise -``` - -#### Returns - -`Promise`\<`Uint8Array`\> - -#### Inherited from - -BarretenbergVerifierBackend.getVerificationKey - -*** - -### verifyProof() - -```ts -verifyProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | `ProofData` | - -#### Returns - -`Promise`\<`boolean`\> - -#### Inherited from - -BarretenbergVerifierBackend.verifyProof - -#### Description - -Verifies a proof - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md deleted file mode 100644 index b49a479f4f4..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md +++ /dev/null @@ -1,21 +0,0 @@ -# BackendOptions - -```ts -type BackendOptions: object; -``` - -## Description - -An options object, currently only used to specify the number of threads to use. - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `memory` | `object` | - | -| `memory.maximum` | `number` | - | -| `threads` | `number` | **Description**

Number of threads | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs deleted file mode 100644 index d7d5128f9e3..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend","label":"BarretenbergBackend"},{"type":"doc","id":"reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier","label":"BarretenbergVerifier"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions","label":"BackendOptions"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/.nojekyll deleted file mode 100644 index e2ac6616add..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/and.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/and.md deleted file mode 100644 index c783283e396..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/and.md +++ /dev/null @@ -1,22 +0,0 @@ -# and() - -```ts -and(lhs, rhs): string -``` - -Performs a bitwise AND operation between `lhs` and `rhs` - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `lhs` | `string` | | -| `rhs` | `string` | | - -## Returns - -`string` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/blake2s256.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/blake2s256.md deleted file mode 100644 index 7882d0da8d5..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/blake2s256.md +++ /dev/null @@ -1,21 +0,0 @@ -# blake2s256() - -```ts -blake2s256(inputs): Uint8Array -``` - -Calculates the Blake2s256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md deleted file mode 100644 index 5e3cd53e9d3..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md +++ /dev/null @@ -1,28 +0,0 @@ -# ecdsa\_secp256k1\_verify() - -```ts -ecdsa_secp256k1_verify( - hashed_msg, - public_key_x_bytes, - public_key_y_bytes, - signature): boolean -``` - -Verifies a ECDSA signature over the secp256k1 curve. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `hashed_msg` | `Uint8Array` | | -| `public_key_x_bytes` | `Uint8Array` | | -| `public_key_y_bytes` | `Uint8Array` | | -| `signature` | `Uint8Array` | | - -## Returns - -`boolean` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md deleted file mode 100644 index 0b20ff68957..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md +++ /dev/null @@ -1,28 +0,0 @@ -# ecdsa\_secp256r1\_verify() - -```ts -ecdsa_secp256r1_verify( - hashed_msg, - public_key_x_bytes, - public_key_y_bytes, - signature): boolean -``` - -Verifies a ECDSA signature over the secp256r1 curve. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `hashed_msg` | `Uint8Array` | | -| `public_key_x_bytes` | `Uint8Array` | | -| `public_key_y_bytes` | `Uint8Array` | | -| `signature` | `Uint8Array` | | - -## Returns - -`boolean` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/keccak256.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/keccak256.md deleted file mode 100644 index d10f155ce86..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/keccak256.md +++ /dev/null @@ -1,21 +0,0 @@ -# keccak256() - -```ts -keccak256(inputs): Uint8Array -``` - -Calculates the Keccak256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/sha256.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/sha256.md deleted file mode 100644 index 6ba4ecac022..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/sha256.md +++ /dev/null @@ -1,21 +0,0 @@ -# sha256() - -```ts -sha256(inputs): Uint8Array -``` - -Calculates the SHA256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/xor.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/xor.md deleted file mode 100644 index 8d762b895d3..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/xor.md +++ /dev/null @@ -1,22 +0,0 @@ -# xor() - -```ts -xor(lhs, rhs): string -``` - -Performs a bitwise XOR operation between `lhs` and `rhs` - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `lhs` | `string` | | -| `rhs` | `string` | | - -## Returns - -`string` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/ErrorWithPayload.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/ErrorWithPayload.md deleted file mode 100644 index e8c2f4aef3d..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/ErrorWithPayload.md +++ /dev/null @@ -1,15 +0,0 @@ -# ErrorWithPayload - -```ts -type ErrorWithPayload: ExecutionError & object; -``` - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `decodedAssertionPayload` | `any` | - | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md deleted file mode 100644 index 812b8b16481..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md +++ /dev/null @@ -1,24 +0,0 @@ -# ForeignCallHandler - -```ts -type ForeignCallHandler: (name, inputs) => Promise; -``` - -A callback which performs an foreign call and returns the response. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `name` | `string` | The identifier for the type of foreign call being performed. | -| `inputs` | [`ForeignCallInput`](ForeignCallInput.md)[] | An array of hex encoded inputs to the foreign call. | - -## Returns - -`Promise`\<[`ForeignCallOutput`](ForeignCallOutput.md)[]\> - -outputs - An array of hex encoded outputs containing the results of the foreign call. - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md deleted file mode 100644 index dd95809186a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md +++ /dev/null @@ -1,9 +0,0 @@ -# ForeignCallInput - -```ts -type ForeignCallInput: string[]; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md deleted file mode 100644 index b71fb78a946..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md +++ /dev/null @@ -1,9 +0,0 @@ -# ForeignCallOutput - -```ts -type ForeignCallOutput: string | string[]; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md deleted file mode 100644 index 258c46f9d0c..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md +++ /dev/null @@ -1,9 +0,0 @@ -# WitnessMap - -```ts -type WitnessMap: Map; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs deleted file mode 100644 index b3156097df6..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/noir_js/classes/Noir","label":"Noir"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ErrorWithPayload","label":"ErrorWithPayload"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallHandler","label":"ForeignCallHandler"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallInput","label":"ForeignCallInput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallOutput","label":"ForeignCallOutput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/WitnessMap","label":"WitnessMap"}]},{"type":"category","label":"Functions","items":[{"type":"doc","id":"reference/NoirJS/noir_js/functions/and","label":"and"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/blake2s256","label":"blake2s256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify","label":"ecdsa_secp256k1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify","label":"ecdsa_secp256r1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/keccak256","label":"keccak256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/sha256","label":"sha256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/xor","label":"xor"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/.nojekyll deleted file mode 100644 index e2ac6616add..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/functions/compile.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/functions/compile.md deleted file mode 100644 index 6faf763b37f..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/functions/compile.md +++ /dev/null @@ -1,51 +0,0 @@ -# compile() - -```ts -compile( - fileManager, - projectPath?, - logFn?, -debugLogFn?): Promise -``` - -Compiles a Noir project - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `fileManager` | `FileManager` | The file manager to use | -| `projectPath`? | `string` | The path to the project inside the file manager. Defaults to the root of the file manager | -| `logFn`? | `LogFn` | A logging function. If not provided, console.log will be used | -| `debugLogFn`? | `LogFn` | A debug logging function. If not provided, logFn will be used | - -## Returns - -`Promise`\<[`ProgramCompilationArtifacts`](../index.md#programcompilationartifacts)\> - -## Example - -```typescript -// Node.js - -import { compile_program, createFileManager } from '@noir-lang/noir_wasm'; - -const fm = createFileManager(myProjectPath); -const myCompiledCode = await compile_program(fm); -``` - -```typescript -// Browser - -import { compile_program, createFileManager } from '@noir-lang/noir_wasm'; - -const fm = createFileManager('/'); -for (const path of files) { - await fm.writeFile(path, await getFileAsStream(path)); -} -const myCompiledCode = await compile_program(fm); -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/functions/compile_contract.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/functions/compile_contract.md deleted file mode 100644 index 7d0b39a43ef..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/functions/compile_contract.md +++ /dev/null @@ -1,51 +0,0 @@ -# compile\_contract() - -```ts -compile_contract( - fileManager, - projectPath?, - logFn?, -debugLogFn?): Promise -``` - -Compiles a Noir project - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `fileManager` | `FileManager` | The file manager to use | -| `projectPath`? | `string` | The path to the project inside the file manager. Defaults to the root of the file manager | -| `logFn`? | `LogFn` | A logging function. If not provided, console.log will be used | -| `debugLogFn`? | `LogFn` | A debug logging function. If not provided, logFn will be used | - -## Returns - -`Promise`\<[`ContractCompilationArtifacts`](../index.md#contractcompilationartifacts)\> - -## Example - -```typescript -// Node.js - -import { compile_contract, createFileManager } from '@noir-lang/noir_wasm'; - -const fm = createFileManager(myProjectPath); -const myCompiledCode = await compile_contract(fm); -``` - -```typescript -// Browser - -import { compile_contract, createFileManager } from '@noir-lang/noir_wasm'; - -const fm = createFileManager('/'); -for (const path of files) { - await fm.writeFile(path, await getFileAsStream(path)); -} -const myCompiledCode = await compile_contract(fm); -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/functions/createFileManager.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/functions/createFileManager.md deleted file mode 100644 index 7e65c1d69c7..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/functions/createFileManager.md +++ /dev/null @@ -1,21 +0,0 @@ -# createFileManager() - -```ts -createFileManager(dataDir): FileManager -``` - -Creates a new FileManager instance based on fs in node and memfs in the browser (via webpack alias) - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `dataDir` | `string` | root of the file system | - -## Returns - -`FileManager` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md deleted file mode 100644 index fcea9275341..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md +++ /dev/null @@ -1,21 +0,0 @@ -# inflateDebugSymbols() - -```ts -inflateDebugSymbols(debugSymbols): any -``` - -Decompresses and decodes the debug symbols - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `debugSymbols` | `string` | The base64 encoded debug symbols | - -## Returns - -`any` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/index.md deleted file mode 100644 index b6e0f9d1bc0..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/index.md +++ /dev/null @@ -1,49 +0,0 @@ -# noir_wasm - -## Exports - -### Functions - -| Function | Description | -| :------ | :------ | -| [compile](functions/compile.md) | Compiles a Noir project | -| [compile\_contract](functions/compile_contract.md) | Compiles a Noir project | -| [createFileManager](functions/createFileManager.md) | Creates a new FileManager instance based on fs in node and memfs in the browser (via webpack alias) | -| [inflateDebugSymbols](functions/inflateDebugSymbols.md) | Decompresses and decodes the debug symbols | - -## References - -### compile\_program - -Renames and re-exports [compile](functions/compile.md) - -## Interfaces - -### ContractCompilationArtifacts - -The compilation artifacts of a given contract. - -#### Properties - -| Property | Type | Description | -| :------ | :------ | :------ | -| `contract` | `ContractArtifact` | The compiled contract. | -| `warnings` | `unknown`[] | Compilation warnings. | - -*** - -### ProgramCompilationArtifacts - -The compilation artifacts of a given program. - -#### Properties - -| Property | Type | Description | -| :------ | :------ | :------ | -| `name` | `string` | not part of the compilation output, injected later | -| `program` | `ProgramArtifact` | The compiled contract. | -| `warnings` | `unknown`[] | Compilation warnings. | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs deleted file mode 100644 index e0870710349..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"doc","id":"reference/NoirJS/noir_wasm/index","label":"API"},{"type":"category","label":"Functions","items":[{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/compile","label":"compile"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/compile_contract","label":"compile_contract"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/createFileManager","label":"createFileManager"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/inflateDebugSymbols","label":"inflateDebugSymbols"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/_category_.json deleted file mode 100644 index 5b6a20a609a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 4, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/debugger/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/debugger/_category_.json deleted file mode 100644 index 27869205ad3..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/debugger/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Debugger", - "position": 1, - "collapsible": true, - "collapsed": true -} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/debugger/debugger_known_limitations.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/debugger/debugger_known_limitations.md deleted file mode 100644 index 936d416ac4b..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/debugger/debugger_known_limitations.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: Known limitations -description: - An overview of known limitations of the current version of the Noir debugger -keywords: - [ - Nargo, - Noir Debugger, - VS Code, - ] -sidebar_position: 2 ---- - -# Debugger Known Limitations - -There are currently some limits to what the debugger can observe. - -## Mutable references - -The debugger is currently blind to any state mutated via a mutable reference. For example, in: - -``` -let mut x = 1; -let y = &mut x; -*y = 2; -``` - -The update on `x` will not be observed by the debugger. That means, when running `vars` from the debugger REPL, or inspecting the _local variables_ pane in the VS Code debugger, `x` will appear with value 1 despite having executed `*y = 2;`. - -## Variables of type function or mutable references are opaque - -When inspecting variables, any variable of type `Function` or `MutableReference` will render its value as `<>` or `<>`. - -## Debugger instrumentation affects resulting ACIR - -In order to make the state of local variables observable, the debugger compiles Noir circuits interleaving foreign calls that track any mutations to them. While this works (except in the cases described above) and doesn't introduce any behavior changes, it does as a side effect produce bigger bytecode. In particular, when running the command `opcodes` on the REPL debugger, you will notice Unconstrained VM blocks that look like this: - -``` -... -5 BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [], q_c: 2 }), Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(2))], q_c: 0 })] - | outputs=[] - 5.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } - 5.1 | Mov { destination: RegisterIndex(3), source: RegisterIndex(1) } - 5.2 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } - 5.3 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } - 5.4 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } - 5.5 | Mov { destination: RegisterIndex(3), source: RegisterIndex(3) } - 5.6 | Call { location: 8 } - 5.7 | Stop - 5.8 | ForeignCall { function: "__debug_var_assign", destinations: [], inputs: [RegisterIndex(RegisterIndex(2)), RegisterIndex(RegisterIndex(3))] } -... -``` - -If you are interested in debugging/inspecting compiled ACIR without these synthetic changes, you can invoke the REPL debugger with the `--skip-instrumentation` flag or launch the VS Code debugger with the `skipConfiguration` property set to true in its launch configuration. You can find more details about those in the [Debugger REPL reference](debugger_repl.md) and the [VS Code Debugger reference](debugger_vscode.md). - -:::note -Skipping debugger instrumentation means you won't be able to inspect values of local variables. -::: - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/debugger/debugger_repl.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/debugger/debugger_repl.md deleted file mode 100644 index 46e2011304e..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/debugger/debugger_repl.md +++ /dev/null @@ -1,360 +0,0 @@ ---- -title: REPL Debugger -description: - Noir Debugger REPL options and commands. -keywords: - [ - Nargo, - Noir CLI, - Noir Debugger, - REPL, - ] -sidebar_position: 1 ---- - -## Running the REPL debugger - -`nargo debug [OPTIONS] [WITNESS_NAME]` - -Runs the Noir REPL debugger. If a `WITNESS_NAME` is provided the debugger writes the resulting execution witness to a `WITNESS_NAME` file. - -### Options - -| Option | Description | -| --------------------- | ------------------------------------------------------------ | -| `-p, --prover-name ` | The name of the toml file which contains the inputs for the prover [default: Prover]| -| `--package ` | The name of the package to debug | -| `--print-acir` | Display the ACIR for compiled circuit | -| `--deny-warnings` | Treat all warnings as errors | -| `--silence-warnings` | Suppress warnings | -| `-h, --help` | Print help | - -None of these options are required. - -:::note -Since the debugger starts by compiling the target package, all Noir compiler options are also available. Check out the [compiler reference](../nargo_commands.md#nargo-compile) to learn more about the compiler options. -::: - -## REPL commands - -Once the debugger is running, it accepts the following commands. - -#### `help` (h) - -Displays the menu of available commands. - -``` -> help -Available commands: - - opcodes display ACIR opcodes - into step into to the next opcode - next step until a new source location is reached - out step until a new source location is reached - and the current stack frame is finished - break LOCATION:OpcodeLocation add a breakpoint at an opcode location - over step until a new source location is reached - without diving into function calls - restart restart the debugging session - delete LOCATION:OpcodeLocation delete breakpoint at an opcode location - witness show witness map - witness index:u32 display a single witness from the witness map - witness index:u32 value:String update a witness with the given value - memset index:usize value:String update a memory cell with the given - value - continue continue execution until the end of the - program - vars show variable values available at this point - in execution - stacktrace display the current stack trace - memory show memory (valid when executing unconstrained code) value - step step to the next ACIR opcode - -Other commands: - - help Show this help message - quit Quit repl - -``` - -### Stepping through programs - -#### `next` (n) - -Step until the next Noir source code location. While other commands, such as [`into`](#into-i) and [`step`](#step-s), allow for finer grained control of the program's execution at the opcode level, `next` is source code centric. For example: - -``` -3 ... -4 fn main(x: u32) { -5 assert(entry_point(x) == 2); -6 swap_entry_point(x, x + 1); -7 -> assert(deep_entry_point(x) == 4); -8 multiple_values_entry_point(x); -9 } -``` - - -Using `next` here would cause the debugger to jump to the definition of `deep_entry_point` (if available). - -If you want to step over `deep_entry_point` and go straight to line 8, use [the `over` command](#over) instead. - -#### `over` - -Step until the next source code location, without diving into function calls. For example: - -``` -3 ... -4 fn main(x: u32) { -5 assert(entry_point(x) == 2); -6 swap_entry_point(x, x + 1); -7 -> assert(deep_entry_point(x) == 4); -8 multiple_values_entry_point(x); -9 } -``` - - -Using `over` here would cause the debugger to execute until line 8 (`multiple_values_entry_point(x);`). - -If you want to step into `deep_entry_point` instead, use [the `next` command](#next-n). - -#### `out` - -Step until the end of the current function call. For example: - -``` - 3 ... - 4 fn main(x: u32) { - 5 assert(entry_point(x) == 2); - 6 swap_entry_point(x, x + 1); - 7 -> assert(deep_entry_point(x) == 4); - 8 multiple_values_entry_point(x); - 9 } - 10 - 11 unconstrained fn returns_multiple_values(x: u32) -> (u32, u32, u32, u32) { - 12 ... - ... - 55 - 56 unconstrained fn deep_entry_point(x: u32) -> u32 { - 57 -> level_1(x + 1) - 58 } - -``` - -Running `out` here will resume execution until line 8. - -#### `step` (s) - -Skips to the next ACIR code. A compiled Noir program is a sequence of ACIR opcodes. However, an unconstrained VM opcode denotes the start of an unconstrained code block, to be executed by the unconstrained VM. For example (redacted for brevity): - -``` -0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] -1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] - 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } - 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } - 1.2 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } - 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } - 1.4 | Call { location: 7 } - ... - 1.43 | Return -2 EXPR [ (1, _1) -2 ] -``` - -The `->` here shows the debugger paused at an ACIR opcode: `BRILLIG`, at index 1, which denotes an unconstrained code block is about to start. - -Using the `step` command at this point would result in the debugger stopping at ACIR opcode 2, `EXPR`, skipping unconstrained computation steps. - -Use [the `into` command](#into-i) instead if you want to follow unconstrained computation step by step. - -#### `into` (i) - -Steps into the next opcode. A compiled Noir program is a sequence of ACIR opcodes. However, a BRILLIG opcode denotes the start of an unconstrained code block, to be executed by the unconstrained VM. For example (redacted for brevity): - -``` -0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] -1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] - 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } - 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } - 1.2 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } - 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } - 1.4 | Call { location: 7 } - ... - 1.43 | Return -2 EXPR [ (1, _1) -2 ] -``` - -The `->` here shows the debugger paused at an ACIR opcode: `BRILLIG`, at index 1, which denotes an unconstrained code block is about to start. - -Using the `into` command at this point would result in the debugger stopping at opcode 1.0, `Mov ...`, allowing the debugger user to follow unconstrained computation step by step. - -Use [the `step` command](#step-s) instead if you want to skip to the next ACIR code directly. - -#### `continue` (c) - -Continues execution until the next breakpoint, or the end of the program. - -#### `restart` (res) - -Interrupts execution, and restarts a new debugging session from scratch. - -#### `opcodes` (o) - -Display the program's ACIR opcode sequence. For example: - -``` -0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] -1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] - 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } - 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } - 1.2 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } - 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } - 1.4 | Call { location: 7 } - ... - 1.43 | Return -2 EXPR [ (1, _1) -2 ] -``` - -### Breakpoints - -#### `break [Opcode]` (or shorthand `b [Opcode]`) - -Sets a breakpoint on the specified opcode index. To get a list of the program opcode numbers, see [the `opcode` command](#opcodes-o). For example: - -``` -0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] -1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] - 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } - 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } - 1.2 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } - 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } - 1.4 | Call { location: 7 } - ... - 1.43 | Return -2 EXPR [ (1, _1) -2 ] -``` - -In this example, issuing a `break 1.2` command adds break on opcode 1.2, as denoted by the `*` character: - -``` -0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] -1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] - 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } - 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } - 1.2 | * Const { destination: RegisterIndex(1), value: Value { inner: 0 } } - 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } - 1.4 | Call { location: 7 } - ... - 1.43 | Return -2 EXPR [ (1, _1) -2 ] -``` - -Running [the `continue` command](#continue-c) at this point would cause the debugger to execute the program until opcode 1.2. - -#### `delete [Opcode]` (or shorthand `d [Opcode]`) - -Deletes a breakpoint at an opcode location. Usage is analogous to [the `break` command](#). - -### Variable inspection - -#### vars - -Show variable values available at this point in execution. - -:::note -The ability to inspect variable values from the debugger depends on compilation to be run in a special debug instrumentation mode. This instrumentation weaves variable tracing code with the original source code. - -So variable value inspection comes at the expense of making the resulting ACIR bytecode bigger and harder to understand and optimize. - -If you find this compromise unacceptable, you can run the debugger with the flag `--skip-debug-instrumentation`. This will compile your circuit without any additional debug information, so the resulting ACIR bytecode will be identical to the one produced by standard Noir compilation. However, if you opt for this, the `vars` command will not be available while debugging. -::: - - -### Stacktrace - -#### `stacktrace` - -Displays the current stack trace. - - -### Witness map - -#### `witness` (w) - -Show witness map. For example: - -``` -_0 = 0 -_1 = 2 -_2 = 1 -``` - -#### `witness [Witness Index]` - -Display a single witness from the witness map. For example: - -``` -> witness 1 -_1 = 2 -``` - -#### `witness [Witness Index] [New value]` - -Overwrite the given index with a new value. For example: - -``` -> witness 1 3 -_1 = 3 -``` - - -### Unconstrained VM memory - -#### `memory` - -Show unconstrained VM memory state. For example: - -``` -> memory -At opcode 1.13: Store { destination_pointer: RegisterIndex(0), source: RegisterIndex(3) } -... -> registers -0 = 0 -1 = 10 -2 = 0 -3 = 1 -4 = 1 -5 = 2³² -6 = 1 -> into -At opcode 1.14: Const { destination: RegisterIndex(5), value: Value { inner: 1 } } -... -> memory -0 = 1 -> -``` - -In the example above: we start with clean memory, then step through a `Store` opcode which stores the value of register 3 (1) into the memory address stored in register 0 (0). Thus now `memory` shows memory address 0 contains value 1. - -:::note -This command is only functional while the debugger is executing unconstrained code. -::: - -#### `memset [Memory address] [New value]` - -Update a memory cell with the given value. For example: - -``` -> memory -0 = 1 -> memset 0 2 -> memory -0 = 2 -> memset 1 4 -> memory -0 = 2 -1 = 4 -> -``` - -:::note -This command is only functional while the debugger is executing unconstrained code. -::: \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/debugger/debugger_vscode.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/debugger/debugger_vscode.md deleted file mode 100644 index c027332b3b0..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/debugger/debugger_vscode.md +++ /dev/null @@ -1,82 +0,0 @@ ---- -title: VS Code Debugger -description: - VS Code Debugger configuration and features. -keywords: - [ - Nargo, - Noir CLI, - Noir Debugger, - VS Code, - IDE, - ] -sidebar_position: 0 ---- - -# VS Code Noir Debugger Reference - -The Noir debugger enabled by the vscode-noir extension ships with default settings such that the most common scenario should run without any additional configuration steps. - -These defaults can nevertheless be overridden by defining a launch configuration file. This page provides a reference for the properties you can override via a launch configuration file, as well as documenting the Nargo `dap` command, which is a dependency of the VS Code Noir debugger. - - -## Creating and editing launch configuration files - -To create a launch configuration file from VS Code, open the _debug pane_, and click on _create a launch.json file_. - -![Creating a launch configuration file](@site/static/img/debugger/ref1-create-launch.png) - -A `launch.json` file will be created, populated with basic defaults. - -### Noir Debugger launch.json properties - -#### projectFolder - -_String, optional._ - -Absolute path to the Nargo project to debug. By default, it is dynamically determined by looking for the nearest `Nargo.toml` file to the active file at the moment of launching the debugger. - -#### proverName - -_String, optional._ - -Name of the prover input to use. Defaults to `Prover`, which looks for a file named `Prover.toml` at the `projectFolder`. - -#### generateAcir - -_Boolean, optional._ - -If true, generate ACIR opcodes instead of unconstrained opcodes which will be closer to release binaries but less convenient for debugging. Defaults to `false`. - -#### skipInstrumentation - -_Boolean, optional._ - -Skips variables debugging instrumentation of code, making debugging less convenient but the resulting binary smaller and closer to production. Defaults to `false`. - -:::note -Skipping instrumentation causes the debugger to be unable to inspect local variables. -::: - -## `nargo dap [OPTIONS]` - -When run without any option flags, it starts the Nargo Debug Adapter Protocol server, which acts as the debugging backend for the VS Code Noir Debugger. - -All option flags are related to preflight checks. The Debug Adapter Protocol specifies how errors are to be informed from a running DAP server, but it doesn't specify mechanisms to communicate server initialization errors between the DAP server and its client IDE. - -Thus `nargo dap` ships with a _preflight check_ mode. If flag `--preflight-check` and the rest of the `--preflight-*` flags are provided, Nargo will run the same initialization routine except it will not start the DAP server. - -`vscode-noir` will then run `nargo dap` in preflight check mode first before a debugging session starts. If the preflight check ends in error, vscode-noir will present stderr and stdout output from this process through its own Output pane in VS Code. This makes it possible for users to diagnose what pieces of configuration might be wrong or missing in case of initialization errors. - -If the preflight check succeeds, `vscode-noir` proceeds to start the DAP server normally but running `nargo dap` without any additional flags. - -### Options - -| Option | Description | -| --------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | -| `--preflight-check` | If present, dap runs in preflight check mode. | -| `--preflight-project-folder ` | Absolute path to the project to debug for preflight check. | -| `--preflight-prover-name ` | Name of prover file to use for preflight check | -| `--preflight-generate-acir` | Optional. If present, compile in ACIR mode while running preflight check. | -| `--preflight-skip-instrumentation` | Optional. If present, compile without introducing debug instrumentation while running preflight check. | -| `-h, --help` | Print help. | diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/nargo_commands.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/nargo_commands.md deleted file mode 100644 index ab9dd879d85..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/nargo_commands.md +++ /dev/null @@ -1,244 +0,0 @@ ---- -title: Nargo -description: - Noir CLI Commands for Noir Prover and Verifier to create, execute, prove and verify programs, - generate Solidity verifier smart contract and compile into JSON file containing ACIR - representation and ABI of circuit. -keywords: - [ - Nargo, - Noir CLI, - Noir Prover, - Noir Verifier, - generate Solidity verifier, - compile JSON file, - ACIR representation, - ABI of circuit, - TypeScript, - ] -sidebar_position: 0 ---- - -# Command-Line Help for `nargo` - -This document contains the help content for the `nargo` command-line program. - -**Command Overview:** - -* [`nargo`↴](#nargo) -* [`nargo check`↴](#nargo-check) -* [`nargo fmt`↴](#nargo-fmt) -* [`nargo compile`↴](#nargo-compile) -* [`nargo new`↴](#nargo-new) -* [`nargo init`↴](#nargo-init) -* [`nargo execute`↴](#nargo-execute) -* [`nargo test`↴](#nargo-test) -* [`nargo info`↴](#nargo-info) -* [`nargo lsp`↴](#nargo-lsp) - -## `nargo` - -Noir's package manager - -**Usage:** `nargo ` - -###### **Subcommands:** - -* `check` — Checks the constraint system for errors -* `fmt` — Format the Noir files in a workspace -* `compile` — Compile the program and its secret execution trace into ACIR format -* `new` — Create a Noir project in a new directory -* `init` — Create a Noir project in the current directory -* `execute` — Executes a circuit to calculate its return value -* `test` — Run the tests for this program -* `info` — Provides detailed information on each of a program's function (represented by a single circuit) -* `lsp` — Starts the Noir LSP server - -###### **Options:** - - - - -## `nargo check` - -Checks the constraint system for errors - -**Usage:** `nargo check [OPTIONS]` - -###### **Options:** - -* `--package ` — The name of the package to check -* `--workspace` — Check all packages in the workspace -* `--overwrite` — Force overwrite of existing files -* `--expression-width ` — Override the expression width requested by the backend - - Default value: `4` -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings - - - -## `nargo fmt` - -Format the Noir files in a workspace - -**Usage:** `nargo fmt [OPTIONS]` - -###### **Options:** - -* `--check` — Run noirfmt in check mode - - - -## `nargo compile` - -Compile the program and its secret execution trace into ACIR format - -**Usage:** `nargo compile [OPTIONS]` - -###### **Options:** - -* `--package ` — The name of the package to compile -* `--workspace` — Compile all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend - - Default value: `4` -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings - - - -## `nargo new` - -Create a Noir project in a new directory - -**Usage:** `nargo new [OPTIONS] ` - -###### **Arguments:** - -* `` — The path to save the new project - -###### **Options:** - -* `--name ` — Name of the package [default: package directory name] -* `--lib` — Use a library template -* `--bin` — Use a binary template [default] -* `--contract` — Use a contract template - - - -## `nargo init` - -Create a Noir project in the current directory - -**Usage:** `nargo init [OPTIONS]` - -###### **Options:** - -* `--name ` — Name of the package [default: current directory name] -* `--lib` — Use a library template -* `--bin` — Use a binary template [default] -* `--contract` — Use a contract template - - - -## `nargo execute` - -Executes a circuit to calculate its return value - -**Usage:** `nargo execute [OPTIONS] [WITNESS_NAME]` - -###### **Arguments:** - -* `` — Write the execution witness to named file - -###### **Options:** - -* `-p`, `--prover-name ` — The name of the toml file which contains the inputs for the prover - - Default value: `Prover` -* `--package ` — The name of the package to execute -* `--workspace` — Execute all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend - - Default value: `4` -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings -* `--oracle-resolver ` — JSON RPC url to solve oracle calls - - - -## `nargo test` - -Run the tests for this program - -**Usage:** `nargo test [OPTIONS] [TEST_NAME]` - -###### **Arguments:** - -* `` — If given, only tests with names containing this string will be run - -###### **Options:** - -* `--show-output` — Display output of `println` statements -* `--exact` — Only run tests that match exactly -* `--package ` — The name of the package to test -* `--workspace` — Test all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend - - Default value: `4` -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings -* `--oracle-resolver ` — JSON RPC url to solve oracle calls - - - -## `nargo info` - -Provides detailed information on each of a program's function (represented by a single circuit) - -Current information provided per circuit: 1. The number of ACIR opcodes 2. Counts the final number gates in the circuit used by a backend - -**Usage:** `nargo info [OPTIONS]` - -###### **Options:** - -* `--package ` — The name of the package to detail -* `--workspace` — Detail all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend - - Default value: `4` -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings - - - -## `nargo lsp` - -Starts the Noir LSP server - -Starts an LSP server which allows IDEs such as VS Code to display diagnostics in Noir source. - -VS Code Noir Language Support: https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir - -**Usage:** `nargo lsp` - - - -
- - - This document was generated automatically by - clap-markdown. - - diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/tooling/debugger.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/tooling/debugger.md deleted file mode 100644 index 9b7565ba9ff..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/tooling/debugger.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Debugger -description: Learn about the Noir Debugger, in its REPL or VS Code versions. -keywords: [Nargo, VSCode, Visual Studio Code, REPL, Debugger] -sidebar_position: 2 ---- - -# Noir Debugger - -There are currently two ways of debugging Noir programs: - -1. From VS Code, via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). -2. Via the REPL debugger, which ships with Nargo. - -In order to use either version of the debugger, you will need to install recent enough versions of Noir, [Nargo](../getting_started/installation/index.md) and vscode-noir: - -- Noir & Nargo ≥0.28.0 -- Noir's VS Code extension ≥0.0.11 - -:::info -At the moment, the debugger supports debugging binary projects, but not contracts. -::: - -We cover the VS Code Noir debugger more in depth in [its VS Code debugger how-to guide](../how_to/debugger/debugging_with_vs_code.md) and [the reference](../reference/debugger/debugger_vscode.md). - -The REPL debugger is discussed at length in [the REPL debugger how-to guide](../how_to/debugger/debugging_with_the_repl.md) and [the reference](../reference/debugger/debugger_repl.md). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/tooling/language_server.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/tooling/language_server.md deleted file mode 100644 index 81e0356ef8a..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/tooling/language_server.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Language Server -description: Learn about the Noir Language Server, how to install the components, and configuration that may be required. -keywords: [Nargo, Language Server, LSP, VSCode, Visual Studio Code] -sidebar_position: 0 ---- - -This section helps you install and configure the Noir Language Server. - -The Language Server Protocol (LSP) has two components, the [Server](#language-server) and the [Client](#language-client). Below we describe each in the context of Noir. - -## Language Server - -The Server component is provided by the Nargo command line tool that you installed at the beginning of this guide. -As long as Nargo is installed and you've used it to run other commands in this guide, it should be good to go! - -If you'd like to verify that the `nargo lsp` command is available, you can run `nargo --help` and look for `lsp` in the list of commands. If you see it, you're using a version of Noir with LSP support. - -## Language Client - -The Client component is usually an editor plugin that launches the Server. It communicates LSP messages between the editor and the Server. For example, when you save a file, the Client will alert the Server, so it can try to compile the project and report any errors. - -Currently, Noir provides a Language Client for Visual Studio Code via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). - -> **Note:** Noir's Language Server Protocol support currently assumes users' VSCode workspace root to be the same as users' Noir project root (i.e. where Nargo.toml lies). -> -> If LSP features seem to be missing / malfunctioning, make sure you are opening your Noir project directly (instead of as a sub-folder) in your VSCode instance. - -When your language server is running correctly and the VSCode plugin is installed, you should see handy codelens buttons for compilation, measuring circuit size, execution, and tests: - -![Compile and Execute](@site/static/img/codelens_compile_execute.png) -![Run test](@site/static/img/codelens_run_test.png) - -You should also see your tests in the `testing` panel: - -![Testing panel](@site/static/img/codelens_testing_panel.png) - -### Configuration - -- **Noir: Enable LSP** - If checked, the extension will launch the Language Server via `nargo lsp` and communicate with it. -- **Noir: Nargo Flags** - Additional flags may be specified if you require them to be added when the extension calls `nargo lsp`. -- **Noir: Nargo Path** - An absolute path to a Nargo binary with the `lsp` command. This may be useful if Nargo is not within the `PATH` of your editor. -- **Noir > Trace: Server** - Setting this to `"messages"` or `"verbose"` will log LSP messages between the Client and Server. Useful for debugging. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/tooling/testing.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/tooling/testing.md deleted file mode 100644 index d3e0c522473..00000000000 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/tooling/testing.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -title: Testing in Noir -description: Learn how to use Nargo to test your Noir program in a quick and easy way -keywords: [Nargo, testing, Noir, compile, test] -sidebar_position: 1 ---- - -You can test your Noir programs using Noir circuits. - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. - -For example if you have a program like: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test] -fn test_add() { - assert(add(2,2) == 4); - assert(add(0,1) == 1); - assert(add(1,0) == 1); -} -``` - -Running `nargo test` will test that the `test_add` function can be executed while satisfying all -the constraints which allows you to test that add returns the expected values. Test functions can't -have any arguments currently. - -### Test fail - -You can write tests that are expected to fail by using the decorator `#[test(should_fail)]`. For example: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test(should_fail)] -fn test_add() { - assert(add(2,2) == 5); -} -``` - -You can be more specific and make it fail with a specific reason by using `should_fail_with = "`: - -```rust -fn main(african_swallow_avg_speed : Field) { - assert(african_swallow_avg_speed == 65, "What is the airspeed velocity of an unladen swallow"); -} - -#[test] -fn test_king_arthur() { - main(65); -} - -#[test(should_fail_with = "What is the airspeed velocity of an unladen swallow")] -fn test_bridgekeeper() { - main(32); -} - -``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.34.0/explainers/cspell.json b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/explainers/cspell.json new file mode 100644 index 00000000000..c60b0a597b1 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/explainers/cspell.json @@ -0,0 +1,5 @@ +{ + "words": [ + "Cryptdoku" + ] +} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/explainers/explainer-oracle.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/explainers/explainer-oracle.md similarity index 91% rename from noir/noir-repo/docs/versioned_docs/version-v0.23.0/explainers/explainer-oracle.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/explainers/explainer-oracle.md index b84ca5dd986..821e1f95c04 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/explainers/explainer-oracle.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/explainers/explainer-oracle.md @@ -31,7 +31,7 @@ In short, anything that can be constrained in a Noir program but needs to be fet Just like in The Matrix, Oracles are powerful. But with great power, comes great responsibility. Just because you're using them in a Noir program doesn't mean they're true. Noir has no superpowers. If you want to prove that Portugal won the Euro Cup 2016, you're still relying on potentially untrusted information. -To give a concrete example, Alice wants to login to the [NounsDAO](https://nouns.wtf/) forum with her username "noir_nouner" by proving she owns a noun without revealing her ethereum address. Her Noir program could have a oracle call like this: +To give a concrete example, Alice wants to login to the [NounsDAO](https://nouns.wtf/) forum with her username "noir_nouner" by proving she owns a noun without revealing her ethereum address. Her Noir program could have an oracle call like this: ```rust #[oracle(getNoun)] @@ -52,6 +52,6 @@ If you don't constrain the return of your oracle, you could be clearly opening a On CLI, Nargo resolves oracles by making JSON RPC calls, which means it would require an RPC node to be running. -In JavaScript, NoirJS accepts and resolves arbitrary call handlers (that is, not limited to JSON) as long as they matches the expected types the developer defines. Refer to [Foreign Call Handler](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) to learn more about NoirJS's call handling. +In JavaScript, NoirJS accepts and resolves arbitrary call handlers (that is, not limited to JSON) as long as they match the expected types the developer defines. Refer to [Foreign Call Handler](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) to learn more about NoirJS's call handling. If you want to build using oracles, follow through to the [oracle guide](../how_to/how-to-oracles.md) for a simple example on how to do that. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/explainers/explainer-recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/explainers/explainer-recursion.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.23.0/explainers/explainer-recursion.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/explainers/explainer-recursion.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.34.0/explainers/explainer-writing-noir.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/explainers/explainer-writing-noir.md new file mode 100644 index 00000000000..3ef6e014a2f --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/explainers/explainer-writing-noir.md @@ -0,0 +1,177 @@ +--- +title: Writing Performant Noir +description: Understand new considerations when writing Noir +keywords: [Noir, programming, rust] +tags: [Optimization] +sidebar_position: 0 +--- + + +This article intends to set you up with key concepts essential for writing more viable applications that use zero knowledge proofs, namely around efficient circuits. + +## Context - 'Efficient' is subjective + +When writing a web application for a performant computer with high-speed internet connection, writing efficient code sometimes is seen as an afterthought only if needed. Large multiplications running at the innermost of nested loops may not even be on a dev's radar. +When writing firmware for a battery-powered microcontroller, you think of cpu cycles as rations to keep within a product's power budget. + +> Code is written to create applications that perform specific tasks within specific constraints + +And these constraints differ depending on where the compiled code is execute. + +### The Ethereum Virtual Machine (EVM) + +In scenarios where extremely low gas costs are required for an Ethereum application to be viable/competitive, Ethereum smart contract developers get into what is colloquially known as: "*gas golfing*". Finding the lowest execution cost of their compiled code (EVM bytecode) to achieve a specific task. + +The equivalent optimization task when writing zk circuits is affectionately referred to as "*gate golfing*", finding the lowest gate representation of the compiled Noir code. + +### Coding for circuits - a paradigm shift + +In zero knowledge cryptography, code is compiled to "circuits" consisting of arithmetic gates, and gate count is the significant cost. Depending on the proving system this is linearly proportionate to proving time, and so from a product point this should be kept as low as possible. + +Whilst writing efficient code for web apps and Solidity has a few key differences, writing efficient circuits have a different set of considerations. It is a bit of a paradigm shift, like writing code for GPUs for the first time... + +For example, drawing a circle at (0, 0) of radius `r`: +- For a single CPU thread, +``` +for theta in 0..2*pi { + let x = r * cos(theta); + let y = r * sin(theta); + draw(x, y); +} // note: would do 0 - pi/2 and draw +ve/-ve x and y. +``` + +- For GPUs (simultaneous parallel calls with x, y across image), +``` +if (x^2 + y^2 = r^2) { + draw(x, y); +} +``` + +([Related](https://www.youtube.com/watch?v=-P28LKWTzrI)) + +Whilst this CPU -> GPU does not translate to circuits exactly, it is intended to exemplify the difference in intuition when coding for different machine capabilities/constraints. + +### Context Takeaway + +For those coming from a primarily web app background, this article will explain what you need to consider when writing circuits. Furthermore, for those experienced writing efficient machine code, prepare to shift what you think is efficient 😬 + +## Translating from Rust + +For some applications using Noir, existing code might be a convenient starting point to then proceed to optimize the gate count of. + +:::note +Many valuable functions and algorithms have been written in more established languages (C/C++), and converted to modern ones (like Rust). +::: + +Fortunately for Noir developers, when needing a particular function a Rust implementation can be readily compiled into Noir with some key changes. While the compiler does a decent amount of optimizations, it won't be able to change code that has been optimized for clock-cycles into code optimized for arithmetic gates. + +A few things to do when converting Rust code to Noir: +- `println!` is not a macro, use `println` function (same for `assert_eq`) +- No early `return` in function. Use constrain via assertion instead +- No passing by reference. Remove `&` operator to pass by value (copy) +- No boolean operators (`&&`, `||`). Use bitwise operators (`&`, `|`) with boolean values +- No type `usize`. Use types `u8`, `u32`, `u64`, ... +- `main` return must be public, `pub` +- No `const`, use `global` +- Noir's LSP is your friend, so error message should be informative enough to resolve syntax issues. + +## Writing efficient Noir for performant products + +The following points help refine our understanding over time. + +:::note +A Noir program makes a statement that can be verified. +::: + +It compiles to a structure that represents the calculation, and can assert results within the calculation at any stage (via the `constrain` keyword). + +A Noir program compiles to an Abstract Circuit Intermediate Representation which is: + - Conceptually a tree structure + - Leaves (inputs) are the `Field` type + - Nodes contain arithmetic operations to combine them (gates) + - The root is the final result (return value) + +:::tip +The command `nargo info` shows the programs circuit size, and is useful to compare the value of changes made. +You can dig deeper and use the `--print-acir` param to take a closer look at individual ACIR opcodes, and the proving backend to see its gate count (eg for barretenberg, `bb gates -b ./target/program.json`). +::: + +### Use the `Field` type + +Since the native type of values in circuits are `Field`s, using them for variables in Noir means less gates converting them under the hood. +Some things to be mindful of when using a Field type for a regular integer value: +- A variable of type `Field` can be cast `as` an integer type (eg `u8`, `u64`) + - Note: this retains only the bits of the integer type. Eg a Field value of 260 as a `u8` becomes 4 +- For Field types arithmetic operations meaningfully overflow/underflow, yet for integer types they are checked according to their size +- Comparisons and bitwise operations do not exist for `Field`s, cast to an appropriately sized integer type when you need to + +:::tip +Where possible, use `Field` type for values. Using smaller value types, and bit-packing strategies, will result in MORE gates +::: + + +### Use Arithmetic over non-arithmetic operations + +Since circuits are made of arithmetic gates, the cost of arithmetic operations tends to be one gate. Whereas for procedural code, they represent several clock cycles. + +Inversely, non-arithmetic operators are achieved with multiple gates, vs 1 clock cycle for procedural code. + +| (cost\op) | arithmetic
(`*`, `+`) | bit-wise ops
(eg `<`, `\|`, `>>`) | +| - | - | - | +| **cycles** | 10+ | 1 | +| **gates** | 1 | 10+ | + +Bit-wise operations (e.g. bit shifts `<<` and `>>`), albeit commonly used in general programming and especially for clock cycle optimizations, are on the contrary expensive in gates when performed within circuits. + +Translate away from bit shifts when writing constrained functions for the best performance. + +On the flip side, feel free to use bit shifts in unconstrained functions and tests if necessary, as they are executed outside of circuits and does not induce performance hits. + +### Use static over dynamic values + +Another general theme that manifests in different ways is that static reads are represented with less gates than dynamic ones. + +Reading from read-only memory (ROM) adds less gates than random-access memory (RAM), 2 vs ~3.25 due to the additional bounds checks. Arrays of fixed length (albeit used at a lower capacity), will generate less gates than dynamic storage. + +Related to this, if an index used to access an array is not known at compile time (ie unknown until run time), then ROM will be converted to RAM, expanding the gate count. + +:::tip +Use arrays and indices that are known at compile time where possible. +Using `assert_constant(i);` before an index, `i`, is used in an array will give a compile error if `i` is NOT known at compile time. +::: + +### Leverage unconstrained execution + +Constrained verification can leverage unconstrained execution, this is especially useful for operations that are represented by many gates. +Use an [unconstrained function](../noir/concepts/unconstrained.md) to perform gate-heavy calculations, then verify and constrain the result. + +Eg division generates more gates than multiplication, so calculating the quotient in an unconstrained function then constraining the product for the quotient and divisor (+ any remainder) equals the dividend will be more efficient. + +Use ` if is_unconstrained() { /`, to conditionally execute code if being called in an unconstrained vs constrained way. + +## Advanced + +Unless you're well into the depth of gate optimization, this advanced section can be ignored. + +### Combine arithmetic operations + +A Noir program can be honed further by combining arithmetic operators in a way that makes the most of each constraint of the backend proving system. This is in scenarios where the backend might not be doing this perfectly. + +Eg Barretenberg backend (current default for Noir) is a width-4 PLONKish constraint system +$ w_1*w_2*q_m + w_1*q_1 + w_2*q_2 + w_3*q_3 + w_4*q_4 + q_c = 0 $ + +Here we see there is one occurrence of witness 1 and 2 ($w_1$, $w_2$) being multiplied together, with addition to witnesses 1-4 ($w_1$ .. $w_4$) multiplied by 4 corresponding circuit constants ($q_1$ .. $q_4$) (plus a final circuit constant, $q_c$). + +Use `nargo info --print-acir`, to inspect the ACIR opcodes (and the proving system for gates), and it may present opportunities to amend the order of operations and reduce the number of constraints. + +#### Variable as witness vs expression + +If you've come this far and really know what you're doing at the equation level, a temporary lever (that will become unnecessary/useless over time) is: `std::as_witness`. This informs the compiler to save a variable as a witness not an expression. + +The compiler will mostly be correct and optimal, but this may help some near term edge cases that are yet to optimize. +Note: When used incorrectly it will create **less** efficient circuits (higher gate count). + +## References +- Guillaume's ["`Cryptdoku`" talk](https://www.youtube.com/watch?v=MrQyzuogxgg) (Jun'23) +- Tips from Tom, Jake and Zac. +- [Idiomatic Noir](https://www.vlayer.xyz/blog/idiomatic-noir-part-1-collections) blog post diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/getting_started/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/getting_started/_category_.json similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.22.0/getting_started/_category_.json rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/getting_started/_category_.json diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/backend/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/getting_started/backend/_category_.json similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/backend/_category_.json rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/getting_started/backend/_category_.json diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/backend/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/getting_started/backend/index.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/backend/index.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/getting_started/backend/index.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/hello_noir/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/getting_started/hello_noir/_category_.json similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/hello_noir/_category_.json rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/getting_started/hello_noir/_category_.json diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/hello_noir/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/getting_started/hello_noir/index.md similarity index 93% rename from noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/hello_noir/index.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/getting_started/hello_noir/index.md index 3baae217eb3..6760e54aad1 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/hello_noir/index.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/getting_started/hello_noir/index.md @@ -129,6 +129,11 @@ bb prove -b ./target/hello_world.json -w ./target/witness-name.gz -o ./target/pr The proof generated will then be written to the file `./target/proof`. +:::tip +Since the params for `nargo` and `bb` often specify multiple filenames to read from or write to, remember to check each command is referring to the desired filenames. +Or for greater certainty, delete the target folder and go through each step again (compile, witness, prove, ...) to ensure files generated in past commands are being referenced in future ones. +::: + ### 6. Verify the execution proof Once a proof is generated, we can verify correct execution of our Noir program by verifying the proof file. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/hello_noir/project_breakdown.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/getting_started/hello_noir/project_breakdown.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/hello_noir/project_breakdown.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/getting_started/hello_noir/project_breakdown.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/getting_started/installation/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/getting_started/installation/_category_.json similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.22.0/getting_started/installation/_category_.json rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/getting_started/installation/_category_.json diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/installation/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/getting_started/installation/index.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/installation/index.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/getting_started/installation/index.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/installation/other_install_methods.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/getting_started/installation/other_install_methods.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/installation/other_install_methods.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/getting_started/installation/other_install_methods.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/how_to/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/how_to/_category_.json similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.22.0/how_to/_category_.json rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/how_to/_category_.json diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/how_to/debugger/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/how_to/debugger/_category_.json similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.28.0/how_to/debugger/_category_.json rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/how_to/debugger/_category_.json diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/how_to/debugger/debugging_with_the_repl.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/how_to/debugger/debugging_with_the_repl.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.28.0/how_to/debugger/debugging_with_the_repl.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/how_to/debugger/debugging_with_the_repl.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/how_to/debugger/debugging_with_vs_code.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/how_to/debugger/debugging_with_vs_code.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.28.0/how_to/debugger/debugging_with_vs_code.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/how_to/debugger/debugging_with_vs_code.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/how-to-oracles.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/how_to/how-to-oracles.md similarity index 95% rename from noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/how-to-oracles.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/how_to/how-to-oracles.md index 2d2ed5c94b9..2f69902062c 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/how-to-oracles.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/how_to/how-to-oracles.md @@ -46,7 +46,7 @@ unconstrained fn get_sqrt(number: Field) -> Field { } ``` -In this example, we're wrapping our oracle function in a unconstrained method, and decorating it with `oracle(getSqrt)`. We can then call the unconstrained function as we would call any other function: +In this example, we're wrapping our oracle function in an unconstrained method, and decorating it with `oracle(getSqrt)`. We can then call the unconstrained function as we would call any other function: ```rust fn main(input: Field) { @@ -234,11 +234,11 @@ const client = new JSONRPCClient((jsonRPCRequest) => { // declaring a function that takes the name of the foreign call (getSqrt) and the inputs const foreignCallHandler = async (name, input) => { // notice that the "inputs" parameter contains *all* the inputs - // in this case we to make the RPC request with the first parameter "numbers", which would be input[0] + // in this case we make the RPC request with the first parameter "numbers", which would be input[0] const oracleReturn = await client.request(name, [ - { Array: input[0].map((i) => i.toString("hex")) }, + input[0].map((i) => i.toString("hex")), ]); - return [oracleReturn.values[0].Array]; + return { values: oracleReturn }; }; // the rest of your NoirJS code diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/how-to-recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/how_to/how-to-recursion.md similarity index 99% rename from noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/how-to-recursion.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/how_to/how-to-recursion.md index aac84e29fac..71f02fa5435 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/how-to-recursion.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/how_to/how-to-recursion.md @@ -47,7 +47,7 @@ In a standard recursive app, you're also dealing with at least two circuits. For - `main`: a circuit of type `assert(x != y)`, where `main` is marked with a `#[recursive]` attribute. This attribute states that the backend should generate proofs that are friendly for verification within another circuit. - `recursive`: a circuit that verifies `main` -For a full example on how recursive proofs work, please refer to the [noir-examples](https://github.com/noir-lang/noir-examples) repository. We will *not* be using it as a reference for this guide. +For a full example of how recursive proofs work, please refer to the [noir-examples](https://github.com/noir-lang/noir-examples) repository. We will *not* be using it as a reference for this guide. ## Step 1: Setup diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/how-to-solidity-verifier.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/how_to/how-to-solidity-verifier.md similarity index 95% rename from noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/how-to-solidity-verifier.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/how_to/how-to-solidity-verifier.md index e6ed9abaec6..3bb96c66795 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/how-to-solidity-verifier.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/how_to/how-to-solidity-verifier.md @@ -40,7 +40,7 @@ Generating a Solidity Verifier contract is actually a one-command process. Howev ## Step 1 - Generate a contract -This is by far the most straight-forward step. Just run: +This is by far the most straightforward step. Just run: ```sh nargo compile @@ -99,7 +99,7 @@ This time we will see a warning about an unused function parameter. This is expe ## Step 3 - Deploying -At this point we should have a compiled contract read to deploy. If we navigate to the deploy section in Remix, we will see many different environments we can deploy to. The steps to deploy on each environment would be out-of-scope for this guide, so we will just use the default Remix VM. +At this point we should have a compiled contract ready to deploy. If we navigate to the deploy section in Remix, we will see many different environments we can deploy to. The steps to deploy on each environment would be out-of-scope for this guide, so we will just use the default Remix VM. Looking closely, we will notice that our "Solidity Verifier" is actually three contracts working together: @@ -111,7 +111,7 @@ Remix will take care of the dependencies for us so we can simply deploy the Ultr ![Deploying UltraVerifier](@site/static/img/how-tos/solidity_verifier_5.png) -A contract will show up in the "Deployed Contracts" section, where we can retrieve the Verification Key Hash. This is particularly useful for double-checking the deployer contract is the correct one. +A contract will show up in the "Deployed Contracts" section, where we can retrieve the Verification Key Hash. This is particularly useful for double-checking that the deployer contract is the correct one. :::note @@ -133,7 +133,7 @@ function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) externa When using the default example in the [Hello Noir](../getting_started/hello_noir/index.md) guide, the easiest way to confirm that the verifier contract is doing its job is by calling the `verify` function via remix with the required parameters. Note that the public inputs must be passed in separately to the rest of the proof so we must split the proof as returned from `bb`. -First generate a proof with `bb` at the location `./proof` using the steps in [get started](../getting_started/hello_noir/index.md), this proof is in a binary format but we want to convert it into a hex string to pass into Remix, this can be done with the +First generate a proof with `bb` at the location `./proof` using the steps in [get started](../getting_started/hello_noir/index.md), this proof is in a binary format but we want to convert it into a hex string to pass into Remix, this can be done with the ```bash # This value must be changed to match the number of public inputs (including return values!) in your program. @@ -239,6 +239,12 @@ For example, chains like `zkSync ERA` and `Polygon zkEVM` do not currently suppo - Polygon PoS - Scroll - Celo +- BSC +- Blast L2 +- Avalanche C-Chain +- Mode +- Linea +- Moonbeam If you test any other chains, please open a PR on this page to update the list. See [this doc](https://github.com/noir-lang/noir-starter/tree/main/with-foundry#testing-on-chain) for more info about testing verifier contracts on different EVM chains. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/merkle-proof.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/how_to/merkle-proof.mdx similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/merkle-proof.mdx rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/how_to/merkle-proof.mdx diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/how_to/using-devcontainers.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/how_to/using-devcontainers.mdx similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.23.0/how_to/using-devcontainers.mdx rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/how_to/using-devcontainers.mdx diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/index.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/index.mdx similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.31.0/index.mdx rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/index.mdx diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/migration_notes.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/migration_notes.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.25.0/migration_notes.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/migration_notes.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/_category_.json similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/_category_.json rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/_category_.json diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/assert.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/assert.md similarity index 51% rename from noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/assert.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/assert.md index bcff613a695..2132de42072 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/assert.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/assert.md @@ -1,9 +1,9 @@ --- title: Assert Function description: - Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or - comparison expression that follows to be true, and what happens if the expression is false at - runtime. + Learn about the `assert` and `static_assert` functions in Noir, which can be used to explicitly + constrain the predicate or comparison expression that follows to be true, and what happens if + the expression is false at runtime or compile-time, respectively. keywords: [Noir programming language, assert statement, predicate expression, comparison expression] sidebar_position: 4 --- @@ -43,3 +43,36 @@ let s = myStruct { myField: y }; assert(s.myField == x, s); ``` +There is also a special `static_assert` function that behaves like `assert`, +but that runs at compile-time. + +```rust +fn main(xs: [Field; 3]) { + let x = 2 + 2; + let y = 4; + static_assert(x == y, "expected 2 + 2 to equal 4"); + + // This passes since the length of `xs` is known at compile-time + static_assert(xs.len() == 3, "expected the input to have 3 elements"); +} +``` + +This function fails when passed a dynamic (run-time) argument: + +```rust +fn main(x : Field, y : Field) { + // this fails because `x` is not known at compile-time + static_assert(x == 2, "expected x to be known at compile-time and equal to 2"); + + let mut example_slice = &[]; + if y == 4 { + example_slice = example_slice.push_back(0); + } + + // This fails because the length of `example_slice` is not known at + // compile-time + let error_message = "expected an empty slice, known at compile-time"; + static_assert(example_slice.len() == 0, error_message); +} +``` + diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/comments.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/comments.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/comments.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/comments.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/comptime.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/comptime.md new file mode 100644 index 00000000000..6f91fde9bd8 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/comptime.md @@ -0,0 +1,424 @@ +--- +title: Compile-time Code & Metaprogramming +description: Learn how to use metaprogramming in Noir to create macros or derive your own traits +keywords: [Noir, comptime, compile-time, metaprogramming, macros, quote, unquote] +sidebar_position: 15 +--- + +# Overview + +Metaprogramming in Noir is comprised of three parts: +1. `comptime` code +2. Quoting and unquoting +3. The metaprogramming API in `std::meta` + +Each of these are explained in more detail in the next sections but the wide picture is that +`comptime` allows us to write code which runs at compile-time. In this `comptime` code we +can quote and unquote snippets of the program, manipulate them, and insert them in other +parts of the program. Comptime functions which do this are said to be macros. Additionally, +there's a compile-time API of built-in types and functions provided by the compiler which allows +for greater analysis and modification of programs. + +--- + +# Comptime + +`comptime` is a new keyword in Noir which marks an item as executing or existing at compile-time. It can be used in several ways: + +- `comptime fn` to define functions which execute exclusively during compile-time. +- `comptime global` to define a global variable which is evaluated at compile-time. + - Unlike runtime globals, `comptime global`s can be mutable. +- `comptime { ... }` to execute a block of statements during compile-time. +- `comptime let` to define a variable whose value is evaluated at compile-time. +- `comptime for` to run a for loop at compile-time. Syntax sugar for `comptime { for .. }`. + +## Scoping + +Note that while in a `comptime` context, any runtime variables _local to the current function_ are never visible. + +## Evaluating + +Evaluation rules of `comptime` follows the normal unconstrained evaluation rules for other Noir code. There are a few things to note though: + +- Certain built-in functions may not be available, although more may be added over time. +- Evaluation order of global items is currently unspecified. For example, given the following two functions we can't guarantee +which `println` will execute first. The ordering of the two printouts will be arbitrary, but should be stable across multiple compilations with the same `nargo` version as long as the program is also unchanged. + +```rust +fn one() { + comptime { println("one"); } +} + +fn two() { + comptime { println("two"); } +} +``` + +- Since evaluation order is unspecified, care should be taken when using mutable globals so that they do not rely on a particular ordering. +For example, using globals to generate unique ids should be fine but relying on certain ids always being produced (especially after edits to the program) should be avoided. +- Although most ordering of globals is unspecified, two are: + - Dependencies of a crate will always be evaluated before the dependent crate. + - Any annotations on a function will be run before the function itself is resolved. This is to allow the annotation to modify the function if necessary. Note that if the + function itself was called at compile-time previously, it will already be resolved and cannot be modified. To prevent accidentally calling functions you wish to modify + at compile-time, it may be helpful to sort your `comptime` annotation functions into a different crate along with any dependencies they require. + +## Lowering + +When a `comptime` value is used in runtime code it must be lowered into a runtime value. This means replacing the expression with the literal that it evaluated to. For example, the code: + +```rust +struct Foo { array: [Field; 2], len: u32 } + +fn main() { + println(comptime { + let mut foo = std::mem::zeroed::(); + foo.array[0] = 4; + foo.len = 1; + foo + }); +} +``` + +will be converted to the following after `comptime` expressions are evaluated: + +```rust +struct Foo { array: [Field; 2], len: u32 } + +fn main() { + println(Foo { array: [4, 0], len: 1 }); +} +``` + +Not all types of values can be lowered. For example, `Type`s and `TypeDefinition`s (among other types) cannot be lowered at all. + +```rust +fn main() { + // There's nothing we could inline here to create a Type value at runtime + // let _ = get_type!(); +} + +comptime fn get_type() -> Type { ... } +``` + +--- + +# (Quasi) Quote + +Macros in Noir are `comptime` functions which return code as a value which is inserted into the call site when it is lowered there. +A code value in this case is of type `Quoted` and can be created by a `quote { ... }` expression. +More specifically, the code value `quote` creates is a token stream - a representation of source code as a series of words, numbers, string literals, or operators. +For example, the expression `quote { Hi "there reader"! }` would quote three tokens: the word "hi", the string "there reader", and an exclamation mark. +You'll note that snippets that would otherwise be invalid syntax can still be quoted. + +When a `Quoted` value is used in runtime code, it is lowered into a `quote { ... }` expression. Since this expression is only valid +in compile-time code however, we'd get an error if we tried this. Instead, we can use macro insertion to insert each token into the +program at that point, and parse it as an expression. To do this, we have to add a `!` after the function name returning the `Quoted` value. +If the value was created locally and there is no function returning it, `std::meta::unquote!(_)` can be used instead. +Calling such a function at compile-time without `!` will just return the `Quoted` value to be further manipulated. For example: + +```rust title="quote-example" showLineNumbers +comptime fn quote_one() -> Quoted { + quote { 1 } + } + + #[test] + fn returning_versus_macro_insertion() { + comptime + { + // let _a: Quoted = quote { 1 }; + let _a: Quoted = quote_one(); + + // let _b: i32 = 1; + let _b: i32 = quote_one!(); + } + } +``` +> Source code: noir_stdlib/src/meta/mod.nr#L120-L136 + + +For those familiar with quoting from other languages (primarily lisps), Noir's `quote` is actually a _quasiquote_. +This means we can escape the quoting by using the unquote operator to splice values in the middle of quoted code. + +# Unquote + +The unquote operator `$` is usable within a `quote` expression. +It takes a variable as an argument, evaluates the variable, and splices the resulting value into the quoted token stream at that point. For example, + +```rust +comptime { + let x = 1 + 2; + let y = quote { $x + 4 }; +} +``` + +The value of `y` above will be the token stream containing `3`, `+`, and `4`. We can also use this to combine `Quoted` values into larger token streams: + +```rust +comptime { + let x = quote { 1 + 2 }; + let y = quote { $x + 4 }; +} +``` + +The value of `y` above is now the token stream containing five tokens: `1 + 2 + 4`. + +Note that to unquote something, a variable name _must_ follow the `$` operator in a token stream. +If it is an expression (even a parenthesized one), it will do nothing. Most likely a parse error will be given when the macro is later unquoted. + +Unquoting can also be avoided by escaping the `$` with a backslash: + +``` +comptime { + let x = quote { 1 + 2 }; + + // y contains the four tokens: `$x + 4` + let y = quote { \$x + 4 }; +} +``` + +--- + +# Annotations + +Annotations provide a way to run a `comptime` function on an item in the program. +When you use an annotation, the function with the same name will be called with that item as an argument: + +```rust +#[my_struct_annotation] +struct Foo {} + +comptime fn my_struct_annotation(s: StructDefinition) { + println("Called my_struct_annotation!"); +} + +#[my_function_annotation] +fn foo() {} + +comptime fn my_function_annotation(f: FunctionDefinition) { + println("Called my_function_annotation!"); +} +``` + +Anything returned from one of these functions will be inserted at top-level along with the original item. +Note that expressions are not valid at top-level so you'll get an error trying to return `3` or similar just as if you tried to write a program containing `3; struct Foo {}`. +You can insert other top-level items such as trait impls, structs, or functions this way though. +For example, this is the mechanism used to insert additional trait implementations into the program when deriving a trait impl from a struct: + +```rust title="derive-field-count-example" showLineNumbers +trait FieldCount { + fn field_count() -> u32; + } + + #[derive_field_count] + struct Bar { x: Field, y: [Field; 2] } + + comptime fn derive_field_count(s: StructDefinition) -> Quoted { + let typ = s.as_type(); + let field_count = s.fields().len(); + quote { + impl FieldCount for $typ { + fn field_count() -> u32 { + $field_count + } + } + } + } +``` +> Source code: noir_stdlib/src/meta/mod.nr#L138-L157 + + +## Calling annotations with additional arguments + +Arguments may optionally be given to annotations. +When this is done, these additional arguments are passed to the annotation function after the item argument. + +```rust title="annotation-arguments-example" showLineNumbers +#[assert_field_is_type(quote { i32 }.as_type())] + struct MyStruct { my_field: i32 } + + comptime fn assert_field_is_type(s: StructDefinition, typ: Type) { + // Assert the first field in `s` has type `typ` + let fields = s.fields(); + assert_eq(fields[0].1, typ); + } +``` +> Source code: noir_stdlib/src/meta/mod.nr#L159-L168 + + +We can also take any number of arguments by adding the `varargs` annotation: + +```rust title="annotation-varargs-example" showLineNumbers +#[assert_three_args(1, 2, 3)] + struct MyOtherStruct { my_other_field: u32 } + + #[varargs] + comptime fn assert_three_args(_s: StructDefinition, args: [Field]) { + assert_eq(args.len(), 3); + } +``` +> Source code: noir_stdlib/src/meta/mod.nr#L170-L178 + + +--- + +# Comptime API + +Although `comptime`, `quote`, and unquoting provide a flexible base for writing macros, +Noir's true metaprogramming ability comes from being able to interact with the compiler through a compile-time API. +This API can be accessed through built-in functions in `std::meta` as well as on methods of several `comptime` types. + +The following is an incomplete list of some `comptime` types along with some useful methods on them. + +- `Quoted`: A token stream +- `Type`: The type of a Noir type + - `fn implements(self, constraint: TraitConstraint) -> bool` + - Returns true if `self` implements the given trait constraint +- `Expr`: A syntactically valid expression. Can be used to recur on a program's parse tree to inspect how it is structured. + - Methods: + - `fn as_function_call(self) -> Option<(Expr, [Expr])>` + - If this is a function call expression, return `(function, arguments)` + - `fn as_block(self) -> Option<[Expr]>` + - If this is a block, return each statement in the block +- `FunctionDefinition`: A function definition + - Methods: + - `fn parameters(self) -> [(Quoted, Type)]` + - Returns a slice of `(name, type)` pairs for each parameter +- `StructDefinition`: A struct definition + - Methods: + - `fn as_type(self) -> Type` + - Returns this `StructDefinition` as a `Type`. Any generics are kept as-is + - `fn generics(self) -> [Quoted]` + - Return the name of each generic on this struct + - `fn fields(self) -> [(Quoted, Type)]` + - Return the name and type of each field +- `TraitConstraint`: A trait constraint such as `From` +- `TypedExpr`: A type-checked expression. +- `UnresolvedType`: A syntactic notation that refers to a Noir type that hasn't been resolved yet + +There are many more functions available by exploring the `std::meta` module and its submodules. +Using these methods is the key to writing powerful metaprogramming libraries. + +--- + +# Example: Derive + +Using all of the above, we can write a `derive` macro that behaves similarly to Rust's but is not built into the language. +From the user's perspective it will look like this: + +```rust +// Example usage +#[derive(Default, Eq, Ord)] +struct MyStruct { my_field: u32 } +``` + +To implement `derive` we'll have to create a `comptime` function that accepts +a variable amount of traits. + +```rust title="derive_example" showLineNumbers +// These are needed for the unconstrained hashmap we're using to store derive functions +use crate::collections::umap::UHashMap; +use crate::hash::BuildHasherDefault; +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; + +// We'll keep a global HANDLERS map to keep track of the derive handler for each trait +comptime mut global HANDLERS: UHashMap> = UHashMap::default(); + +// Given a struct and a slice of traits to derive, create trait impls for each. +// This function is as simple as iterating over the slice, checking if we have a trait +// handler registered for the given trait, calling it, and appending the result. +#[varargs] +pub comptime fn derive(s: StructDefinition, traits: [TraitDefinition]) -> Quoted { + let mut result = quote {}; + + for trait_to_derive in traits { + let handler = unsafe { + HANDLERS.get(trait_to_derive) + }; + assert(handler.is_some(), f"No derive function registered for `{trait_to_derive}`"); + + let trait_impl = handler.unwrap()(s); + result = quote { $result $trait_impl }; + } + + result +} +``` +> Source code: noir_stdlib/src/meta/mod.nr#L30-L64 + + +Registering a derive function could be done as follows: + +```rust title="derive_via" showLineNumbers +// To register a handler for a trait, just add it to our handlers map +pub comptime fn derive_via(t: TraitDefinition, f: DeriveFunction) { + HANDLERS.insert(t, f); +} +``` +> Source code: noir_stdlib/src/meta/mod.nr#L66-L73 + + +```rust title="big-derive-usage-example" showLineNumbers +// Finally, to register a handler we call the above function as an annotation + // with our handler function. + #[derive_via(derive_do_nothing)] + trait DoNothing { + fn do_nothing(self); + } + + comptime fn derive_do_nothing(s: StructDefinition) -> Quoted { + // This is simplified since we don't handle generics or where clauses! + // In a real example we'd likely also need to introduce each of + // `s.generics()` as well as a trait constraint for each generic + // to ensure they also implement the trait. + let typ = s.as_type(); + quote { + impl DoNothing for $typ { + fn do_nothing(self) { + // Traits can't tell us what to do + println("something"); + } + } + } + } + + // Since `DoNothing` is a simple trait which: + // 1. Only has one method + // 2. Does not have any generics on the trait itself + // We can use `std::meta::make_trait_impl` to help us out. + // This helper function will generate our impl for us along with any + // necessary where clauses and still provides a flexible interface + // for us to work on each field on the struct. + comptime fn derive_do_nothing_alt(s: StructDefinition) -> Quoted { + let trait_name = quote { DoNothing }; + let method_signature = quote { fn do_nothing(self) }; + + // Call `do_nothing` recursively on each field in the struct + let for_each_field = |field_name| quote { self.$field_name.do_nothing(); }; + + // Some traits like Eq want to join each field expression with something like `&`. + // We don't need that here + let join_fields_with = quote {}; + + // The body function is a spot to insert any extra setup/teardown needed. + // We'll insert our println here. Since we recur on each field, we should see + // one println for the struct itself, followed by a println for every field (recursively). + let body = |body| quote { + println("something"); + $body + }; + crate::meta::make_trait_impl( + s, + trait_name, + method_signature, + for_each_field, + join_fields_with, + body + ) + } +``` +> Source code: noir_stdlib/src/meta/mod.nr#L180-L238 + diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/control_flow.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/control_flow.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/control_flow.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/control_flow.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_bus.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/data_bus.mdx similarity index 88% rename from noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_bus.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/data_bus.mdx index e54fc861257..e55e58622ce 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_bus.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/data_bus.mdx @@ -2,7 +2,9 @@ title: Data Bus sidebar_position: 13 --- -**Disclaimer** this feature is experimental, do not use it! +import Experimental from '@site/src/components/Notes/_experimental.mdx'; + + The data bus is an optimization that the backend can use to make recursion more efficient. In order to use it, you must define some inputs of the program entry points (usually the `main()` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/data_types/_category_.json similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/_category_.json rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/data_types/_category_.json diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/data_types/arrays.md similarity index 86% rename from noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/arrays.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/data_types/arrays.md index 9b02d52e8a8..d0d8eb70aa6 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/arrays.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/data_types/arrays.md @@ -128,7 +128,9 @@ fn main() { ### sort_via -Sorts the array with a custom comparison function +Sorts the array with a custom comparison function. The ordering function must return true if the first argument should be sorted to be before the second argument or is equal to the second argument. + +Using this method with an operator like `<` that does not return `true` for equal values will result in an assertion failure for arrays with equal elements. ```rust fn sort_via(self, ordering: fn(T, T) -> bool) -> [T; N] @@ -199,7 +201,7 @@ fn main() { ### reduce -Same as fold, but uses the first element as starting element. +Same as fold, but uses the first element as the starting element. ```rust fn reduce(self, f: fn(T, T) -> T) -> T @@ -251,3 +253,23 @@ fn main() { } ``` + +### as_str_unchecked + +Converts a byte array of type `[u8; N]` to a string. Note that this performs no UTF-8 validation - +the given array is interpreted as-is as a string. + +```rust +impl [u8; N] { + pub fn as_str_unchecked(self) -> str +} +``` + +example: + +```rust +fn main() { + let hi = [104, 105].as_str_unchecked(); + assert_eq(hi, "hi"); +} +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/data_types/booleans.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/booleans.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/data_types/booleans.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/data_types/fields.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/data_types/fields.md new file mode 100644 index 00000000000..23367a32451 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/data_types/fields.md @@ -0,0 +1,240 @@ +--- +title: Fields +description: + Dive deep into the Field data type in Noir. Understand its methods, practical examples, and best practices to effectively use Fields in your Noir programs. +keywords: + [ + noir, + field type, + methods, + examples, + best practices, + ] +sidebar_position: 0 +--- + +The field type corresponds to the native field type of the proving backend. + +The size of a Noir field depends on the elliptic curve's finite field for the proving backend +adopted. For example, a field would be a 254-bit integer when paired with the default backend that +spans the Grumpkin curve. + +Fields support integer arithmetic and are often used as the default numeric type in Noir: + +```rust +fn main(x : Field, y : Field) { + let z = x + y; +} +``` + +`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new +private value `z` constrained to be equal to `x + y`. + +If proving efficiency is of priority, fields should be used as a default for solving problems. +Smaller integer types (e.g. `u64`) incur extra range constraints. + +## Methods + +After declaring a Field, you can use these common methods on it: + +### to_le_bits + +Transforms the field into an array of bits, Little Endian. + +```rust title="to_le_bits" showLineNumbers +pub fn to_le_bits(self: Self) -> [u1; N] {} +``` +> Source code: noir_stdlib/src/field/mod.nr#L32-L34 + + +example: + +```rust title="to_le_bits_example" showLineNumbers +fn test_to_le_bits() { + let field = 2; + let bits: [u1; 8] = field.to_le_bits(); + assert_eq(bits, [0, 1, 0, 0, 0, 0, 0, 0]); + } +``` +> Source code: noir_stdlib/src/field/mod.nr#L196-L202 + + + +### to_be_bits + +Transforms the field into an array of bits, Big Endian. + +```rust title="to_be_bits" showLineNumbers +pub fn to_be_bits(self: Self) -> [u1; N] {} +``` +> Source code: noir_stdlib/src/field/mod.nr#L48-L50 + + +example: + +```rust title="to_be_bits_example" showLineNumbers +fn test_to_be_bits() { + let field = 2; + let bits: [u1; 8] = field.to_be_bits(); + assert_eq(bits, [0, 0, 0, 0, 0, 0, 1, 0]); + } +``` +> Source code: noir_stdlib/src/field/mod.nr#L187-L193 + + + +### to_le_bytes + +Transforms into an array of bytes, Little Endian + +```rust title="to_le_bytes" showLineNumbers +pub fn to_le_bytes(self: Self) -> [u8; N] { + self.to_le_radix(256) + } +``` +> Source code: noir_stdlib/src/field/mod.nr#L63-L67 + + +example: + +```rust title="to_le_bytes_example" showLineNumbers +fn test_to_le_bytes() { + let field = 2; + let bits: [u8; 8] = field.to_le_bytes(); + assert_eq(bits, [2, 0, 0, 0, 0, 0, 0, 0]); + } +``` +> Source code: noir_stdlib/src/field/mod.nr#L214-L220 + + +### to_be_bytes + +Transforms into an array of bytes, Big Endian + +```rust title="to_be_bytes" showLineNumbers +pub fn to_be_bytes(self: Self) -> [u8; N] { + self.to_be_radix(256) + } +``` +> Source code: noir_stdlib/src/field/mod.nr#L80-L84 + + +example: + +```rust title="to_be_bytes_example" showLineNumbers +fn test_to_be_bytes() { + let field = 2; + let bits: [u8; 8] = field.to_be_bytes(); + assert_eq(bits, [0, 0, 0, 0, 0, 0, 0, 2]); + } +``` +> Source code: noir_stdlib/src/field/mod.nr#L205-L211 + + + +### to_le_radix + +Decomposes into an array over the specified base, Little Endian + +```rust title="to_le_radix" showLineNumbers +pub fn to_le_radix(self: Self, radix: u32) -> [u8; N] { + crate::assert_constant(radix); + self.__to_le_radix(radix) + } +``` +> Source code: noir_stdlib/src/field/mod.nr#L86-L91 + + + +example: + +```rust title="to_le_radix_example" showLineNumbers +fn test_to_le_radix() { + let field = 2; + let bits: [u8; 8] = field.to_le_radix(256); + assert_eq(bits, [2, 0, 0, 0, 0, 0, 0, 0]); + } +``` +> Source code: noir_stdlib/src/field/mod.nr#L232-L238 + + + +### to_be_radix + +Decomposes into an array over the specified base, Big Endian + +```rust title="to_be_radix" showLineNumbers +pub fn to_be_radix(self: Self, radix: u32) -> [u8; N] { + crate::assert_constant(radix); + self.__to_be_radix(radix) + } +``` +> Source code: noir_stdlib/src/field/mod.nr#L93-L98 + + +example: + +```rust title="to_be_radix_example" showLineNumbers +fn test_to_be_radix() { + let field = 2; + let bits: [u8; 8] = field.to_be_radix(256); + assert_eq(bits, [0, 0, 0, 0, 0, 0, 0, 2]); + } +``` +> Source code: noir_stdlib/src/field/mod.nr#L223-L229 + + + +### pow_32 + +Returns the value to the power of the specified exponent + +```rust +fn pow_32(self, exponent: Field) -> Field +``` + +example: + +```rust +fn main() { + let field = 2 + let pow = field.pow_32(4); + assert(pow == 16); +} +``` + +### assert_max_bit_size + +Adds a constraint to specify that the field can be represented with `bit_size` number of bits + +```rust title="assert_max_bit_size" showLineNumbers +pub fn assert_max_bit_size(self, bit_size: u32) { +``` +> Source code: noir_stdlib/src/field/mod.nr#L9-L11 + + +example: + +```rust +fn main() { + let field = 2 + field.assert_max_bit_size(32); +} +``` + +### sgn0 + +Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. + +```rust +fn sgn0(self) -> u1 +``` + + +### lt + +Returns true if the field is less than the other field + +```rust +pub fn lt(self, another: Field) -> bool +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/function_types.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/data_types/function_types.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/function_types.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/data_types/function_types.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/data_types/index.md similarity index 86% rename from noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/index.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/data_types/index.md index 357813c147a..3eadb2dc8a4 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/index.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/data_types/index.md @@ -105,6 +105,14 @@ type Bad2 = Bad1; // ^^^^^^^^^^^ 'Bad2' recursively depends on itself: Bad2 -> Bad1 -> Bad2 ``` +## 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. + +```rust +let a: [_; 4] = foo(b); +``` + + ### BigInt You can achieve BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/integers.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/data_types/integers.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/integers.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/data_types/integers.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/references.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/data_types/references.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/references.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/data_types/references.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/slices.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/data_types/slices.mdx similarity index 55% rename from noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/slices.mdx rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/data_types/slices.mdx index dff08d63ffb..a0c87c29259 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/slices.mdx +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/data_types/slices.mdx @@ -20,7 +20,7 @@ fn main() -> pub u32 { } ``` -To write a slice literal, use a preceeding ampersand as in: `&[0; 2]` or +To write a slice literal, use a preceding ampersand as in: `&[0; 2]` or `&[1, 2, 3]`. It is important to note that slices are not references to arrays. In Noir, @@ -191,3 +191,168 @@ fn main() { assert(array[1] == slice[1]); } ``` + +### map + +Applies a function to each element of the slice, returning a new slice containing the mapped elements. + +```rust +fn map(self, f: fn[Env](T) -> U) -> [U] +``` + +example + +```rust +let a = &[1, 2, 3]; +let b = a.map(|a| a * 2); // b is now &[2, 4, 6] +``` + +### fold + +Applies a function to each element of the slice, returning the final accumulated value. The first +parameter is the initial value. + +```rust +fn fold(self, mut accumulator: U, f: fn[Env](U, T) -> U) -> U +``` + +This is a left fold, so the given function will be applied to the accumulator and first element of +the slice, then the second, and so on. For a given call the expected result would be equivalent to: + +```rust +let a1 = &[1]; +let a2 = &[1, 2]; +let a3 = &[1, 2, 3]; + +let f = |a, b| a - b; +a1.fold(10, f) //=> f(10, 1) +a2.fold(10, f) //=> f(f(10, 1), 2) +a3.fold(10, f) //=> f(f(f(10, 1), 2), 3) +``` + +example: + +```rust + +fn main() { + let slice = &[2, 2, 2, 2, 2]; + let folded = slice.fold(0, |a, b| a + b); + assert(folded == 10); +} + +``` + +### reduce + +Same as fold, but uses the first element as the starting element. + +```rust +fn reduce(self, f: fn[Env](T, T) -> T) -> T +``` + +example: + +```rust +fn main() { + let slice = &[2, 2, 2, 2, 2]; + let reduced = slice.reduce(|a, b| a + b); + assert(reduced == 10); +} +``` + +### filter + +Returns a new slice containing only elements for which the given predicate returns true. + +```rust +fn filter(self, f: fn[Env](T) -> bool) -> Self +``` + +example: + +```rust +fn main() { + let slice = &[1, 2, 3, 4, 5]; + let odds = slice.filter(|x| x % 2 == 1); + assert_eq(odds, &[1, 3, 5]); +} +``` + +### join + +Flatten each element in the slice into one value, separated by `separator`. + +Note that although slices implement `Append`, `join` cannot be used on slice +elements since nested slices are prohibited. + +```rust +fn join(self, separator: T) -> T where T: Append +``` + +example: + +```rust +struct Accumulator { + total: Field, +} + +// "Append" two accumulators by adding them +impl Append for Accumulator { + fn empty() -> Self { + Self { total: 0 } + } + + fn append(self, other: Self) -> Self { + Self { total: self.total + other.total } + } +} + +fn main() { + let slice = &[1, 2, 3, 4, 5].map(|total| Accumulator { total }); + + let result = slice.join(Accumulator::empty()); + assert_eq(result, Accumulator { total: 15 }); + + // We can use a non-empty separator to insert additional elements to sum: + let separator = Accumulator { total: 10 }; + let result = slice.join(separator); + assert_eq(result, Accumulator { total: 55 }); +} +``` + +### all + +Returns true if all the elements satisfy the given predicate + +```rust +fn all(self, predicate: fn[Env](T) -> bool) -> bool +``` + +example: + +```rust +fn main() { + let slice = &[2, 2, 2, 2, 2]; + let all = slice.all(|a| a == 2); + assert(all); +} +``` + +### any + +Returns true if any of the elements satisfy the given predicate + +```rust +fn any(self, predicate: fn[Env](T) -> bool) -> bool +``` + +example: + +```rust +fn main() { + let slice = &[2, 2, 2, 2, 5]; + let any = slice.any(|a| a == 5); + assert(any); +} + +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/data_types/strings.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/strings.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/data_types/strings.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/structs.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/data_types/structs.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/structs.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/data_types/structs.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/tuples.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/data_types/tuples.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/tuples.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/data_types/tuples.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/functions.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/functions.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/functions.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/functions.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/generics.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/generics.md new file mode 100644 index 00000000000..1f313cef58e --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/generics.md @@ -0,0 +1,258 @@ +--- +title: Generics +description: Learn how to use Generics in Noir +keywords: [Noir, Rust, generics, functions, structs] +sidebar_position: 7 +--- + +Generics allow you to use the same functions with multiple different concrete data types. You can +read more about the concept of generics in the Rust documentation +[here](https://doc.rust-lang.org/book/ch10-01-syntax.html). + +Here is a trivial example showing the identity function that supports any type. In Rust, it is +common to refer to the most general type as `T`. We follow the same convention in Noir. + +```rust +fn id(x: T) -> T { + x +} +``` + +## In Structs + +Generics are useful for specifying types in structs. For example, we can specify that a field in a +struct will be of a certain generic type. In this case `value` is of type `T`. + +```rust +struct RepeatedValue { + value: T, + count: Field, +} + +impl RepeatedValue { + fn print(self) { + for _i in 0 .. self.count { + println(self.value); + } + } +} + +fn main() { + let repeated = RepeatedValue { value: "Hello!", count: 2 }; + repeated.print(); +} +``` + +The `print` function will print `Hello!` an arbitrary number of times, twice in this case. + +## Numeric Generics + +If we want to be generic over array lengths (which are type-level integers), we can use numeric +generics. Using these looks similar to using regular generics, but introducing them into scope +requires declaring them with `let MyGenericName: IntegerType`. This can be done anywhere a normal +generic is declared. Instead of types, these generics resolve to integers at compile-time. +Here's an example of a struct that is generic over the size of the array it contains internally: + +```rust +struct BigInt { + limbs: [u32; N], +} + +impl BigInt { + // `N` is in scope of all methods in the impl + fn first(first: BigInt, second: BigInt) -> Self { + assert(first.limbs != second.limbs); + first + + fn second(first: BigInt, second: Self) -> Self { + assert(first.limbs != second.limbs); + second + } +} +``` + +## Calling functions on generic parameters + +Since a generic type `T` can represent any type, how can we call functions on the underlying type? +In other words, how can we go from "any type `T`" to "any type `T` that has certain methods available?" + +This is what [traits](../concepts/traits.md) are for in Noir. Here's an example of a function generic over +any type `T` that implements the `Eq` trait for equality: + +```rust +fn first_element_is_equal(array1: [T; N], array2: [T; N]) -> bool + where T: Eq +{ + if (array1.len() == 0) | (array2.len() == 0) { + true + } else { + array1[0] == array2[0] + } +} + +fn main() { + assert(first_element_is_equal([1, 2, 3], [1, 5, 6])); + + // We can use first_element_is_equal for arrays of any type + // as long as we have an Eq impl for the types we pass in + let array = [MyStruct::new(), MyStruct::new()]; + assert(array_eq(array, array, MyStruct::eq)); +} + +impl Eq for MyStruct { + fn eq(self, other: MyStruct) -> bool { + self.foo == other.foo + } +} +``` + +You can find more details on traits and trait implementations on the [traits page](../concepts/traits.md). + +## Manually Specifying Generics with the Turbofish Operator + +There are times when the compiler cannot reasonably infer what type should be used for a generic, or when the developer themselves may want to manually distinguish generic type parameters. This is where the `::<>` turbofish operator comes into play. + +The `::<>` operator can follow a variable or path and can be used to manually specify generic arguments within the angle brackets. +The name "turbofish" comes from that `::<>` looks like a little fish. + +Examples: +```rust +fn main() { + let mut slice = []; + slice = slice.push_back(1); + slice = slice.push_back(2); + // Without turbofish a type annotation would be needed on the left hand side + let array = slice.as_array::<2>(); +} +``` +```rust +fn double() -> u32 { + N * 2 +} +fn example() { + assert(double::<9>() == 18); + assert(double::<7 + 8>() == 30); +} +``` +```rust +trait MyTrait { + fn ten() -> Self; +} + +impl MyTrait for Field { + fn ten() -> Self { 10 } +} + +struct Foo { + inner: T +} + +impl Foo { + fn generic_method(_self: Self) -> U where U: MyTrait { + U::ten() + } +} + +fn example() { + let foo: Foo = Foo { inner: 1 }; + // Using a type other than `Field` here (e.g. u32) would fail as + // there is no matching impl for `u32: MyTrait`. + // + // Substituting the `10` on the left hand side of this assert + // with `10 as u32` would also fail with a type mismatch as we + // are expecting a `Field` from the right hand side. + assert(10 as u32 == foo.generic_method::()); +} +``` + +## Arithmetic Generics + +In addition to numeric generics, Noir also allows a limited form of arithmetic on generics. +When you have a numeric generic such as `N`, you can use the following operators on it in a +type position: `+`, `-`, `*`, `/`, and `%`. + +Note that type checking arithmetic generics is a best effort guess from the compiler and there +are many cases of types that are equal that the compiler may not see as such. For example, +we know that `T * (N + M)` should be equal to `T*N + T*M` but the compiler does not currently +apply the distributive law and thus sees these as different types. + +Even with this limitation though, the compiler can handle common cases decently well: + +```rust +trait Serialize { + fn serialize(self) -> [Field; N]; +} + +impl Serialize<1> for Field { + fn serialize(self) -> [Field; 1] { + [self] + } +} + +impl Serialize for [T; N] + where T: Serialize { .. } + +impl Serialize for (T, U) + where T: Serialize, U: Serialize { .. } + +fn main() { + let data = (1, [2, 3, 4]); + assert_eq(data.serialize().len(), 4); +} +``` + +Note that if there is any over or underflow the types will fail to unify: + +```rust title="underflow-example" showLineNumbers +fn pop(array: [Field; N]) -> [Field; N - 1] { + let mut result: [Field; N - 1] = std::mem::zeroed(); + for i in 0..N - 1 { + result[i] = array[i]; + } + result +} + +fn main() { + // error: Could not determine array length `(0 - 1)` + pop([]); +} +``` +> Source code: test_programs/compile_failure/arithmetic_generics_underflow/src/main.nr#L1-L14 + + +This also applies if there is underflow in an intermediate calculation: + +```rust title="intermediate-underflow-example" showLineNumbers +fn main() { + // From main it looks like there's nothing sketchy going on + seems_fine([]); +} + +// Since `seems_fine` says it can receive and return any length N +fn seems_fine(array: [Field; N]) -> [Field; N] { + // But inside `seems_fine` we pop from the array which + // requires the length to be greater than zero. + + // error: Could not determine array length `(0 - 1)` + push_zero(pop(array)) +} + +fn pop(array: [Field; N]) -> [Field; N - 1] { + let mut result: [Field; N - 1] = std::mem::zeroed(); + for i in 0..N - 1 { + result[i] = array[i]; + } + result +} + +fn push_zero(array: [Field; N]) -> [Field; N + 1] { + let mut result: [Field; N + 1] = std::mem::zeroed(); + for i in 0..N { + result[i] = array[i]; + } + // index N is already zeroed + result +} +``` +> Source code: test_programs/compile_failure/arithmetic_generics_intermediate_underflow/src/main.nr#L1-L32 + diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/globals.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/globals.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/globals.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/globals.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/lambdas.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/lambdas.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/lambdas.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/lambdas.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/mutability.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/mutability.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/mutability.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/mutability.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/ops.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/ops.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/ops.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/ops.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/oracles.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/oracles.mdx similarity index 78% rename from noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/oracles.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/oracles.mdx index aa380b5f7b8..77a2ac1550a 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/oracles.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/oracles.mdx @@ -11,11 +11,9 @@ keywords: sidebar_position: 6 --- -:::note +import Experimental from '@site/src/components/Notes/_experimental.mdx'; -This is an experimental feature that is not fully documented. If you notice any outdated information or potential improvements to this page, pull request contributions are very welcome: https://github.com/noir-lang/noir - -::: + Noir has support for Oracles via RPC calls. This means Noir will make an RPC call and use the return value for proof generation. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/shadowing.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/shadowing.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/shadowing.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/shadowing.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/traits.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/traits.md similarity index 82% rename from noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/traits.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/traits.md index df7cb9ebda0..597c62c737c 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/traits.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/traits.md @@ -147,7 +147,7 @@ fn main() { ### Generic Trait Implementations With Where Clauses -Where clauses can also be placed on trait implementations themselves to restrict generics in a similar way. +Where clauses can be placed on trait implementations themselves to restrict generics in a similar way. For example, while `impl Foo for T` implements the trait `Foo` for every type, `impl Foo for T where T: Bar` will implement `Foo` only for types that also implement `Bar`. This is often used for implementing generic types. For example, here is the implementation for array equality: @@ -169,6 +169,22 @@ impl Eq for [T; N] where T: Eq { } ``` +Where clauses can also be placed on struct implementations. +For example, here is a method utilizing a generic type that implements the equality trait. + +```rust +struct Foo { + a: u32, + b: T, +} + +impl Foo where T: Eq { + fn eq(self, other: Self) -> bool { + (self.a == other.a) & self.b.eq(other.b) + } +} +``` + ## Generic Traits Traits themselves can also be generic by placing the generic arguments after the trait name. These generics are in @@ -209,6 +225,66 @@ fn main() { } ``` +### Associated Types and Constants + +Traits also support associated types and constraints which can be thought of as additional generics that are referred to by name. + +Here's an example of a trait with an associated type `Foo` and a constant `Bar`: + +```rust +trait MyTrait { + type Foo; + + let Bar: u32; +} +``` + +Now when we're implementing `MyTrait` we also have to provide values for `Foo` and `Bar`: + +```rust +impl MyTrait for Field { + type Foo = i32; + + let Bar: u32 = 11; +} +``` + +Since associated constants can also be used in a type position, its values are limited to only other +expression kinds allowed in numeric generics. + +Note that currently all associated types and constants must be explicitly specified in a trait constraint. +If we leave out any, we'll get an error that we're missing one: + +```rust +// Error! Constraint is missing associated constant for `Bar` +fn foo(x: T) where T: MyTrait { + ... +} +``` + +Because all associated types and constants must be explicitly specified, they are essentially named generics, +although this is set to change in the future. Future versions of Noir will allow users to elide associated types +in trait constraints similar to Rust. When this is done, you may still refer to their value with the `::AssociatedType` +syntax: + +```rust +// Only valid in future versions of Noir: +fn foo(x: T) where T: MyTrait { + let _: ::Foo = ...; +} +``` + +The type as trait syntax is possible in Noir today but is less useful when each type must be explicitly specified anyway: + +```rust +fn foo(x: T) where T: MyTrait { + // Works, but could just use F directly + let _: >::Foo = ...; + + let _: F = ...; +} +``` + ## Trait Methods With No `self` A trait can contain any number of methods, each of which have access to the `Self` type which represents each type diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/unconstrained.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/unconstrained.md similarity index 91% rename from noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/unconstrained.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/unconstrained.md index 96f824c5e42..b5221b8d2dd 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/unconstrained.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/concepts/unconstrained.md @@ -62,11 +62,13 @@ Those are some nice savings already but we can do better. This code is all const It turns out that truncating a u72 into a u8 is hard to do inside a snark, each time we do as u8 we lay down 4 ACIR opcodes which get converted into multiple gates. It's actually much easier to calculate num from out than the other way around. All we need to do is multiply each element of out by a constant and add them all together, both relatively easy operations inside a snark. -We can then run u72_to_u8 as unconstrained brillig code in order to calculate out, then use that result in our constrained function and assert that if we were to do the reverse calculation we'd get back num. This looks a little like the below: +We can then run `u72_to_u8` as unconstrained brillig code in order to calculate out, then use that result in our constrained function and assert that if we were to do the reverse calculation we'd get back num. This looks a little like the below: ```rust fn main(num: u72) -> pub [u8; 8] { - let out = u72_to_u8(num); + let out = unsafe { + u72_to_u8(num) + }; let mut reconstructed_num: u72 = 0; for i in 0..8 { @@ -92,6 +94,9 @@ Backend circuit size: 2902 This ends up taking off another ~250 gates from our circuit! We've ended up with more ACIR opcodes than before but they're easier for the backend to prove (resulting in fewer gates). +Note that in order to invoke unconstrained functions we need to wrap them in an `unsafe` block, +to make it clear that the call is unconstrained. + Generally we want to use brillig whenever there's something that's easy to verify but hard to compute within the circuit. For example, if you wanted to calculate a square root of a number it'll be a much better idea to calculate this in brillig and then assert that if you square the result you get back your number. ## Break and Continue diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/modules_packages_crates/_category_.json similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/_category_.json rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/modules_packages_crates/_category_.json diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/crates_and_packages.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/modules_packages_crates/crates_and_packages.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/crates_and_packages.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/modules_packages_crates/crates_and_packages.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/modules_packages_crates/dependencies.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/dependencies.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/modules_packages_crates/dependencies.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/modules.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/modules_packages_crates/modules.md similarity index 51% rename from noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/modules.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/modules_packages_crates/modules.md index ae822a1cff4..d21b009be3b 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/modules.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/modules_packages_crates/modules.md @@ -49,6 +49,27 @@ crate ``` +The module filename may also be the name of the module as a directory with the contents in a +file named `mod.nr` within that directory. The above example can alternatively be expressed like this: + +Filename : `src/main.nr` + +```rust +mod foo; + +fn main() { + foo::hello_world(); +} +``` + +Filename : `src/foo/mod.nr` + +```rust +fn from_foo() {} +``` + +Note that it's an error to have both files `src/foo.nr` and `src/foo/mod.nr` in the filesystem. + ### Importing a module throughout the tree All modules are accessible from the `crate::` namespace. @@ -103,3 +124,88 @@ crate └── bar └── from_bar ``` + +Similar to importing a module in the crate root, modules can be placed in a `mod.nr` file, like this: + +Filename : `src/main.nr` + +```rust +mod foo; + +fn main() { + foo::from_foo(); +} +``` + +Filename : `src/foo/mod.nr` + +```rust +mod bar; +fn from_foo() {} +``` + +Filename : `src/foo/bar/mod.nr` + +```rust +fn from_bar() {} +``` + +### Referencing a parent module + +Given a submodule, you can refer to its parent module using the `super` keyword. + +Filename : `src/main.nr` + +```rust +mod foo; + +fn main() { + foo::from_foo(); +} +``` + +Filename : `src/foo.nr` + +```rust +mod bar; + +fn from_foo() {} +``` + +Filename : `src/foo/bar.nr` + +```rust +// Same as bar::from_foo +use super::from_foo; + +fn from_bar() { + from_foo(); // invokes super::from_foo(), which is bar::from_foo() + super::from_foo(); // also invokes bar::from_foo() +} +``` + +### `use` visibility + +`use` declarations are private to the containing module, by default. However, like functions, +they can be marked as `pub` or `pub(crate)`. Such a use declaration serves to _re-export_ a name. +A public `use` declaration can therefore redirect some public name to a different target definition: +even a definition with a private canonical path, inside a different module. + +An example of re-exporting: + +```rust +mod some_module { + pub use foo::{bar, baz}; + mod foo { + pub fn bar() {} + pub fn baz() {} + } +} + +fn main() { + some_module::bar(); + some_module::baz(); +} +``` + +In this example, the module `some_module` re-exports two public names defined in `foo`. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/workspaces.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/modules_packages_crates/workspaces.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/workspaces.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/modules_packages_crates/workspaces.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/_category_.json similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/_category_.json rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/_category_.json diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/bigint.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/bigint.md similarity index 88% rename from noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/bigint.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/bigint.md index 2bfdeec6631..bcbb6b0d252 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/bigint.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/bigint.md @@ -15,6 +15,11 @@ The BigInt module in the standard library exposes some class of integers which d The module can currently be considered as `Field`s with fixed modulo sizes used by a set of elliptic curves, in addition to just the native curve. [More work](https://github.com/noir-lang/noir/issues/510) is needed to achieve arbitrarily sized big integers. +:::note + +`nargo` can be built with `--profile release-pedantic` to enable extra overflow checks which may affect `BigInt` results in some cases. +Consider the [`noir-bignum`](https://github.com/noir-lang/noir-bignum) library for an optimized alternative approach. + ::: Currently 6 classes of integers (i.e 'big' prime numbers) are available in the module, namely: @@ -53,7 +58,7 @@ fn big_int_example(x: u8, y: u8) { println(d[0]); } ``` -> Source code: test_programs/execution_success/bigint/src/main.nr#L70-L78 +> Source code: test_programs/execution_success/bigint/src/main.nr#L72-L80 ## Methods diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/black_box_fns.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/black_box_fns.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/black_box_fns.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/bn254.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/bn254.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/bn254.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/bn254.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/containers/boundedvec.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/containers/boundedvec.md similarity index 97% rename from noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/containers/boundedvec.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/containers/boundedvec.md index 4349eab67c5..7463ca092f1 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/containers/boundedvec.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/containers/boundedvec.md @@ -52,19 +52,19 @@ Note that whenever calling `new` the maximum length of the vector should always via a type signature: ```rust title="new_example" showLineNumbers -fn foo() -> BoundedVec { +fn good() -> BoundedVec { // Ok! MaxLen is specified with a type annotation let v1: BoundedVec = BoundedVec::new(); let v2 = BoundedVec::new(); - // Ok! MaxLen is known from the type of foo's return value + // Ok! MaxLen is known from the type of `good`'s return value v2 } fn bad() { + // Error: Type annotation needed + // The compiler can't infer `MaxLen` from this code. let mut v3 = BoundedVec::new(); - - // Not Ok! We don't know if v3's MaxLen is at least 1, and the compiler often infers 0 by default. v3.push(5); } ``` @@ -394,7 +394,7 @@ Example: let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]); let result = vec.map(|value| value * 2); ``` -> Source code: noir_stdlib/src/collections/bounded_vec.nr#L214-L217 +> Source code: noir_stdlib/src/collections/bounded_vec.nr#L493-L496 ### any diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/containers/hashmap.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/containers/hashmap.md similarity index 73% rename from noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/containers/hashmap.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/containers/hashmap.md index 408b6ba9da7..39f1ae9b32c 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/containers/hashmap.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/containers/hashmap.md @@ -11,11 +11,6 @@ Note that due to hash collisions, the actual maximum number of elements stored b hashmap is likely lower than `MaxLen`. This is true even with cryptographic hash functions since every hash value will be performed modulo `MaxLen`. -When creating `HashMap`s, the `MaxLen` generic should always be specified if it is not already -known. Otherwise, the compiler may infer a different value for `MaxLen` (such as zero), which -will likely change the result of the program. This behavior is set to become an error in future -versions instead. - Example: ```rust @@ -35,14 +30,21 @@ let two = map.get(1).unwrap(); ### default ```rust title="default" showLineNumbers -impl Default for HashMap +impl Default for HashMap where B: BuildHasher + Default, - H: Hasher + Default -{ + H: Hasher + Default { + /// Constructs an empty HashMap. + /// + /// Example: + /// + /// ```noir + /// let hashmap: HashMap> = HashMap::default(); + /// assert(hashmap.is_empty()); + /// ``` fn default() -> Self { ``` -> Source code: noir_stdlib/src/collections/map.nr#L462-L469 +> Source code: noir_stdlib/src/collections/map.nr#L694-L708 Creates a fresh, empty HashMap. @@ -58,7 +60,7 @@ Example: let hashmap: HashMap> = HashMap::default(); assert(hashmap.is_empty()); ``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L202-L205 +> Source code: test_programs/execution_success/hashmap/src/main.nr#L201-L204 Because `HashMap` has so many generic arguments that are likely to be the same throughout @@ -67,17 +69,17 @@ your program, it may be helpful to create a type alias: ```rust title="type_alias" showLineNumbers type MyMap = HashMap>; ``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L196-L198 +> Source code: test_programs/execution_success/hashmap/src/main.nr#L195-L197 ### with_hasher ```rust title="with_hasher" showLineNumbers -pub fn with_hasher(_build_hasher: B) -> Self +pub fn with_hasher(_build_hasher: B) -> Self where B: BuildHasher { ``` -> Source code: noir_stdlib/src/collections/map.nr#L82-L86 +> Source code: noir_stdlib/src/collections/map.nr#L103-L107 Creates a hashmap with an existing `BuildHasher`. This can be used to ensure multiple @@ -90,13 +92,13 @@ let my_hasher: BuildHasherDefault = Default::default(); let hashmap: HashMap> = HashMap::with_hasher(my_hasher); assert(hashmap.is_empty()); ``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L207-L211 +> Source code: test_programs/execution_success/hashmap/src/main.nr#L206-L210 ### get ```rust title="get" showLineNumbers -pub fn get( +pub fn get( self, key: K ) -> Option @@ -105,7 +107,7 @@ pub fn get( B: BuildHasher, H: Hasher { ``` -> Source code: noir_stdlib/src/collections/map.nr#L278-L287 +> Source code: noir_stdlib/src/collections/map.nr#L470-L479 Retrieves a value from the hashmap, returning `Option::none()` if it was not found. @@ -121,13 +123,13 @@ fn get_example(map: HashMap } } ``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L299-L307 +> Source code: test_programs/execution_success/hashmap/src/main.nr#L298-L306 ### insert ```rust title="insert" showLineNumbers -pub fn insert( +pub fn insert( &mut self, key: K, value: V @@ -137,7 +139,7 @@ pub fn insert( B: BuildHasher, H: Hasher { ``` -> Source code: noir_stdlib/src/collections/map.nr#L313-L323 +> Source code: noir_stdlib/src/collections/map.nr#L514-L524 Inserts a new key-value pair into the map. If the key was already in the map, its @@ -150,13 +152,13 @@ let mut map: HashMap> = Has map.insert(12, 42); assert(map.len() == 1); ``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L213-L217 +> Source code: test_programs/execution_success/hashmap/src/main.nr#L212-L216 ### remove ```rust title="remove" showLineNumbers -pub fn remove( +pub fn remove( &mut self, key: K ) @@ -165,7 +167,7 @@ pub fn remove( B: BuildHasher, H: Hasher { ``` -> Source code: noir_stdlib/src/collections/map.nr#L356-L365 +> Source code: noir_stdlib/src/collections/map.nr#L573-L582 Removes the given key-value pair from the map. If the key was not already present @@ -181,7 +183,7 @@ map.remove(12); map.remove(12); assert(map.is_empty()); ``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L221-L228 +> Source code: test_programs/execution_success/hashmap/src/main.nr#L220-L227 ### is_empty @@ -189,7 +191,7 @@ map.remove(12); ```rust title="is_empty" showLineNumbers pub fn is_empty(self) -> bool { ``` -> Source code: noir_stdlib/src/collections/map.nr#L115-L117 +> Source code: noir_stdlib/src/collections/map.nr#L168-L170 True if the length of the hash map is empty. @@ -205,7 +207,7 @@ assert(map.is_empty()); map.remove(1); assert(map.is_empty()); ``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L230-L238 +> Source code: test_programs/execution_success/hashmap/src/main.nr#L229-L237 ### len @@ -213,7 +215,7 @@ assert(map.is_empty()); ```rust title="len" showLineNumbers pub fn len(self) -> u32 { ``` -> Source code: noir_stdlib/src/collections/map.nr#L264-L266 +> Source code: noir_stdlib/src/collections/map.nr#L429-L431 Returns the current length of this hash map. @@ -236,7 +238,7 @@ Example: map.remove(1); assert(map.len() == 2); ``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L240-L255 +> Source code: test_programs/execution_success/hashmap/src/main.nr#L239-L254 ### capacity @@ -244,7 +246,7 @@ Example: ```rust title="capacity" showLineNumbers pub fn capacity(_self: Self) -> u32 { ``` -> Source code: noir_stdlib/src/collections/map.nr#L271-L273 +> Source code: noir_stdlib/src/collections/map.nr#L451-L453 Returns the maximum capacity of this hashmap. This is always equal to the capacity @@ -263,7 +265,7 @@ let empty_map: HashMap> = assert(empty_map.len() == 0); assert(empty_map.capacity() == 42); ``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L257-L261 +> Source code: test_programs/execution_success/hashmap/src/main.nr#L256-L260 ### clear @@ -271,7 +273,7 @@ let empty_map: HashMap> = ```rust title="clear" showLineNumbers pub fn clear(&mut self) { ``` -> Source code: noir_stdlib/src/collections/map.nr#L93-L95 +> Source code: noir_stdlib/src/collections/map.nr#L122-L124 Clears the hashmap, removing all key-value pairs from it. @@ -283,13 +285,13 @@ assert(!map.is_empty()); map.clear(); assert(map.is_empty()); ``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L263-L267 +> Source code: test_programs/execution_success/hashmap/src/main.nr#L262-L266 ### contains_key ```rust title="contains_key" showLineNumbers -pub fn contains_key( +pub fn contains_key( self, key: K ) -> bool @@ -298,7 +300,7 @@ pub fn contains_key( B: BuildHasher, H: Hasher { ``` -> Source code: noir_stdlib/src/collections/map.nr#L101-L110 +> Source code: noir_stdlib/src/collections/map.nr#L142-L151 True if the hashmap contains the given key. Unlike `get`, this will not also return @@ -314,7 +316,7 @@ if map.contains_key(7) { println("No value for key 7!"); } ``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L269-L276 +> Source code: test_programs/execution_success/hashmap/src/main.nr#L268-L275 ### entries @@ -322,7 +324,7 @@ if map.contains_key(7) { ```rust title="entries" showLineNumbers pub fn entries(self) -> BoundedVec<(K, V), N> { ``` -> Source code: noir_stdlib/src/collections/map.nr#L123-L125 +> Source code: noir_stdlib/src/collections/map.nr#L192-L194 Returns a vector of each key-value pair present in the hashmap. @@ -343,7 +345,7 @@ let entries = map.entries(); } } ``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L310-L321 +> Source code: test_programs/execution_success/hashmap/src/main.nr#L309-L320 ### keys @@ -351,7 +353,7 @@ let entries = map.entries(); ```rust title="keys" showLineNumbers pub fn keys(self) -> BoundedVec { ``` -> Source code: noir_stdlib/src/collections/map.nr#L144-L146 +> Source code: noir_stdlib/src/collections/map.nr#L228-L230 Returns a vector of each key present in the hashmap. @@ -371,7 +373,7 @@ let keys = map.keys(); } } ``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L323-L333 +> Source code: test_programs/execution_success/hashmap/src/main.nr#L322-L332 ### values @@ -379,7 +381,7 @@ let keys = map.keys(); ```rust title="values" showLineNumbers pub fn values(self) -> BoundedVec { ``` -> Source code: noir_stdlib/src/collections/map.nr#L164-L166 +> Source code: noir_stdlib/src/collections/map.nr#L262-L264 Returns a vector of each value present in the hashmap. @@ -398,13 +400,13 @@ let values = map.values(); } } ``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L335-L344 +> Source code: test_programs/execution_success/hashmap/src/main.nr#L334-L343 ### iter_mut ```rust title="iter_mut" showLineNumbers -pub fn iter_mut( +pub fn iter_mut( &mut self, f: fn(K, V) -> (K, V) ) @@ -413,7 +415,7 @@ pub fn iter_mut( B: BuildHasher, H: Hasher { ``` -> Source code: noir_stdlib/src/collections/map.nr#L183-L192 +> Source code: noir_stdlib/src/collections/map.nr#L298-L307 Iterates through each key-value pair of the HashMap, setting each key-value pair to the @@ -432,13 +434,13 @@ Example: // Add 1 to each key in the map, and double the value associated with that key. map.iter_mut(|k, v| (k + 1, v * 2)); ``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L348-L351 +> Source code: test_programs/execution_success/hashmap/src/main.nr#L347-L350 ### iter_keys_mut ```rust title="iter_keys_mut" showLineNumbers -pub fn iter_keys_mut( +pub fn iter_keys_mut( &mut self, f: fn(K) -> K ) @@ -447,7 +449,7 @@ pub fn iter_keys_mut( B: BuildHasher, H: Hasher { ``` -> Source code: noir_stdlib/src/collections/map.nr#L208-L217 +> Source code: noir_stdlib/src/collections/map.nr#L338-L347 Iterates through the HashMap, mutating each key to the result returned from @@ -466,7 +468,7 @@ Example: // Double each key, leaving the value associated with that key untouched map.iter_keys_mut(|k| k * 2); ``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L353-L356 +> Source code: test_programs/execution_success/hashmap/src/main.nr#L352-L355 ### iter_values_mut @@ -474,7 +476,7 @@ Example: ```rust title="iter_values_mut" showLineNumbers pub fn iter_values_mut(&mut self, f: fn(V) -> V) { ``` -> Source code: noir_stdlib/src/collections/map.nr#L233-L235 +> Source code: noir_stdlib/src/collections/map.nr#L372-L374 Iterates through the HashMap, applying the given function to each value and mutating the @@ -487,7 +489,7 @@ Example: // Halve each value map.iter_values_mut(|v| v / 2); ``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L358-L361 +> Source code: test_programs/execution_success/hashmap/src/main.nr#L357-L360 ### retain @@ -495,7 +497,7 @@ Example: ```rust title="retain" showLineNumbers pub fn retain(&mut self, f: fn(K, V) -> bool) { ``` -> Source code: noir_stdlib/src/collections/map.nr#L247-L249 +> Source code: noir_stdlib/src/collections/map.nr#L393-L395 Retains only the key-value pairs for which the given function returns true. @@ -506,7 +508,7 @@ Example: ```rust title="retain_example" showLineNumbers map.retain(|k, v| (k != 0) & (v != 0)); ``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L281-L283 +> Source code: test_programs/execution_success/hashmap/src/main.nr#L280-L282 ## Trait Implementations @@ -514,14 +516,21 @@ map.retain(|k, v| (k != 0) & (v != 0)); ### default ```rust title="default" showLineNumbers -impl Default for HashMap +impl Default for HashMap where B: BuildHasher + Default, - H: Hasher + Default -{ + H: Hasher + Default { + /// Constructs an empty HashMap. + /// + /// Example: + /// + /// ```noir + /// let hashmap: HashMap> = HashMap::default(); + /// assert(hashmap.is_empty()); + /// ``` fn default() -> Self { ``` -> Source code: noir_stdlib/src/collections/map.nr#L462-L469 +> Source code: noir_stdlib/src/collections/map.nr#L694-L708 Constructs an empty HashMap. @@ -532,22 +541,37 @@ Example: let hashmap: HashMap> = HashMap::default(); assert(hashmap.is_empty()); ``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L202-L205 +> Source code: test_programs/execution_success/hashmap/src/main.nr#L201-L204 ### eq ```rust title="eq" showLineNumbers -impl Eq for HashMap +impl Eq for HashMap where K: Eq + Hash, V: Eq, B: BuildHasher, - H: Hasher -{ + H: Hasher { + /// Checks if two HashMaps are equal. + /// + /// Example: + /// + /// ```noir + /// let mut map1: HashMap> = HashMap::default(); + /// let mut map2: HashMap> = HashMap::default(); + /// + /// map1.insert(1, 2); + /// map1.insert(3, 4); + /// + /// map2.insert(3, 4); + /// map2.insert(1, 2); + /// + /// assert(map1 == map2); + /// ``` fn eq(self, other: HashMap) -> bool { ``` -> Source code: noir_stdlib/src/collections/map.nr#L426-L435 +> Source code: noir_stdlib/src/collections/map.nr#L643-L667 Checks if two HashMaps are equal. @@ -566,5 +590,5 @@ let mut map1: HashMap> = Hash assert(map1 == map2); ``` -> Source code: test_programs/execution_success/hashmap/src/main.nr#L285-L296 +> Source code: test_programs/execution_success/hashmap/src/main.nr#L284-L295 diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/containers/index.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/index.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/containers/index.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/containers/vec.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/containers/vec.mdx similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/containers/vec.mdx rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/containers/vec.mdx diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/cryptographic_primitives/_category_.json similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/_category_.json rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/cryptographic_primitives/_category_.json diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/ciphers.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/cryptographic_primitives/ciphers.mdx similarity index 92% rename from noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/ciphers.mdx rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/cryptographic_primitives/ciphers.mdx index e83e26efb97..d75e50d4b89 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/ciphers.mdx +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/cryptographic_primitives/ciphers.mdx @@ -14,7 +14,7 @@ import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; Given a plaintext as an array of bytes, returns the corresponding aes128 ciphertext (CBC mode). Input padding is automatically performed using PKCS#7, so that the output length is `input.len() + (16 - input.len() % 16)`. ```rust title="aes128" showLineNumbers -pub fn aes128_encrypt(input: [u8; N], iv: [u8; 16], key: [u8; 16]) -> [u8] {} +pub fn aes128_encrypt(input: [u8; N], iv: [u8; 16], key: [u8; 16]) -> [u8] {} ``` > Source code: noir_stdlib/src/aes128.nr#L2-L4 diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/ec_primitives.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/cryptographic_primitives/ec_primitives.md similarity index 97% rename from noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/ec_primitives.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/cryptographic_primitives/ec_primitives.md index f839b4a228e..f262d8160d6 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/ec_primitives.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/cryptographic_primitives/ec_primitives.md @@ -18,7 +18,7 @@ curve you want to use, which would be specified using any one of the methods `std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::new` which take the coefficients in the defining equation together with a generator point as parameters. You can find more detail in the comments in -[`noir_stdlib/src/ec.nr`](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr), but +[`noir_stdlib/src/ec/mod.nr`](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec/mod.nr), but the gist of it is that the elliptic curves of interest are usually expressed in one of the standard forms implemented here (Twisted Edwards, Montgomery and Short Weierstraß), and in addition to that, you could choose to use `affine` coordinates (Cartesian coordinates - the usual (x,y) - possibly @@ -67,7 +67,7 @@ does indeed lie on `c` by calling `c.contains(p1)`. the curve configurations, the SWU map-to-curve method may be called as `c.swu_map(z,n)`, where `z: Field` depends on `Field` and `c` and must be chosen by the user (the conditions it needs to satisfy are specified in the comments - [here](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr)). + [here](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec/mod.nr)). ## Examples diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx similarity index 97% rename from noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx index 4394b48f907..8520071e95f 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx @@ -15,7 +15,7 @@ Verifier for ECDSA Secp256k1 signatures. See ecdsa_secp256k1::verify_signature_slice for a version that accepts slices directly. ```rust title="ecdsa_secp256k1" showLineNumbers -pub fn verify_signature( +pub fn verify_signature( public_key_x: [u8; 32], public_key_y: [u8; 32], signature: [u8; 64], @@ -59,7 +59,7 @@ Verifier for ECDSA Secp256r1 signatures. See ecdsa_secp256r1::verify_signature_slice for a version that accepts slices directly. ```rust title="ecdsa_secp256r1" showLineNumbers -pub fn verify_signature( +pub fn verify_signature( public_key_x: [u8; 32], public_key_y: [u8; 32], signature: [u8; 64], diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/eddsa.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/cryptographic_primitives/eddsa.mdx similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/eddsa.mdx rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/cryptographic_primitives/eddsa.mdx diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/embedded_curve_ops.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/cryptographic_primitives/embedded_curve_ops.mdx similarity index 83% rename from noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/embedded_curve_ops.mdx rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/cryptographic_primitives/embedded_curve_ops.mdx index 14d7dda7f0d..8ded020bf27 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/embedded_curve_ops.mdx +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/cryptographic_primitives/embedded_curve_ops.mdx @@ -23,12 +23,12 @@ the curve and returns a sum of the resulting points. Points represented as x and y coordinates [x1, y1, x2, y2, ...], scalars as low and high limbs [low1, high1, low2, high2, ...]. ```rust title="multi_scalar_mul" showLineNumbers -pub fn multi_scalar_mul( +pub fn multi_scalar_mul( points: [EmbeddedCurvePoint; N], scalars: [EmbeddedCurveScalar; N] -) -> [Field; 3] +) -> EmbeddedCurvePoint ``` -> Source code: noir_stdlib/src/embedded_curve_ops.nr#L62-L67 +> Source code: noir_stdlib/src/embedded_curve_ops.nr#L88-L93 example @@ -46,12 +46,9 @@ Performs fixed base scalar multiplication over the embedded curve (multiplies in The function accepts a single scalar on the input represented as 2 fields. ```rust title="fixed_base_scalar_mul" showLineNumbers -pub fn fixed_base_scalar_mul( - scalar_low: Field, - scalar_high: Field -) -> [Field; 3] +pub fn fixed_base_scalar_mul(scalar: EmbeddedCurveScalar) -> EmbeddedCurvePoint ``` -> Source code: noir_stdlib/src/embedded_curve_ops.nr#L70-L75 +> Source code: noir_stdlib/src/embedded_curve_ops.nr#L105-L107 example @@ -81,7 +78,7 @@ fn embedded_curve_add( point2: EmbeddedCurvePoint ) -> EmbeddedCurvePoint ``` -> Source code: noir_stdlib/src/embedded_curve_ops.nr#L84-L89 +> Source code: noir_stdlib/src/embedded_curve_ops.nr#L115-L120 example diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/hashes.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/cryptographic_primitives/hashes.mdx similarity index 78% rename from noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/hashes.mdx rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/cryptographic_primitives/hashes.mdx index 18132b9a4dc..2581690e034 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/hashes.mdx +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/cryptographic_primitives/hashes.mdx @@ -16,9 +16,9 @@ Given an array of bytes, returns the resulting sha256 hash. Specify a message_size to hash only the first `message_size` bytes of the input. ```rust title="sha256" showLineNumbers -pub fn sha256(input: [u8; N]) -> [u8; 32] +pub fn sha256(input: [u8; N]) -> [u8; 32] ``` -> Source code: noir_stdlib/src/hash.nr#L11-L13 +> Source code: noir_stdlib/src/hash/sha256.nr#L8-L10 example: @@ -43,9 +43,9 @@ fn main() { Given an array of bytes, returns an array with the Blake2 hash ```rust title="blake2s" showLineNumbers -pub fn blake2s(input: [u8; N]) -> [u8; 32] +pub fn blake2s(input: [u8; N]) -> [u8; 32] ``` -> Source code: noir_stdlib/src/hash.nr#L17-L19 +> Source code: noir_stdlib/src/hash/mod.nr#L18-L20 example: @@ -64,9 +64,9 @@ fn main() { Given an array of bytes, returns an array with the Blake3 hash ```rust title="blake3" showLineNumbers -pub fn blake3(input: [u8; N]) -> [u8; 32] +pub fn blake3(input: [u8; N]) -> [u8; 32] ``` -> Source code: noir_stdlib/src/hash.nr#L23-L25 +> Source code: noir_stdlib/src/hash/mod.nr#L24-L26 example: @@ -85,9 +85,9 @@ fn main() { Given an array of Fields, returns the Pedersen hash. ```rust title="pedersen_hash" showLineNumbers -pub fn pedersen_hash(input: [Field; N]) -> Field +pub fn pedersen_hash(input: [Field; N]) -> Field ``` -> Source code: noir_stdlib/src/hash.nr#L42-L44 +> Source code: noir_stdlib/src/hash/mod.nr#L77-L79 example: @@ -108,9 +108,9 @@ fn main(x: Field, y: Field, expected_hash: Field) { Given an array of Fields, returns the Pedersen commitment. ```rust title="pedersen_commitment" showLineNumbers -pub fn pedersen_commitment(input: [Field; N]) -> EmbeddedCurvePoint { +pub fn pedersen_commitment(input: [Field; N]) -> EmbeddedCurvePoint { ``` -> Source code: noir_stdlib/src/hash.nr#L28-L30 +> Source code: noir_stdlib/src/hash/mod.nr#L29-L31 example: @@ -134,9 +134,9 @@ Given an array of bytes (`u8`), returns the resulting keccak hash as an array of `message_size` bytes of the input. ```rust title="keccak256" showLineNumbers -pub fn keccak256(input: [u8; N], message_size: u32) -> [u8; 32] +pub fn keccak256(input: [u8; N], message_size: u32) -> [u8; 32] ``` -> Source code: noir_stdlib/src/hash.nr#L64-L66 +> Source code: noir_stdlib/src/hash/mod.nr#L128-L130 example: @@ -180,20 +180,16 @@ example: ```rust title="poseidon" showLineNumbers use std::hash::poseidon; -use std::hash::poseidon2; -fn main(x1: [Field; 2], y1: pub Field, x2: [Field; 4], y2: pub Field, x3: [Field; 4], y3: Field) { +fn main(x1: [Field; 2], y1: pub Field, x2: [Field; 4], y2: pub Field) { let hash1 = poseidon::bn254::hash_2(x1); assert(hash1 == y1); let hash2 = poseidon::bn254::hash_4(x2); assert(hash2 == y2); - - let hash3 = poseidon2::Poseidon2::hash(x3, x3.len()); - assert(hash3 == y3); } ``` -> Source code: test_programs/execution_success/poseidon_bn254_hash/src/main.nr#L1-L15 +> Source code: test_programs/execution_success/poseidon_bn254_hash/src/main.nr#L1-L11 ## poseidon 2 @@ -207,7 +203,18 @@ function, there is only one hash and you can specify a message_size to hash only Poseidon2::hash(input, 3); ``` -The above example for Poseidon also includes Poseidon2. +example: + +```rust title="poseidon2" showLineNumbers +use std::hash::poseidon2; + +fn main(inputs: [Field; 4], expected_hash: Field) { + let hash = poseidon2::Poseidon2::hash(inputs, inputs.len()); + assert_eq(hash, expected_hash); +} +``` +> Source code: test_programs/execution_success/poseidon2/src/main.nr#L1-L8 + ## mimc_bn254 and mimc diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/cryptographic_primitives/index.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/index.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/cryptographic_primitives/index.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/schnorr.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/cryptographic_primitives/schnorr.mdx similarity index 98% rename from noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/schnorr.mdx rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/cryptographic_primitives/schnorr.mdx index b59e69c8f07..a32138daaa6 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/schnorr.mdx +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/cryptographic_primitives/schnorr.mdx @@ -13,7 +13,7 @@ Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpki See schnorr::verify_signature_slice for a version that works directly on slices. ```rust title="schnorr_verify" showLineNumbers -pub fn verify_signature( +pub fn verify_signature( public_key_x: Field, public_key_y: Field, signature: [u8; 64], diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/fmtstr.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/fmtstr.md new file mode 100644 index 00000000000..65a7da9996d --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/fmtstr.md @@ -0,0 +1,17 @@ +--- +title: fmtstr +--- + +`fmtstr` is the type resulting from using format string (`f"..."`). + +## Methods + +### quoted_contents + +```rust title="quoted_contents" showLineNumbers +comptime fn quoted_contents(self) -> Quoted {} +``` +> Source code: noir_stdlib/src/meta/format_string.nr#L3-L5 + + +Returns the format string contents (that is, without the leading and trailing double quotes) as a `Quoted` value. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/is_unconstrained.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/is_unconstrained.md similarity index 89% rename from noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/is_unconstrained.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/is_unconstrained.md index bb157e719dc..51bb1bda8f1 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/is_unconstrained.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/is_unconstrained.md @@ -56,4 +56,14 @@ pub fn external_interface(){ ``` -The is_unconstrained result is resolved at compile time, so in unconstrained contexts the compiler removes the else branch, and in constrained contexts the compiler removes the if branch, reducing the amount of compute necessary to run external_interface. \ No newline at end of file +The is_unconstrained result is resolved at compile time, so in unconstrained contexts the compiler removes the else branch, and in constrained contexts the compiler removes the if branch, reducing the amount of compute necessary to run external_interface. + +Note that using `is_unconstrained` in a `comptime` context will also return `true`: + +``` +fn main() { + comptime { + assert(is_unconstrained()); + } +} +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/logging.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/logging.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/logging.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/logging.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/merkle_trees.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/merkle_trees.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/merkle_trees.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/merkle_trees.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/expr.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/expr.md new file mode 100644 index 00000000000..f226c1eebb3 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/expr.md @@ -0,0 +1,323 @@ +--- +title: Expr +--- + +`std::meta::expr` contains methods on the built-in `Expr` type for quoted, syntactically valid expressions. + +## Methods + +### as_array + +```rust title="as_array" showLineNumbers +comptime fn as_array(self) -> Option<[Expr]> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L7-L9 + + +If this expression is an array, this returns a slice of each element in the array. + +### as_assert + +```rust title="as_assert" showLineNumbers +comptime fn as_assert(self) -> Option<(Expr, Option)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L12-L14 + + +If this expression is an assert, this returns the assert expression and the optional message. + +### as_assert_eq + +```rust title="as_assert_eq" showLineNumbers +comptime fn as_assert_eq(self) -> Option<(Expr, Expr, Option)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L17-L19 + + +If this expression is an assert_eq, this returns the left-hand-side and right-hand-side +expressions, together with the optional message. + +### as_assign + +```rust title="as_assign" showLineNumbers +comptime fn as_assign(self) -> Option<(Expr, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L22-L24 + + +If this expression is an assignment, this returns a tuple with the left hand side +and right hand side in order. + +### as_binary_op + +```rust title="as_binary_op" showLineNumbers +comptime fn as_binary_op(self) -> Option<(Expr, BinaryOp, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L32-L34 + + +If this expression is a binary operator operation ` `, +return the left-hand side, operator, and the right-hand side of the operation. + +### as_block + +```rust title="as_block" showLineNumbers +comptime fn as_block(self) -> Option<[Expr]> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L37-L39 + + +If this expression is a block `{ stmt1; stmt2; ...; stmtN }`, return +a slice containing each statement. + +### as_bool + +```rust title="as_bool" showLineNumbers +comptime fn as_bool(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L42-L44 + + +If this expression is a boolean literal, return that literal. + +### as_comptime + +```rust title="as_comptime" showLineNumbers +comptime fn as_comptime(self) -> Option<[Expr]> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L50-L52 + + +If this expression is a `comptime { stmt1; stmt2; ...; stmtN }` block, +return each statement in the block. + +### as_function_call + +```rust title="as_function_call" showLineNumbers +comptime fn as_function_call(self) -> Option<(Expr, [Expr])> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L55-L57 + + +If this expression is a function call `foo(arg1, ..., argN)`, return +the function and a slice of each argument. + +### as_if + +```rust title="as_if" showLineNumbers +comptime fn as_if(self) -> Option<(Expr, Expr, Option)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L60-L62 + + +If this expression is an `if condition { then_branch } else { else_branch }`, +return the condition, then branch, and else branch. If there is no else branch, +`None` is returned for that branch instead. + +### as_index + +```rust title="as_index" showLineNumbers +comptime fn as_index(self) -> Option<(Expr, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L65-L67 + + +If this expression is an index into an array `array[index]`, return the +array and the index. + +### as_integer + +```rust title="as_integer" showLineNumbers +comptime fn as_integer(self) -> Option<(Field, bool)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L27-L29 + + +If this expression is an integer literal, return the integer as a field +as well as whether the integer is negative (true) or not (false). + +### as_let + +```rust title="as_let" showLineNumbers +comptime fn as_let(self) -> Option<(Expr, Option, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L70-L72 + + +If this expression is a let statement, returns the let pattern as an `Expr`, +the optional type annotation, and the assigned expression. + +### as_member_access + +```rust title="as_member_access" showLineNumbers +comptime fn as_member_access(self) -> Option<(Expr, Quoted)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L75-L77 + + +If this expression is a member access `foo.bar`, return the struct/tuple +expression and the field. The field will be represented as a quoted value. + +### as_method_call + +```rust title="as_method_call" showLineNumbers +comptime fn as_method_call(self) -> Option<(Expr, Quoted, [UnresolvedType], [Expr])> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L80-L82 + + +If this expression is a method call `foo.bar::(arg1, ..., argN)`, return +the receiver, method name, a slice of each generic argument, and a slice of each argument. + +### as_repeated_element_array + +```rust title="as_repeated_element_array" showLineNumbers +comptime fn as_repeated_element_array(self) -> Option<(Expr, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L85-L87 + + +If this expression is a repeated element array `[elem; length]`, return +the repeated element and the length expressions. + +### as_repeated_element_slice + +```rust title="as_repeated_element_slice" showLineNumbers +comptime fn as_repeated_element_slice(self) -> Option<(Expr, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L90-L92 + + +If this expression is a repeated element slice `[elem; length]`, return +the repeated element and the length expressions. + +### as_slice + +```rust title="as_slice" showLineNumbers +comptime fn as_slice(self) -> Option<[Expr]> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L95-L97 + + +If this expression is a slice literal `&[elem1, ..., elemN]`, +return each element of the slice. + +### as_tuple + +```rust title="as_tuple" showLineNumbers +comptime fn as_tuple(self) -> Option<[Expr]> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L100-L102 + + +If this expression is a tuple `(field1, ..., fieldN)`, +return each element of the tuple. + +### as_unary_op + +```rust title="as_unary_op" showLineNumbers +comptime fn as_unary_op(self) -> Option<(UnaryOp, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L105-L107 + + +If this expression is a unary operation ` `, +return the unary operator as well as the right-hand side expression. + +### as_unsafe + +```rust title="as_unsafe" showLineNumbers +comptime fn as_unsafe(self) -> Option<[Expr]> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L110-L112 + + +If this expression is an `unsafe { stmt1; ...; stmtN }` block, +return each statement inside in a slice. + +### has_semicolon + +```rust title="has_semicolon" showLineNumbers +comptime fn has_semicolon(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L115-L117 + + +`true` if this expression is trailed by a semicolon. E.g. + +``` +comptime { + let expr1 = quote { 1 + 2 }.as_expr().unwrap(); + let expr2 = quote { 1 + 2; }.as_expr().unwrap(); + + assert(expr1.as_binary_op().is_some()); + assert(expr2.as_binary_op().is_some()); + + assert(!expr1.has_semicolon()); + assert(expr2.has_semicolon()); +} +``` + +### is_break + +```rust title="is_break" showLineNumbers +comptime fn is_break(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L120-L122 + + +`true` if this expression is `break`. + +### is_continue + +```rust title="is_continue" showLineNumbers +comptime fn is_continue(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L125-L127 + + +`true` if this expression is `continue`. + +### modify + +```rust title="modify" showLineNumbers +comptime fn modify(self, f: fn[Env](Expr) -> Option) -> Expr { +``` +> Source code: noir_stdlib/src/meta/expr.nr#L129-L131 + + +Applies a mapping function to this expression and to all of its sub-expressions. +`f` will be applied to each sub-expression first, then applied to the expression itself. + +This happens recursively for every expression within `self`. + +For example, calling `modify` on `(&[1], &[2, 3])` with an `f` that returns `Option::some` +for expressions that are integers, doubling them, would return `(&[2], &[4, 6])`. + +### quoted + +```rust title="quoted" showLineNumbers +comptime fn quoted(self) -> Quoted { +``` +> Source code: noir_stdlib/src/meta/expr.nr#L161-L163 + + +Returns this expression as a `Quoted` value. It's the same as `quote { $self }`. + +### resolve + +```rust title="resolve" showLineNumbers +comptime fn resolve(self, in_function: Option) -> TypedExpr {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L168-L170 + + +Resolves and type-checks this expression and returns the result as a `TypedExpr`. + +The `in_function` argument specifies where the expression is resolved: +- If it's `none`, the expression is resolved in the function where `resolve` was called +- If it's `some`, the expression is resolved in the given function + +If any names used by this expression are not in scope or if there are any type errors, +this will give compiler errors as if the expression was written directly into +the current `comptime` function. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/function_def.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/function_def.md new file mode 100644 index 00000000000..e490af68f7f --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/function_def.md @@ -0,0 +1,166 @@ +--- +title: FunctionDefinition +--- + +`std::meta::function_def` contains methods on the built-in `FunctionDefinition` type representing +a function definition in the source program. + +## Methods + +### add_attribute + +```rust title="add_attribute" showLineNumbers +comptime fn add_attribute(self, attribute: str) {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L3-L5 + + +Adds an attribute to the function. This is only valid +on functions in the current crate which have not yet been resolved. +This means any functions called at compile-time are invalid targets for this method. + +### body + +```rust title="body" showLineNumbers +comptime fn body(self) -> Expr {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L8-L10 + + +Returns the body of the function as an expression. This is only valid +on functions in the current crate which have not yet been resolved. +This means any functions called at compile-time are invalid targets for this method. + +### has_named_attribute + +```rust title="has_named_attribute" showLineNumbers +comptime fn has_named_attribute(self, name: str) -> bool {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L13-L15 + + +Returns true if this function has a custom attribute with the given name. + +### is_unconstrained + +```rust title="is_unconstrained" showLineNumbers +comptime fn is_unconstrained(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L18-L20 + + +Returns true if this function is unconstrained. + +### module + +```rust title="module" showLineNumbers +comptime fn module(self) -> Module {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L23-L25 + + +Returns the module where the function is defined. + +### name + +```rust title="name" showLineNumbers +comptime fn name(self) -> Quoted {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L28-L30 + + +Returns the name of the function. + +### parameters + +```rust title="parameters" showLineNumbers +comptime fn parameters(self) -> [(Quoted, Type)] {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L33-L35 + + +Returns each parameter of the function as a tuple of (parameter pattern, parameter type). + +### return_type + +```rust title="return_type" showLineNumbers +comptime fn return_type(self) -> Type {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L38-L40 + + +The return type of the function. + +### set_body + +```rust title="set_body" showLineNumbers +comptime fn set_body(self, body: Expr) {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L43-L45 + + +Mutate the function body to a new expression. This is only valid +on functions in the current crate which have not yet been resolved. +This means any functions called at compile-time are invalid targets for this method. + +### set_parameters + +```rust title="set_parameters" showLineNumbers +comptime fn set_parameters(self, parameters: [(Quoted, Type)]) {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L48-L50 + + +Mutates the function's parameters to a new set of parameters. This is only valid +on functions in the current crate which have not yet been resolved. +This means any functions called at compile-time are invalid targets for this method. + +Expects a slice of (parameter pattern, parameter type) for each parameter. Requires +each parameter pattern to be a syntactically valid parameter. + +### set_return_type + +```rust title="set_return_type" showLineNumbers +comptime fn set_return_type(self, return_type: Type) {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L53-L55 + + +Mutates the function's return type to a new type. This is only valid +on functions in the current crate which have not yet been resolved. +This means any functions called at compile-time are invalid targets for this method. + +### set_return_public + +```rust title="set_return_public" showLineNumbers +comptime fn set_return_public(self, public: bool) {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L58-L60 + + +Mutates the function's return visibility to public (if `true` is given) or private (if `false` is given). +This is only valid on functions in the current crate which have not yet been resolved. +This means any functions called at compile-time are invalid targets for this method. + +### set_unconstrained + +```rust title="set_unconstrained" showLineNumbers +comptime fn set_unconstrained(self, value: bool) {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L63-L65 + + +Mutates the function to be unconstrained (if `true` is given) or not (if `false` is given). +This is only valid on functions in the current crate which have not yet been resolved. +This means any functions called at compile-time are invalid targets for this method. + +## Trait Implementations + +```rust +impl Eq for FunctionDefinition +impl Hash for FunctionDefinition +``` + +Note that each function is assigned a unique ID internally and this is what is used for +equality and hashing. So even functions with identical signatures and bodies may not +be equal in this sense if they were originally different items in the source program. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/index.md new file mode 100644 index 00000000000..73d6fe52285 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/index.md @@ -0,0 +1,210 @@ +--- +title: Metaprogramming +description: Noir's Metaprogramming API +keywords: [metaprogramming, comptime, macros, macro, quote, unquote] +--- + +`std::meta` is the entry point for Noir's metaprogramming API. This consists of `comptime` functions +and types used for inspecting and modifying Noir programs. + +## Functions + +### type_of + +```rust title="type_of" showLineNumbers +pub comptime fn type_of(x: T) -> Type {} +``` +> Source code: noir_stdlib/src/meta/mod.nr#L26-L28 + + +Returns the type of a variable at compile-time. + +Example: +```rust +comptime { + let x: i32 = 1; + let x_type: Type = std::meta::type_of(x); + + assert_eq(x_type, quote { i32 }.as_type()); +} +``` + +### unquote + +```rust title="unquote" showLineNumbers +pub comptime fn unquote(code: Quoted) -> Quoted { +``` +> Source code: noir_stdlib/src/meta/mod.nr#L18-L20 + + +Unquotes the passed-in token stream where this function was called. + +Example: +```rust +comptime { + let code = quote { 1 + 2 }; + + // let x = 1 + 2; + let x = unquote!(code); +} +``` + +### derive + +```rust title="derive" showLineNumbers +#[varargs] +pub comptime fn derive(s: StructDefinition, traits: [TraitDefinition]) -> Quoted { +``` +> Source code: noir_stdlib/src/meta/mod.nr#L46-L49 + + +Attribute placed on struct definitions. + +Creates a trait impl for each trait passed in as an argument. +To do this, the trait must have a derive handler registered +with `derive_via` beforehand. The traits in the stdlib that +can be derived this way are `Eq`, `Ord`, `Default`, and `Hash`. + +Example: +```rust +#[derive(Eq, Default)] +struct Foo { + x: i32, + y: T, +} + +fn main() { + let foo1 = Foo::default(); + let foo2 = Foo { x: 0, y: &[0] }; + assert_eq(foo1, foo2); +} +``` + +### derive_via + +```rust title="derive_via_signature" showLineNumbers +pub comptime fn derive_via(t: TraitDefinition, f: DeriveFunction) { +``` +> Source code: noir_stdlib/src/meta/mod.nr#L68-L70 + + +Attribute placed on trait definitions. + +Registers a function to create impls for the given trait +when the trait is used in a `derive` call. Users may use +this to register their own functions to enable their traits +to be derived by `derive`. + +Because this function requires a function as an argument which +should produce a trait impl for any given struct, users may find +it helpful to use a function like `std::meta::make_trait_impl` to +help creating these impls. + +Example: +```rust +#[derive_via(derive_do_nothing)] +trait DoNothing { + fn do_nothing(self); +} + +comptime fn derive_do_nothing(s: StructDefinition) -> Quoted { + let typ = s.as_type(); + quote { + impl DoNothing for $typ { + fn do_nothing(self) { + println("Nothing"); + } + } + } +} +``` + +As another example, `derive_eq` in the stdlib is used to derive the `Eq` +trait for any struct. It makes use of `make_trait_impl` to do this: + +```rust title="derive_eq" showLineNumbers +comptime fn derive_eq(s: StructDefinition) -> Quoted { + let signature = quote { fn eq(_self: Self, _other: Self) -> bool }; + let for_each_field = |name| quote { (_self.$name == _other.$name) }; + let body = |fields| { + if s.fields().len() == 0 { + quote { true } + } else { + fields + } + }; + crate::meta::make_trait_impl(s, quote { Eq }, signature, for_each_field, quote { & }, body) +} +``` +> Source code: noir_stdlib/src/cmp.nr#L10-L23 + + +### make_trait_impl + +```rust title="make_trait_impl" showLineNumbers +pub comptime fn make_trait_impl( + s: StructDefinition, + trait_name: Quoted, + function_signature: Quoted, + for_each_field: fn[Env1](Quoted) -> Quoted, + join_fields_with: Quoted, + body: fn[Env2](Quoted) -> Quoted +) -> Quoted { +``` +> Source code: noir_stdlib/src/meta/mod.nr#L87-L96 + + +A helper function to more easily create trait impls while deriving traits. + +Note that this function only works for traits which: +1. Have only one method +2. Have no generics on the trait itself. + - E.g. Using this on a trait such as `trait Foo { ... }` will result in the + generated impl incorrectly missing the `T` generic. + +If your trait fits these criteria then `make_trait_impl` is likely the easiest +way to write your derive handler. The arguments are as follows: + +- `s`: The struct to make the impl for +- `trait_name`: The name of the trait to derive. E.g. `quote { Eq }`. +- `function_signature`: The signature of the trait method to derive. E.g. `fn eq(self, other: Self) -> bool`. +- `for_each_field`: An operation to be performed on each field. E.g. `|name| quote { (self.$name == other.$name) }`. +- `join_fields_with`: A separator to join each result of `for_each_field` with. + E.g. `quote { & }`. You can also use an empty `quote {}` for no separator. +- `body`: The result of the field operations are passed into this function for any final processing. + This is the place to insert any setup/teardown code the trait requires. If the trait doesn't require + any such code, you can return the body as-is: `|body| body`. + +Example deriving `Hash`: + +```rust title="derive_hash" showLineNumbers +comptime fn derive_hash(s: StructDefinition) -> Quoted { + let name = quote { Hash }; + let signature = quote { fn hash(_self: Self, _state: &mut H) where H: std::hash::Hasher }; + let for_each_field = |name| quote { _self.$name.hash(_state); }; + crate::meta::make_trait_impl(s, name, signature, for_each_field, quote {}, |fields| fields) +} +``` +> Source code: noir_stdlib/src/hash/mod.nr#L147-L154 + + +Example deriving `Ord`: + +```rust title="derive_ord" showLineNumbers +comptime fn derive_ord(s: StructDefinition) -> Quoted { + let signature = quote { fn cmp(_self: Self, _other: Self) -> std::cmp::Ordering }; + let for_each_field = |name| quote { + if result == std::cmp::Ordering::equal() { + result = _self.$name.cmp(_other.$name); + } + }; + let body = |fields| quote { + let mut result = std::cmp::Ordering::equal(); + $fields + result + }; + crate::meta::make_trait_impl(s, quote { Ord }, signature, for_each_field, quote {}, body) +} +``` +> Source code: noir_stdlib/src/cmp.nr#L181-L196 + diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/module.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/module.md new file mode 100644 index 00000000000..efd3e61e125 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/module.md @@ -0,0 +1,82 @@ +--- +title: Module +--- + +`std::meta::module` contains methods on the built-in `Module` type which represents a module in the source program. +Note that this type represents a module generally, it isn't limited to only `mod my_submodule { ... }` +declarations in the source program. + +## Methods + +### add_item + +```rust title="add_item" showLineNumbers +comptime fn add_item(self, item: Quoted) {} +``` +> Source code: noir_stdlib/src/meta/module.nr#L3-L5 + + +Adds a top-level item (a function, a struct, a global, etc.) to the module. +Adding multiple items in one go is also valid if the `Quoted` value has multiple items in it. +Note that the items are type-checked as if they are inside the module they are being added to. + +### functions + +```rust title="functions" showLineNumbers +comptime fn functions(self) -> [FunctionDefinition] {} +``` +> Source code: noir_stdlib/src/meta/module.nr#L18-L20 + + +Returns each function defined in the module. + +### has_named_attribute + +```rust title="has_named_attribute" showLineNumbers +comptime fn has_named_attribute(self, name: str) -> bool {} +``` +> Source code: noir_stdlib/src/meta/module.nr#L8-L10 + + +Returns true if this module has a custom attribute with the given name. + +### is_contract + +```rust title="is_contract" showLineNumbers +comptime fn is_contract(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/module.nr#L13-L15 + + +`true` if this module is a contract module (was declared via `contract foo { ... }`). + +### name + +```rust title="name" showLineNumbers +comptime fn name(self) -> Quoted {} +``` +> Source code: noir_stdlib/src/meta/module.nr#L28-L30 + + +Returns the name of the module. + +### structs + +```rust title="structs" showLineNumbers +comptime fn structs(self) -> [StructDefinition] {} +``` +> Source code: noir_stdlib/src/meta/module.nr#L23-L25 + + +Returns each struct defined in the module. + +## Trait Implementations + +```rust +impl Eq for Module +impl Hash for Module +``` + +Note that each module is assigned a unique ID internally and this is what is used for +equality and hashing. So even modules with identical names and contents may not +be equal in this sense if they were originally different items in the source program. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/op.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/op.md new file mode 100644 index 00000000000..18d1f0768fd --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/op.md @@ -0,0 +1,244 @@ +--- +title: UnaryOp and BinaryOp +--- + +`std::meta::op` contains the `UnaryOp` and `BinaryOp` types as well as methods on them. +These types are used to represent a unary or binary operator respectively in Noir source code. + +## Types + +### UnaryOp + +Represents a unary operator. One of `-`, `!`, `&mut`, or `*`. + +### Methods + +#### is_minus + +```rust title="is_minus" showLineNumbers +pub fn is_minus(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L7-L9 + + +Returns `true` if this operator is `-`. + +#### is_not + +```rust title="is_not" showLineNumbers +pub fn is_not(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L13-L15 + + +`true` if this operator is `!` + +#### is_mutable_reference + +```rust title="is_mutable_reference" showLineNumbers +pub fn is_mutable_reference(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L19-L21 + + +`true` if this operator is `&mut` + +#### is_dereference + +```rust title="is_dereference" showLineNumbers +pub fn is_dereference(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L25-L27 + + +`true` if this operator is `*` + +#### quoted + +```rust title="unary_quoted" showLineNumbers +pub comptime fn quoted(self) -> Quoted { +``` +> Source code: noir_stdlib/src/meta/op.nr#L31-L33 + + +Returns this operator as a `Quoted` value. + +### Trait Implementations + +```rust +impl Eq for UnaryOp +impl Hash for UnaryOp +``` + +### BinaryOp + +Represents a binary operator. One of `+`, `-`, `*`, `/`, `%`, `==`, `!=`, `<`, `<=`, `>`, `>=`, `&`, `|`, `^`, `>>`, or `<<`. + +### Methods + +#### is_add + +```rust title="is_add" showLineNumbers +pub fn is_add(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L55-L57 + + +`true` if this operator is `+` + +#### is_subtract + +```rust title="is_subtract" showLineNumbers +pub fn is_subtract(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L61-L63 + + +`true` if this operator is `-` + +#### is_multiply + +```rust title="is_multiply" showLineNumbers +pub fn is_multiply(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L67-L69 + + +`true` if this operator is `*` + +#### is_divide + +```rust title="is_divide" showLineNumbers +pub fn is_divide(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L73-L75 + + +`true` if this operator is `/` + +#### is_modulo + +```rust title="is_modulo" showLineNumbers +pub fn is_modulo(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L145-L147 + + +`true` if this operator is `%` + +#### is_equal + +```rust title="is_equal" showLineNumbers +pub fn is_equal(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L79-L81 + + +`true` if this operator is `==` + +#### is_not_equal + +```rust title="is_not_equal" showLineNumbers +pub fn is_not_equal(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L85-L87 + + +`true` if this operator is `!=` + +#### is_less_than + +```rust title="is_less_than" showLineNumbers +pub fn is_less_than(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L91-L93 + + +`true` if this operator is `<` + +#### is_less_than_or_equal + +```rust title="is_less_than_or_equal" showLineNumbers +pub fn is_less_than_or_equal(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L97-L99 + + +`true` if this operator is `<=` + +#### is_greater_than + +```rust title="is_greater_than" showLineNumbers +pub fn is_greater_than(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L103-L105 + + +`true` if this operator is `>` + +#### is_greater_than_or_equal + +```rust title="is_greater_than_or_equal" showLineNumbers +pub fn is_greater_than_or_equal(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L109-L111 + + +`true` if this operator is `>=` + +#### is_and + +```rust title="is_and" showLineNumbers +pub fn is_and(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L115-L117 + + +`true` if this operator is `&` + +#### is_or + +```rust title="is_or" showLineNumbers +pub fn is_or(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L121-L123 + + +`true` if this operator is `|` + +#### is_shift_right + +```rust title="is_shift_right" showLineNumbers +pub fn is_shift_right(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L133-L135 + + +`true` if this operator is `>>` + +#### is_shift_left + +```rust title="is_shift_right" showLineNumbers +pub fn is_shift_right(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L133-L135 + + +`true` if this operator is `<<` + +#### quoted + +```rust title="binary_quoted" showLineNumbers +pub comptime fn quoted(self) -> Quoted { +``` +> Source code: noir_stdlib/src/meta/op.nr#L151-L153 + + +Returns this operator as a `Quoted` value. + +### Trait Implementations + +```rust +impl Eq for BinaryOp +impl Hash for BinaryOp +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/quoted.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/quoted.md new file mode 100644 index 00000000000..8fc188b25da --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/quoted.md @@ -0,0 +1,138 @@ +--- +title: Quoted +--- + +`std::meta::quoted` contains methods on the built-in `Quoted` type which represents +quoted token streams and is the result of the `quote { ... }` expression. + +## Methods + +### as_expr + +```rust title="as_expr" showLineNumbers +comptime fn as_expr(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/quoted.nr#L6-L8 + + +Parses the quoted token stream as an expression. Returns `Option::none()` if +the expression failed to parse. + +Example: + +```rust title="as_expr_example" showLineNumbers +#[test] + fn test_expr_as_function_call() { + comptime + { + let expr = quote { foo(42) }.as_expr().unwrap(); + let (_function, args) = expr.as_function_call().unwrap(); + assert_eq(args.len(), 1); + assert_eq(args[0].as_integer().unwrap(), (42, false)); + } + } +``` +> Source code: test_programs/noir_test_success/comptime_expr/src/main.nr#L331-L342 + + +### as_module + +```rust title="as_module" showLineNumbers +comptime fn as_module(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/quoted.nr#L11-L13 + + +Interprets this token stream as a module path leading to the name of a module. +Returns `Option::none()` if the module isn't found or this token stream cannot be parsed as a path. + +Example: + +```rust title="as_module_example" showLineNumbers +mod baz { + mod qux {} +} + +#[test] +fn as_module_test() { + comptime + { + let my_mod = quote { baz::qux }.as_module().unwrap(); + assert_eq(my_mod.name(), quote { qux }); + } +} +``` +> Source code: test_programs/compile_success_empty/comptime_module/src/main.nr#L102-L115 + + +### as_trait_constraint + +```rust title="as_trait_constraint" showLineNumbers +comptime fn as_trait_constraint(self) -> TraitConstraint {} +``` +> Source code: noir_stdlib/src/meta/quoted.nr#L16-L18 + + +Interprets this token stream as a trait constraint (without an object type). +Note that this function panics instead of returning `Option::none()` if the token +stream does not parse and resolve to a valid trait constraint. + +Example: + +```rust title="implements_example" showLineNumbers +fn function_with_where(_x: T) where T: SomeTrait { + comptime + { + let t = quote { T }.as_type(); + let some_trait_i32 = quote { SomeTrait }.as_trait_constraint(); + assert(t.implements(some_trait_i32)); + + assert(t.get_trait_impl(some_trait_i32).is_none()); + } +} +``` +> Source code: test_programs/compile_success_empty/comptime_type/src/main.nr#L154-L165 + + +### as_type + +```rust title="as_type" showLineNumbers +comptime fn as_type(self) -> Type {} +``` +> Source code: noir_stdlib/src/meta/quoted.nr#L21-L23 + + +Interprets this token stream as a resolved type. Panics if the token +stream doesn't parse to a type or if the type isn't a valid type in scope. + +```rust title="implements_example" showLineNumbers +fn function_with_where(_x: T) where T: SomeTrait { + comptime + { + let t = quote { T }.as_type(); + let some_trait_i32 = quote { SomeTrait }.as_trait_constraint(); + assert(t.implements(some_trait_i32)); + + assert(t.get_trait_impl(some_trait_i32).is_none()); + } +} +``` +> Source code: test_programs/compile_success_empty/comptime_type/src/main.nr#L154-L165 + + +### tokens + +```rust title="tokens" showLineNumbers +comptime fn tokens(self) -> [Quoted] {} +``` +> Source code: noir_stdlib/src/meta/quoted.nr#L26-L28 + + +Returns a slice of the individual tokens that form this token stream. + +## Trait Implementations + +```rust +impl Eq for Quoted +impl Hash for Quoted +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/struct_def.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/struct_def.md new file mode 100644 index 00000000000..212c636d12a --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/struct_def.md @@ -0,0 +1,177 @@ +--- +title: StructDefinition +--- + +`std::meta::struct_def` contains methods on the built-in `StructDefinition` type. +This type corresponds to `struct Name { field1: Type1, ... }` items in the source program. + +## Methods + +### add_attribute + +```rust title="add_attribute" showLineNumbers +comptime fn add_attribute(self, attribute: str) {} +``` +> Source code: noir_stdlib/src/meta/struct_def.nr#L3-L5 + + +Adds an attribute to the struct. + +### add_generic + +```rust title="add_generic" showLineNumbers +comptime fn add_generic(self, generic_name: str) -> Type {} +``` +> Source code: noir_stdlib/src/meta/struct_def.nr#L8-L10 + + +Adds an generic to the struct. Returns the new generic type. +Errors if the given generic name isn't a single identifier or if +the struct already has a generic with the same name. + +This method should be used carefully, if there is existing code referring +to the struct type it may be checked before this function is called and +see the struct with the original number of generics. This method should +thus be preferred to use on code generated from other macros and structs +that are not used in function signatures. + +Example: + +```rust title="add-generic-example" showLineNumbers +comptime fn add_generic(s: StructDefinition) { + assert_eq(s.generics().len(), 0); + let new_generic = s.add_generic("T"); + + let generics = s.generics(); + assert_eq(generics.len(), 1); + assert_eq(generics[0], new_generic); + } +``` +> Source code: test_programs/compile_success_empty/comptime_struct_definition/src/main.nr#L38-L47 + + +### as_type + +```rust title="as_type" showLineNumbers +comptime fn as_type(self) -> Type {} +``` +> Source code: noir_stdlib/src/meta/struct_def.nr#L15-L17 + + +Returns this struct as a type in the source program. If this struct has +any generics, the generics are also included as-is. + +### generics + +```rust title="generics" showLineNumbers +comptime fn generics(self) -> [Type] {} +``` +> Source code: noir_stdlib/src/meta/struct_def.nr#L26-L28 + + +Returns each generic on this struct. + +Example: + +``` +#[example] +struct Foo { + bar: [T; 2], + baz: Baz, +} + +comptime fn example(foo: StructDefinition) { + assert_eq(foo.generics().len(), 2); + + // Fails because `T` isn't in scope + // let t = quote { T }.as_type(); + // assert_eq(foo.generics()[0], t); +} +``` + +### fields + +```rust title="fields" showLineNumbers +comptime fn fields(self) -> [(Quoted, Type)] {} +``` +> Source code: noir_stdlib/src/meta/struct_def.nr#L33-L35 + + +Returns each field of this struct as a pair of (field name, field type). + +### has_named_attribute + +```rust title="has_named_attribute" showLineNumbers +comptime fn has_named_attribute(self, name: str) -> bool {} +``` +> Source code: noir_stdlib/src/meta/struct_def.nr#L20-L22 + + +Returns true if this struct has a custom attribute with the given name. + +### module + +```rust title="module" showLineNumbers +comptime fn module(self) -> Module {} +``` +> Source code: noir_stdlib/src/meta/struct_def.nr#L38-L40 + + +Returns the module where the struct is defined. + +### name + +```rust title="name" showLineNumbers +comptime fn name(self) -> Quoted {} +``` +> Source code: noir_stdlib/src/meta/struct_def.nr#L43-L45 + + +Returns the name of this struct + +Note that the returned quoted value will be just the struct name, it will +not be the full path to the struct, nor will it include any generics. + +### set_fields + +```rust title="set_fields" showLineNumbers +comptime fn set_fields(self, new_fields: [(Quoted, Type)]) {} +``` +> Source code: noir_stdlib/src/meta/struct_def.nr#L52-L54 + + +Sets the fields of this struct to the given fields list where each element +is a pair of the field's name and the field's type. Expects each field name +to be a single identifier. Note that this will override any previous fields +on this struct. If those should be preserved, use `.fields()` to retrieve the +current fields on the struct type and append the new fields from there. + +Example: + +```rust +// Change this struct to: +// struct Foo { +// a: u32, +// b: i8, +// } +#[mangle_fields] +struct Foo { x: Field } + +comptime fn mangle_fields(s: StructDefinition) { + s.set_fields(&[ + (quote { a }, quote { u32 }.as_type()), + (quote { b }, quote { i8 }.as_type()), + ]); +} +``` + +## Trait Implementations + +```rust +impl Eq for StructDefinition +impl Hash for StructDefinition +``` + +Note that each struct is assigned a unique ID internally and this is what is used for +equality and hashing. So even structs with identical generics and fields may not +be equal in this sense if they were originally different items in the source program. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/trait_constraint.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/trait_constraint.md new file mode 100644 index 00000000000..3106f732b5a --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/trait_constraint.md @@ -0,0 +1,17 @@ +--- +title: TraitConstraint +--- + +`std::meta::trait_constraint` contains methods on the built-in `TraitConstraint` type which represents +a trait constraint that can be used to search for a trait implementation. This is similar +syntactically to just the trait itself, but can also contain generic arguments. E.g. `Eq`, `Default`, +`BuildHasher`. + +This type currently has no public methods but it can be used alongside `Type` in `implements` or `get_trait_impl`. + +## Trait Implementations + +```rust +impl Eq for TraitConstraint +impl Hash for TraitConstraint +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/trait_def.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/trait_def.md new file mode 100644 index 00000000000..a1f363d46ff --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/trait_def.md @@ -0,0 +1,26 @@ +--- +title: TraitDefinition +--- + +`std::meta::trait_def` contains methods on the built-in `TraitDefinition` type. This type +represents trait definitions such as `trait Foo { .. }` at the top-level of a program. + +## Methods + +### as_trait_constraint + +```rust title="as_trait_constraint" showLineNumbers +comptime fn as_trait_constraint(_self: Self) -> TraitConstraint {} +``` +> Source code: noir_stdlib/src/meta/trait_def.nr#L6-L8 + + +Converts this trait into a trait constraint. If there are any generics on this +trait, they will be kept as-is without instantiating or replacing them. + +## Trait Implementations + +```rust +impl Eq for TraitDefinition +impl Hash for TraitDefinition +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/trait_impl.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/trait_impl.md new file mode 100644 index 00000000000..66d31ed2560 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/trait_impl.md @@ -0,0 +1,60 @@ +--- +title: TraitImpl +--- + +`std::meta::trait_impl` contains methods on the built-in `TraitImpl` type which represents a trait +implementation such as `impl Foo for Bar { ... }`. + +## Methods + +### trait_generic_args + +```rust title="trait_generic_args" showLineNumbers +comptime fn trait_generic_args(self) -> [Type] {} +``` +> Source code: noir_stdlib/src/meta/trait_impl.nr#L3-L5 + + +Returns any generic arguments on the trait of this trait implementation, if any. + +```rs +impl Foo for Bar { ... } + +comptime { + let bar_type = quote { Bar }.as_type(); + let foo = quote { Foo }.as_trait_constraint(); + + let my_impl: TraitImpl = bar_type.get_trait_impl(foo).unwrap(); + + let generics = my_impl.trait_generic_args(); + assert_eq(generics.len(), 2); + + assert_eq(generics[0], quote { i32 }.as_type()); + assert_eq(generics[1], quote { Field }.as_type()); +} +``` + +### methods + +```rust title="methods" showLineNumbers +comptime fn methods(self) -> [FunctionDefinition] {} +``` +> Source code: noir_stdlib/src/meta/trait_impl.nr#L8-L10 + + +Returns each method in this trait impl. + +Example: + +```rs +comptime { + let i32_type = quote { i32 }.as_type(); + let eq = quote { Eq }.as_trait_constraint(); + + let impl_eq_for_i32: TraitImpl = i32_type.get_trait_impl(eq).unwrap(); + let methods = impl_eq_for_i32.methods(); + + assert_eq(methods.len(), 1); + assert_eq(methods[0].name(), quote { eq }); +} +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/typ.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/typ.md new file mode 100644 index 00000000000..6c9f4b8d087 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/typ.md @@ -0,0 +1,239 @@ +--- +title: Type +--- + +`std::meta::typ` contains methods on the built-in `Type` type used for representing +a type in the source program. + +## Functions + +```rust title="fresh_type_variable" showLineNumbers +pub comptime fn fresh_type_variable() -> Type {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L5-L7 + + +Creates and returns an unbound type variable. This is a special kind of type internal +to type checking which will type check with any other type. When it is type checked +against another type it will also be set to that type. For example, if `a` is a type +variable and we have the type equality `(a, i32) = (u8, i32)`, the compiler will set +`a` equal to `u8`. + +Unbound type variables will often be rendered as `_` while printing them. Bound type +variables will appear as the type they are bound to. + +This can be used in conjunction with functions which internally perform type checks +such as `Type::implements` or `Type::get_trait_impl` to potentially grab some of the types used. + +Note that calling `Type::implements` or `Type::get_trait_impl` on a type variable will always +fail. + +Example: + +```rust title="serialize-setup" showLineNumbers +trait Serialize {} + +impl Serialize<1> for Field {} + +impl Serialize for [T; N] + where T: Serialize {} + +impl Serialize for (T, U) + where T: Serialize, U: Serialize {} +``` +> Source code: test_programs/compile_success_empty/comptime_type/src/main.nr#L20-L30 + +```rust title="fresh-type-variable-example" showLineNumbers +let typevar1 = std::meta::typ::fresh_type_variable(); + let constraint = quote { Serialize<$typevar1> }.as_trait_constraint(); + let field_type = quote { Field }.as_type(); + + // Search for a trait impl (binding typevar1 to 1 when the impl is found): + assert(field_type.implements(constraint)); + + // typevar1 should be bound to the "1" generic now: + assert_eq(typevar1.as_constant().unwrap(), 1); + + // If we want to do the same with a different type, we need to + // create a new type variable now that `typevar1` is bound + let typevar2 = std::meta::typ::fresh_type_variable(); + let constraint = quote { Serialize<$typevar2> }.as_trait_constraint(); + let array_type = quote { [(Field, Field); 5] }.as_type(); + assert(array_type.implements(constraint)); + + // Now typevar2 should be bound to the serialized pair size 2 times the array length 5 + assert_eq(typevar2.as_constant().unwrap(), 10); +``` +> Source code: test_programs/compile_success_empty/comptime_type/src/main.nr#L130-L150 + + +## Methods + +### as_array + +```rust title="as_array" showLineNumbers +comptime fn as_array(self) -> Option<(Type, Type)> {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L11-L13 + + +If this type is an array, return a pair of (element type, size type). + +Example: + +```rust +comptime { + let array_type = quote { [Field; 3] }.as_type(); + let (field_type, three_type) = array_type.as_array().unwrap(); + + assert(field_type.is_field()); + assert_eq(three_type.as_constant().unwrap(), 3); +} +``` + +### as_constant + +```rust title="as_constant" showLineNumbers +comptime fn as_constant(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L16-L18 + + +If this type is a constant integer (such as the `3` in the array type `[Field; 3]`), +return the numeric constant. + +### as_integer + +```rust title="as_integer" showLineNumbers +comptime fn as_integer(self) -> Option<(bool, u8)> {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L21-L23 + + +If this is an integer type, return a boolean which is `true` +if the type is signed, as well as the number of bits of this integer type. + +### as_slice + +```rust title="as_slice" showLineNumbers +comptime fn as_slice(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L26-L28 + + +If this is a slice type, return the element type of the slice. + +### as_str + +```rust title="as_str" showLineNumbers +comptime fn as_str(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L31-L33 + + +If this is a `str` type, returns the length `N` as a type. + +### as_struct + +```rust title="as_struct" showLineNumbers +comptime fn as_struct(self) -> Option<(StructDefinition, [Type])> {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L36-L38 + + +If this is a struct type, returns the struct in addition to +any generic arguments on this type. + +### as_tuple + +```rust title="as_tuple" showLineNumbers +comptime fn as_tuple(self) -> Option<[Type]> {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L41-L43 + + +If this is a tuple type, returns each element type of the tuple. + +### get_trait_impl + +```rust title="get_trait_impl" showLineNumbers +comptime fn get_trait_impl(self, constraint: TraitConstraint) -> Option {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L46-L48 + + +Retrieves the trait implementation that implements the given +trait constraint for this type. If the trait constraint is not +found, `None` is returned. Note that since the concrete trait implementation +for a trait constraint specified from a `where` clause is unknown, +this function will return `None` in these cases. If you only want to know +whether a type implements a trait, use `implements` instead. + +Example: + +```rust +comptime { + let field_type = quote { Field }.as_type(); + let default = quote { Default }.as_trait_constraint(); + + let the_impl: TraitImpl = field_type.get_trait_impl(default).unwrap(); + assert(the_impl.methods().len(), 1); +} +``` + +### implements + +```rust title="implements" showLineNumbers +comptime fn implements(self, constraint: TraitConstraint) -> bool {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L51-L53 + + +`true` if this type implements the given trait. Note that unlike +`get_trait_impl` this will also return true for any `where` constraints +in scope. + +Example: + +```rust +fn foo() where T: Default { + comptime { + let field_type = quote { Field }.as_type(); + let default = quote { Default }.as_trait_constraint(); + assert(field_type.implements(default)); + + let t = quote { T }.as_type(); + assert(t.implements(default)); + } +} +``` + +### is_bool + +```rust title="is_bool" showLineNumbers +comptime fn is_bool(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L56-L58 + + +`true` if this type is `bool`. + +### is_field + +```rust title="is_field" showLineNumbers +comptime fn is_field(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L61-L63 + + +`true` if this type is `Field`. + +## Trait Implementations + +```rust +impl Eq for Type +impl Hash for Type +``` +Note that this is syntactic equality, this is not the same as whether two types will type check +to be the same type. Unless type inference or generics are being used however, users should not +typically have to worry about this distinction unless `std::meta::typ::fresh_type_variable` is used. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/typed_expr.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/typed_expr.md new file mode 100644 index 00000000000..1ee71c8b064 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/typed_expr.md @@ -0,0 +1,27 @@ +--- +title: TypedExpr +--- + +`std::meta::typed_expr` contains methods on the built-in `TypedExpr` type for resolved and type-checked expressions. + +## Methods + +### get_type + +```rust title="as_function_definition" showLineNumbers +comptime fn as_function_definition(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/typed_expr.nr#L7-L9 + + +If this expression refers to a function definitions, returns it. Otherwise returns `Option::none()`. + +### get_type + +```rust title="get_type" showLineNumbers +comptime fn get_type(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/typed_expr.nr#L13-L15 + + +Returns the type of the expression, or `Option::none()` if there were errors when the expression was previously resolved. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/unresolved_type.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/unresolved_type.md new file mode 100644 index 00000000000..d6f2b1494bb --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/meta/unresolved_type.md @@ -0,0 +1,17 @@ +--- +title: UnresolvedType +--- + +`std::meta::unresolved_type` contains methods on the built-in `UnresolvedType` type for the syntax of types. + +## Methods + +### is_field + +```rust title="is_field" showLineNumbers +comptime fn is_field(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/unresolved_type.nr#L3-L5 + + +Returns true if this type refers to the Field type. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/options.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/options.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/options.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/options.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/recursion.md similarity index 93% rename from noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/recursion.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/recursion.md index 8cfb37fc52d..7f4dcebf084 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/recursion.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/recursion.md @@ -49,16 +49,16 @@ fn main( proof_b : [Field; 93], ) { std::verify_proof( - verification_key.as_slice(), - proof.as_slice(), - public_inputs.as_slice(), + verification_key, + proof, + public_inputs, key_hash ); std::verify_proof( - verification_key.as_slice(), - proof_b.as_slice(), - public_inputs.as_slice(), + verification_key, + proof_b, + public_inputs, key_hash ); } diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/traits.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/traits.md similarity index 71% rename from noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/traits.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/traits.md index a14312d2792..0629623a15a 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/traits.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/traits.md @@ -13,7 +13,7 @@ trait Default { fn default() -> Self; } ``` -> Source code: noir_stdlib/src/default.nr#L1-L5 +> Source code: noir_stdlib/src/default.nr#L4-L8 Constructs a default value of a type. @@ -57,6 +57,7 @@ For primitive integer types, the return value of `default` is `0`. Container types such as arrays are filled with default values of their element type, except slices whose length is unknown and thus defaulted to zero. +--- ## `std::convert` @@ -76,32 +77,96 @@ The Noir standard library provides a number of implementations of `From` between ```rust title="from-impls" showLineNumbers // Unsigned integers -impl From for u32 { fn from(value: u8) -> u32 { value as u32 } } +impl From for u32 { + fn from(value: u8) -> u32 { + value as u32 + } +} -impl From for u64 { fn from(value: u8) -> u64 { value as u64 } } -impl From for u64 { fn from(value: u32) -> u64 { value as u64 } } +impl From for u64 { + fn from(value: u8) -> u64 { + value as u64 + } +} +impl From for u64 { + fn from(value: u32) -> u64 { + value as u64 + } +} -impl From for Field { fn from(value: u8) -> Field { value as Field } } -impl From for Field { fn from(value: u32) -> Field { value as Field } } -impl From for Field { fn from(value: u64) -> Field { value as Field } } +impl From for Field { + fn from(value: u8) -> Field { + value as Field + } +} +impl From for Field { + fn from(value: u32) -> Field { + value as Field + } +} +impl From for Field { + fn from(value: u64) -> Field { + value as Field + } +} // Signed integers -impl From for i32 { fn from(value: i8) -> i32 { value as i32 } } +impl From for i32 { + fn from(value: i8) -> i32 { + value as i32 + } +} -impl From for i64 { fn from(value: i8) -> i64 { value as i64 } } -impl From for i64 { fn from(value: i32) -> i64 { value as i64 } } +impl From for i64 { + fn from(value: i8) -> i64 { + value as i64 + } +} +impl From for i64 { + fn from(value: i32) -> i64 { + value as i64 + } +} // Booleans -impl From for u8 { fn from(value: bool) -> u8 { value as u8 } } -impl From for u32 { fn from(value: bool) -> u32 { value as u32 } } -impl From for u64 { fn from(value: bool) -> u64 { value as u64 } } -impl From for i8 { fn from(value: bool) -> i8 { value as i8 } } -impl From for i32 { fn from(value: bool) -> i32 { value as i32 } } -impl From for i64 { fn from(value: bool) -> i64 { value as i64 } } -impl From for Field { fn from(value: bool) -> Field { value as Field } } +impl From for u8 { + fn from(value: bool) -> u8 { + value as u8 + } +} +impl From for u32 { + fn from(value: bool) -> u32 { + value as u32 + } +} +impl From for u64 { + fn from(value: bool) -> u64 { + value as u64 + } +} +impl From for i8 { + fn from(value: bool) -> i8 { + value as i8 + } +} +impl From for i32 { + fn from(value: bool) -> i32 { + value as i32 + } +} +impl From for i64 { + fn from(value: bool) -> i64 { + value as i64 + } +} +impl From for Field { + fn from(value: bool) -> Field { + value as Field + } +} ``` -> Source code: noir_stdlib/src/convert.nr#L25-L52 +> Source code: noir_stdlib/src/convert.nr#L25-L116 #### When to implement `From` @@ -128,9 +193,9 @@ trait Into { } impl Into for U where T: From { - fn into(self) -> T { - T::from(self) - } + fn into(self) -> T { + T::from(self) + } } ``` > Source code: noir_stdlib/src/convert.nr#L13-L23 @@ -138,6 +203,7 @@ impl Into for U where T: From { `Into` is most useful when passing function arguments where the types don't quite match up with what the function expects. In this case, the compiler has enough type information to perform the necessary conversion by just appending `.into()` onto the arguments in question. +--- ## `std::cmp` @@ -148,7 +214,7 @@ trait Eq { fn eq(self, other: Self) -> bool; } ``` -> Source code: noir_stdlib/src/cmp.nr#L1-L5 +> Source code: noir_stdlib/src/cmp.nr#L4-L8 Returns `true` if `self` is equal to `other`. Implementing this trait on a type @@ -197,7 +263,7 @@ trait Ord { fn cmp(self, other: Self) -> Ordering; } ``` -> Source code: noir_stdlib/src/cmp.nr#L102-L106 +> Source code: noir_stdlib/src/cmp.nr#L175-L179 `a.cmp(b)` compares two values returning `Ordering::less()` if `a < b`, @@ -243,6 +309,8 @@ impl Ord for (A, B, C, D, E) where A: Ord, B: Ord, C: Ord, D: Ord, E: Ord { .. } ``` +--- + ## `std::ops` ### `std::ops::Add`, `std::ops::Sub`, `std::ops::Mul`, and `std::ops::Div` @@ -263,21 +331,21 @@ trait Sub { fn sub(self, other: Self) -> Self; } ``` -> Source code: noir_stdlib/src/ops/arith.nr#L19-L23 +> Source code: noir_stdlib/src/ops/arith.nr#L60-L64 ```rust title="mul-trait" showLineNumbers trait Mul { fn mul(self, other: Self) -> Self; } ``` -> Source code: noir_stdlib/src/ops/arith.nr#L37-L41 +> Source code: noir_stdlib/src/ops/arith.nr#L119-L123 ```rust title="div-trait" showLineNumbers trait Div { fn div(self, other: Self) -> Self; } ``` -> Source code: noir_stdlib/src/ops/arith.nr#L55-L59 +> Source code: noir_stdlib/src/ops/arith.nr#L178-L182 The implementations block below is given for the `Add` trait, but the same types that implement @@ -305,7 +373,7 @@ trait Rem{ fn rem(self, other: Self) -> Self; } ``` -> Source code: noir_stdlib/src/ops/arith.nr#L73-L77 +> Source code: noir_stdlib/src/ops/arith.nr#L237-L241 `Rem::rem(a, b)` is the remainder function returning the result of what is @@ -334,21 +402,41 @@ trait Neg { fn neg(self) -> Self; } ``` -> Source code: noir_stdlib/src/ops/arith.nr#L89-L93 +> Source code: noir_stdlib/src/ops/arith.nr#L290-L294 `Neg::neg` is equivalent to the unary negation operator `-`. Implementations: ```rust title="neg-trait-impls" showLineNumbers -impl Neg for Field { fn neg(self) -> Field { -self } } +impl Neg for Field { + fn neg(self) -> Field { + -self + } +} -impl Neg for i8 { fn neg(self) -> i8 { -self } } -impl Neg for i16 { fn neg(self) -> i16 { -self } } -impl Neg for i32 { fn neg(self) -> i32 { -self } } -impl Neg for i64 { fn neg(self) -> i64 { -self } } +impl Neg for i8 { + fn neg(self) -> i8 { + -self + } +} +impl Neg for i16 { + fn neg(self) -> i16 { + -self + } +} +impl Neg for i32 { + fn neg(self) -> i32 { + -self + } +} +impl Neg for i64 { + fn neg(self) -> i64 { + -self + } +} ``` -> Source code: noir_stdlib/src/ops/arith.nr#L95-L102 +> Source code: noir_stdlib/src/ops/arith.nr#L296-L323 ### `std::ops::Not` @@ -365,20 +453,60 @@ trait Not { Implementations: ```rust title="not-trait-impls" showLineNumbers -impl Not for bool { fn not(self) -> bool { !self } } - -impl Not for u64 { fn not(self) -> u64 { !self } } -impl Not for u32 { fn not(self) -> u32 { !self } } -impl Not for u16 { fn not(self) -> u16 { !self } } -impl Not for u8 { fn not(self) -> u8 { !self } } -impl Not for u1 { fn not(self) -> u1 { !self } } - -impl Not for i8 { fn not(self) -> i8 { !self } } -impl Not for i16 { fn not(self) -> i16 { !self } } -impl Not for i32 { fn not(self) -> i32 { !self } } -impl Not for i64 { fn not(self) -> i64 { !self } } +impl Not for bool { + fn not(self) -> bool { + !self + } +} + +impl Not for u64 { + fn not(self) -> u64 { + !self + } +} +impl Not for u32 { + fn not(self) -> u32 { + !self + } +} +impl Not for u16 { + fn not(self) -> u16 { + !self + } +} +impl Not for u8 { + fn not(self) -> u8 { + !self + } +} +impl Not for u1 { + fn not(self) -> u1 { + !self + } +} + +impl Not for i8 { + fn not(self) -> i8 { + !self + } +} +impl Not for i16 { + fn not(self) -> i16 { + !self + } +} +impl Not for i32 { + fn not(self) -> i32 { + !self + } +} +impl Not for i64 { + fn not(self) -> i64 { + !self + } +} ``` -> Source code: noir_stdlib/src/ops/bit.nr#L7-L20 +> Source code: noir_stdlib/src/ops/bit.nr#L7-L60 ### `std::ops::{ BitOr, BitAnd, BitXor }` @@ -388,21 +516,21 @@ trait BitOr { fn bitor(self, other: Self) -> Self; } ``` -> Source code: noir_stdlib/src/ops/bit.nr#L22-L26 +> Source code: noir_stdlib/src/ops/bit.nr#L62-L66 ```rust title="bitand-trait" showLineNumbers trait BitAnd { fn bitand(self, other: Self) -> Self; } ``` -> Source code: noir_stdlib/src/ops/bit.nr#L40-L44 +> Source code: noir_stdlib/src/ops/bit.nr#L121-L125 ```rust title="bitxor-trait" showLineNumbers trait BitXor { fn bitxor(self, other: Self) -> Self; } ``` -> Source code: noir_stdlib/src/ops/bit.nr#L58-L62 +> Source code: noir_stdlib/src/ops/bit.nr#L180-L184 Traits for the bitwise operations `|`, `&`, and `^`. @@ -435,14 +563,14 @@ trait Shl { fn shl(self, other: u8) -> Self; } ``` -> Source code: noir_stdlib/src/ops/bit.nr#L76-L80 +> Source code: noir_stdlib/src/ops/bit.nr#L239-L243 ```rust title="shr-trait" showLineNumbers trait Shr { fn shr(self, other: u8) -> Self; } ``` -> Source code: noir_stdlib/src/ops/bit.nr#L93-L97 +> Source code: noir_stdlib/src/ops/bit.nr#L292-L296 Traits for a bit shift left and bit shift right. @@ -462,3 +590,36 @@ impl Shl for u16 { fn shl(self, other: u16) -> u16 { self << other } } impl Shl for u32 { fn shl(self, other: u32) -> u32 { self << other } } impl Shl for u64 { fn shl(self, other: u64) -> u64 { self << other } } ``` + +--- + +## `std::append` + +### `std::append::Append` + +`Append` can abstract over types that can be appended to - usually container types: + +```rust title="append-trait" showLineNumbers +trait Append { + fn empty() -> Self; + fn append(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/append.nr#L9-L14 + + +`Append` requires two methods: + +- `empty`: Constructs an empty value of `Self`. +- `append`: Append two values together, returning the result. + +Additionally, it is expected that for any implementation: + +- `T::empty().append(x) == x` +- `x.append(T::empty()) == x` + +Implementations: +```rust +impl Append for [T] +impl Append for Quoted +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/zeroed.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/zeroed.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/zeroed.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/noir/standard_library/zeroed.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/backend_barretenberg/.nojekyll similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/.nojekyll rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/backend_barretenberg/.nojekyll diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md similarity index 83% rename from noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md index b18c1926b93..42f065f4a4e 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md @@ -2,6 +2,7 @@ ## Implements +- [`Backend`](../index.md#backend) - [`Backend`](../index.md#backend) ## Constructors @@ -23,6 +24,15 @@ new BarretenbergBackend(acirCircuit, options): BarretenbergBackend [`BarretenbergBackend`](BarretenbergBackend.md) +## Properties + +| Property | Type | Description | +| :------ | :------ | :------ | +| `acirComposer` | `any` | - | +| `acirUncompressedBytecode` | `Uint8Array` | - | +| `api` | `Barretenberg` | - | +| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | - | + ## Methods ### destroy() @@ -94,6 +104,18 @@ const artifacts = await backend.generateRecursiveProofArtifacts(proof, numOfPubl *** +### getVerificationKey() + +```ts +getVerificationKey(): Promise +``` + +#### Returns + +`Promise`\<`Uint8Array`\> + +*** + ### verifyProof() ```ts diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/backend_barretenberg/classes/UltraHonkBackend.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/backend_barretenberg/classes/UltraHonkBackend.md new file mode 100644 index 00000000000..be1cd9ad465 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/backend_barretenberg/classes/UltraHonkBackend.md @@ -0,0 +1,116 @@ +# UltraHonkBackend + +## Implements + +- [`Backend`](../index.md#backend) +- [`Backend`](../index.md#backend) + +## Constructors + +### new UltraHonkBackend(acirCircuit, options) + +```ts +new UltraHonkBackend(acirCircuit, options): UltraHonkBackend +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `acirCircuit` | `CompiledCircuit` | +| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | + +#### Returns + +[`UltraHonkBackend`](UltraHonkBackend.md) + +## Properties + +| Property | Type | Description | +| :------ | :------ | :------ | +| `acirUncompressedBytecode` | `Uint8Array` | - | +| `api` | `Barretenberg` | - | +| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | - | + +## Methods + +### destroy() + +```ts +destroy(): Promise +``` + +#### Returns + +`Promise`\<`void`\> + +*** + +### generateProof() + +```ts +generateProof(decompressedWitness): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `decompressedWitness` | `Uint8Array` | + +#### Returns + +`Promise`\<`ProofData`\> + +*** + +### generateRecursiveProofArtifacts() + +```ts +generateRecursiveProofArtifacts(_proofData, _numOfPublicInputs): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `_proofData` | `ProofData` | +| `_numOfPublicInputs` | `number` | + +#### Returns + +`Promise`\<`object`\> + +*** + +### getVerificationKey() + +```ts +getVerificationKey(): Promise +``` + +#### Returns + +`Promise`\<`Uint8Array`\> + +*** + +### verifyProof() + +```ts +verifyProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | `ProofData` | + +#### Returns + +`Promise`\<`boolean`\> + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/backend_barretenberg/classes/UltraHonkVerifier.md similarity index 80% rename from noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/backend_barretenberg/classes/UltraHonkVerifier.md index 500276ea748..aee9460153f 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/backend_barretenberg/classes/UltraHonkVerifier.md @@ -1,11 +1,11 @@ -# BarretenbergVerifier +# UltraHonkVerifier ## Constructors -### new BarretenbergVerifier(options) +### new UltraHonkVerifier(options) ```ts -new BarretenbergVerifier(options): BarretenbergVerifier +new UltraHonkVerifier(options): UltraHonkVerifier ``` #### Parameters @@ -16,7 +16,7 @@ new BarretenbergVerifier(options): BarretenbergVerifier #### Returns -[`BarretenbergVerifier`](BarretenbergVerifier.md) +[`UltraHonkVerifier`](UltraHonkVerifier.md) ## Methods diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/backend_barretenberg/index.md similarity index 85% rename from noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/index.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/backend_barretenberg/index.md index 14dfac681d4..4699e16dee6 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/index.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/backend_barretenberg/index.md @@ -8,6 +8,8 @@ | :------ | :------ | | [BarretenbergBackend](classes/BarretenbergBackend.md) | - | | [BarretenbergVerifier](classes/BarretenbergVerifier.md) | - | +| [UltraHonkBackend](classes/UltraHonkBackend.md) | - | +| [UltraHonkVerifier](classes/UltraHonkVerifier.md) | - | ### Type Aliases diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs new file mode 100644 index 00000000000..8ecf05c0163 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs @@ -0,0 +1,4 @@ +// @ts-check +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend","label":"BarretenbergBackend"},{"type":"doc","id":"reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier","label":"BarretenbergVerifier"},{"type":"doc","id":"reference/NoirJS/backend_barretenberg/classes/UltraHonkBackend","label":"UltraHonkBackend"},{"type":"doc","id":"reference/NoirJS/backend_barretenberg/classes/UltraHonkVerifier","label":"UltraHonkVerifier"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions","label":"BackendOptions"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_js/.nojekyll similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/.nojekyll rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_js/.nojekyll diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/classes/Noir.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_js/classes/Noir.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/classes/Noir.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_js/classes/Noir.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/functions/and.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_js/functions/and.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/functions/and.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_js/functions/and.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/functions/blake2s256.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_js/functions/blake2s256.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/functions/blake2s256.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_js/functions/blake2s256.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/functions/keccak256.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_js/functions/keccak256.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/functions/keccak256.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_js/functions/keccak256.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/functions/sha256.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_js/functions/sha256.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/functions/sha256.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_js/functions/sha256.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/functions/xor.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_js/functions/xor.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/functions/xor.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_js/functions/xor.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_js/index.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/index.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_js/index.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/type-aliases/ErrorWithPayload.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_js/type-aliases/ErrorWithPayload.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/type-aliases/ErrorWithPayload.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_js/type-aliases/ErrorWithPayload.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/type-aliases/ForeignCallHandler.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/type-aliases/ForeignCallHandler.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/type-aliases/ForeignCallInput.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/type-aliases/ForeignCallInput.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/type-aliases/ForeignCallOutput.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/type-aliases/ForeignCallOutput.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/type-aliases/WitnessMap.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/type-aliases/WitnessMap.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_wasm/.nojekyll similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/.nojekyll rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_wasm/.nojekyll diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_wasm/functions/compile.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_wasm/functions/compile.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_wasm/functions/compile.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_wasm/functions/compile.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_wasm/functions/compile_contract.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_wasm/functions/compile_contract.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_wasm/functions/compile_contract.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_wasm/functions/compile_contract.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_wasm/functions/createFileManager.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_wasm/functions/createFileManager.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_wasm/functions/createFileManager.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_wasm/functions/createFileManager.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.23.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_wasm/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_wasm/index.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_wasm/index.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_wasm/index.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/_category_.json similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.22.0/reference/_category_.json rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/_category_.json diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/debugger/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/debugger/_category_.json similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/debugger/_category_.json rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/debugger/_category_.json diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/debugger/debugger_known_limitations.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/debugger/debugger_known_limitations.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/debugger/debugger_known_limitations.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/debugger/debugger_known_limitations.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/debugger/debugger_repl.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/debugger/debugger_repl.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/debugger/debugger_repl.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/debugger/debugger_repl.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/debugger/debugger_vscode.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/debugger/debugger_vscode.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.28.0/reference/debugger/debugger_vscode.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/debugger/debugger_vscode.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/nargo_commands.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/nargo_commands.md similarity index 54% rename from noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/nargo_commands.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/nargo_commands.md index 218fcfb0c8c..b46ad4cda98 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/reference/nargo_commands.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/nargo_commands.md @@ -26,21 +26,13 @@ This document contains the help content for the `nargo` command-line program. **Command Overview:** * [`nargo`↴](#nargo) -* [`nargo backend`↴](#nargo-backend) -* [`nargo backend current`↴](#nargo-backend-current) -* [`nargo backend ls`↴](#nargo-backend-ls) -* [`nargo backend use`↴](#nargo-backend-use) -* [`nargo backend install`↴](#nargo-backend-install) -* [`nargo backend uninstall`↴](#nargo-backend-uninstall) * [`nargo check`↴](#nargo-check) * [`nargo fmt`↴](#nargo-fmt) -* [`nargo codegen-verifier`↴](#nargo-codegen-verifier) * [`nargo compile`↴](#nargo-compile) * [`nargo new`↴](#nargo-new) * [`nargo init`↴](#nargo-init) * [`nargo execute`↴](#nargo-execute) -* [`nargo prove`↴](#nargo-prove) -* [`nargo verify`↴](#nargo-verify) +* [`nargo debug`↴](#nargo-debug) * [`nargo test`↴](#nargo-test) * [`nargo info`↴](#nargo-info) * [`nargo lsp`↴](#nargo-lsp) @@ -53,16 +45,13 @@ Noir's package manager ###### **Subcommands:** -* `backend` — Install and select custom backends used to generate and verify proofs * `check` — Checks the constraint system for errors * `fmt` — Format the Noir files in a workspace -* `codegen-verifier` — Generates a Solidity verifier smart contract for the program * `compile` — Compile the program and its secret execution trace into ACIR format * `new` — Create a Noir project in a new directory * `init` — Create a Noir project in the current directory * `execute` — Executes a circuit to calculate its return value -* `prove` — Create proof for this program. The proof is returned as a hex encoded string -* `verify` — Given a proof and a program, verify whether the proof is valid +* `debug` — Executes a circuit in debug mode * `test` — Run the tests for this program * `info` — Provides detailed information on each of a program's function (represented by a single circuit) * `lsp` — Starts the Noir LSP server @@ -72,75 +61,6 @@ Noir's package manager -## `nargo backend` - -Install and select custom backends used to generate and verify proofs - -**Usage:** `nargo backend ` - -###### **Subcommands:** - -* `current` — Prints the name of the currently active backend -* `ls` — Prints the list of currently installed backends -* `use` — Select the backend to use -* `install` — Install a new backend from a URL -* `uninstall` — Uninstalls a backend - - - -## `nargo backend current` - -Prints the name of the currently active backend - -**Usage:** `nargo backend current` - - - -## `nargo backend ls` - -Prints the list of currently installed backends - -**Usage:** `nargo backend ls` - - - -## `nargo backend use` - -Select the backend to use - -**Usage:** `nargo backend use ` - -###### **Arguments:** - -* `` - - - -## `nargo backend install` - -Install a new backend from a URL - -**Usage:** `nargo backend install ` - -###### **Arguments:** - -* `` — The name of the backend to install -* `` — The URL from which to download the backend - - - -## `nargo backend uninstall` - -Uninstalls a backend - -**Usage:** `nargo backend uninstall ` - -###### **Arguments:** - -* `` — The name of the backend to uninstall - - - ## `nargo check` Checks the constraint system for errors @@ -152,11 +72,16 @@ Checks the constraint system for errors * `--package ` — The name of the package to check * `--workspace` — Check all packages in the workspace * `--overwrite` — Force overwrite of existing files -* `--expression-width ` — Override the expression width requested by the backend +* `--expression-width ` — Specify the backend expression width that should be targeted +* `--bounded-codegen` — Generate ACIR with the target backend expression width. The default is to generate ACIR without a bound and split expressions after code generation. Activating this flag can sometimes provide optimizations for certain programs + + Default value: `false` * `--force` — Force a full recompilation * `--print-acir` — Display the ACIR for compiled circuit * `--deny-warnings` — Treat all warnings as errors * `--silence-warnings` — Suppress warnings +* `--debug-comptime-in-file ` — Enable printing results of comptime evaluation: provide a path suffix for the module to debug, e.g. "package_name/src/main.nr" +* `--skip-underconstrained-check` — Flag to turn off the compiler check for under constrained values. Warning: This can improve compilation speed but can also lead to correctness errors. This check should always be run on production code @@ -172,24 +97,6 @@ Format the Noir files in a workspace -## `nargo codegen-verifier` - -Generates a Solidity verifier smart contract for the program - -**Usage:** `nargo codegen-verifier [OPTIONS]` - -###### **Options:** - -* `--package ` — The name of the package to codegen -* `--workspace` — Codegen all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings - - - ## `nargo compile` Compile the program and its secret execution trace into ACIR format @@ -200,11 +107,16 @@ Compile the program and its secret execution trace into ACIR format * `--package ` — The name of the package to compile * `--workspace` — Compile all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend +* `--expression-width ` — Specify the backend expression width that should be targeted +* `--bounded-codegen` — Generate ACIR with the target backend expression width. The default is to generate ACIR without a bound and split expressions after code generation. Activating this flag can sometimes provide optimizations for certain programs + + Default value: `false` * `--force` — Force a full recompilation * `--print-acir` — Display the ACIR for compiled circuit * `--deny-warnings` — Treat all warnings as errors * `--silence-warnings` — Suppress warnings +* `--debug-comptime-in-file ` — Enable printing results of comptime evaluation: provide a path suffix for the module to debug, e.g. "package_name/src/main.nr" +* `--skip-underconstrained-check` — Flag to turn off the compiler check for under constrained values. Warning: This can improve compilation speed but can also lead to correctness errors. This check should always be run on production code @@ -259,59 +171,51 @@ Executes a circuit to calculate its return value Default value: `Prover` * `--package ` — The name of the package to execute * `--workspace` — Execute all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend +* `--expression-width ` — Specify the backend expression width that should be targeted +* `--bounded-codegen` — Generate ACIR with the target backend expression width. The default is to generate ACIR without a bound and split expressions after code generation. Activating this flag can sometimes provide optimizations for certain programs + + Default value: `false` * `--force` — Force a full recompilation * `--print-acir` — Display the ACIR for compiled circuit * `--deny-warnings` — Treat all warnings as errors * `--silence-warnings` — Suppress warnings +* `--debug-comptime-in-file ` — Enable printing results of comptime evaluation: provide a path suffix for the module to debug, e.g. "package_name/src/main.nr" +* `--skip-underconstrained-check` — Flag to turn off the compiler check for under constrained values. Warning: This can improve compilation speed but can also lead to correctness errors. This check should always be run on production code * `--oracle-resolver ` — JSON RPC url to solve oracle calls -## `nargo prove` +## `nargo debug` -Create proof for this program. The proof is returned as a hex encoded string +Executes a circuit in debug mode -**Usage:** `nargo prove [OPTIONS]` +**Usage:** `nargo debug [OPTIONS] [WITNESS_NAME]` + +###### **Arguments:** + +* `` — Write the execution witness to named file ###### **Options:** * `-p`, `--prover-name ` — The name of the toml file which contains the inputs for the prover Default value: `Prover` -* `-v`, `--verifier-name ` — The name of the toml file which contains the inputs for the verifier +* `--package ` — The name of the package to execute +* `--expression-width ` — Specify the backend expression width that should be targeted +* `--bounded-codegen` — Generate ACIR with the target backend expression width. The default is to generate ACIR without a bound and split expressions after code generation. Activating this flag can sometimes provide optimizations for certain programs - Default value: `Verifier` -* `--verify` — Verify proof after proving -* `--package ` — The name of the package to prove -* `--workspace` — Prove all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend + Default value: `false` * `--force` — Force a full recompilation * `--print-acir` — Display the ACIR for compiled circuit * `--deny-warnings` — Treat all warnings as errors * `--silence-warnings` — Suppress warnings -* `--oracle-resolver ` — JSON RPC url to solve oracle calls - - +* `--debug-comptime-in-file ` — Enable printing results of comptime evaluation: provide a path suffix for the module to debug, e.g. "package_name/src/main.nr" +* `--skip-underconstrained-check` — Flag to turn off the compiler check for under constrained values. Warning: This can improve compilation speed but can also lead to correctness errors. This check should always be run on production code +* `--acir-mode` — Force ACIR output (disabling instrumentation) +* `--skip-instrumentation ` — Disable vars debug instrumentation (enabled by default) -## `nargo verify` + Possible values: `true`, `false` -Given a proof and a program, verify whether the proof is valid - -**Usage:** `nargo verify [OPTIONS]` - -###### **Options:** - -* `-v`, `--verifier-name ` — The name of the toml file which contains the inputs for the verifier - - Default value: `Verifier` -* `--package ` — The name of the package verify -* `--workspace` — Verify all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend -* `--force` — Force a full recompilation -* `--print-acir` — Display the ACIR for compiled circuit -* `--deny-warnings` — Treat all warnings as errors -* `--silence-warnings` — Suppress warnings @@ -331,11 +235,16 @@ Run the tests for this program * `--exact` — Only run tests that match exactly * `--package ` — The name of the package to test * `--workspace` — Test all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend +* `--expression-width ` — Specify the backend expression width that should be targeted +* `--bounded-codegen` — Generate ACIR with the target backend expression width. The default is to generate ACIR without a bound and split expressions after code generation. Activating this flag can sometimes provide optimizations for certain programs + + Default value: `false` * `--force` — Force a full recompilation * `--print-acir` — Display the ACIR for compiled circuit * `--deny-warnings` — Treat all warnings as errors * `--silence-warnings` — Suppress warnings +* `--debug-comptime-in-file ` — Enable printing results of comptime evaluation: provide a path suffix for the module to debug, e.g. "package_name/src/main.nr" +* `--skip-underconstrained-check` — Flag to turn off the compiler check for under constrained values. Warning: This can improve compilation speed but can also lead to correctness errors. This check should always be run on production code * `--oracle-resolver ` — JSON RPC url to solve oracle calls @@ -352,11 +261,16 @@ Current information provided per circuit: 1. The number of ACIR opcodes 2. Count * `--package ` — The name of the package to detail * `--workspace` — Detail all packages in the workspace -* `--expression-width ` — Override the expression width requested by the backend +* `--expression-width ` — Specify the backend expression width that should be targeted +* `--bounded-codegen` — Generate ACIR with the target backend expression width. The default is to generate ACIR without a bound and split expressions after code generation. Activating this flag can sometimes provide optimizations for certain programs + + Default value: `false` * `--force` — Force a full recompilation * `--print-acir` — Display the ACIR for compiled circuit * `--deny-warnings` — Treat all warnings as errors * `--silence-warnings` — Suppress warnings +* `--debug-comptime-in-file ` — Enable printing results of comptime evaluation: provide a path suffix for the module to debug, e.g. "package_name/src/main.nr" +* `--skip-underconstrained-check` — Flag to turn off the compiler check for under constrained values. Warning: This can improve compilation speed but can also lead to correctness errors. This check should always be run on production code diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/tooling/noir_codegen.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/noir_codegen.md similarity index 97% rename from noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/tooling/noir_codegen.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/noir_codegen.md index f7505bef7ab..db8f07dc22e 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/tooling/noir_codegen.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/reference/noir_codegen.md @@ -33,7 +33,7 @@ yarn add @noir-lang/noir_codegen -D ``` ### Nargo library -Make sure you have Nargo, v0.25.0 or greater, installed. If you don't, follow the [installation guide](../installation/index.md). +Make sure you have Nargo, v0.25.0 or greater, installed. If you don't, follow the [installation guide](../getting_started/installation/index.md). If you're in a new project, make a `circuits` folder and create a new Noir library: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/tooling/debugger.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/tooling/debugger.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.28.0/tooling/debugger.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/tooling/debugger.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/getting_started/tooling/language_server.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/tooling/language_server.md similarity index 100% rename from noir/noir-repo/docs/versioned_docs/version-v0.22.0/getting_started/tooling/language_server.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/tooling/language_server.md diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/getting_started/tooling/testing.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/tooling/testing.md similarity index 74% rename from noir/noir-repo/docs/versioned_docs/version-v0.22.0/getting_started/tooling/testing.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/tooling/testing.md index d3e0c522473..866677da567 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/getting_started/tooling/testing.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/tooling/testing.md @@ -42,7 +42,7 @@ fn test_add() { } ``` -You can be more specific and make it fail with a specific reason by using `should_fail_with = "`: +You can be more specific and make it fail with a specific reason by using `should_fail_with = ""`: ```rust fn main(african_swallow_avg_speed : Field) { @@ -58,5 +58,22 @@ fn test_king_arthur() { fn test_bridgekeeper() { main(32); } - ``` + +The string given to `should_fail_with` doesn't need to exactly match the failure reason, it just needs to be a substring of it: + +```rust +fn main(african_swallow_avg_speed : Field) { + assert(african_swallow_avg_speed == 65, "What is the airspeed velocity of an unladen swallow"); +} + +#[test] +fn test_king_arthur() { + main(65); +} + +#[test(should_fail_with = "airspeed velocity")] +fn test_bridgekeeper() { + main(32); +} +``` \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/tutorials/noirjs_app.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/tutorials/noirjs_app.md similarity index 94% rename from noir/noir-repo/docs/versioned_docs/version-v0.31.0/tutorials/noirjs_app.md rename to noir/noir-repo/docs/versioned_docs/version-v0.34.0/tutorials/noirjs_app.md index 8c23b639f12..eac28168445 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/tutorials/noirjs_app.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/tutorials/noirjs_app.md @@ -346,3 +346,17 @@ You have successfully generated a client-side Noir web app! You can see how noirjs is used in a full stack Next.js hardhat application in the [noir-starter repo here](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat). The example shows how to calculate a proof in the browser and verify it with a deployed Solidity verifier contract from noirjs. You should also check out the more advanced examples in the [noir-examples repo](https://github.com/noir-lang/noir-examples), where you'll find reference usage for some cool apps. + +## UltraHonk Backend + +Barretenberg has recently exposed a new UltraHonk backend. We can use UltraHonk in NoirJS after version 0.33.0. Everything will be the same as the tutorial above, except that the class we need to import will change: +```js +import { UltraHonkBackend, UltraHonkVerifier as Verifier } from '@noir-lang/backend_barretenberg'; +``` +The backend will then be instantiated as such: +```js +const backend = new UltraHonkBackend(circuit); +``` +Then all the commands to prove and verify your circuit will be same. + +The only feature currently unsupported with UltraHonk are [recursive proofs](../explainers/explainer-recursion.md). \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_sidebars/version-v0.17.0-sidebars.json b/noir/noir-repo/docs/versioned_sidebars/version-v0.17.0-sidebars.json deleted file mode 100644 index a9ec39925d9..00000000000 --- a/noir/noir-repo/docs/versioned_sidebars/version-v0.17.0-sidebars.json +++ /dev/null @@ -1,141 +0,0 @@ -{ - "sidebar": [ - { - "type": "doc", - "id": "index", - "label": "Noir" - }, - { - "type": "category", - "label": "Getting Started", - "items": [ - { - "type": "autogenerated", - "dirName": "getting_started" - } - ] - }, - { - "type": "category", - "label": "Examples", - "items": [ - { - "type": "autogenerated", - "dirName": "examples" - } - ] - }, - { - "type": "category", - "label": "Nargo", - "items": [ - { - "type": "autogenerated", - "dirName": "nargo" - } - ] - }, - { - "type": "category", - "label": "Language Concepts", - "items": [ - { - "type": "category", - "label": "Data Types", - "link": { - "type": "doc", - "id": "language_concepts/data_types" - }, - "items": [ - { - "type": "autogenerated", - "dirName": "language_concepts/data_types" - } - ] - }, - "language_concepts/functions", - "language_concepts/control_flow", - "language_concepts/ops", - "language_concepts/assert", - "language_concepts/unconstrained", - "language_concepts/generics", - "language_concepts/mutability", - "language_concepts/lambdas", - "language_concepts/comments", - "language_concepts/distinct", - "language_concepts/shadowing" - ] - }, - { - "type": "category", - "label": "Noir Standard Library", - "items": [ - { - "type": "category", - "label": "Cryptographic Primitives", - "link": { - "type": "doc", - "id": "standard_library/cryptographic_primitives" - }, - "items": [ - { - "type": "autogenerated", - "dirName": "standard_library/cryptographic_primitives" - } - ] - }, - "standard_library/recursion", - "standard_library/logging", - "standard_library/merkle_trees", - "standard_library/zeroed", - "standard_library/black_box_fns", - "standard_library/options" - ] - }, - { - "type": "category", - "label": "Modules, Packages and Crates", - "items": [ - { - "type": "autogenerated", - "dirName": "modules_packages_crates" - } - ] - }, - { - "type": "category", - "label": "NoirJS", - "link": { - "type": "doc", - "id": "noir_js/noir_js" - }, - "items": [ - { - "type": "category", - "label": "Guides", - "items": [ - { - "type": "autogenerated", - "dirName": "noir_js/getting_started" - } - ] - }, - { - "type": "category", - "label": "Reference", - "items": [ - { - "type": "autogenerated", - "dirName": "noir_js/reference" - } - ] - } - ] - }, - { - "type": "doc", - "id": "migration_notes", - "label": "Migration notes" - } - ] -} diff --git a/noir/noir-repo/docs/versioned_sidebars/version-v0.19.0-sidebars.json b/noir/noir-repo/docs/versioned_sidebars/version-v0.19.0-sidebars.json deleted file mode 100644 index a9ec39925d9..00000000000 --- a/noir/noir-repo/docs/versioned_sidebars/version-v0.19.0-sidebars.json +++ /dev/null @@ -1,141 +0,0 @@ -{ - "sidebar": [ - { - "type": "doc", - "id": "index", - "label": "Noir" - }, - { - "type": "category", - "label": "Getting Started", - "items": [ - { - "type": "autogenerated", - "dirName": "getting_started" - } - ] - }, - { - "type": "category", - "label": "Examples", - "items": [ - { - "type": "autogenerated", - "dirName": "examples" - } - ] - }, - { - "type": "category", - "label": "Nargo", - "items": [ - { - "type": "autogenerated", - "dirName": "nargo" - } - ] - }, - { - "type": "category", - "label": "Language Concepts", - "items": [ - { - "type": "category", - "label": "Data Types", - "link": { - "type": "doc", - "id": "language_concepts/data_types" - }, - "items": [ - { - "type": "autogenerated", - "dirName": "language_concepts/data_types" - } - ] - }, - "language_concepts/functions", - "language_concepts/control_flow", - "language_concepts/ops", - "language_concepts/assert", - "language_concepts/unconstrained", - "language_concepts/generics", - "language_concepts/mutability", - "language_concepts/lambdas", - "language_concepts/comments", - "language_concepts/distinct", - "language_concepts/shadowing" - ] - }, - { - "type": "category", - "label": "Noir Standard Library", - "items": [ - { - "type": "category", - "label": "Cryptographic Primitives", - "link": { - "type": "doc", - "id": "standard_library/cryptographic_primitives" - }, - "items": [ - { - "type": "autogenerated", - "dirName": "standard_library/cryptographic_primitives" - } - ] - }, - "standard_library/recursion", - "standard_library/logging", - "standard_library/merkle_trees", - "standard_library/zeroed", - "standard_library/black_box_fns", - "standard_library/options" - ] - }, - { - "type": "category", - "label": "Modules, Packages and Crates", - "items": [ - { - "type": "autogenerated", - "dirName": "modules_packages_crates" - } - ] - }, - { - "type": "category", - "label": "NoirJS", - "link": { - "type": "doc", - "id": "noir_js/noir_js" - }, - "items": [ - { - "type": "category", - "label": "Guides", - "items": [ - { - "type": "autogenerated", - "dirName": "noir_js/getting_started" - } - ] - }, - { - "type": "category", - "label": "Reference", - "items": [ - { - "type": "autogenerated", - "dirName": "noir_js/reference" - } - ] - } - ] - }, - { - "type": "doc", - "id": "migration_notes", - "label": "Migration notes" - } - ] -} diff --git a/noir/noir-repo/docs/versioned_sidebars/version-v0.19.1-sidebars.json b/noir/noir-repo/docs/versioned_sidebars/version-v0.19.1-sidebars.json deleted file mode 100644 index 6823055c5d3..00000000000 --- a/noir/noir-repo/docs/versioned_sidebars/version-v0.19.1-sidebars.json +++ /dev/null @@ -1,288 +0,0 @@ -{ - "sidebar": [ - { - "type": "doc", - "id": "index", - "label": "Noir" - }, - { - "type": "category", - "label": "Getting Started", - "items": [ - { - "type": "autogenerated", - "dirName": "getting_started" - } - ] - }, - { - "type": "category", - "label": "Examples", - "items": [ - { - "type": "autogenerated", - "dirName": "examples" - } - ] - }, - { - "type": "category", - "label": "Nargo", - "items": [ - { - "type": "autogenerated", - "dirName": "nargo" - } - ] - }, - { - "type": "category", - "label": "Language Concepts", - "items": [ - { - "type": "category", - "label": "Data Types", - "link": { - "type": "doc", - "id": "language_concepts/data_types" - }, - "items": [ - { - "type": "autogenerated", - "dirName": "language_concepts/data_types" - } - ] - }, - "language_concepts/functions", - "language_concepts/control_flow", - "language_concepts/ops", - "language_concepts/assert", - "language_concepts/unconstrained", - "language_concepts/generics", - "language_concepts/mutability", - "language_concepts/lambdas", - "language_concepts/comments", - "language_concepts/distinct", - "language_concepts/shadowing" - ] - }, - { - "type": "category", - "label": "Noir Standard Library", - "items": [ - { - "type": "category", - "label": "Cryptographic Primitives", - "link": { - "type": "doc", - "id": "standard_library/cryptographic_primitives" - }, - "items": [ - { - "type": "autogenerated", - "dirName": "standard_library/cryptographic_primitives" - } - ] - }, - "standard_library/recursion", - "standard_library/logging", - "standard_library/merkle_trees", - "standard_library/zeroed", - "standard_library/black_box_fns", - "standard_library/options" - ] - }, - { - "type": "category", - "label": "Modules, Packages and Crates", - "items": [ - { - "type": "autogenerated", - "dirName": "modules_packages_crates" - } - ] - }, - { - "type": "category", - "label": "NoirJS", - "link": { - "type": "doc", - "id": "noir_js/noir_js" - }, - "items": [ - { - "type": "category", - "label": "Guides", - "items": [ - { - "type": "autogenerated", - "dirName": "noir_js/getting_started" - } - ] - }, - { - "type": "category", - "label": "Reference", - "items": [ - { - "type": "category", - "label": "Noir JS", - "link": { - "type": "doc", - "id": "noir_js/reference/noir_js/index" - }, - "items": [ - { - "type": "category", - "label": "Classes", - "items": [ - { - "type": "doc", - "id": "noir_js/reference/noir_js/classes/Noir", - "label": "Noir" - } - ] - }, - { - "type": "category", - "label": "Type Aliases", - "items": [ - { - "type": "doc", - "id": "noir_js/reference/noir_js/type-aliases/CompiledCircuit", - "label": "CompiledCircuit" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/type-aliases/ForeignCallHandler", - "label": "ForeignCallHandler" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/type-aliases/ForeignCallInput", - "label": "ForeignCallInput" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/type-aliases/ForeignCallOutput", - "label": "ForeignCallOutput" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/type-aliases/ProofData", - "label": "ProofData" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/type-aliases/WitnessMap", - "label": "WitnessMap" - } - ] - }, - { - "type": "category", - "label": "Functions", - "items": [ - { - "type": "doc", - "id": "noir_js/reference/noir_js/functions/and", - "label": "and" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/functions/blake2s256", - "label": "blake2s256" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify", - "label": "ecdsa_secp256k1_verify" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify", - "label": "ecdsa_secp256r1_verify" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/functions/keccak256", - "label": "keccak256" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/functions/sha256", - "label": "sha256" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/functions/xor", - "label": "xor" - } - ] - } - ] - }, - { - "type": "category", - "label": "Backend Barretenberg", - "link": { - "type": "doc", - "id": "noir_js/reference/backend_barretenberg/index" - }, - "items": [ - { - "type": "category", - "label": "Classes", - "items": [ - { - "type": "doc", - "id": "noir_js/reference/backend_barretenberg/classes/BarretenbergBackend", - "label": "BarretenbergBackend" - } - ] - }, - { - "type": "category", - "label": "Interfaces", - "items": [ - { - "type": "doc", - "id": "noir_js/reference/backend_barretenberg/interfaces/Backend", - "label": "Backend" - } - ] - }, - { - "type": "category", - "label": "Type Aliases", - "items": [ - { - "type": "doc", - "id": "noir_js/reference/backend_barretenberg/type-aliases/BackendOptions", - "label": "BackendOptions" - }, - { - "type": "doc", - "id": "noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit", - "label": "CompiledCircuit" - }, - { - "type": "doc", - "id": "noir_js/reference/backend_barretenberg/type-aliases/ProofData", - "label": "ProofData" - } - ] - } - ] - } - ] - } - ] - }, - { - "type": "doc", - "id": "migration_notes", - "label": "Migration notes" - } - ] -} diff --git a/noir/noir-repo/docs/versioned_sidebars/version-v0.19.2-sidebars.json b/noir/noir-repo/docs/versioned_sidebars/version-v0.19.2-sidebars.json deleted file mode 100644 index 6823055c5d3..00000000000 --- a/noir/noir-repo/docs/versioned_sidebars/version-v0.19.2-sidebars.json +++ /dev/null @@ -1,288 +0,0 @@ -{ - "sidebar": [ - { - "type": "doc", - "id": "index", - "label": "Noir" - }, - { - "type": "category", - "label": "Getting Started", - "items": [ - { - "type": "autogenerated", - "dirName": "getting_started" - } - ] - }, - { - "type": "category", - "label": "Examples", - "items": [ - { - "type": "autogenerated", - "dirName": "examples" - } - ] - }, - { - "type": "category", - "label": "Nargo", - "items": [ - { - "type": "autogenerated", - "dirName": "nargo" - } - ] - }, - { - "type": "category", - "label": "Language Concepts", - "items": [ - { - "type": "category", - "label": "Data Types", - "link": { - "type": "doc", - "id": "language_concepts/data_types" - }, - "items": [ - { - "type": "autogenerated", - "dirName": "language_concepts/data_types" - } - ] - }, - "language_concepts/functions", - "language_concepts/control_flow", - "language_concepts/ops", - "language_concepts/assert", - "language_concepts/unconstrained", - "language_concepts/generics", - "language_concepts/mutability", - "language_concepts/lambdas", - "language_concepts/comments", - "language_concepts/distinct", - "language_concepts/shadowing" - ] - }, - { - "type": "category", - "label": "Noir Standard Library", - "items": [ - { - "type": "category", - "label": "Cryptographic Primitives", - "link": { - "type": "doc", - "id": "standard_library/cryptographic_primitives" - }, - "items": [ - { - "type": "autogenerated", - "dirName": "standard_library/cryptographic_primitives" - } - ] - }, - "standard_library/recursion", - "standard_library/logging", - "standard_library/merkle_trees", - "standard_library/zeroed", - "standard_library/black_box_fns", - "standard_library/options" - ] - }, - { - "type": "category", - "label": "Modules, Packages and Crates", - "items": [ - { - "type": "autogenerated", - "dirName": "modules_packages_crates" - } - ] - }, - { - "type": "category", - "label": "NoirJS", - "link": { - "type": "doc", - "id": "noir_js/noir_js" - }, - "items": [ - { - "type": "category", - "label": "Guides", - "items": [ - { - "type": "autogenerated", - "dirName": "noir_js/getting_started" - } - ] - }, - { - "type": "category", - "label": "Reference", - "items": [ - { - "type": "category", - "label": "Noir JS", - "link": { - "type": "doc", - "id": "noir_js/reference/noir_js/index" - }, - "items": [ - { - "type": "category", - "label": "Classes", - "items": [ - { - "type": "doc", - "id": "noir_js/reference/noir_js/classes/Noir", - "label": "Noir" - } - ] - }, - { - "type": "category", - "label": "Type Aliases", - "items": [ - { - "type": "doc", - "id": "noir_js/reference/noir_js/type-aliases/CompiledCircuit", - "label": "CompiledCircuit" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/type-aliases/ForeignCallHandler", - "label": "ForeignCallHandler" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/type-aliases/ForeignCallInput", - "label": "ForeignCallInput" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/type-aliases/ForeignCallOutput", - "label": "ForeignCallOutput" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/type-aliases/ProofData", - "label": "ProofData" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/type-aliases/WitnessMap", - "label": "WitnessMap" - } - ] - }, - { - "type": "category", - "label": "Functions", - "items": [ - { - "type": "doc", - "id": "noir_js/reference/noir_js/functions/and", - "label": "and" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/functions/blake2s256", - "label": "blake2s256" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify", - "label": "ecdsa_secp256k1_verify" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify", - "label": "ecdsa_secp256r1_verify" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/functions/keccak256", - "label": "keccak256" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/functions/sha256", - "label": "sha256" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/functions/xor", - "label": "xor" - } - ] - } - ] - }, - { - "type": "category", - "label": "Backend Barretenberg", - "link": { - "type": "doc", - "id": "noir_js/reference/backend_barretenberg/index" - }, - "items": [ - { - "type": "category", - "label": "Classes", - "items": [ - { - "type": "doc", - "id": "noir_js/reference/backend_barretenberg/classes/BarretenbergBackend", - "label": "BarretenbergBackend" - } - ] - }, - { - "type": "category", - "label": "Interfaces", - "items": [ - { - "type": "doc", - "id": "noir_js/reference/backend_barretenberg/interfaces/Backend", - "label": "Backend" - } - ] - }, - { - "type": "category", - "label": "Type Aliases", - "items": [ - { - "type": "doc", - "id": "noir_js/reference/backend_barretenberg/type-aliases/BackendOptions", - "label": "BackendOptions" - }, - { - "type": "doc", - "id": "noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit", - "label": "CompiledCircuit" - }, - { - "type": "doc", - "id": "noir_js/reference/backend_barretenberg/type-aliases/ProofData", - "label": "ProofData" - } - ] - } - ] - } - ] - } - ] - }, - { - "type": "doc", - "id": "migration_notes", - "label": "Migration notes" - } - ] -} diff --git a/noir/noir-repo/docs/versioned_sidebars/version-v0.19.3-sidebars.json b/noir/noir-repo/docs/versioned_sidebars/version-v0.19.3-sidebars.json deleted file mode 100644 index 6823055c5d3..00000000000 --- a/noir/noir-repo/docs/versioned_sidebars/version-v0.19.3-sidebars.json +++ /dev/null @@ -1,288 +0,0 @@ -{ - "sidebar": [ - { - "type": "doc", - "id": "index", - "label": "Noir" - }, - { - "type": "category", - "label": "Getting Started", - "items": [ - { - "type": "autogenerated", - "dirName": "getting_started" - } - ] - }, - { - "type": "category", - "label": "Examples", - "items": [ - { - "type": "autogenerated", - "dirName": "examples" - } - ] - }, - { - "type": "category", - "label": "Nargo", - "items": [ - { - "type": "autogenerated", - "dirName": "nargo" - } - ] - }, - { - "type": "category", - "label": "Language Concepts", - "items": [ - { - "type": "category", - "label": "Data Types", - "link": { - "type": "doc", - "id": "language_concepts/data_types" - }, - "items": [ - { - "type": "autogenerated", - "dirName": "language_concepts/data_types" - } - ] - }, - "language_concepts/functions", - "language_concepts/control_flow", - "language_concepts/ops", - "language_concepts/assert", - "language_concepts/unconstrained", - "language_concepts/generics", - "language_concepts/mutability", - "language_concepts/lambdas", - "language_concepts/comments", - "language_concepts/distinct", - "language_concepts/shadowing" - ] - }, - { - "type": "category", - "label": "Noir Standard Library", - "items": [ - { - "type": "category", - "label": "Cryptographic Primitives", - "link": { - "type": "doc", - "id": "standard_library/cryptographic_primitives" - }, - "items": [ - { - "type": "autogenerated", - "dirName": "standard_library/cryptographic_primitives" - } - ] - }, - "standard_library/recursion", - "standard_library/logging", - "standard_library/merkle_trees", - "standard_library/zeroed", - "standard_library/black_box_fns", - "standard_library/options" - ] - }, - { - "type": "category", - "label": "Modules, Packages and Crates", - "items": [ - { - "type": "autogenerated", - "dirName": "modules_packages_crates" - } - ] - }, - { - "type": "category", - "label": "NoirJS", - "link": { - "type": "doc", - "id": "noir_js/noir_js" - }, - "items": [ - { - "type": "category", - "label": "Guides", - "items": [ - { - "type": "autogenerated", - "dirName": "noir_js/getting_started" - } - ] - }, - { - "type": "category", - "label": "Reference", - "items": [ - { - "type": "category", - "label": "Noir JS", - "link": { - "type": "doc", - "id": "noir_js/reference/noir_js/index" - }, - "items": [ - { - "type": "category", - "label": "Classes", - "items": [ - { - "type": "doc", - "id": "noir_js/reference/noir_js/classes/Noir", - "label": "Noir" - } - ] - }, - { - "type": "category", - "label": "Type Aliases", - "items": [ - { - "type": "doc", - "id": "noir_js/reference/noir_js/type-aliases/CompiledCircuit", - "label": "CompiledCircuit" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/type-aliases/ForeignCallHandler", - "label": "ForeignCallHandler" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/type-aliases/ForeignCallInput", - "label": "ForeignCallInput" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/type-aliases/ForeignCallOutput", - "label": "ForeignCallOutput" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/type-aliases/ProofData", - "label": "ProofData" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/type-aliases/WitnessMap", - "label": "WitnessMap" - } - ] - }, - { - "type": "category", - "label": "Functions", - "items": [ - { - "type": "doc", - "id": "noir_js/reference/noir_js/functions/and", - "label": "and" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/functions/blake2s256", - "label": "blake2s256" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify", - "label": "ecdsa_secp256k1_verify" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify", - "label": "ecdsa_secp256r1_verify" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/functions/keccak256", - "label": "keccak256" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/functions/sha256", - "label": "sha256" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/functions/xor", - "label": "xor" - } - ] - } - ] - }, - { - "type": "category", - "label": "Backend Barretenberg", - "link": { - "type": "doc", - "id": "noir_js/reference/backend_barretenberg/index" - }, - "items": [ - { - "type": "category", - "label": "Classes", - "items": [ - { - "type": "doc", - "id": "noir_js/reference/backend_barretenberg/classes/BarretenbergBackend", - "label": "BarretenbergBackend" - } - ] - }, - { - "type": "category", - "label": "Interfaces", - "items": [ - { - "type": "doc", - "id": "noir_js/reference/backend_barretenberg/interfaces/Backend", - "label": "Backend" - } - ] - }, - { - "type": "category", - "label": "Type Aliases", - "items": [ - { - "type": "doc", - "id": "noir_js/reference/backend_barretenberg/type-aliases/BackendOptions", - "label": "BackendOptions" - }, - { - "type": "doc", - "id": "noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit", - "label": "CompiledCircuit" - }, - { - "type": "doc", - "id": "noir_js/reference/backend_barretenberg/type-aliases/ProofData", - "label": "ProofData" - } - ] - } - ] - } - ] - } - ] - }, - { - "type": "doc", - "id": "migration_notes", - "label": "Migration notes" - } - ] -} diff --git a/noir/noir-repo/docs/versioned_sidebars/version-v0.19.4-sidebars.json b/noir/noir-repo/docs/versioned_sidebars/version-v0.19.4-sidebars.json deleted file mode 100644 index a1675eca18d..00000000000 --- a/noir/noir-repo/docs/versioned_sidebars/version-v0.19.4-sidebars.json +++ /dev/null @@ -1,293 +0,0 @@ -{ - "sidebar": [ - { - "type": "doc", - "id": "index", - "label": "Noir" - }, - { - "type": "category", - "label": "Getting Started", - "items": [ - { - "type": "autogenerated", - "dirName": "getting_started" - } - ] - }, - { - "type": "category", - "label": "Examples", - "items": [ - { - "type": "autogenerated", - "dirName": "examples" - } - ] - }, - { - "type": "category", - "label": "Nargo", - "items": [ - { - "type": "autogenerated", - "dirName": "nargo" - } - ] - }, - { - "type": "category", - "label": "Language Concepts", - "items": [ - { - "type": "category", - "label": "Data Types", - "link": { - "type": "doc", - "id": "language_concepts/data_types" - }, - "items": [ - { - "type": "autogenerated", - "dirName": "language_concepts/data_types" - } - ] - }, - "language_concepts/functions", - "language_concepts/control_flow", - "language_concepts/ops", - "language_concepts/assert", - "language_concepts/unconstrained", - "language_concepts/generics", - "language_concepts/mutability", - "language_concepts/lambdas", - "language_concepts/comments", - "language_concepts/distinct", - "language_concepts/shadowing" - ] - }, - { - "type": "category", - "label": "Noir Standard Library", - "items": [ - { - "type": "category", - "label": "Cryptographic Primitives", - "link": { - "type": "doc", - "id": "standard_library/cryptographic_primitives" - }, - "items": [ - { - "type": "autogenerated", - "dirName": "standard_library/cryptographic_primitives" - } - ] - }, - "standard_library/recursion", - "standard_library/logging", - "standard_library/merkle_trees", - "standard_library/zeroed", - "standard_library/black_box_fns", - "standard_library/options" - ] - }, - { - "type": "category", - "label": "Modules, Packages and Crates", - "items": [ - { - "type": "autogenerated", - "dirName": "modules_packages_crates" - } - ] - }, - { - "type": "category", - "label": "NoirJS", - "link": { - "type": "doc", - "id": "noir_js/noir_js" - }, - "items": [ - { - "type": "category", - "label": "Guides", - "items": [ - { - "type": "autogenerated", - "dirName": "noir_js/getting_started" - } - ] - }, - { - "type": "category", - "label": "Reference", - "items": [ - { - "type": "category", - "label": "Noir JS", - "link": { - "type": "doc", - "id": "noir_js/reference/noir_js/index" - }, - "items": [ - { - "type": "category", - "label": "Classes", - "items": [ - { - "type": "doc", - "id": "noir_js/reference/noir_js/classes/Noir", - "label": "Noir" - } - ] - }, - { - "type": "category", - "label": "Type Aliases", - "items": [ - { - "type": "doc", - "id": "noir_js/reference/noir_js/type-aliases/CompiledCircuit", - "label": "CompiledCircuit" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/type-aliases/ForeignCallHandler", - "label": "ForeignCallHandler" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/type-aliases/ForeignCallInput", - "label": "ForeignCallInput" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/type-aliases/ForeignCallOutput", - "label": "ForeignCallOutput" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/type-aliases/InputMap", - "label": "InputMap" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/type-aliases/ProofData", - "label": "ProofData" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/type-aliases/WitnessMap", - "label": "WitnessMap" - } - ] - }, - { - "type": "category", - "label": "Functions", - "items": [ - { - "type": "doc", - "id": "noir_js/reference/noir_js/functions/and", - "label": "and" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/functions/blake2s256", - "label": "blake2s256" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify", - "label": "ecdsa_secp256k1_verify" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify", - "label": "ecdsa_secp256r1_verify" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/functions/keccak256", - "label": "keccak256" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/functions/sha256", - "label": "sha256" - }, - { - "type": "doc", - "id": "noir_js/reference/noir_js/functions/xor", - "label": "xor" - } - ] - } - ] - }, - { - "type": "category", - "label": "Backend Barretenberg", - "link": { - "type": "doc", - "id": "noir_js/reference/backend_barretenberg/index" - }, - "items": [ - { - "type": "category", - "label": "Classes", - "items": [ - { - "type": "doc", - "id": "noir_js/reference/backend_barretenberg/classes/BarretenbergBackend", - "label": "BarretenbergBackend" - } - ] - }, - { - "type": "category", - "label": "Interfaces", - "items": [ - { - "type": "doc", - "id": "noir_js/reference/backend_barretenberg/interfaces/Backend", - "label": "Backend" - } - ] - }, - { - "type": "category", - "label": "Type Aliases", - "items": [ - { - "type": "doc", - "id": "noir_js/reference/backend_barretenberg/type-aliases/BackendOptions", - "label": "BackendOptions" - }, - { - "type": "doc", - "id": "noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit", - "label": "CompiledCircuit" - }, - { - "type": "doc", - "id": "noir_js/reference/backend_barretenberg/type-aliases/ProofData", - "label": "ProofData" - } - ] - } - ] - } - ] - } - ] - }, - { - "type": "doc", - "id": "migration_notes", - "label": "Migration notes" - } - ] -} diff --git a/noir/noir-repo/docs/versioned_sidebars/version-v0.22.0-sidebars.json b/noir/noir-repo/docs/versioned_sidebars/version-v0.22.0-sidebars.json deleted file mode 100644 index b16f79cc176..00000000000 --- a/noir/noir-repo/docs/versioned_sidebars/version-v0.22.0-sidebars.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "sidebar": [ - { - "type": "doc", - "id": "index" - }, - { - "type": "category", - "label": "Getting Started", - "items": [ - { - "type": "autogenerated", - "dirName": "getting_started" - } - ] - }, - { - "type": "category", - "label": "The Noir Language", - "items": [ - { - "type": "autogenerated", - "dirName": "noir" - } - ] - }, - { - "type": "html", - "value": "
", - "defaultStyle": true - }, - { - "type": "category", - "label": "How To Guides", - "items": [ - { - "type": "autogenerated", - "dirName": "how_to" - } - ] - }, - { - "type": "category", - "label": "Explainers", - "items": [ - { - "type": "autogenerated", - "dirName": "explainers" - } - ] - }, - { - "type": "category", - "label": "Tutorials", - "items": [ - { - "type": "autogenerated", - "dirName": "tutorials" - } - ] - }, - { - "type": "category", - "label": "Reference", - "items": [ - { - "type": "autogenerated", - "dirName": "reference" - } - ] - }, - { - "type": "html", - "value": "
", - "defaultStyle": true - }, - { - "type": "doc", - "id": "migration_notes", - "label": "Migration notes" - } - ] -} diff --git a/noir/noir-repo/docs/versioned_sidebars/version-v0.23.0-sidebars.json b/noir/noir-repo/docs/versioned_sidebars/version-v0.23.0-sidebars.json deleted file mode 100644 index b16f79cc176..00000000000 --- a/noir/noir-repo/docs/versioned_sidebars/version-v0.23.0-sidebars.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "sidebar": [ - { - "type": "doc", - "id": "index" - }, - { - "type": "category", - "label": "Getting Started", - "items": [ - { - "type": "autogenerated", - "dirName": "getting_started" - } - ] - }, - { - "type": "category", - "label": "The Noir Language", - "items": [ - { - "type": "autogenerated", - "dirName": "noir" - } - ] - }, - { - "type": "html", - "value": "
", - "defaultStyle": true - }, - { - "type": "category", - "label": "How To Guides", - "items": [ - { - "type": "autogenerated", - "dirName": "how_to" - } - ] - }, - { - "type": "category", - "label": "Explainers", - "items": [ - { - "type": "autogenerated", - "dirName": "explainers" - } - ] - }, - { - "type": "category", - "label": "Tutorials", - "items": [ - { - "type": "autogenerated", - "dirName": "tutorials" - } - ] - }, - { - "type": "category", - "label": "Reference", - "items": [ - { - "type": "autogenerated", - "dirName": "reference" - } - ] - }, - { - "type": "html", - "value": "
", - "defaultStyle": true - }, - { - "type": "doc", - "id": "migration_notes", - "label": "Migration notes" - } - ] -} diff --git a/noir/noir-repo/docs/versioned_sidebars/version-v0.24.0-sidebars.json b/noir/noir-repo/docs/versioned_sidebars/version-v0.24.0-sidebars.json deleted file mode 100644 index b16f79cc176..00000000000 --- a/noir/noir-repo/docs/versioned_sidebars/version-v0.24.0-sidebars.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "sidebar": [ - { - "type": "doc", - "id": "index" - }, - { - "type": "category", - "label": "Getting Started", - "items": [ - { - "type": "autogenerated", - "dirName": "getting_started" - } - ] - }, - { - "type": "category", - "label": "The Noir Language", - "items": [ - { - "type": "autogenerated", - "dirName": "noir" - } - ] - }, - { - "type": "html", - "value": "
", - "defaultStyle": true - }, - { - "type": "category", - "label": "How To Guides", - "items": [ - { - "type": "autogenerated", - "dirName": "how_to" - } - ] - }, - { - "type": "category", - "label": "Explainers", - "items": [ - { - "type": "autogenerated", - "dirName": "explainers" - } - ] - }, - { - "type": "category", - "label": "Tutorials", - "items": [ - { - "type": "autogenerated", - "dirName": "tutorials" - } - ] - }, - { - "type": "category", - "label": "Reference", - "items": [ - { - "type": "autogenerated", - "dirName": "reference" - } - ] - }, - { - "type": "html", - "value": "
", - "defaultStyle": true - }, - { - "type": "doc", - "id": "migration_notes", - "label": "Migration notes" - } - ] -} diff --git a/noir/noir-repo/docs/versioned_sidebars/version-v0.25.0-sidebars.json b/noir/noir-repo/docs/versioned_sidebars/version-v0.25.0-sidebars.json deleted file mode 100644 index b16f79cc176..00000000000 --- a/noir/noir-repo/docs/versioned_sidebars/version-v0.25.0-sidebars.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "sidebar": [ - { - "type": "doc", - "id": "index" - }, - { - "type": "category", - "label": "Getting Started", - "items": [ - { - "type": "autogenerated", - "dirName": "getting_started" - } - ] - }, - { - "type": "category", - "label": "The Noir Language", - "items": [ - { - "type": "autogenerated", - "dirName": "noir" - } - ] - }, - { - "type": "html", - "value": "
", - "defaultStyle": true - }, - { - "type": "category", - "label": "How To Guides", - "items": [ - { - "type": "autogenerated", - "dirName": "how_to" - } - ] - }, - { - "type": "category", - "label": "Explainers", - "items": [ - { - "type": "autogenerated", - "dirName": "explainers" - } - ] - }, - { - "type": "category", - "label": "Tutorials", - "items": [ - { - "type": "autogenerated", - "dirName": "tutorials" - } - ] - }, - { - "type": "category", - "label": "Reference", - "items": [ - { - "type": "autogenerated", - "dirName": "reference" - } - ] - }, - { - "type": "html", - "value": "
", - "defaultStyle": true - }, - { - "type": "doc", - "id": "migration_notes", - "label": "Migration notes" - } - ] -} diff --git a/noir/noir-repo/docs/versioned_sidebars/version-v0.26.0-sidebars.json b/noir/noir-repo/docs/versioned_sidebars/version-v0.26.0-sidebars.json deleted file mode 100644 index b16f79cc176..00000000000 --- a/noir/noir-repo/docs/versioned_sidebars/version-v0.26.0-sidebars.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "sidebar": [ - { - "type": "doc", - "id": "index" - }, - { - "type": "category", - "label": "Getting Started", - "items": [ - { - "type": "autogenerated", - "dirName": "getting_started" - } - ] - }, - { - "type": "category", - "label": "The Noir Language", - "items": [ - { - "type": "autogenerated", - "dirName": "noir" - } - ] - }, - { - "type": "html", - "value": "
", - "defaultStyle": true - }, - { - "type": "category", - "label": "How To Guides", - "items": [ - { - "type": "autogenerated", - "dirName": "how_to" - } - ] - }, - { - "type": "category", - "label": "Explainers", - "items": [ - { - "type": "autogenerated", - "dirName": "explainers" - } - ] - }, - { - "type": "category", - "label": "Tutorials", - "items": [ - { - "type": "autogenerated", - "dirName": "tutorials" - } - ] - }, - { - "type": "category", - "label": "Reference", - "items": [ - { - "type": "autogenerated", - "dirName": "reference" - } - ] - }, - { - "type": "html", - "value": "
", - "defaultStyle": true - }, - { - "type": "doc", - "id": "migration_notes", - "label": "Migration notes" - } - ] -} diff --git a/noir/noir-repo/docs/versioned_sidebars/version-v0.27.0-sidebars.json b/noir/noir-repo/docs/versioned_sidebars/version-v0.27.0-sidebars.json deleted file mode 100644 index b16f79cc176..00000000000 --- a/noir/noir-repo/docs/versioned_sidebars/version-v0.27.0-sidebars.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "sidebar": [ - { - "type": "doc", - "id": "index" - }, - { - "type": "category", - "label": "Getting Started", - "items": [ - { - "type": "autogenerated", - "dirName": "getting_started" - } - ] - }, - { - "type": "category", - "label": "The Noir Language", - "items": [ - { - "type": "autogenerated", - "dirName": "noir" - } - ] - }, - { - "type": "html", - "value": "
", - "defaultStyle": true - }, - { - "type": "category", - "label": "How To Guides", - "items": [ - { - "type": "autogenerated", - "dirName": "how_to" - } - ] - }, - { - "type": "category", - "label": "Explainers", - "items": [ - { - "type": "autogenerated", - "dirName": "explainers" - } - ] - }, - { - "type": "category", - "label": "Tutorials", - "items": [ - { - "type": "autogenerated", - "dirName": "tutorials" - } - ] - }, - { - "type": "category", - "label": "Reference", - "items": [ - { - "type": "autogenerated", - "dirName": "reference" - } - ] - }, - { - "type": "html", - "value": "
", - "defaultStyle": true - }, - { - "type": "doc", - "id": "migration_notes", - "label": "Migration notes" - } - ] -} diff --git a/noir/noir-repo/docs/versioned_sidebars/version-v0.29.0-sidebars.json b/noir/noir-repo/docs/versioned_sidebars/version-v0.29.0-sidebars.json deleted file mode 100644 index b9ad026f69f..00000000000 --- a/noir/noir-repo/docs/versioned_sidebars/version-v0.29.0-sidebars.json +++ /dev/null @@ -1,93 +0,0 @@ -{ - "sidebar": [ - { - "type": "doc", - "id": "index" - }, - { - "type": "category", - "label": "Getting Started", - "items": [ - { - "type": "autogenerated", - "dirName": "getting_started" - } - ] - }, - { - "type": "category", - "label": "The Noir Language", - "items": [ - { - "type": "autogenerated", - "dirName": "noir" - } - ] - }, - { - "type": "html", - "value": "
", - "defaultStyle": true - }, - { - "type": "category", - "label": "How To Guides", - "items": [ - { - "type": "autogenerated", - "dirName": "how_to" - } - ] - }, - { - "type": "category", - "label": "Explainers", - "items": [ - { - "type": "autogenerated", - "dirName": "explainers" - } - ] - }, - { - "type": "category", - "label": "Tutorials", - "items": [ - { - "type": "autogenerated", - "dirName": "tutorials" - } - ] - }, - { - "type": "category", - "label": "Reference", - "items": [ - { - "type": "autogenerated", - "dirName": "reference" - } - ] - }, - { - "type": "category", - "label": "Tooling", - "items": [ - { - "type": "autogenerated", - "dirName": "tooling" - } - ] - }, - { - "type": "html", - "value": "
", - "defaultStyle": true - }, - { - "type": "doc", - "id": "migration_notes", - "label": "Migration notes" - } - ] -} diff --git a/noir/noir-repo/docs/versioned_sidebars/version-v0.30.0-sidebars.json b/noir/noir-repo/docs/versioned_sidebars/version-v0.30.0-sidebars.json deleted file mode 100644 index b9ad026f69f..00000000000 --- a/noir/noir-repo/docs/versioned_sidebars/version-v0.30.0-sidebars.json +++ /dev/null @@ -1,93 +0,0 @@ -{ - "sidebar": [ - { - "type": "doc", - "id": "index" - }, - { - "type": "category", - "label": "Getting Started", - "items": [ - { - "type": "autogenerated", - "dirName": "getting_started" - } - ] - }, - { - "type": "category", - "label": "The Noir Language", - "items": [ - { - "type": "autogenerated", - "dirName": "noir" - } - ] - }, - { - "type": "html", - "value": "
", - "defaultStyle": true - }, - { - "type": "category", - "label": "How To Guides", - "items": [ - { - "type": "autogenerated", - "dirName": "how_to" - } - ] - }, - { - "type": "category", - "label": "Explainers", - "items": [ - { - "type": "autogenerated", - "dirName": "explainers" - } - ] - }, - { - "type": "category", - "label": "Tutorials", - "items": [ - { - "type": "autogenerated", - "dirName": "tutorials" - } - ] - }, - { - "type": "category", - "label": "Reference", - "items": [ - { - "type": "autogenerated", - "dirName": "reference" - } - ] - }, - { - "type": "category", - "label": "Tooling", - "items": [ - { - "type": "autogenerated", - "dirName": "tooling" - } - ] - }, - { - "type": "html", - "value": "
", - "defaultStyle": true - }, - { - "type": "doc", - "id": "migration_notes", - "label": "Migration notes" - } - ] -} diff --git a/noir/noir-repo/docs/versioned_sidebars/version-v0.31.0-sidebars.json b/noir/noir-repo/docs/versioned_sidebars/version-v0.31.0-sidebars.json deleted file mode 100644 index b9ad026f69f..00000000000 --- a/noir/noir-repo/docs/versioned_sidebars/version-v0.31.0-sidebars.json +++ /dev/null @@ -1,93 +0,0 @@ -{ - "sidebar": [ - { - "type": "doc", - "id": "index" - }, - { - "type": "category", - "label": "Getting Started", - "items": [ - { - "type": "autogenerated", - "dirName": "getting_started" - } - ] - }, - { - "type": "category", - "label": "The Noir Language", - "items": [ - { - "type": "autogenerated", - "dirName": "noir" - } - ] - }, - { - "type": "html", - "value": "
", - "defaultStyle": true - }, - { - "type": "category", - "label": "How To Guides", - "items": [ - { - "type": "autogenerated", - "dirName": "how_to" - } - ] - }, - { - "type": "category", - "label": "Explainers", - "items": [ - { - "type": "autogenerated", - "dirName": "explainers" - } - ] - }, - { - "type": "category", - "label": "Tutorials", - "items": [ - { - "type": "autogenerated", - "dirName": "tutorials" - } - ] - }, - { - "type": "category", - "label": "Reference", - "items": [ - { - "type": "autogenerated", - "dirName": "reference" - } - ] - }, - { - "type": "category", - "label": "Tooling", - "items": [ - { - "type": "autogenerated", - "dirName": "tooling" - } - ] - }, - { - "type": "html", - "value": "
", - "defaultStyle": true - }, - { - "type": "doc", - "id": "migration_notes", - "label": "Migration notes" - } - ] -} diff --git a/noir/noir-repo/docs/versioned_sidebars/version-v0.28.0-sidebars.json b/noir/noir-repo/docs/versioned_sidebars/version-v0.34.0-sidebars.json similarity index 100% rename from noir/noir-repo/docs/versioned_sidebars/version-v0.28.0-sidebars.json rename to noir/noir-repo/docs/versioned_sidebars/version-v0.34.0-sidebars.json diff --git a/noir/noir-repo/noir_stdlib/src/append.nr b/noir/noir-repo/noir_stdlib/src/append.nr index 22baa9205a0..5f41dae8046 100644 --- a/noir/noir-repo/noir_stdlib/src/append.nr +++ b/noir/noir-repo/noir_stdlib/src/append.nr @@ -7,7 +7,7 @@ // - `T::empty().append(x) == x` // - `x.append(T::empty()) == x` // docs:start:append-trait -trait Append { +pub trait Append { fn empty() -> Self; fn append(self, other: Self) -> Self; } diff --git a/noir/noir-repo/noir_stdlib/src/array/mod.nr b/noir/noir-repo/noir_stdlib/src/array/mod.nr index f3cf6b78081..46acf619dd2 100644 --- a/noir/noir-repo/noir_stdlib/src/array/mod.nr +++ b/noir/noir-repo/noir_stdlib/src/array/mod.nr @@ -6,15 +6,42 @@ mod check_shuffle; mod quicksort; impl [T; N] { - /// Returns the length of the slice. + /// Returns the length of this array. + /// + /// ```noir + /// fn len(self) -> Field + /// ``` + /// + /// example + /// + /// ```noir + /// fn main() { + /// let array = [42, 42]; + /// assert(array.len() == 2); + /// } + /// ``` #[builtin(array_len)] pub fn len(self) -> u32 {} + /// Returns this array as a slice. + /// + /// ```noir + /// let array = [1, 2]; + /// let slice = array.as_slice(); + /// assert_eq(slice, &[1, 2]); + /// ``` #[builtin(as_slice)] pub fn as_slice(self) -> [T] {} - // Apply a function to each element of an array, returning a new array - // containing the mapped elements. + /// Applies a function to each element of this array, returning a new array containing the mapped elements. + /// + /// Example: + /// + /// ```rust + /// let a = [1, 2, 3]; + /// let b = a.map(|a| a * 2); + /// assert_eq(b, [2, 4, 6]); + /// ``` pub fn map(self, f: fn[Env](T) -> U) -> [U; N] { let first_elem = f(self[0]); let mut ret = [first_elem; N]; @@ -26,9 +53,24 @@ impl [T; N] { ret } - // Apply a function to each element of the array and an accumulator value, - // returning the final accumulated value. This function is also sometimes - // called `foldl`, `fold_left`, `reduce`, or `inject`. + /// Applies a function to each element of the array, returning the final accumulated value. The first + /// parameter is the initial value. + /// + /// This is a left fold, so the given function will be applied to the accumulator and first element of + /// the array, then the second, and so on. For a given call the expected result would be equivalent to: + /// + /// ```rust + /// let a1 = [1]; + /// let a2 = [1, 2]; + /// let a3 = [1, 2, 3]; + /// + /// let f = |a, b| a - b; + /// a1.fold(10, f); //=> f(10, 1) + /// a2.fold(10, f); //=> f(f(10, 1), 2) + /// a3.fold(10, f); //=> f(f(f(10, 1), 2), 3) + /// + /// assert_eq(a3.fold(10, f), 10 - 1 - 2 - 3); + /// ``` pub fn fold(self, mut accumulator: U, f: fn[Env](U, T) -> U) -> U { for elem in self { accumulator = f(accumulator, elem); @@ -36,9 +78,17 @@ impl [T; N] { accumulator } - // Apply a function to each element of the array and an accumulator value, - // returning the final accumulated value. Unlike fold, reduce uses the first - // element of the given array as its starting accumulator value. + /// Same as fold, but uses the first element as the starting element. + /// + /// Example: + /// + /// ```noir + /// fn main() { + /// let arr = [1, 2, 3, 4]; + /// let reduced = arr.reduce(|a, b| a + b); + /// assert(reduced == 10); + /// } + /// ``` pub fn reduce(self, f: fn[Env](T, T) -> T) -> T { let mut accumulator = self[0]; for i in 1..self.len() { @@ -47,7 +97,17 @@ impl [T; N] { accumulator } - // Returns true if all elements in the array satisfy the predicate + /// Returns true if all the elements in this array satisfy the given predicate. + /// + /// Example: + /// + /// ```noir + /// fn main() { + /// let arr = [2, 2, 2, 2, 2]; + /// let all = arr.all(|a| a == 2); + /// assert(all); + /// } + /// ``` pub fn all(self, predicate: fn[Env](T) -> bool) -> bool { let mut ret = true; for elem in self { @@ -56,7 +116,17 @@ impl [T; N] { ret } - // Returns true if any element in the array satisfies the predicate + /// Returns true if any of the elements in this array satisfy the given predicate. + /// + /// Example: + /// + /// ```noir + /// fn main() { + /// let arr = [2, 2, 2, 2, 5]; + /// let any = arr.any(|a| a == 5); + /// assert(any); + /// } + /// ``` pub fn any(self, predicate: fn[Env](T) -> bool) -> bool { let mut ret = false; for elem in self { @@ -67,17 +137,44 @@ impl [T; N] { } impl [T; N] where T: Ord + Eq { + /// Returns a new sorted array. The original array remains untouched. Notice that this function will + /// only work for arrays of fields or integers, not for any arbitrary type. This is because the sorting + /// logic it uses internally is optimized specifically for these values. If you need a sort function to + /// sort any type, you should use the `sort_via` function. + /// + /// Example: + /// + /// ```rust + /// fn main() { + /// let arr = [42, 32]; + /// let sorted = arr.sort(); + /// assert(sorted == [32, 42]); + /// } + /// ``` pub fn sort(self) -> Self { self.sort_via(|a: T, b: T| a <= b) } } impl [T; N] where T: Eq { - - /// Sorts the array using a custom predicate function `ordering`. - /// - /// The `ordering` function must be designed to return `true` for equal valued inputs - /// If this is not done, `sort_via` will fail to sort inputs with duplicated elements. + /// Returns a new sorted array by sorting it with a custom comparison function. + /// The original array remains untouched. + /// The ordering function must return true if the first argument should be sorted to be before the second argument or is equal to the second argument. + /// + /// Using this method with an operator like `<` that does not return `true` for equal values will result in an assertion failure for arrays with equal elements. + /// + /// Example: + /// + /// ```rust + /// fn main() { + /// let arr = [42, 32] + /// let sorted_ascending = arr.sort_via(|a, b| a <= b); + /// assert(sorted_ascending == [32, 42]); // verifies + /// + /// let sorted_descending = arr.sort_via(|a, b| a >= b); + /// assert(sorted_descending == [32, 42]); // does not verify + /// } + /// ``` pub fn sort_via(self, ordering: fn[Env](T, T) -> bool) -> Self { unsafe { // Safety: `sorted` array is checked to be: @@ -99,13 +196,23 @@ impl [T; N] where T: Eq { } impl [u8; N] { - /// Convert a sequence of bytes as-is into a string. - /// This function performs no UTF-8 validation or similar. + /// Converts a byte array of type `[u8; N]` to a string. Note that this performs no UTF-8 validation - + /// the given array is interpreted as-is as a string. + /// + /// Example: + /// + /// ```rust + /// fn main() { + /// let hi = [104, 105].as_str_unchecked(); + /// assert_eq(hi, "hi"); + /// } + /// ``` #[builtin(array_as_str_unchecked)] pub fn as_str_unchecked(self) -> str {} } impl From> for [u8; N] { + /// Returns an array of the string bytes. fn from(s: str) -> Self { s.as_bytes() } diff --git a/noir/noir-repo/noir_stdlib/src/bigint.nr b/noir/noir-repo/noir_stdlib/src/bigint.nr index 34eca47046d..0015f480794 100644 --- a/noir/noir-repo/noir_stdlib/src/bigint.nr +++ b/noir/noir-repo/noir_stdlib/src/bigint.nr @@ -12,7 +12,7 @@ global secpr1_fq = &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF]; global secpr1_fr = &[81, 37, 99, 252, 194, 202, 185, 243, 132, 158, 23, 167, 173, 250, 230, 188, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255]; // docs:start:big_int_definition -struct BigInt { +pub struct BigInt { pointer: u32, modulus: u32, } @@ -43,13 +43,13 @@ impl BigInt { } } -trait BigField { +pub trait BigField { fn from_le_bytes(bytes: [u8]) -> Self; fn from_le_bytes_32(bytes: [u8; 32]) -> Self; fn to_le_bytes(self) -> [u8]; } -struct Secpk1Fq { +pub struct Secpk1Fq { array: [u8;32], } @@ -106,7 +106,7 @@ impl Eq for Secpk1Fq { } } -struct Secpk1Fr { +pub struct Secpk1Fr { array: [u8;32], } @@ -163,7 +163,7 @@ impl Eq for Secpk1Fr { } } -struct Bn254Fr { +pub struct Bn254Fr { array: [u8;32], } @@ -220,7 +220,7 @@ impl Eq for Bn254Fr { } } -struct Bn254Fq { +pub struct Bn254Fq { array: [u8;32], } @@ -277,7 +277,7 @@ impl Eq for Bn254Fq { } } -struct Secpr1Fq { +pub struct Secpr1Fq { array: [u8;32], } @@ -334,7 +334,7 @@ impl Eq for Secpr1Fq { } } -struct Secpr1Fr { +pub struct Secpr1Fr { array: [u8;32], } diff --git a/noir/noir-repo/noir_stdlib/src/cmp.nr b/noir/noir-repo/noir_stdlib/src/cmp.nr index e76116951c5..ac7e3df66ad 100644 --- a/noir/noir-repo/noir_stdlib/src/cmp.nr +++ b/noir/noir-repo/noir_stdlib/src/cmp.nr @@ -2,7 +2,7 @@ use crate::meta::derive_via; #[derive_via(derive_eq)] // docs:start:eq-trait -trait Eq { +pub trait Eq { fn eq(self, other: Self) -> bool; } // docs:end:eq-trait @@ -150,7 +150,7 @@ impl Eq for Ordering { // Noir doesn't have enums yet so we emulate (Lt | Eq | Gt) with a struct // that has 3 public functions for constructing the struct. -struct Ordering { +pub struct Ordering { result: Field, } @@ -173,7 +173,7 @@ impl Ordering { #[derive_via(derive_ord)] // docs:start:ord-trait -trait Ord { +pub trait Ord { fn cmp(self, other: Self) -> Ordering; } // docs:end:ord-trait diff --git a/noir/noir-repo/noir_stdlib/src/collections/bounded_vec.nr b/noir/noir-repo/noir_stdlib/src/collections/bounded_vec.nr index 315e398f097..7cd9942e02a 100644 --- a/noir/noir-repo/noir_stdlib/src/collections/bounded_vec.nr +++ b/noir/noir-repo/noir_stdlib/src/collections/bounded_vec.nr @@ -22,7 +22,7 @@ use crate::{cmp::Eq, convert::From}; /// assert(vector.len() == 5); /// assert(vector.max_len() == 10); /// ``` -struct BoundedVec { +pub struct BoundedVec { storage: [T; MaxLen], len: u32, } @@ -56,7 +56,7 @@ impl BoundedVec { /// /// fn bad() { /// // Error: Type annotation needed - /// // The compiller can't infer `MaxLen` from the following code: + /// // The compiler can't infer `MaxLen` from the following code: /// let mut v3 = BoundedVec::new(); /// v3.push(5); /// } diff --git a/noir/noir-repo/noir_stdlib/src/collections/map.nr b/noir/noir-repo/noir_stdlib/src/collections/map.nr index def15f718ca..d3c4d3d99b4 100644 --- a/noir/noir-repo/noir_stdlib/src/collections/map.nr +++ b/noir/noir-repo/noir_stdlib/src/collections/map.nr @@ -30,7 +30,7 @@ global MAX_LOAD_FACTOR_DEN0MINATOR = 4; /// /// let two = map.get(1).unwrap(); /// ``` -struct HashMap { +pub struct HashMap { _table: [Slot; N], /// Amount of valid elements in the map. diff --git a/noir/noir-repo/noir_stdlib/src/collections/umap.nr b/noir/noir-repo/noir_stdlib/src/collections/umap.nr index aa944404751..9d23e216731 100644 --- a/noir/noir-repo/noir_stdlib/src/collections/umap.nr +++ b/noir/noir-repo/noir_stdlib/src/collections/umap.nr @@ -11,7 +11,7 @@ use crate::hash::{Hash, Hasher, BuildHasher}; // // Compared to the constrained HashMap type, UHashMap can grow automatically // as needed and is more efficient since it can break out of loops early. -struct UHashMap { +pub struct UHashMap { _table: [Slot], // Amount of valid elements in the map. diff --git a/noir/noir-repo/noir_stdlib/src/collections/vec.nr b/noir/noir-repo/noir_stdlib/src/collections/vec.nr index cedae7f5ce1..f24ed4ac783 100644 --- a/noir/noir-repo/noir_stdlib/src/collections/vec.nr +++ b/noir/noir-repo/noir_stdlib/src/collections/vec.nr @@ -1,4 +1,4 @@ -struct Vec { +pub struct Vec { slice: [T] } // A mutable vector type implemented as a wrapper around immutable slices. diff --git a/noir/noir-repo/noir_stdlib/src/convert.nr b/noir/noir-repo/noir_stdlib/src/convert.nr index 0b2bd4f2eb7..a38a54ce365 100644 --- a/noir/noir-repo/noir_stdlib/src/convert.nr +++ b/noir/noir-repo/noir_stdlib/src/convert.nr @@ -1,5 +1,5 @@ // docs:start:from-trait -trait From { +pub trait From { fn from(input: T) -> Self; } // docs:end:from-trait @@ -11,7 +11,7 @@ impl From for T { } // docs:start:into-trait -trait Into { +pub trait Into { fn into(self) -> T; } diff --git a/noir/noir-repo/noir_stdlib/src/default.nr b/noir/noir-repo/noir_stdlib/src/default.nr index 3dcc04c7d0c..00bb278fd48 100644 --- a/noir/noir-repo/noir_stdlib/src/default.nr +++ b/noir/noir-repo/noir_stdlib/src/default.nr @@ -2,7 +2,7 @@ use crate::meta::derive_via; #[derive_via(derive_default)] // docs:start:default-trait -trait Default { +pub trait Default { fn default() -> Self; } // docs:end:default-trait diff --git a/noir/noir-repo/noir_stdlib/src/ec/consts/te.nr b/noir/noir-repo/noir_stdlib/src/ec/consts/te.nr index 8cea7654e39..349e518cdb2 100644 --- a/noir/noir-repo/noir_stdlib/src/ec/consts/te.nr +++ b/noir/noir-repo/noir_stdlib/src/ec/consts/te.nr @@ -1,7 +1,7 @@ use crate::ec::tecurve::affine::Point as TEPoint; use crate::ec::tecurve::affine::Curve as TECurve; -struct BabyJubjub { +pub struct BabyJubjub { curve: TECurve, base8: TEPoint, suborder: Field, diff --git a/noir/noir-repo/noir_stdlib/src/ec/montcurve.nr b/noir/noir-repo/noir_stdlib/src/ec/montcurve.nr index 676b1cd81a7..68b5c67dcba 100644 --- a/noir/noir-repo/noir_stdlib/src/ec/montcurve.nr +++ b/noir/noir-repo/noir_stdlib/src/ec/montcurve.nr @@ -15,14 +15,14 @@ mod affine { use crate::cmp::Eq; // Curve specification - struct Curve { // Montgomery Curve configuration (ky^2 = x^3 + j*x^2 + x) + pub struct Curve { // Montgomery Curve configuration (ky^2 = x^3 + j*x^2 + x) j: Field, k: Field, // Generator as point in Cartesian coordinates gen: Point } // Point in Cartesian coordinates - struct Point { + pub struct Point { x: Field, y: Field, infty: bool // Indicator for point at infinity @@ -222,14 +222,14 @@ mod curvegroup { use crate::ec::tecurve::curvegroup::Point as TEPoint; use crate::cmp::Eq; - struct Curve { // Montgomery Curve configuration (ky^2 z = x*(x^2 + j*x*z + z*z)) + pub struct Curve { // Montgomery Curve configuration (ky^2 z = x*(x^2 + j*x*z + z*z)) j: Field, k: Field, // Generator as point in projective coordinates gen: Point } // Point in projective coordinates - struct Point { + pub struct Point { x: Field, y: Field, z: Field diff --git a/noir/noir-repo/noir_stdlib/src/ec/swcurve.nr b/noir/noir-repo/noir_stdlib/src/ec/swcurve.nr index 9620b23948d..238b0ce3c91 100644 --- a/noir/noir-repo/noir_stdlib/src/ec/swcurve.nr +++ b/noir/noir-repo/noir_stdlib/src/ec/swcurve.nr @@ -10,7 +10,7 @@ mod affine { use crate::cmp::Eq; // Curve specification - struct Curve { // Short Weierstraß curve + pub struct Curve { // Short Weierstraß curve // Coefficients in defining equation y^2 = x^3 + ax + b a: Field, b: Field, @@ -18,7 +18,7 @@ mod affine { gen: Point } // Point in Cartesian coordinates - struct Point { + pub struct Point { x: Field, y: Field, infty: bool // Indicator for point at infinity @@ -194,7 +194,7 @@ mod curvegroup { use crate::cmp::Eq; // Curve specification - struct Curve { // Short Weierstraß curve + pub struct Curve { // Short Weierstraß curve // Coefficients in defining equation y^2 = x^3 + axz^4 + bz^6 a: Field, b: Field, @@ -202,7 +202,7 @@ mod curvegroup { gen: Point } // Point in three-dimensional Jacobian coordinates - struct Point { + pub struct Point { x: Field, y: Field, z: Field // z = 0 corresponds to point at infinity. diff --git a/noir/noir-repo/noir_stdlib/src/ec/tecurve.nr b/noir/noir-repo/noir_stdlib/src/ec/tecurve.nr index 9973678a048..760d9dc2b82 100644 --- a/noir/noir-repo/noir_stdlib/src/ec/tecurve.nr +++ b/noir/noir-repo/noir_stdlib/src/ec/tecurve.nr @@ -12,7 +12,7 @@ mod affine { use crate::cmp::Eq; // Curve specification - struct Curve { // Twisted Edwards curve + pub struct Curve { // Twisted Edwards curve // Coefficients in defining equation ax^2 + y^2 = 1 + dx^2y^2 a: Field, d: Field, @@ -20,7 +20,7 @@ mod affine { gen: Point } // Point in Cartesian coordinates - struct Point { + pub struct Point { x: Field, y: Field } @@ -204,7 +204,7 @@ mod curvegroup { use crate::cmp::Eq; // Curve specification - struct Curve { // Twisted Edwards curve + pub struct Curve { // Twisted Edwards curve // Coefficients in defining equation a(x^2 + y^2)z^2 = z^4 + dx^2y^2 a: Field, d: Field, @@ -212,7 +212,7 @@ mod curvegroup { gen: Point } // Point in extended twisted Edwards coordinates - struct Point { + pub struct Point { x: Field, y: Field, t: Field, diff --git a/noir/noir-repo/noir_stdlib/src/embedded_curve_ops.nr b/noir/noir-repo/noir_stdlib/src/embedded_curve_ops.nr index 094ad5204c3..445b6d96554 100644 --- a/noir/noir-repo/noir_stdlib/src/embedded_curve_ops.nr +++ b/noir/noir-repo/noir_stdlib/src/embedded_curve_ops.nr @@ -4,7 +4,7 @@ use crate::cmp::Eq; /// A point on the embedded elliptic curve /// By definition, the base field of the embedded curve is the scalar field of the proof system curve, i.e the Noir Field. /// x and y denotes the Weierstrass coordinates of the point, if is_infinite is false. -struct EmbeddedCurvePoint { +pub struct EmbeddedCurvePoint { x: Field, y: Field, is_infinite: bool @@ -56,7 +56,7 @@ impl Eq for EmbeddedCurvePoint { /// Scalar for the embedded curve represented as low and high limbs /// By definition, the scalar field of the embedded curve is base field of the proving system curve. /// It may not fit into a Field element, so it is represented with two Field elements; its low and high limbs. -struct EmbeddedCurveScalar { +pub struct EmbeddedCurveScalar { lo: Field, hi: Field, } @@ -71,6 +71,21 @@ impl EmbeddedCurveScalar { let (a,b) = crate::field::bn254::decompose(scalar); EmbeddedCurveScalar { lo: a, hi: b } } + + //Bytes to scalar: take the first (after the specified offset) 16 bytes of the input as the lo value, and the next 16 bytes as the hi value + #[field(bn254)] + fn from_bytes(bytes: [u8; 64], offset: u32) -> EmbeddedCurveScalar { + let mut v = 1; + let mut lo = 0 as Field; + let mut hi = 0 as Field; + for i in 0..16 { + lo = lo + (bytes[offset+31 - i] as Field) * v; + hi = hi + (bytes[offset+15 - i] as Field) * v; + v = v * 256; + } + let sig_s = crate::embedded_curve_ops::EmbeddedCurveScalar { lo, hi }; + sig_s + } } impl Eq for EmbeddedCurveScalar { @@ -110,20 +125,63 @@ pub fn fixed_base_scalar_mul(scalar: EmbeddedCurveScalar) -> EmbeddedCurvePoint multi_scalar_mul([g1], [scalar]) } -// This is a hack as returning an `EmbeddedCurvePoint` from a foreign function in brillig returns a [BrilligVariable::SingleAddr; 2] rather than BrilligVariable::BrilligArray +/// This function only assumes that the points are on the curve +/// It handles corner cases around the infinity point causing some overhead compared to embedded_curve_add_not_nul and embedded_curve_add_unsafe +// This is a hack because returning an `EmbeddedCurvePoint` from a foreign function in brillig returns a [BrilligVariable::SingleAddr; 2] rather than BrilligVariable::BrilligArray // as is defined in the brillig bytecode format. This is a workaround which allows us to fix this without modifying the serialization format. // docs:start:embedded_curve_add -fn embedded_curve_add( - point1: EmbeddedCurvePoint, - point2: EmbeddedCurvePoint -) -> EmbeddedCurvePoint -// docs:end:embedded_curve_add -{ - let point_array = embedded_curve_add_array_return(point1, point2); - let x = point_array[0]; - let y = point_array[1]; - EmbeddedCurvePoint { x, y, is_infinite: point_array[2] == 1 } +pub fn embedded_curve_add(point1: EmbeddedCurvePoint, point2: EmbeddedCurvePoint) -> EmbeddedCurvePoint { + // docs:end:embedded_curve_add + let x_coordinates_match = point1.x == point2.x; + let y_coordinates_match = point1.y == point2.y; + let double_predicate = (x_coordinates_match & y_coordinates_match); + let infinity_predicate = (x_coordinates_match & !y_coordinates_match); + let point1_1 = EmbeddedCurvePoint { x: point1.x + (x_coordinates_match as Field), y: point1.y, is_infinite: x_coordinates_match }; + // point1_1 is guaranteed to have a different abscissa than point2 + let mut result = embedded_curve_add_unsafe(point1_1, point2); + result.is_infinite = x_coordinates_match; + + // dbl if x_match, y_match + let double = embedded_curve_add_unsafe(point1, point1); + result = if double_predicate { double } else { result }; + + // infinity if x_match, !y_match + if point1.is_infinite { + result= point2; + } + if point2.is_infinite { + result = point1; + } + let mut result_is_infinity = infinity_predicate & (!point1.is_infinite & !point2.is_infinite); + result.is_infinite = result_is_infinity | (point1.is_infinite & point2.is_infinite); + result } #[foreign(embedded_curve_add)] fn embedded_curve_add_array_return(_point1: EmbeddedCurvePoint, _point2: EmbeddedCurvePoint) -> [Field; 3] {} + +/// This function assumes that: +/// The points are on the curve, and +/// The points don't share an x-coordinate, and +/// Neither point is the infinity point. +/// If it is used with correct input, the function ensures the correct non-zero result is returned. +/// Except for points on the curve, the other assumptions are checked by the function. It will cause assertion failure if they are not respected. +pub fn embedded_curve_add_not_nul(point1: EmbeddedCurvePoint, point2: EmbeddedCurvePoint) -> EmbeddedCurvePoint { + assert(point1.x != point2.x); + assert(!point1.is_infinite); + assert(!point2.is_infinite); + embedded_curve_add_unsafe(point1, point2) +} + +/// Unsafe ec addition +/// If the inputs are the same, it will perform a doubling, but only if point1 and point2 are the same variable. +/// If they have the same value but are different variables, the result will be incorrect because in this case +/// it assumes (but does not check) that the points' x-coordinates are not equal. +/// It also assumes neither point is the infinity point. +pub fn embedded_curve_add_unsafe(point1: EmbeddedCurvePoint, point2: EmbeddedCurvePoint) -> EmbeddedCurvePoint { + let point_array = embedded_curve_add_array_return(point1, point2); + let x = point_array[0]; + let y = point_array[1]; + + EmbeddedCurvePoint { x, y, is_infinite: false } +} diff --git a/noir/noir-repo/noir_stdlib/src/hash/keccak.nr b/noir/noir-repo/noir_stdlib/src/hash/keccak.nr index 36787c7b4af..c3321b62693 100644 --- a/noir/noir-repo/noir_stdlib/src/hash/keccak.nr +++ b/noir/noir-repo/noir_stdlib/src/hash/keccak.nr @@ -2,7 +2,7 @@ use crate::collections::vec::Vec; use crate::runtime::is_unconstrained; global LIMBS_PER_BLOCK = 17; //BLOCK_SIZE / 8; -global NUM_KECCAK_LANES = 25; +global NUM_KECCAK_LANES: u32 = 25; global BLOCK_SIZE = 136; //(1600 - BITS * 2) / WORD_SIZE; global WORD_SIZE = 8; @@ -77,7 +77,7 @@ pub(crate) fn keccak256(input: [u8; N], message_size: u32) -> [u8; 3 } //2. sponge_absorb - let mut state : [u64;NUM_KECCAK_LANES]= [0; NUM_KECCAK_LANES]; + let mut state : [u64; NUM_KECCAK_LANES]= [0; NUM_KECCAK_LANES]; // When in an unconstrained runtime we can take advantage of runtime loop bounds, // thus allowing us to simplify the loop body. if is_unconstrained() { diff --git a/noir/noir-repo/noir_stdlib/src/hash/mimc.nr b/noir/noir-repo/noir_stdlib/src/hash/mimc.nr index 6145a387f26..8c43536d18b 100644 --- a/noir/noir-repo/noir_stdlib/src/hash/mimc.nr +++ b/noir/noir-repo/noir_stdlib/src/hash/mimc.nr @@ -18,7 +18,7 @@ fn mimc(x: Field, k: Field, constants: [Field; N], exp: Field) -> Fi h + k } -global MIMC_BN254_ROUNDS = 91; +global MIMC_BN254_ROUNDS: u32 = 91; //generated from seed "mimc" using keccak256 global MIMC_BN254_CONSTANTS: [Field; MIMC_BN254_ROUNDS] = [ 0, @@ -126,7 +126,7 @@ pub fn mimc_bn254(array: [Field; N]) -> Field { r } -struct MimcHasher { +pub struct MimcHasher { _state: [Field], } diff --git a/noir/noir-repo/noir_stdlib/src/hash/mod.nr b/noir/noir-repo/noir_stdlib/src/hash/mod.nr index 4c67a0cfa8b..9aa7d220593 100644 --- a/noir/noir-repo/noir_stdlib/src/hash/mod.nr +++ b/noir/noir-repo/noir_stdlib/src/hash/mod.nr @@ -140,7 +140,7 @@ pub fn poseidon2_permutation(_input: [Field; N], _state_length: u32) // Hash trait shall be implemented per type. #[derive_via(derive_hash)] -trait Hash { +pub trait Hash { fn hash(self, state: &mut H) where H: Hasher; } @@ -155,18 +155,18 @@ comptime fn derive_hash(s: StructDefinition) -> Quoted { // Hasher trait shall be implemented by algorithms to provide hash-agnostic means. // TODO: consider making the types generic here ([u8], [Field], etc.) -trait Hasher{ +pub trait Hasher { fn finish(self) -> Field; fn write(&mut self, input: Field); } // BuildHasher is a factory trait, responsible for production of specific Hasher. -trait BuildHasher where H: Hasher{ +pub trait BuildHasher where H: Hasher { fn build_hasher(self) -> H; } -struct BuildHasherDefault; +pub struct BuildHasherDefault; impl BuildHasher for BuildHasherDefault where diff --git a/noir/noir-repo/noir_stdlib/src/hash/poseidon/mod.nr b/noir/noir-repo/noir_stdlib/src/hash/poseidon/mod.nr index 47403e0c1d3..8a1025ada71 100644 --- a/noir/noir-repo/noir_stdlib/src/hash/poseidon/mod.nr +++ b/noir/noir-repo/noir_stdlib/src/hash/poseidon/mod.nr @@ -5,7 +5,7 @@ use crate::default::Default; // A config struct defining the parameters of the Poseidon instance to use. // // A thorough writeup of this method (along with an unoptimized method) can be found at: https://spec.filecoin.io/algorithms/crypto/poseidon/ -struct PoseidonConfig { +pub struct PoseidonConfig { // State width, should be equal to `T` t: Field, // Number of full rounds. should be even @@ -165,7 +165,7 @@ fn sigma(x: [Field; O]) -> [Field; O] { y } -struct PoseidonHasher{ +pub struct PoseidonHasher{ _state: [Field], } diff --git a/noir/noir-repo/noir_stdlib/src/hash/poseidon2.nr b/noir/noir-repo/noir_stdlib/src/hash/poseidon2.nr index 9f28cf3e904..6b61ca32302 100644 --- a/noir/noir-repo/noir_stdlib/src/hash/poseidon2.nr +++ b/noir/noir-repo/noir_stdlib/src/hash/poseidon2.nr @@ -3,7 +3,7 @@ use crate::default::Default; comptime global RATE: u32 = 3; -struct Poseidon2 { +pub struct Poseidon2 { cache: [Field;3], state: [Field;4], cache_size: u32, @@ -82,7 +82,7 @@ impl Poseidon2 { } } -struct Poseidon2Hasher{ +pub struct Poseidon2Hasher{ _state: [Field], } diff --git a/noir/noir-repo/noir_stdlib/src/meta/ctstring.nr b/noir/noir-repo/noir_stdlib/src/meta/ctstring.nr new file mode 100644 index 00000000000..ec205fa6f88 --- /dev/null +++ b/noir/noir-repo/noir_stdlib/src/meta/ctstring.nr @@ -0,0 +1,98 @@ +use crate::append::Append; + +impl CtString { + // docs:start:new + comptime fn new() -> Self { + // docs:end:new + "".as_ctstring() + } + + // Bug: using &mut self as the object results in this method not being found + // docs:start:append_str + comptime fn append_str(self, s: str) -> Self { + // docs:end:append_str + f"{self}{s}".as_ctstring() + } + + // docs:start:append_fmtstr + comptime fn append_fmtstr(self, s: fmtstr) -> Self { + // docs:end:append_fmtstr + f"{self}{s}".as_ctstring() + } + + /// CtString cannot directly return a str since the size would not be known. + /// To get around this, we return a quoted str and the underlying str can + /// be accessed using macro insertion `foo.as_quoted_str!()`. + // docs:start:as_quoted_str + comptime fn as_quoted_str(self) -> Quoted { + // docs:end:as_quoted_str + quote { $self } + } +} + +impl Append for CtString { + fn empty() -> Self { + "".as_ctstring() + } + + fn append(self, other: Self) -> Self { + f"{self}{other}".as_ctstring() + } +} + +// docs:start:as-ctstring +pub trait AsCtString { + comptime fn as_ctstring(self) -> CtString; +} +// docs:end:as-ctstring + +impl AsCtString for str { + comptime fn as_ctstring(self) -> CtString { + str_as_ctstring(self) + } +} + +impl AsCtString for fmtstr { + comptime fn as_ctstring(self) -> CtString { + fmtstr_as_ctstring(self) + } +} + +impl crate::cmp::Eq for CtString { + comptime fn eq(self, other: Self) -> bool { + ctstring_eq(self, other) + } +} + +impl crate::hash::Hash for CtString { + comptime fn hash(self, state: &mut H) where H: crate::hash::Hasher { + state.write(ctstring_hash(self)); + } +} + +#[builtin(str_as_ctstring)] +comptime fn str_as_ctstring(_s: str) -> CtString {} + +#[builtin(fmtstr_as_ctstring)] +comptime fn fmtstr_as_ctstring(_s: fmtstr) -> CtString {} + +#[builtin(ctstring_eq)] +comptime fn ctstring_eq(_first: CtString, _second: CtString) -> bool {} + +#[builtin(ctstring_hash)] +comptime fn ctstring_hash(_string: CtString) -> Field {} + +mod test { + #[test] + fn as_quoted_str_example() { + comptime + { + // docs:start:as_quoted_str_example + let my_ctstring = "foo bar".as_ctstring(); + let my_str = my_ctstring.as_quoted_str!(); + + assert_eq(crate::meta::type_of(my_str), quote { str<7> }.as_type()); + // docs:end:as_quoted_str_example + } + } +} diff --git a/noir/noir-repo/noir_stdlib/src/meta/expr.nr b/noir/noir-repo/noir_stdlib/src/meta/expr.nr index 72e1a88cea8..c96f7d27442 100644 --- a/noir/noir-repo/noir_stdlib/src/meta/expr.nr +++ b/noir/noir-repo/noir_stdlib/src/meta/expr.nr @@ -1,131 +1,229 @@ +//! Contains methods on the built-in `Expr` type for quoted, syntactically valid expressions. + use crate::option::Option; use crate::meta::op::UnaryOp; use crate::meta::op::BinaryOp; impl Expr { + /// If this expression is an array literal `[elem1, ..., elemN]`, this returns a slice of each element in the array. #[builtin(expr_as_array)] // docs:start:as_array comptime fn as_array(self) -> Option<[Expr]> {} // docs:end:as_array + /// If this expression is an assert, this returns the assert expression and the optional message. #[builtin(expr_as_assert)] // docs:start:as_assert comptime fn as_assert(self) -> Option<(Expr, Option)> {} // docs:end:as_assert + /// If this expression is an assert_eq, this returns the left-hand-side and right-hand-side + /// expressions, together with the optional message. #[builtin(expr_as_assert_eq)] // docs:start:as_assert_eq comptime fn as_assert_eq(self) -> Option<(Expr, Expr, Option)> {} // docs:end:as_assert_eq + /// If this expression is an assignment, this returns a tuple with the left hand side + /// and right hand side in order. #[builtin(expr_as_assign)] // docs:start:as_assign comptime fn as_assign(self) -> Option<(Expr, Expr)> {} // docs:end:as_assign - #[builtin(expr_as_integer)] - // docs:start:as_integer - comptime fn as_integer(self) -> Option<(Field, bool)> {} - // docs:end:as_integer - + /// If this expression is a binary operator operation ` `, + /// return the left-hand side, operator, and the right-hand side of the operation. #[builtin(expr_as_binary_op)] // docs:start:as_binary_op comptime fn as_binary_op(self) -> Option<(Expr, BinaryOp, Expr)> {} // docs:end:as_binary_op + /// If this expression is a block `{ stmt1; stmt2; ...; stmtN }`, return + /// a slice containing each statement. #[builtin(expr_as_block)] // docs:start:as_block comptime fn as_block(self) -> Option<[Expr]> {} // docs:end:as_block + /// If this expression is a boolean literal, return that literal. #[builtin(expr_as_bool)] // docs:start:as_bool comptime fn as_bool(self) -> Option {} // docs:end:as_bool + /// If this expression is a cast expression `expr as type`, returns the casted + /// expression and the type to cast to. + // docs:start:as_cast #[builtin(expr_as_cast)] comptime fn as_cast(self) -> Option<(Expr, UnresolvedType)> {} + // docs:end:as_cast + /// If this expression is a `comptime { stmt1; stmt2; ...; stmtN }` block, + /// return each statement in the block. #[builtin(expr_as_comptime)] // docs:start:as_comptime comptime fn as_comptime(self) -> Option<[Expr]> {} // docs:end:as_comptime + /// If this expression is a constructor `Type { field1: expr1, ..., fieldN: exprN }`, + /// return the type and the fields. + #[builtin(expr_as_constructor)] + // docs:start:as_constructor + comptime fn as_constructor(self) -> Option<(UnresolvedType, [(Quoted, Expr)])> {} + // docs:end:as_constructor + + /// If this expression is a for statement over a single expression, return the identifier, + /// the expression and the for loop body. + #[builtin(expr_as_for)] + // docs:start:as_for + comptime fn as_for(self) -> Option<(Quoted, Expr, Expr)> {} + // docs:end:as_for + + /// If this expression is a for statement over a range, return the identifier, + /// the range start, the range end and the for loop body. + #[builtin(expr_as_for_range)] + // docs:start:as_for_range + comptime fn as_for_range(self) -> Option<(Quoted, Expr, Expr, Expr)> {} + // docs:end:as_for_range + + /// If this expression is a function call `foo(arg1, ..., argN)`, return + /// the function and a slice of each argument. #[builtin(expr_as_function_call)] // docs:start:as_function_call comptime fn as_function_call(self) -> Option<(Expr, [Expr])> {} // docs:end:as_function_call + /// If this expression is an `if condition { then_branch } else { else_branch }`, + /// return the condition, then branch, and else branch. If there is no else branch, + /// `None` is returned for that branch instead. #[builtin(expr_as_if)] // docs:start:as_if comptime fn as_if(self) -> Option<(Expr, Expr, Option)> {} // docs:end:as_if + /// If this expression is an index into an array `array[index]`, return the + /// array and the index. #[builtin(expr_as_index)] // docs:start:as_index comptime fn as_index(self) -> Option<(Expr, Expr)> {} // docs:end:as_index + /// If this expression is an integer literal, return the integer as a field + /// as well as whether the integer is negative (true) or not (false). + #[builtin(expr_as_integer)] + // docs:start:as_integer + comptime fn as_integer(self) -> Option<(Field, bool)> {} + // docs:end:as_integer + + /// If this expression is a lambda, returns the parameters, return type and body. + #[builtin(expr_as_lambda)] + // docs:start:as_lambda + comptime fn as_lambda(self) -> Option<([(Expr, Option)], Option, Expr)> {} + // docs:end:as_lambda + + /// If this expression is a let statement, returns the let pattern as an `Expr`, + /// the optional type annotation, and the assigned expression. #[builtin(expr_as_let)] // docs:start:as_let comptime fn as_let(self) -> Option<(Expr, Option, Expr)> {} // docs:end:as_let + /// If this expression is a member access `foo.bar`, return the struct/tuple + /// expression and the field. The field will be represented as a quoted value. #[builtin(expr_as_member_access)] // docs:start:as_member_access comptime fn as_member_access(self) -> Option<(Expr, Quoted)> {} // docs:end:as_member_access + /// If this expression is a method call `foo.bar::(arg1, ..., argN)`, return + /// the receiver, method name, a slice of each generic argument, and a slice of each argument. #[builtin(expr_as_method_call)] // docs:start:as_method_call comptime fn as_method_call(self) -> Option<(Expr, Quoted, [UnresolvedType], [Expr])> {} // docs:end:as_method_call + /// If this expression is a repeated element array `[elem; length]`, return + /// the repeated element and the length expressions. #[builtin(expr_as_repeated_element_array)] // docs:start:as_repeated_element_array comptime fn as_repeated_element_array(self) -> Option<(Expr, Expr)> {} // docs:end:as_repeated_element_array + /// If this expression is a repeated element slice `[elem; length]`, return + /// the repeated element and the length expressions. #[builtin(expr_as_repeated_element_slice)] // docs:start:as_repeated_element_slice comptime fn as_repeated_element_slice(self) -> Option<(Expr, Expr)> {} // docs:end:as_repeated_element_slice + /// If this expression is a slice literal `&[elem1, ..., elemN]`, + /// return each element of the slice. #[builtin(expr_as_slice)] // docs:start:as_slice comptime fn as_slice(self) -> Option<[Expr]> {} // docs:end:as_slice + /// If this expression is a tuple `(field1, ..., fieldN)`, + /// return each element of the tuple. #[builtin(expr_as_tuple)] // docs:start:as_tuple comptime fn as_tuple(self) -> Option<[Expr]> {} // docs:end:as_tuple + /// If this expression is a unary operation ` `, + /// return the unary operator as well as the right-hand side expression. #[builtin(expr_as_unary_op)] // docs:start:as_unary_op comptime fn as_unary_op(self) -> Option<(UnaryOp, Expr)> {} // docs:end:as_unary_op + /// If this expression is an `unsafe { stmt1; ...; stmtN }` block, + /// return each statement inside in a slice. #[builtin(expr_as_unsafe)] // docs:start:as_unsafe comptime fn as_unsafe(self) -> Option<[Expr]> {} // docs:end:as_unsafe + /// Returns `true` if this expression is trailed by a semicolon. + /// + /// Example: + /// + /// ```noir + /// comptime { + /// let expr1 = quote { 1 + 2 }.as_expr().unwrap(); + /// let expr2 = quote { 1 + 2; }.as_expr().unwrap(); + /// + /// assert(expr1.as_binary_op().is_some()); + /// assert(expr2.as_binary_op().is_some()); + /// + /// assert(!expr1.has_semicolon()); + /// assert(expr2.has_semicolon()); + /// } + /// ``` #[builtin(expr_has_semicolon)] // docs:start:has_semicolon comptime fn has_semicolon(self) -> bool {} // docs:end:has_semicolon + /// Returns `true` if this expression is `break`. #[builtin(expr_is_break)] // docs:start:is_break comptime fn is_break(self) -> bool {} // docs:end:is_break + /// Returns `true` if this expression is `continue`. #[builtin(expr_is_continue)] // docs:start:is_continue comptime fn is_continue(self) -> bool {} // docs:end:is_continue + /// Applies a mapping function to this expression and to all of its sub-expressions. + /// `f` will be applied to each sub-expression first, then applied to the expression itself. + /// + /// This happens recursively for every expression within `self`. + /// + /// For example, calling `modify` on `(&[1], &[2, 3])` with an `f` that returns `Option::some` + /// for expressions that are integers, doubling them, would return `(&[2], &[4, 6])`. // docs:start:modify comptime fn modify(self, f: fn[Env](Expr) -> Option) -> Expr { // docs:end:modify @@ -137,8 +235,12 @@ impl Expr { let result = result.or_else(|| modify_block(self, f)); let result = result.or_else(|| modify_cast(self, f)); let result = result.or_else(|| modify_comptime(self, f)); + let result = result.or_else(|| modify_constructor(self, f)); let result = result.or_else(|| modify_if(self, f)); let result = result.or_else(|| modify_index(self, f)); + let result = result.or_else(|| modify_for(self, f)); + let result = result.or_else(|| modify_for_range(self, f)); + let result = result.or_else(|| modify_lambda(self, f)); let result = result.or_else(|| modify_let(self, f)); let result = result.or_else(|| modify_function_call(self, f)); let result = result.or_else(|| modify_member_access(self, f)); @@ -158,12 +260,22 @@ impl Expr { } } + /// Returns this expression as a `Quoted` value. It's the same as `quote { $self }`. // docs:start:quoted comptime fn quoted(self) -> Quoted { // docs:end:quoted quote { $self } } + /// Resolves and type-checks this expression and returns the result as a `TypedExpr`. + /// + /// The `in_function` argument specifies where the expression is resolved: + /// - If it's `none`, the expression is resolved in the function where `resolve` was called + /// - If it's `some`, the expression is resolved in the given function + /// + /// If any names used by this expression are not in scope or if there are any type errors, + /// this will give compiler errors as if the expression was written directly into + /// the current `comptime` function. #[builtin(expr_resolve)] // docs:start:resolve comptime fn resolve(self, in_function: Option) -> TypedExpr {} @@ -252,6 +364,19 @@ comptime fn modify_comptime(expr: Expr, f: fn[Env](Expr) -> Option) - ) } +comptime fn modify_constructor(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_constructor().map( + |expr: (UnresolvedType, [(Quoted, Expr)])| { + let (typ, fields) = expr; + let fields = fields.map(|field: (Quoted, Expr)| { + let (name, value) = field; + (name, value.modify(f)) + }); + new_constructor(typ, fields) + } + ) +} + comptime fn modify_function_call(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { expr.as_function_call().map( |expr: (Expr, [Expr])| { @@ -286,6 +411,40 @@ comptime fn modify_index(expr: Expr, f: fn[Env](Expr) -> Option) -> O ) } +comptime fn modify_for(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_for().map( + |expr: (Quoted, Expr, Expr)| { + let (identifier, array, body) = expr; + let array = array.modify(f); + let body = body.modify(f); + new_for(identifier, array, body) + } + ) +} + +comptime fn modify_for_range(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_for_range().map( + |expr: (Quoted, Expr, Expr, Expr)| { + let (identifier, from, to, body) = expr; + let from = from.modify(f); + let to = to.modify(f); + let body = body.modify(f); + new_for_range(identifier, from, to, body) + } + ) +} + +comptime fn modify_lambda(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_lambda().map( + |expr: ([(Expr, Option)], Option, Expr)| { + let (params, return_type, body) = expr; + let params = params.map(|param: (Expr, Option)| (param.0.modify(f), param.1)); + let body = body.modify(f); + new_lambda(params, return_type, body) + } + ) +} + comptime fn modify_let(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { expr.as_let().map( |expr: (Expr, Option, Expr)| { @@ -427,6 +586,16 @@ comptime fn new_comptime(exprs: [Expr]) -> Expr { quote { comptime { $exprs }}.as_expr().unwrap() } +comptime fn new_constructor(typ: UnresolvedType, fields: [(Quoted, Expr)]) -> Expr { + let fields = fields.map( + |field: (Quoted, Expr)| { + let (name, value) = field; + quote { $name: $value } + } + ).join(quote { , }); + quote { $typ { $fields }}.as_expr().unwrap() +} + comptime fn new_if(condition: Expr, consequence: Expr, alternative: Option) -> Expr { if alternative.is_some() { let alternative = alternative.unwrap(); @@ -436,10 +605,43 @@ comptime fn new_if(condition: Expr, consequence: Expr, alternative: Option } } +comptime fn new_for(identifier: Quoted, array: Expr, body: Expr) -> Expr { + quote { for $identifier in $array { $body } }.as_expr().unwrap() +} + +comptime fn new_for_range(identifier: Quoted, from: Expr, to: Expr, body: Expr) -> Expr { + quote { for $identifier in $from .. $to { $body } }.as_expr().unwrap() +} + comptime fn new_index(object: Expr, index: Expr) -> Expr { quote { $object[$index] }.as_expr().unwrap() } +comptime fn new_lambda( + params: [(Expr, Option)], + return_type: Option, + body: Expr +) -> Expr { + let params = params.map( + |param: (Expr, Option)| { + let (name, typ) = param; + if typ.is_some() { + let typ = typ.unwrap(); + quote { $name: $typ } + } else { + quote { $name } + } + } + ).join(quote { , }); + + if return_type.is_some() { + let return_type = return_type.unwrap(); + quote { |$params| -> $return_type { $body } }.as_expr().unwrap() + } else { + quote { |$params| { $body } }.as_expr().unwrap() + } +} + comptime fn new_let(pattern: Expr, typ: Option, expr: Expr) -> Expr { if typ.is_some() { let typ = typ.unwrap(); @@ -501,189 +703,3 @@ comptime fn new_unsafe(exprs: [Expr]) -> Expr { comptime fn join_expressions(exprs: [Expr], separator: Quoted) -> Quoted { exprs.map(|expr: Expr| expr.quoted()).join(separator) } - -mod tests { - use crate::meta::op::UnaryOp; - use crate::meta::op::BinaryOp; - - #[test] - fn test_expr_as_array() { - comptime - { - let expr = quote { [1, 2, 4] }.as_expr().unwrap(); - let elems = expr.as_array().unwrap(); - assert_eq(elems.len(), 3); - assert_eq(elems[0].as_integer().unwrap(), (1, false)); - assert_eq(elems[1].as_integer().unwrap(), (2, false)); - assert_eq(elems[2].as_integer().unwrap(), (4, false)); - } - } - - #[test] - fn test_expr_as_integer() { - comptime - { - let expr = quote { 1 }.as_expr().unwrap(); - assert_eq((1, false), expr.as_integer().unwrap()); - - let expr = quote { -2 }.as_expr().unwrap(); - assert_eq((2, true), expr.as_integer().unwrap()); - } - } - - #[test] - fn test_expr_as_binary_op() { - comptime - { - assert(get_binary_op(quote { x + y }).is_add()); - assert(get_binary_op(quote { x - y }).is_subtract()); - assert(get_binary_op(quote { x * y }).is_multiply()); - assert(get_binary_op(quote { x / y }).is_divide()); - assert(get_binary_op(quote { x == y }).is_equal()); - assert(get_binary_op(quote { x != y }).is_not_equal()); - assert(get_binary_op(quote { x < y }).is_less_than()); - assert(get_binary_op(quote { x <= y }).is_less_than_or_equal()); - assert(get_binary_op(quote { x > y }).is_greater_than()); - assert(get_binary_op(quote { x >= y }).is_greater_than_or_equal()); - assert(get_binary_op(quote { x & y }).is_and()); - assert(get_binary_op(quote { x | y }).is_or()); - assert(get_binary_op(quote { x ^ y }).is_xor()); - assert(get_binary_op(quote { x >> y }).is_shift_right()); - assert(get_binary_op(quote { x << y }).is_shift_left()); - assert(get_binary_op(quote { x % y }).is_modulo()); - } - } - - #[test] - fn test_expr_as_bool() { - comptime - { - let expr = quote { false }.as_expr().unwrap(); - assert(expr.as_bool().unwrap() == false); - - let expr = quote { true }.as_expr().unwrap(); - assert_eq(expr.as_bool().unwrap(), true); - } - } - - #[test] - fn test_expr_as_function_call() { - comptime - { - let expr = quote { foo(42) }.as_expr().unwrap(); - let (_function, args) = expr.as_function_call().unwrap(); - assert_eq(args.len(), 1); - assert_eq(args[0].as_integer().unwrap(), (42, false)); - } - } - - #[test] - fn test_expr_as_if() { - comptime - { - let expr = quote { if 1 { 2 } }.as_expr().unwrap(); - let (_condition, _consequence, alternative) = expr.as_if().unwrap(); - assert(alternative.is_none()); - - let expr = quote { if 1 { 2 } else { 3 } }.as_expr().unwrap(); - let (_condition, _consequence, alternative) = expr.as_if().unwrap(); - assert(alternative.is_some()); - } - } - - #[test] - fn test_expr_as_index() { - comptime - { - let expr = quote { foo[bar] }.as_expr().unwrap(); - assert(expr.as_index().is_some()); - } - } - - #[test] - fn test_expr_as_member_access() { - comptime - { - let expr = quote { foo.bar }.as_expr().unwrap(); - let (_, name) = expr.as_member_access().unwrap(); - assert_eq(name, quote { bar }); - } - } - - #[test] - fn test_expr_as_repeated_element_array() { - comptime - { - let expr = quote { [1; 3] }.as_expr().unwrap(); - let (expr, length) = expr.as_repeated_element_array().unwrap(); - assert_eq(expr.as_integer().unwrap(), (1, false)); - assert_eq(length.as_integer().unwrap(), (3, false)); - } - } - - #[test] - fn test_expr_as_repeated_element_slice() { - comptime - { - let expr = quote { &[1; 3] }.as_expr().unwrap(); - let (expr, length) = expr.as_repeated_element_slice().unwrap(); - assert_eq(expr.as_integer().unwrap(), (1, false)); - assert_eq(length.as_integer().unwrap(), (3, false)); - } - } - - #[test] - fn test_expr_as_slice() { - comptime - { - let expr = quote { &[1, 3, 5] }.as_expr().unwrap(); - let elems = expr.as_slice().unwrap(); - assert_eq(elems.len(), 3); - assert_eq(elems[0].as_integer().unwrap(), (1, false)); - assert_eq(elems[1].as_integer().unwrap(), (3, false)); - assert_eq(elems[2].as_integer().unwrap(), (5, false)); - } - } - - #[test] - fn test_expr_as_tuple() { - comptime - { - let expr = quote { (1, 2) }.as_expr().unwrap(); - let tuple_exprs = expr.as_tuple().unwrap(); - assert_eq(tuple_exprs.len(), 2); - } - } - - #[test] - fn test_expr_as_unary_op() { - comptime - { - assert(get_unary_op(quote { -x }).is_minus()); - assert(get_unary_op(quote { !x }).is_not()); - assert(get_unary_op(quote { &mut x }).is_mutable_reference()); - assert(get_unary_op(quote { *x }).is_dereference()); - } - } - - #[test] - fn test_automatically_unwraps_parenthesized_expression() { - comptime - { - let expr = quote { ((if 1 { 2 })) }.as_expr().unwrap(); - assert(expr.as_if().is_some()); - } - } - - comptime fn get_unary_op(quoted: Quoted) -> UnaryOp { - let expr = quoted.as_expr().unwrap(); - let (op, _) = expr.as_unary_op().unwrap(); - op - } - - comptime fn get_binary_op(quoted: Quoted) -> BinaryOp { - let expr = quoted.as_expr().unwrap(); - let (_, op, _) = expr.as_binary_op().unwrap(); - op - } -} diff --git a/noir/noir-repo/noir_stdlib/src/meta/mod.nr b/noir/noir-repo/noir_stdlib/src/meta/mod.nr index 1079cc6013a..1d787ebcdc1 100644 --- a/noir/noir-repo/noir_stdlib/src/meta/mod.nr +++ b/noir/noir-repo/noir_stdlib/src/meta/mod.nr @@ -1,3 +1,4 @@ +mod ctstring; mod expr; mod format_string; mod function_def; @@ -129,8 +130,13 @@ mod tests { // let _a: Quoted = quote { 1 }; let _a: Quoted = quote_one(); - // let _b: i32 = 1; - let _b: i32 = quote_one!(); + // let _b: Field = 1; + let _b: Field = quote_one!(); + + // Since integers default to fields, if we + // want a different type we have to explicitly cast + // let _c: i32 = 1 as i32; + let _c: i32 = quote_one!() as i32; } } // docs:end:quote-example @@ -236,4 +242,14 @@ mod tests { ) } // docs:end:big-derive-usage-example + + // 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 _ = derive_do_nothing(crate::panic::panic(f"")); + let _ = derive_do_nothing_alt(crate::panic::panic(f"")); + remove_unused_warnings(); + } } diff --git a/noir/noir-repo/noir_stdlib/src/meta/op.nr b/noir/noir-repo/noir_stdlib/src/meta/op.nr index 31a815f07ba..197daaabaa6 100644 --- a/noir/noir-repo/noir_stdlib/src/meta/op.nr +++ b/noir/noir-repo/noir_stdlib/src/meta/op.nr @@ -1,5 +1,5 @@ #[derive(Eq, Hash)] -struct UnaryOp { +pub struct UnaryOp { op: Field } @@ -47,7 +47,7 @@ impl UnaryOp { } #[derive(Eq, Hash)] -struct BinaryOp { +pub struct BinaryOp { op: Field } diff --git a/noir/noir-repo/noir_stdlib/src/ops/arith.nr b/noir/noir-repo/noir_stdlib/src/ops/arith.nr index 653dfd59978..195ae777580 100644 --- a/noir/noir-repo/noir_stdlib/src/ops/arith.nr +++ b/noir/noir-repo/noir_stdlib/src/ops/arith.nr @@ -1,5 +1,5 @@ // docs:start:add-trait -trait Add { +pub trait Add { fn add(self, other: Self) -> Self; } // docs:end:add-trait @@ -58,7 +58,7 @@ impl Add for i64 { } // docs:start:sub-trait -trait Sub { +pub trait Sub { fn sub(self, other: Self) -> Self; } // docs:end:sub-trait @@ -117,7 +117,7 @@ impl Sub for i64 { } // docs:start:mul-trait -trait Mul { +pub trait Mul { fn mul(self, other: Self) -> Self; } // docs:end:mul-trait @@ -176,7 +176,7 @@ impl Mul for i64 { } // docs:start:div-trait -trait Div { +pub trait Div { fn div(self, other: Self) -> Self; } // docs:end:div-trait @@ -235,7 +235,7 @@ impl Div for i64 { } // docs:start:rem-trait -trait Rem{ +pub trait Rem { fn rem(self, other: Self) -> Self; } // docs:end:rem-trait @@ -288,7 +288,7 @@ impl Rem for i64 { } // docs:start:neg-trait -trait Neg { +pub trait Neg { fn neg(self) -> Self; } // docs:end:neg-trait diff --git a/noir/noir-repo/noir_stdlib/src/ops/bit.nr b/noir/noir-repo/noir_stdlib/src/ops/bit.nr index 0c0329efe4c..70c52ac38b0 100644 --- a/noir/noir-repo/noir_stdlib/src/ops/bit.nr +++ b/noir/noir-repo/noir_stdlib/src/ops/bit.nr @@ -1,5 +1,5 @@ // docs:start:not-trait -trait Not { +pub trait Not { fn not(self: Self) -> Self; } // docs:end:not-trait @@ -60,7 +60,7 @@ impl Not for i64 { // docs:end:not-trait-impls // docs:start:bitor-trait -trait BitOr { +pub trait BitOr { fn bitor(self, other: Self) -> Self; } // docs:end:bitor-trait @@ -119,7 +119,7 @@ impl BitOr for i64 { } // docs:start:bitand-trait -trait BitAnd { +pub trait BitAnd { fn bitand(self, other: Self) -> Self; } // docs:end:bitand-trait @@ -178,7 +178,7 @@ impl BitAnd for i64 { } // docs:start:bitxor-trait -trait BitXor { +pub trait BitXor { fn bitxor(self, other: Self) -> Self; } // docs:end:bitxor-trait @@ -237,7 +237,7 @@ impl BitXor for i64 { } // docs:start:shl-trait -trait Shl { +pub trait Shl { fn shl(self, other: u8) -> Self; } // docs:end:shl-trait @@ -290,7 +290,7 @@ impl Shl for i64 { } // docs:start:shr-trait -trait Shr { +pub trait Shr { fn shr(self, other: u8) -> Self; } // docs:end:shr-trait diff --git a/noir/noir-repo/noir_stdlib/src/option.nr b/noir/noir-repo/noir_stdlib/src/option.nr index 2823ba8af1b..6b3a2bf2f3c 100644 --- a/noir/noir-repo/noir_stdlib/src/option.nr +++ b/noir/noir-repo/noir_stdlib/src/option.nr @@ -2,7 +2,7 @@ use crate::hash::{Hash, Hasher}; use crate::cmp::{Ordering, Ord, Eq}; use crate::default::Default; -struct Option { +pub struct Option { _is_some: bool, _value: T, } diff --git a/noir/noir-repo/noir_stdlib/src/schnorr.nr b/noir/noir-repo/noir_stdlib/src/schnorr.nr index 24ca514025c..336041fec19 100644 --- a/noir/noir-repo/noir_stdlib/src/schnorr.nr +++ b/noir/noir-repo/noir_stdlib/src/schnorr.nr @@ -1,3 +1,6 @@ +use crate::collections::vec::Vec; +use crate::embedded_curve_ops::{EmbeddedCurvePoint, EmbeddedCurveScalar}; + #[foreign(schnorr_verify)] // docs:start:schnorr_verify pub fn verify_signature( @@ -20,3 +23,65 @@ 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 { + //scalar lo/hi from bytes + let sig_s = EmbeddedCurveScalar::from_bytes(signature, 0); + let sig_e = EmbeddedCurveScalar::from_bytes(signature, 32); + // pub_key is on Grumpkin curve + let mut is_ok = (public_key.y * public_key.y == public_key.x * public_key.x * public_key.x - 17) + & (!public_key.is_infinite); + + if ((sig_s.lo != 0) | (sig_s.hi != 0)) & ((sig_e.lo != 0) | (sig_e.hi != 0)) { + let (r_is_infinite, result) = calculate_signature_challenge(public_key, sig_s, sig_e, message); + + is_ok = !r_is_infinite; + for i in 0..32 { + is_ok &= result[i] == signature[32 + i]; + } + } + is_ok +} + +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); + + // assert pub_key is on Grumpkin curve + assert(public_key.y * public_key.y == public_key.x * public_key.x * public_key.x - 17); + assert(public_key.is_infinite == false); + // assert signature is not null + assert((sig_s.lo != 0) | (sig_s.hi != 0)); + assert((sig_e.lo != 0) | (sig_e.hi != 0)); + + let (r_is_infinite, result) = calculate_signature_challenge(public_key, sig_s, sig_e, message); + + assert(!r_is_infinite); + for i in 0..32 { + assert(result[i] == signature[32 + i]); + } +} + +fn calculate_signature_challenge( + public_key: EmbeddedCurvePoint, + sig_s: EmbeddedCurveScalar, + sig_e: EmbeddedCurveScalar, + message: [u8; N] +) -> (bool, [u8; 32]) { + let g1 = EmbeddedCurvePoint { x: 1, y: 17631683881184975370165255887551781615748388533673675138860, is_infinite: false }; + let r = crate::embedded_curve_ops::multi_scalar_mul([g1, public_key], [sig_s, sig_e]); + // compare the _hashes_ rather than field elements modulo r + let pedersen_hash = crate::hash::pedersen_hash([r.x, public_key.x, public_key.y]); + let pde: [u8; 32] = pedersen_hash.to_be_bytes(); + + let mut hash_input = [0; N + 32]; + for i in 0..32 { + hash_input[i] = pde[i]; + } + for i in 0..N { + hash_input[32+i] = message[i]; + } + + let result = crate::hash::blake2s(hash_input); + (r.is_infinite, result) +} diff --git a/noir/noir-repo/noir_stdlib/src/test.nr b/noir/noir-repo/noir_stdlib/src/test.nr index f8db6079193..e906ad54d55 100644 --- a/noir/noir-repo/noir_stdlib/src/test.nr +++ b/noir/noir-repo/noir_stdlib/src/test.nr @@ -16,7 +16,7 @@ unconstrained fn set_mock_times_oracle(id: Field, times: u64) {} #[oracle(clear_mock)] unconstrained fn clear_mock_oracle(id: Field) {} -struct OracleMock { +pub struct OracleMock { id: Field, } diff --git a/noir/noir-repo/noir_stdlib/src/uint128.nr b/noir/noir-repo/noir_stdlib/src/uint128.nr index 91c3369f889..a3d7491eaff 100644 --- a/noir/noir-repo/noir_stdlib/src/uint128.nr +++ b/noir/noir-repo/noir_stdlib/src/uint128.nr @@ -3,7 +3,7 @@ use crate::cmp::{Eq, Ord, Ordering}; global pow64 : Field = 18446744073709551616; //2^64; global pow63 : Field = 9223372036854775808; // 2^63; -struct U128 { +pub struct U128 { lo: Field, hi: Field, } diff --git a/noir/noir-repo/scripts/install_bb.sh b/noir/noir-repo/scripts/install_bb.sh index 015091c07cf..d60c73c0976 100755 --- a/noir/noir-repo/scripts/install_bb.sh +++ b/noir/noir-repo/scripts/install_bb.sh @@ -1,6 +1,6 @@ #!/bin/bash -VERSION="0.51.1" +VERSION="0.55.0" BBUP_PATH=~/.bb/bbup diff --git a/noir/noir-repo/test_programs/compile_failure/comptime_parse_all_tokens/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/comptime_parse_all_tokens/Nargo.toml new file mode 100644 index 00000000000..2d9b78c9c38 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/comptime_parse_all_tokens/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "comptime_parse_all_tokens" +type = "bin" +authors = [""] +compiler_version = ">=0.34.0" + +[dependencies] diff --git a/noir/noir-repo/test_programs/compile_failure/comptime_parse_all_tokens/src/main.nr b/noir/noir-repo/test_programs/compile_failure/comptime_parse_all_tokens/src/main.nr new file mode 100644 index 00000000000..8e9a607f44a --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/comptime_parse_all_tokens/src/main.nr @@ -0,0 +1,9 @@ +#[foo] +fn main() {} + +comptime fn foo(_f: FunctionDefinition) -> Quoted { + let t = quote { Field }.as_type(); + // We parse 0 or more top level expressions from attribute output + // so for invalid input we previously "successfully" parsed 0 items. + quote { use $t; } +} diff --git a/noir/noir-repo/test_programs/compile_failure/global_without_a_type_used_as_array_length/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/global_without_a_type_used_as_array_length/Nargo.toml new file mode 100644 index 00000000000..b2c83a26988 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/global_without_a_type_used_as_array_length/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "global_without_a_type_used_as_array_length" +type = "bin" +authors = [""] +compiler_version = ">=0.33.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_failure/global_without_a_type_used_as_array_length/src/main.nr b/noir/noir-repo/test_programs/compile_failure/global_without_a_type_used_as_array_length/src/main.nr new file mode 100644 index 00000000000..9edda231dec --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/global_without_a_type_used_as_array_length/src/main.nr @@ -0,0 +1,2 @@ +global BAR = OOPS; +global X: [Field; BAR] = []; diff --git a/noir/noir-repo/test_programs/compile_failure/macro_result_type/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/macro_result_type/Nargo.toml new file mode 100644 index 00000000000..664e405d5fe --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/macro_result_type/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "macro_result_type" +type = "bin" +authors = [""] +compiler_version = ">=0.34.0" + +[dependencies] diff --git a/noir/noir-repo/test_programs/compile_failure/macro_result_type/src/main.nr b/noir/noir-repo/test_programs/compile_failure/macro_result_type/src/main.nr new file mode 100644 index 00000000000..4dc97d1d422 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/macro_result_type/src/main.nr @@ -0,0 +1,13 @@ +fn main() { + comptime + { + let signature = "hello".as_ctstring(); + let string = signature.as_quoted_str!(); + let result = half(string); + assert_eq(result, 2); + } +} + +comptime fn half(_s: str) -> u32 { + N / 2 +} diff --git a/noir/noir-repo/test_programs/compile_success_empty/arithmetic_generics/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/arithmetic_generics/src/main.nr index ad8dff6c7b9..0a7d319485c 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/arithmetic_generics/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_empty/arithmetic_generics/src/main.nr @@ -101,8 +101,11 @@ fn demo_proof() -> Equiv, (Equiv, (), W, () let p1: Equiv, (), W, ()> = mul_comm(); let p2: Equiv, (), W, ()> = mul_add::(); let p3_sub: Equiv, (), W, ()> = mul_one_r(); - let p3: Equiv, (), W, ()> = add_equiv_r::(p3_sub); - equiv_trans(equiv_trans(p1, p2), p3) + let _p3: Equiv, (), W, ()> = add_equiv_r::(p3_sub); + let _p1_to_2 = equiv_trans(p1, p2); + + // equiv_trans(p1_to_2, p3) + std::mem::zeroed() } fn test_constant_folding() { diff --git a/noir/noir-repo/test_programs/compile_success_empty/closure_explicit_types/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/closure_explicit_types/src/main.nr index b6c8a6b7b3c..c43fc9cb34b 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/closure_explicit_types/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_empty/closure_explicit_types/src/main.nr @@ -35,7 +35,7 @@ fn add_results(f1: fn[Env1]() -> Field, f2: fn[Env2]() -> Field) -> f1() + f2() } // a *really* generic function -fn map(arr: [T; N], f: fn[Env](T) -> U) -> [U; N] { +fn map(arr: [T; N], f: fn[Env](T) -> U) -> [U; N] { let first_elem = f(arr[0]); let mut ret = [first_elem; N]; diff --git a/noir/noir-repo/test_programs/compile_success_empty/comptime_change_type_each_iteration/Nargo.toml b/noir/noir-repo/test_programs/compile_success_empty/comptime_change_type_each_iteration/Nargo.toml new file mode 100644 index 00000000000..38e72395bb5 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/comptime_change_type_each_iteration/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "comptime_change_type_each_iteration" +type = "bin" +authors = [""] +compiler_version = ">=0.34.0" + +[dependencies] diff --git a/noir/noir-repo/test_programs/compile_success_empty/comptime_change_type_each_iteration/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/comptime_change_type_each_iteration/src/main.nr new file mode 100644 index 00000000000..7b34c112d4f --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/comptime_change_type_each_iteration/src/main.nr @@ -0,0 +1,19 @@ +fn main() { + comptime + { + for i in 9..11 { + // Lengths are different on each iteration: + // foo9, foo10 + let name = f"foo{i}".as_ctstring().as_quoted_str!(); + + // So to call `from_signature` we need to delay the type check + // by quoting the function call so that we re-typecheck on each iteration + let hash = std::meta::unquote!(quote { from_signature($name) }); + assert(hash > 3); + } + } +} + +fn from_signature(_signature: str) -> u32 { + N +} diff --git a/noir/noir-repo/test_programs/compile_success_empty/comptime_parse_statement_as_expression/Nargo.toml b/noir/noir-repo/test_programs/compile_success_empty/comptime_parse_statement_as_expression/Nargo.toml new file mode 100644 index 00000000000..65fa5b1ed06 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/comptime_parse_statement_as_expression/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "comptime_parse_statement_as_expression" +type = "bin" +authors = [""] +compiler_version = ">=0.33.0" + +[dependencies] diff --git a/noir/noir-repo/test_programs/compile_success_empty/comptime_parse_statement_as_expression/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/comptime_parse_statement_as_expression/src/main.nr new file mode 100644 index 00000000000..4fa47dbc2f7 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/comptime_parse_statement_as_expression/src/main.nr @@ -0,0 +1,27 @@ +fn main() { + comptime + { + let block = quote[{ + 1; + 2; + 3 + }]; + let statements = block.as_expr().unwrap().as_block().unwrap(); + let last = statements.pop_back().1; + + // `3` should fit in an expression position even though it is + // originally a StatementKind::Expression + let regression1 = quote[{ + let _ = $last; + }]; + assert(regression1.as_expr().is_some()); + + // `1;` should fit in an expression position even though it is + // originally a StatementKind::Semi + let first = statements.pop_front().0; + let regression2 = quote[{ + let _ = $first; + }]; + assert(regression2.as_expr().is_some()); + } +} diff --git a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Nargo.toml b/noir/noir-repo/test_programs/compile_success_empty/comptime_to_radix/Nargo.toml similarity index 66% rename from noir/noir-repo/test_programs/execution_success/verify_honk_proof/Nargo.toml rename to noir/noir-repo/test_programs/compile_success_empty/comptime_to_radix/Nargo.toml index 8fce1bf44b6..35713aff805 100644 --- a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Nargo.toml +++ b/noir/noir-repo/test_programs/compile_success_empty/comptime_to_radix/Nargo.toml @@ -1,5 +1,5 @@ [package] -name = "verify_honk_proof" +name = "comptime_to_radix" type = "bin" authors = [""] diff --git a/noir/noir-repo/test_programs/compile_success_empty/comptime_to_radix/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/comptime_to_radix/src/main.nr new file mode 100644 index 00000000000..959a7c12007 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/comptime_to_radix/src/main.nr @@ -0,0 +1,10 @@ +fn main() { + comptime + { + let le_bytes: [u8; 3] = 257.to_le_bytes(); + assert_eq(le_bytes, [1, 1, 0]); + + let be_bytes: [u8; 3] = 257.to_be_bytes(); + assert_eq(be_bytes, [0, 1, 1]); + } +} diff --git a/noir/noir-repo/test_programs/compile_success_empty/ctstring/Nargo.toml b/noir/noir-repo/test_programs/compile_success_empty/ctstring/Nargo.toml new file mode 100644 index 00000000000..493fd8a6e4b --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/ctstring/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "ctstring" +type = "bin" +authors = [""] +compiler_version = ">=0.33.0" + +[dependencies] diff --git a/noir/noir-repo/test_programs/compile_success_empty/ctstring/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/ctstring/src/main.nr new file mode 100644 index 00000000000..b2329cb1997 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/ctstring/src/main.nr @@ -0,0 +1,18 @@ +fn main() { + comptime + { + let msg1 = "msg1"; + let msg2 = f" (msg2 contains {msg1}) "; + + let s1 = msg1.as_ctstring(); + let s2 = msg2.as_ctstring(); + + let s3 = &[s1, s2, s1].join("".as_ctstring()); + assert_eq(s3, "msg1 (msg2 contains msg1) msg1".as_ctstring()); + + let mut s4 = s1; + s4 = s4.append_fmtstr(msg2); + s4 = s4.append_str(msg1); + assert_eq(s3, s4); + } +} diff --git a/noir/noir-repo/test_programs/compile_success_empty/field_or_integer_static_trait_method/Nargo.toml b/noir/noir-repo/test_programs/compile_success_empty/field_or_integer_static_trait_method/Nargo.toml new file mode 100644 index 00000000000..18d9fc90d9e --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/field_or_integer_static_trait_method/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "field_or_int_static_trait_method" +type = "bin" +authors = [""] +compiler_version = ">=0.32.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_success_empty/field_or_integer_static_trait_method/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/field_or_integer_static_trait_method/src/main.nr new file mode 100644 index 00000000000..f5a54c82ce5 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/field_or_integer_static_trait_method/src/main.nr @@ -0,0 +1,25 @@ +trait Read { + fn read(data: [Field; 1]) -> Self; +} + +impl Read for Field { + fn read(data: [Field; 1]) -> Self { + data[0] * 10 + } +} + +impl Read for u32 { + fn read(data: [Field; 1]) -> Self { + data[0] as u32 + } +} + +fn main() { + let data = [1]; + + let value: u32 = u32::read(data); + assert_eq(value, 1); + + let value: Field = Field::read(data); + assert_eq(value, 10); +} diff --git a/noir/noir-repo/test_programs/compile_success_empty/macros_in_comptime/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/macros_in_comptime/src/main.nr index c5cc7880112..197f4e87f0b 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/macros_in_comptime/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_empty/macros_in_comptime/src/main.nr @@ -1,11 +1,14 @@ use std::field::modulus_num_bits; use std::meta::unquote; +// Numeric generics default to u32 +global three_field: Field = 3; + fn main() { comptime { unsafe { - foo::<3>(5) + foo::(5) }; submodule::bar(); } diff --git a/noir/noir-repo/test_programs/compile_success_empty/numeric_generics/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/numeric_generics/src/main.nr index 340c18c2a1d..04f170aef58 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/numeric_generics/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_empty/numeric_generics/src/main.nr @@ -14,15 +14,15 @@ fn main() { assert(foo(itWorks2).data[0] == itWorks2.data[0] + 1); } -fn id(x: [Field; I]) -> [Field; I] { +fn id(x: [Field; I]) -> [Field; I] { x } -struct MyStruct { +struct MyStruct { data: [Field; S], } -impl MyStruct { +impl MyStruct { fn insert(mut self: Self, index: Field, elem: Field) -> Self { // Regression test for numeric generics on impls assert(index as u64 < S as u64); diff --git a/noir/noir-repo/test_programs/compile_success_empty/numeric_generics_explicit/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/numeric_generics_explicit/src/main.nr index 7c4f7761ff6..5c618e9db36 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/numeric_generics_explicit/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_empty/numeric_generics_explicit/src/main.nr @@ -28,7 +28,7 @@ fn main() { } // Used in the signature of a function -fn id(x: [Field; I]) -> [Field; I] { +fn id(x: [Field; I]) -> [Field; I] { x } diff --git a/noir/noir-repo/test_programs/compile_success_empty/parenthesized_expression_in_array_length/Nargo.toml b/noir/noir-repo/test_programs/compile_success_empty/parenthesized_expression_in_array_length/Nargo.toml new file mode 100644 index 00000000000..e56e9643f40 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/parenthesized_expression_in_array_length/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "parenthesized_expression_in_array_length" +type = "bin" +authors = [""] +compiler_version = ">=0.32.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_success_empty/parenthesized_expression_in_array_length/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/parenthesized_expression_in_array_length/src/main.nr new file mode 100644 index 00000000000..b596d331e7f --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/parenthesized_expression_in_array_length/src/main.nr @@ -0,0 +1,6 @@ +global N = 100; +global BLOCK_SIZE = 10; + +fn main() { + let _: [Field; 110] = [0; ((N + BLOCK_SIZE) * BLOCK_SIZE) / BLOCK_SIZE]; +} diff --git a/noir/noir-repo/test_programs/compile_success_empty/references_aliasing/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/references_aliasing/src/main.nr index d3e4257851b..b2b625477e7 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/references_aliasing/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_empty/references_aliasing/src/main.nr @@ -6,6 +6,7 @@ fn main() { regression_2445(); single_alias_inside_loop(); + assert(5 == struct_field_refs_across_blocks(MyStruct { a: 5, b: 10 })[0]); } fn increment(mut r: &mut Field) { @@ -39,3 +40,20 @@ fn single_alias_inside_loop() { assert(var == 2); assert(**ref == 2); } + +struct MyStruct { + a: Field, + b: u32, +} + +fn struct_field_refs_across_blocks(mut my_struct: MyStruct) -> [Field; 1] { + [compute_dummy_hash(my_struct.a, my_struct.b, 20)] +} + +fn compute_dummy_hash(input: Field, rhs: u32, in_len: u32) -> Field { + let mut res = 0; + if rhs < in_len { + res += input; + } + res +} diff --git a/noir/noir-repo/test_programs/compile_success_empty/regression_4635/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/regression_4635/src/main.nr index 6709a421470..6bccdf9e30f 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/regression_4635/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_empty/regression_4635/src/main.nr @@ -12,7 +12,7 @@ trait Deserialize { fn deserialize(fields: [Field; N]) -> Self; } -global AZTEC_ADDRESS_LENGTH = 1; +global AZTEC_ADDRESS_LENGTH: u32 = 1; struct AztecAddress { inner : Field diff --git a/noir/noir-repo/test_programs/compile_success_empty/regression_6077/Nargo.toml b/noir/noir-repo/test_programs/compile_success_empty/regression_6077/Nargo.toml new file mode 100644 index 00000000000..0c1118245f4 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/regression_6077/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_6077" +type = "bin" +authors = [""] +compiler_version = ">=0.30.0" + +[dependencies] diff --git a/noir/noir-repo/test_programs/compile_success_empty/regression_6077/Prover.toml b/noir/noir-repo/test_programs/compile_success_empty/regression_6077/Prover.toml new file mode 100644 index 00000000000..ba3522cab01 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/regression_6077/Prover.toml @@ -0,0 +1 @@ +a = 0 diff --git a/noir/noir-repo/test_programs/compile_success_empty/regression_6077/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/regression_6077/src/main.nr new file mode 100644 index 00000000000..fe067177e77 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/regression_6077/src/main.nr @@ -0,0 +1,28 @@ +struct WeirdStruct { + a: T, + b: U, +} + +#[mangle_fn] +pub fn my_fn() -> [u8; 3] { + [0; 3] +} + +comptime fn mangle_fn(f: FunctionDefinition) { + let return_type = f.return_type(); + + // This relies on how types are displayed + let generics = f"Field,{return_type}".quoted_contents(); + let new_return_type = quote { WeirdStruct<$generics>}.as_type(); + + let new_body = quote { + { + WeirdStruct { a: 1, b: [0;3] } + } + }.as_expr().unwrap(); + + f.set_return_type(new_return_type); + f.set_body(new_body); +} + +fn main() {} diff --git a/noir/noir-repo/test_programs/compile_success_empty/serialize/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/serialize/src/main.nr index 6fee6fb72a6..19f3f0319b8 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/serialize/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_empty/serialize/src/main.nr @@ -7,7 +7,7 @@ trait Serialize { impl Serialize for (A, B) where A: Serialize, B: Serialize { // let Size = ::Size + ::Size; - let Size = AS + BS; + let Size: u32 = AS + BS; fn serialize(self: Self) -> [Field; Self::Size] { let mut array: [Field; Self::Size] = std::mem::zeroed(); @@ -26,7 +26,7 @@ impl Serialize for (A, B) where A: Serialize Serialize for [T; N] where T: Serialize { // let Size = ::Size * N; - let Size = TS * N; + let Size: u32 = TS * N; fn serialize(self: Self) -> [Field; Self::Size] { let mut array: [Field; Self::Size] = std::mem::zeroed(); @@ -46,7 +46,7 @@ impl Serialize for [T; N] where T: Serialize [Field; Self::Size] { [self] diff --git a/noir/noir-repo/test_programs/compile_success_empty/trait_generics/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/trait_generics/src/main.nr index 15591f2f2ea..77309ca4bee 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/trait_generics/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_empty/trait_generics/src/main.nr @@ -44,13 +44,13 @@ impl Serializable<2> for Data { } } -fn sum(data: T) -> Field where T: Serializable { +fn sum(data: T) -> Field where T: Serializable { let serialized = data.serialize(); serialized.fold(0, |acc, elem| acc + elem) } // Test static trait method syntax -fn sum_static(data: T) -> Field where T: Serializable { +fn sum_static(data: T) -> Field where T: Serializable { let serialized = Serializable::serialize(data); serialized.fold(0, |acc, elem| acc + elem) } diff --git a/noir/noir-repo/test_programs/compile_success_empty/type_path/Nargo.toml b/noir/noir-repo/test_programs/compile_success_empty/type_path/Nargo.toml new file mode 100644 index 00000000000..0e76437d15f --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/type_path/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "type_path" +type = "bin" +authors = [""] +compiler_version = ">=0.34.0" + +[dependencies] diff --git a/noir/noir-repo/test_programs/compile_success_empty/type_path/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/type_path/src/main.nr new file mode 100644 index 00000000000..96f3a29d96b --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/type_path/src/main.nr @@ -0,0 +1,15 @@ +fn main() { + comptime + { + let foo = quote { Foo }.as_type(); + quote { + $foo::static() + } + } +} + +struct Foo {} + +impl Foo { + fn static() {} +} diff --git a/noir/noir-repo/test_programs/compile_success_empty/use_callers_scope/Nargo.toml b/noir/noir-repo/test_programs/compile_success_empty/use_callers_scope/Nargo.toml new file mode 100644 index 00000000000..14402c7d7b1 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/use_callers_scope/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "use_callers_scope" +type = "bin" +authors = [""] +compiler_version = ">=0.34.0" + +[dependencies] diff --git a/noir/noir-repo/test_programs/compile_success_empty/use_callers_scope/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/use_callers_scope/src/main.nr new file mode 100644 index 00000000000..b4e8a7f7c4d --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/use_callers_scope/src/main.nr @@ -0,0 +1,34 @@ +#[bar::struct_attr] +struct Foo {} + +struct Bar {} + +#[bar::fn_attr] +fn main() {} + +mod bar { + #[use_callers_scope] + pub comptime fn struct_attr(_: StructDefinition) { + let _ = quote { Bar }.as_type(); + } + + #[use_callers_scope] + pub comptime fn fn_attr(_: FunctionDefinition) { + let _ = quote { Bar }.as_type(); + let _ = nested(); + + // Ensure closures can still access Bar even + // though `map` separates them from `fn_attr`. + let _ = &[1, 2, 3].map( + |_| { + quote { Bar }.as_type() + } + ); + } + + // use_callers_scope should also work nested + #[use_callers_scope] + comptime fn nested() -> Type { + quote { Bar }.as_type() + } +} diff --git a/noir/noir-repo/test_programs/compile_success_no_bug/databus_mapping_regression/Nargo.toml b/noir/noir-repo/test_programs/compile_success_no_bug/databus_mapping_regression/Nargo.toml new file mode 100644 index 00000000000..7ce13902c32 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_no_bug/databus_mapping_regression/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "databus_mapping_regression" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] diff --git a/noir/noir-repo/test_programs/compile_success_no_bug/databus_mapping_regression/src/main.nr b/noir/noir-repo/test_programs/compile_success_no_bug/databus_mapping_regression/src/main.nr new file mode 100644 index 00000000000..a3aae2911bb --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_no_bug/databus_mapping_regression/src/main.nr @@ -0,0 +1,42 @@ +trait Empty { + fn empty() -> Self; +} + +impl Empty for Field { + fn empty() -> Self { + 0 + } +} + +pub fn is_empty(item: T) -> bool where T: Empty + Eq { + item.eq(T::empty()) +} + +pub fn array_to_bounded_vec(array: [T; N]) -> BoundedVec where T: Empty + Eq { + let mut len = 0; + for elem in array { + if !is_empty(elem) { + len += 1; + } + } + + BoundedVec { storage: array, len } +} + +global TX_SIZE = 5; +global APP_CALL_SIZE = 2; + +fn main( + a: call_data(0) [Field; TX_SIZE], + b: call_data(1) [Field; APP_CALL_SIZE] +) -> return_data [Field; TX_SIZE] { + let mut a_as_bounded_vec = array_to_bounded_vec(a); + + for i in 0..APP_CALL_SIZE { + let value = b[i]; + if value != 0 { + a_as_bounded_vec.push(value); + } + } + a_as_bounded_vec.storage +} diff --git a/noir/noir-repo/test_programs/execution_success/7_function/src/main.nr b/noir/noir-repo/test_programs/execution_success/7_function/src/main.nr index dc56f2bea4f..32227b841bd 100644 --- a/noir/noir-repo/test_programs/execution_success/7_function/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/7_function/src/main.nr @@ -82,7 +82,7 @@ fn test_multiple6(a: my2, b: my_struct, c: (my2, my_struct)) { assert(c.0.aa.a == c.1.a); } -fn foo(a: [Field; N]) -> [Field; N] { +fn foo(a: [Field; N]) -> [Field; N] { a } diff --git a/noir/noir-repo/test_programs/execution_success/aes128_encrypt/src/main.nr b/noir/noir-repo/test_programs/execution_success/aes128_encrypt/src/main.nr index 9cf07841b9e..b937c801860 100644 --- a/noir/noir-repo/test_programs/execution_success/aes128_encrypt/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/aes128_encrypt/src/main.nr @@ -8,7 +8,7 @@ unconstrained fn decode_ascii(ascii: u8) -> u8 { } } -unconstrained fn decode_hex(s: str) -> [u8; M] { +unconstrained fn decode_hex(s: str) -> [u8; M] { let mut result: [u8; M] = [0; M]; let as_bytes = s.as_bytes(); for i in 0..N { diff --git a/noir/noir-repo/test_programs/execution_success/array_len/src/main.nr b/noir/noir-repo/test_programs/execution_success/array_len/src/main.nr index 126fcd18d3f..d794690711a 100644 --- a/noir/noir-repo/test_programs/execution_success/array_len/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/array_len/src/main.nr @@ -1,12 +1,12 @@ -fn len_plus_1(array: [T; N]) -> u32 { +fn len_plus_1(array: [T; N]) -> u32 { array.len() + 1 } -fn add_lens(a: [T; N], b: [Field; M]) -> u32 { +fn add_lens(a: [T; N], b: [Field; M]) -> u32 { a.len() + b.len() } -fn nested_call(b: [Field; N]) -> u32 { +fn nested_call(b: [Field; N]) -> u32 { len_plus_1(b) } diff --git a/noir/noir-repo/test_programs/execution_success/array_to_slice/src/main.nr b/noir/noir-repo/test_programs/execution_success/array_to_slice/src/main.nr index 0d0f9562d7b..3ca8bfff2ae 100644 --- a/noir/noir-repo/test_programs/execution_success/array_to_slice/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/array_to_slice/src/main.nr @@ -1,5 +1,5 @@ // Converts an array into a slice. -fn as_slice_push(xs: [T; N]) -> [T] { +fn as_slice_push(xs: [T; N]) -> [T] { let mut slice = &[]; for elem in xs { slice = slice.push_back(elem); diff --git a/noir/noir-repo/test_programs/execution_success/brillig_constant_reference_regression/Nargo.toml b/noir/noir-repo/test_programs/execution_success/brillig_constant_reference_regression/Nargo.toml new file mode 100644 index 00000000000..2df127c83e8 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/brillig_constant_reference_regression/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "brillig_constant_reference_regression" +type = "bin" +authors = [""] + +[dependencies] diff --git a/noir/noir-repo/test_programs/execution_success/brillig_constant_reference_regression/Prover.toml b/noir/noir-repo/test_programs/execution_success/brillig_constant_reference_regression/Prover.toml new file mode 100644 index 00000000000..8fbe88fbb98 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/brillig_constant_reference_regression/Prover.toml @@ -0,0 +1 @@ +sorted_index = ["1", "0"] diff --git a/noir/noir-repo/test_programs/execution_success/brillig_constant_reference_regression/src/main.nr b/noir/noir-repo/test_programs/execution_success/brillig_constant_reference_regression/src/main.nr new file mode 100644 index 00000000000..c975d20a3b6 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/brillig_constant_reference_regression/src/main.nr @@ -0,0 +1,16 @@ +unconstrained fn main(sorted_index: [u32; 2]) { + let original = [ + 55, + 11 + ]; + + let mut sorted = original; // Stores the constant "original" into the sorted reference + + for i in 0..2 { + let index = sorted_index[i]; + let value = original[index]; + sorted[i] = value; // On first iteration, we should not mutate the original constant array, RC should be > 1 + } + + assert_eq(sorted[1], 55); +} diff --git a/noir/noir-repo/test_programs/execution_success/brillig_cow_regression/src/main.nr b/noir/noir-repo/test_programs/execution_success/brillig_cow_regression/src/main.nr index adeadfc9f20..3fce7fb2c7d 100644 --- a/noir/noir-repo/test_programs/execution_success/brillig_cow_regression/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/brillig_cow_regression/src/main.nr @@ -1,16 +1,16 @@ // Tests a performance regression found in aztec-packages with brillig cow optimization -global MAX_NOTE_HASHES_PER_TX: u64 = 64; -global MAX_NULLIFIERS_PER_TX: u64 = 64; -global MAX_L2_TO_L1_MSGS_PER_TX: u64 = 2; -global MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX: u64 = 16; -global MAX_NEW_CONTRACTS_PER_TX: u64 = 1; -global NUM_ENCRYPTED_LOGS_HASHES_PER_TX: u64 = 1; -global NUM_UNENCRYPTED_LOGS_HASHES_PER_TX: u64 = 1; -global NUM_FIELDS_PER_SHA256 = 2; +global MAX_NOTE_HASHES_PER_TX: u32 = 64; +global MAX_NULLIFIERS_PER_TX: u32 = 64; +global MAX_L2_TO_L1_MSGS_PER_TX: u32 = 2; +global MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX: u32 = 16; +global MAX_NEW_CONTRACTS_PER_TX: u32 = 1; +global NUM_ENCRYPTED_LOGS_HASHES_PER_TX: u32 = 1; +global NUM_UNENCRYPTED_LOGS_HASHES_PER_TX: u32 = 1; +global NUM_FIELDS_PER_SHA256: u32 = 2; global TX_EFFECT_HASH_INPUT_SIZE = 169; -global TX_EFFECT_HASH_LOG_FIELDS = 4; -global TX_EFFECT_HASH_FULL_FIELDS = 165; +global TX_EFFECT_HASH_LOG_FIELDS: u32 = 4; +global TX_EFFECT_HASH_FULL_FIELDS: u32 = 165; struct PublicDataUpdateRequest { leaf_slot : Field, diff --git a/noir/noir-repo/test_programs/execution_success/brillig_keccak/src/main.nr b/noir/noir-repo/test_programs/execution_success/brillig_keccak/src/main.nr index dd339208659..9674ed92942 100644 --- a/noir/noir-repo/test_programs/execution_success/brillig_keccak/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/brillig_keccak/src/main.nr @@ -21,6 +21,6 @@ fn main(x: Field, result: [u8; 32]) { } } -unconstrained fn keccak256(data: [u8; N], msg_len: u32) -> [u8; 32] { +unconstrained fn keccak256(data: [u8; N], msg_len: u32) -> [u8; 32] { std::hash::keccak256(data, msg_len) } diff --git a/noir/noir-repo/test_programs/execution_success/cast_and_shift_global/src/main.nr b/noir/noir-repo/test_programs/execution_success/cast_and_shift_global/src/main.nr index 577de78465c..2c0158fc71a 100644 --- a/noir/noir-repo/test_programs/execution_success/cast_and_shift_global/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/cast_and_shift_global/src/main.nr @@ -1,6 +1,6 @@ -global THREE: u64 = 3; -global EIGHT: u64 = 1 << THREE as u8; -global SEVEN: u64 = EIGHT - 1; +global THREE: u32 = 3; +global EIGHT: u32 = 1 << THREE as u8; +global SEVEN: u32 = EIGHT - 1; fn main() { assert([0; EIGHT] == [0; 8]); diff --git a/noir/noir-repo/test_programs/execution_success/debug_logs/src/main.nr b/noir/noir-repo/test_programs/execution_success/debug_logs/src/main.nr index c7fd01ebbc5..d1314406068 100644 --- a/noir/noir-repo/test_programs/execution_success/debug_logs/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/debug_logs/src/main.nr @@ -79,11 +79,11 @@ fn string_identity(string: fmtstr<14, (Field, Field)>) -> fmtstr<14, (Field, Fie string } -fn string_with_generics(string: fmtstr) -> fmtstr { +fn string_with_generics(string: fmtstr) -> fmtstr { string } -fn string_with_partial_generics(string: fmtstr) -> fmtstr { +fn string_with_partial_generics(string: fmtstr) -> fmtstr { string } diff --git a/noir/noir-repo/test_programs/execution_success/fold_numeric_generic_poseidon/src/main.nr b/noir/noir-repo/test_programs/execution_success/fold_numeric_generic_poseidon/src/main.nr index 8727b2a23de..8eaea086ec0 100644 --- a/noir/noir-repo/test_programs/execution_success/fold_numeric_generic_poseidon/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/fold_numeric_generic_poseidon/src/main.nr @@ -1,6 +1,6 @@ use std::hash::{pedersen_hash_with_separator, poseidon2::Poseidon2}; -global NUM_HASHES = 2; +global NUM_HASHES: u32 = 2; global HASH_LENGTH = 10; #[fold] diff --git a/noir/noir-repo/test_programs/execution_success/generics/src/main.nr b/noir/noir-repo/test_programs/execution_success/generics/src/main.nr index 75a7f8a3154..329759caea0 100644 --- a/noir/noir-repo/test_programs/execution_success/generics/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/generics/src/main.nr @@ -8,11 +8,11 @@ fn foo(bar: Bar) { assert(bar.one == bar.two); } -struct BigInt { +struct BigInt { limbs: [u32; N], } -impl BigInt { +impl BigInt { // `N` is in scope of all methods in the impl fn first(first: BigInt, second: BigInt) -> Self { assert(first.limbs != second.limbs); @@ -69,7 +69,7 @@ fn main(x: Field, y: Field) { let _ = regression_2055([1, 2, 3]); } -fn regression_2055(bytes: [u8; LEN]) -> Field { +fn regression_2055(bytes: [u8; LEN]) -> Field { let mut f = 0; let mut b = 1; let mut len = LEN - 1; // FAILS diff --git a/noir/noir-repo/test_programs/execution_success/global_consts/src/foo.nr b/noir/noir-repo/test_programs/execution_success/global_consts/src/foo.nr index 413b9c3a74b..50e331493dc 100644 --- a/noir/noir-repo/test_programs/execution_success/global_consts/src/foo.nr +++ b/noir/noir-repo/test_programs/execution_success/global_consts/src/foo.nr @@ -1,7 +1,7 @@ mod bar; -global N: u64 = 5; -global MAGIC_NUMBER: u64 = 3; +global N: u32 = 5; +global MAGIC_NUMBER: u32 = 3; global TYPE_INFERRED = 42; pub fn from_foo(x: [Field; bar::N]) { diff --git a/noir/noir-repo/test_programs/execution_success/global_consts/src/foo/bar.nr b/noir/noir-repo/test_programs/execution_success/global_consts/src/foo/bar.nr index 5404c9cf1e3..61ac1e8e8ed 100644 --- a/noir/noir-repo/test_programs/execution_success/global_consts/src/foo/bar.nr +++ b/noir/noir-repo/test_programs/execution_success/global_consts/src/foo/bar.nr @@ -1,4 +1,4 @@ -global N: u64 = 5; +global N: u32 = 5; pub fn from_bar(x: Field) -> Field { x * N as Field diff --git a/noir/noir-repo/test_programs/execution_success/global_consts/src/main.nr b/noir/noir-repo/test_programs/execution_success/global_consts/src/main.nr index 966be2741d6..0b382ff6b8b 100644 --- a/noir/noir-repo/test_programs/execution_success/global_consts/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/global_consts/src/main.nr @@ -1,13 +1,13 @@ mod foo; mod baz; -global M: Field = 32; +global M: u32 = 32; global L: Field = 10; // Unused globals currently allowed -global N: u64 = 5; -global T_LEN = 2; // Type inference is allowed on globals +global N: u32 = 5; +global T_LEN: u32 = 2; // Globals can reference other globals -global DERIVED = M + L; +global DERIVED: Field = M as Field + L; struct Dummy { x: [Field; N], @@ -41,7 +41,7 @@ fn main( assert(test_struct.y[i] != NESTED[1][0].v); } - assert(N as Field != M); + assert(N as Field != M as Field); let expected: u32 = 42; assert(foo::TYPE_INFERRED == expected); @@ -49,7 +49,7 @@ fn main( let mut y = 5; let mut x = M; for i in 0..N * N { - let M: Field = 10; + let M: u32 = 10; x = M; y = i; @@ -62,14 +62,14 @@ fn main( arrays_neq(a, b); - let t: [Field; T_LEN] = [N as Field, M]; + let t: [Field; T_LEN] = [N as Field, M as Field]; assert(t[1] == 32); assert(15 == my_submodule::my_helper()); - let add_submodules_N = my_submodule::N + foo::bar::N as Field; + let add_submodules_N = my_submodule::N as Field + foo::bar::N as Field; assert(15 == add_submodules_N); - let add_from_bar_N = my_submodule::N + foo::bar::from_bar(1); + let add_from_bar_N = my_submodule::N as Field + foo::bar::from_bar(1); assert(15 == add_from_bar_N); // Example showing an array filled with (my_submodule::N + 2) 0's let sugared = [0; my_submodule::N + 2]; @@ -80,13 +80,13 @@ fn main( foo::from_foo(d); baz::from_baz(c); - assert(DERIVED == M + L); + assert(DERIVED == M as Field + L); assert(CALCULATED_GLOBAL == 42); } fn multiplyByM(x: Field) -> Field { - x * M + x * M as Field } fn arrays_neq(a: [Field; M], b: [Field; M]) { @@ -94,7 +94,7 @@ fn arrays_neq(a: [Field; M], b: [Field; M]) { } mod my_submodule { - global N: Field = 10; + global N: u32 = 10; global L: Field = 50; fn my_bool_or(x: u1, y: u1) { @@ -102,8 +102,8 @@ mod my_submodule { } pub fn my_helper() -> Field { - let N: Field = 15; // Like in Rust, local variables override globals - let x = N; + let N: u32 = 15; // Like in Rust, local variables override globals + let x = N as Field; x } } diff --git a/noir/noir-repo/test_programs/execution_success/hashmap/src/main.nr b/noir/noir-repo/test_programs/execution_success/hashmap/src/main.nr index 56b13d6779b..e8bc486e1e2 100644 --- a/noir/noir-repo/test_programs/execution_success/hashmap/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/hashmap/src/main.nr @@ -15,7 +15,7 @@ struct Entry{ value: Field } -global HASHMAP_CAP = 8; +global HASHMAP_CAP: u32 = 8; global HASHMAP_LEN = 6; global FIELD_CMP = |a: Field, b: Field| a.lt(b); diff --git a/noir/noir-repo/test_programs/execution_success/hashmap/src/utils.nr b/noir/noir-repo/test_programs/execution_success/hashmap/src/utils.nr index ee73245a902..de6c78f5adf 100644 --- a/noir/noir-repo/test_programs/execution_success/hashmap/src/utils.nr +++ b/noir/noir-repo/test_programs/execution_success/hashmap/src/utils.nr @@ -1,5 +1,5 @@ // Compile-time: cuts the M first elements from the BoundedVec. -pub(crate) fn cut(input: BoundedVec) -> [T; M] { +pub(crate) fn cut(input: BoundedVec) -> [T; M] { assert(M < N, "M should be less than N."); let mut new = BoundedVec::new(); diff --git a/noir/noir-repo/test_programs/execution_success/no_predicates_numeric_generic_poseidon/src/main.nr b/noir/noir-repo/test_programs/execution_success/no_predicates_numeric_generic_poseidon/src/main.nr index 60a7d2f8d17..d6b463dbe30 100644 --- a/noir/noir-repo/test_programs/execution_success/no_predicates_numeric_generic_poseidon/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/no_predicates_numeric_generic_poseidon/src/main.nr @@ -1,6 +1,6 @@ -use std::hash::{pedersen_hash_with_separator, poseidon2::Poseidon2}; +use std::hash::poseidon2::Poseidon2; -global NUM_HASHES = 2; +global NUM_HASHES: u32 = 2; global HASH_LENGTH = 10; #[no_predicates] diff --git a/noir/noir-repo/test_programs/execution_success/reference_only_used_as_alias/Nargo.toml b/noir/noir-repo/test_programs/execution_success/reference_only_used_as_alias/Nargo.toml new file mode 100644 index 00000000000..d7531756822 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/reference_only_used_as_alias/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "reference_only_used_as_alias" +type = "bin" +authors = [""] +compiler_version = ">=0.33.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/reference_only_used_as_alias/Prover.toml b/noir/noir-repo/test_programs/execution_success/reference_only_used_as_alias/Prover.toml new file mode 100644 index 00000000000..ef34b9eba70 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/reference_only_used_as_alias/Prover.toml @@ -0,0 +1,3 @@ +input = [0, 1, 2, 3] +context_input = 4 +randomness = 5 diff --git a/noir/noir-repo/test_programs/execution_success/reference_only_used_as_alias/src/main.nr b/noir/noir-repo/test_programs/execution_success/reference_only_used_as_alias/src/main.nr new file mode 100644 index 00000000000..c04d68d1748 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/reference_only_used_as_alias/src/main.nr @@ -0,0 +1,88 @@ +struct ExampleEvent0 { + value0: Field, + value1: Field, +} + +trait EventInterface { + fn emit(self, _emit: fn[Env](Self) -> ()); +} + +impl EventInterface for ExampleEvent0 { + fn emit(self: ExampleEvent0, _emit: fn[Env](Self) -> ()) { + _emit(self); + } +} + +struct ExampleEvent1 { + value2: u8, + value3: u8, +} + +struct Context { + a: u32, + b: [u32; 3], + log_hashes: BoundedVec, +} + +struct LogHash { + value: Field, + counter: u32, + length: Field, + randomness: Field, +} + +impl Context { + fn emit_raw_log(&mut self, randomness: Field, _log: [u8; M], log_hash: Field) { + let log_hash = LogHash { value: log_hash, counter: 0, length: 0, randomness }; + self.log_hashes.push(log_hash); + } +} + +fn compute(_event: Event) -> ([u8; 5], Field) where Event: EventInterface { + ([0 as u8; 5], 0) +} + +fn emit_with_keys( + context: &mut Context, + randomness: Field, + event: Event, + inner_compute: fn(Event) -> ([u8; OB], Field) +) where Event: EventInterface { + let (log, log_hash) = inner_compute(event); + context.emit_raw_log(randomness, log, log_hash); +} + +pub fn encode_event_with_randomness( + context: &mut Context, + randomness: Field +) -> fn[(&mut Context, Field)](Event) -> () where Event: EventInterface { + | e: Event | { + unsafe { + func(context.a); + } + emit_with_keys(context, randomness, e, compute); + } +} + +unconstrained fn func(input: u32) { + let mut var = input; + let ref = &mut &mut var; + + for _ in 0..1 { + **ref = 2; + } + + assert(var == 2); + assert(**ref == 2); +} + +// This test aims to allocate a reference which is aliased and only accessed through its alias +// across multiple blocks. We want to guarantee that this allocation is not removed. +fn main(input: [Field; 4], randomness: Field, context_input: u32) { + let b = [context_input, context_input, context_input]; + let mut context = Context { a: context_input, b, log_hashes: BoundedVec::new() }; + + let event0 = ExampleEvent0 { value0: input[0], value1: input[1] }; + event0.emit(encode_event_with_randomness(&mut context, randomness)); +} + diff --git a/noir/noir-repo/test_programs/execution_success/regression/src/main.nr b/noir/noir-repo/test_programs/execution_success/regression/src/main.nr index e60791aface..e6226de29ef 100644 --- a/noir/noir-repo/test_programs/execution_success/regression/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/regression/src/main.nr @@ -20,7 +20,7 @@ impl Eq for U4 { } } -fn compact_decode(input: [u8; N], length: Field) -> ([U4; NIBBLE_LENGTH], Field) { +fn compact_decode(input: [u8; N], length: Field) -> ([U4; NIBBLE_LENGTH], Field) { assert(2 * input.len() <= NIBBLE_LENGTH); assert(length as u32 <= input.len()); @@ -53,7 +53,7 @@ fn compact_decode(input: [u8; N], length: Field) -> ([U4; NIBBLE_LENGTH], Fie out } -fn enc(value: [u8; N], value_length: Field) -> ([u8; 32], Field) { +fn enc(value: [u8; N], value_length: Field) -> ([u8; 32], Field) { assert(value.len() as u8 >= value_length as u8); let mut out_value = [0; 32]; if value_length == 0 { diff --git a/noir/noir-repo/test_programs/execution_success/regression_4088/src/main.nr b/noir/noir-repo/test_programs/execution_success/regression_4088/src/main.nr index 12a7afca68c..b2a050b5db3 100644 --- a/noir/noir-repo/test_programs/execution_success/regression_4088/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/regression_4088/src/main.nr @@ -16,7 +16,7 @@ fn check(serialized_note: [Field; N]) { assert(serialized_note[0] == 0); } -fn oopsie(note: Note) where Note: Serialize { +fn oopsie(note: Note) where Note: Serialize { let serialized_note = Note::serialize(note); check(serialized_note) diff --git a/noir/noir-repo/test_programs/execution_success/regression_4124/src/main.nr b/noir/noir-repo/test_programs/execution_success/regression_4124/src/main.nr index 7b5060062da..b0e1a394c32 100644 --- a/noir/noir-repo/test_programs/execution_success/regression_4124/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/regression_4124/src/main.nr @@ -24,7 +24,7 @@ impl PublicMutable { PublicMutable { storage_slot } } - pub fn read(_self: Self) -> T where T: MyDeserialize { + pub fn read(_self: Self) -> T where T: MyDeserialize { // storage_read returns slice here let fields: [Field; T_SERIALIZED_LEN] = storage_read(); T::deserialize(fields) diff --git a/noir/noir-repo/test_programs/execution_success/regression_unsafe_no_predicates/Nargo.toml b/noir/noir-repo/test_programs/execution_success/regression_unsafe_no_predicates/Nargo.toml new file mode 100644 index 00000000000..7cd42687c34 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/regression_unsafe_no_predicates/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "regression_unsafe_no_predicates" +type = "bin" +authors = [""] +[dependencies] diff --git a/noir/noir-repo/test_programs/execution_success/regression_unsafe_no_predicates/Prover.toml b/noir/noir-repo/test_programs/execution_success/regression_unsafe_no_predicates/Prover.toml new file mode 100644 index 00000000000..aaa42715899 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/regression_unsafe_no_predicates/Prover.toml @@ -0,0 +1,2 @@ +x = 239 +nest = false \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/regression_unsafe_no_predicates/src/main.nr b/noir/noir-repo/test_programs/execution_success/regression_unsafe_no_predicates/src/main.nr new file mode 100644 index 00000000000..63c2493fc89 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/regression_unsafe_no_predicates/src/main.nr @@ -0,0 +1,25 @@ +fn main(x: u8, nest: bool) { + if nest { + let foo = unsafe_assert([x]); + assert(foo != 0); + } +} + +#[no_predicates] +pub fn unsafe_assert(msg: [u8; N]) -> u8 { + let block = unsafe { + get_block(msg) + }; + verify_block(msg, block); + block[0] +} + +unconstrained fn get_block(msg: [u8; N]) -> [u8; 2] { + let mut block: [u8; 2] = [0; 2]; + block[0] = msg[0]; + block +} + +fn verify_block(msg: [u8; N], block: [u8; 2]) { + assert_eq(block[0], msg[0]); +} diff --git a/noir/noir-repo/test_programs/execution_success/schnorr/src/main.nr b/noir/noir-repo/test_programs/execution_success/schnorr/src/main.nr index 8b3b4735145..835ea2ffb1f 100644 --- a/noir/noir-repo/test_programs/execution_success/schnorr/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/schnorr/src/main.nr @@ -12,11 +12,6 @@ fn main( // Regression for issue #2421 // We want to make sure that we can accurately verify a signature whose message is a slice vs. an array let message_field_bytes: [u8; 10] = message_field.to_be_bytes(); - let mut message2 = [0; 42]; - for i in 0..10 { - assert(message[i] == message_field_bytes[i]); - message2[i] = message[i]; - } // Is there ever a situation where someone would want // to ensure that a signature was invalid? @@ -27,94 +22,7 @@ fn main( let valid_signature = std::schnorr::verify_signature(pub_key_x, pub_key_y, signature, message); assert(valid_signature); let pub_key = embedded_curve_ops::EmbeddedCurvePoint { x: pub_key_x, y: pub_key_y, is_infinite: false }; - let valid_signature = verify_signature_noir(pub_key, signature, message2); + let valid_signature = std::schnorr::verify_signature_noir(pub_key, signature, message); assert(valid_signature); - assert_valid_signature(pub_key, signature, message2); -} - -// TODO: to put in the stdlib once we have numeric generics -// Meanwhile, you have to use a message with 32 additional bytes: -// If you want to verify a signature on a message of 10 bytes, you need to pass a message of length 42, -// where the first 10 bytes are the one from the original message (the other bytes are not used) -pub fn verify_signature_noir(public_key: embedded_curve_ops::EmbeddedCurvePoint, signature: [u8; 64], message: [u8; M]) -> bool { - let N = message.len() - 32; - - //scalar lo/hi from bytes - let sig_s = bytes_to_scalar(signature, 0); - let sig_e = bytes_to_scalar(signature, 32); - // pub_key is on Grumpkin curve - let mut is_ok = (public_key.y * public_key.y == public_key.x * public_key.x * public_key.x - 17) - & (!public_key.is_infinite); - - if ((sig_s.lo != 0) | (sig_s.hi != 0)) & ((sig_e.lo != 0) | (sig_e.hi != 0)) { - let g1 = embedded_curve_ops::EmbeddedCurvePoint { x: 1, y: 17631683881184975370165255887551781615748388533673675138860, is_infinite: false }; - let r = embedded_curve_ops::multi_scalar_mul([g1, public_key], [sig_s, sig_e]); - // compare the _hashes_ rather than field elements modulo r - let pedersen_hash = std::hash::pedersen_hash([r.x, public_key.x, public_key.y]); - let mut hash_input = [0; M]; - let pde: [u8; 32] = pedersen_hash.to_be_bytes(); - - for i in 0..32 { - hash_input[i] = pde[i]; - } - for i in 0..N { - hash_input[32+i] = message[i]; - } - let result = std::hash::blake2s(hash_input); - - is_ok = !r.is_infinite; - for i in 0..32 { - if result[i] != signature[32 + i] { - is_ok = false; - } - } - } - is_ok -} - -pub fn bytes_to_scalar(bytes: [u8; 64], offset: u32) -> embedded_curve_ops::EmbeddedCurveScalar { - let mut v = 1; - let mut lo = 0 as Field; - let mut hi = 0 as Field; - for i in 0..16 { - lo = lo + (bytes[offset+31 - i] as Field) * v; - hi = hi + (bytes[offset+15 - i] as Field) * v; - v = v * 256; - } - let sig_s = embedded_curve_ops::EmbeddedCurveScalar { lo, hi }; - sig_s -} - -pub fn assert_valid_signature(public_key: embedded_curve_ops::EmbeddedCurvePoint, signature: [u8; 64], message: [u8; M]) { - let N = message.len() - 32; - //scalar lo/hi from bytes - let sig_s = bytes_to_scalar(signature, 0); - let sig_e = bytes_to_scalar(signature, 32); - - // assert pub_key is on Grumpkin curve - assert(public_key.y * public_key.y == public_key.x * public_key.x * public_key.x - 17); - assert(public_key.is_infinite == false); - // assert signature is not null - assert((sig_s.lo != 0) | (sig_s.hi != 0)); - assert((sig_e.lo != 0) | (sig_e.hi != 0)); - - let g1 = embedded_curve_ops::EmbeddedCurvePoint { x: 1, y: 17631683881184975370165255887551781615748388533673675138860, is_infinite: false }; - let r = embedded_curve_ops::multi_scalar_mul([g1, public_key], [sig_s, sig_e]); - // compare the _hashes_ rather than field elements modulo r - let pedersen_hash = std::hash::pedersen_hash([r.x, public_key.x, public_key.y]); - let mut hash_input = [0; M]; - let pde: [u8; 32] = pedersen_hash.to_be_bytes(); - - for i in 0..32 { - hash_input[i] = pde[i]; - } - for i in 0..N { - hash_input[32+i] = message[i]; - } - let result = std::hash::blake2s(hash_input); - - assert(!r.is_infinite); - for i in 0..32 { - assert(result[i] == signature[32 + i]); - } + std::schnorr::assert_valid_signature(pub_key, signature, message); } diff --git a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml b/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml deleted file mode 100644 index 3f6bf0b427a..00000000000 --- a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml +++ /dev/null @@ -1,4 +0,0 @@ -key_hash = "0x0000000000000000000000000000000000000000000000000000000000000000" -proof = ["0x0000000000000000000000000000000000000000000000000000000000000040", "0x0000000000000000000000000000000000000000000000000000000000000011", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000042ab5d6d1986846cf", "0x00000000000000000000000000000000000000000000000b75c020998797da78", "0x0000000000000000000000000000000000000000000000005a107acb64952eca", "0x000000000000000000000000000000000000000000000000000031e97a575e9d", "0x00000000000000000000000000000000000000000000000b5666547acf8bd5a4", "0x00000000000000000000000000000000000000000000000c410db10a01750aeb", "0x00000000000000000000000000000000000000000000000d722669117f9758a4", "0x000000000000000000000000000000000000000000000000000178cbf4206471", "0x000000000000000000000000000000000000000000000000e91b8a11e7842c38", "0x000000000000000000000000000000000000000000000007fd51009034b3357f", "0x000000000000000000000000000000000000000000000009889939f81e9c7402", "0x0000000000000000000000000000000000000000000000000000f94656a2ca48", "0x000000000000000000000000000000000000000000000006fb128b46c1ddb67f", "0x0000000000000000000000000000000000000000000000093fe27776f50224bd", "0x000000000000000000000000000000000000000000000004a0c80c0da527a081", "0x0000000000000000000000000000000000000000000000000001b52c2020d746", "0x0000000000000000000000000000005a9bae947e1e91af9e4033d8d6aa6ed632", "0x000000000000000000000000000000000025e485e013446d4ac7981c88ba6ecc", "0x000000000000000000000000000000ff1e0496e30ab24a63b32b2d1120b76e62", "0x00000000000000000000000000000000001afe0a8a685d7cd85d1010e55d9d7c", "0x000000000000000000000000000000b0804efd6573805f991458295f510a2004", "0x00000000000000000000000000000000000c81a178016e2fe18605022d5a8b0e", "0x000000000000000000000000000000eba51e76eb1cfff60a53a0092a3c3dea47", "0x000000000000000000000000000000000022e7466247b533282f5936ac4e6c15", "0x00000000000000000000000000000071b1d76edf770edff98f00ff4deec264cd", "0x00000000000000000000000000000000001e48128e68794d8861fcbb2986a383", "0x000000000000000000000000000000d3a2af4915ae6d86b097adc377fafda2d4", "0x000000000000000000000000000000000006359de9ca452dab3a4f1f8d9c9d98", "0x0000000000000000000000000000006cf7dd96d7636fda5953191b1ad776d491", "0x00000000000000000000000000000000001633d881a08d136e834cb13a28fcc6", "0x00000000000000000000000000000001254956cff6908b069fca0e6cf1c47eb1", "0x000000000000000000000000000000000006f4d4dd3890e997e75e75886bf8f7", "0x0000000000000000000000000000006cf7dd96d7636fda5953191b1ad776d491", "0x00000000000000000000000000000000001633d881a08d136e834cb13a28fcc6", "0x00000000000000000000000000000001254956cff6908b069fca0e6cf1c47eb1", "0x000000000000000000000000000000000006f4d4dd3890e997e75e75886bf8f7", "0x000000000000000000000000000000f968b227a358a305607f3efc933823d288", "0x00000000000000000000000000000000000eaf8adb390375a76d95e918b65e08", "0x000000000000000000000000000000bb34b4b447aae56f5e24f81c3acd6d547f", "0x00000000000000000000000000000000002175d012746260ebcfe339a91a81e1", "0x00000000000000000000000000000052eebbd1f6f7554e837f60c44000ed14b6", "0x00000000000000000000000000000000001c1c045a3ec94b8801f2272cc0b3f4", "0x0000000000000000000000000000004d2ef74134578f6b431a9df071ffca4292", "0x0000000000000000000000000000000000291326ade7aa6f0dfc8900eab5580b", "0x0000000000000000000000000000002433eec6418a6dba820c9527e2581fc8bc", "0x00000000000000000000000000000000000e88b7daad19af2ac2f9bdf9e50ee2", "0x000000000000000000000000000000dcfce2c427155cc3e4d035735d3dd5ece8", "0x00000000000000000000000000000000002d7d473cac1a15d0fee8b22c1a7b3e", "0x23fb9503f571d567261006e2ca8b4326d325820140b488bb71617583602f4e3e", "0x0c68b96eebbfcac292403ed3b6f61536550e66473904e7d5d28080108fd0b1c3", "0x08d3bdbefd6d437c50fb9e3e3861913433e76577a18d81aa0ea4b8843e55f9ae", "0x08f6173fe87b72da6d821a496eb99b0cfe0ccadcffd25e5a3b718d83ff9adb1a", "0x1e6bd0a24c2cc58c93cf255cc68dd0c57299c99fd934267906b34facb0145cf4", "0x1175996557630bc376d38636f72b277cb8d54a969a39988a7e78f464c03eaeda", "0x03c3bd1f43baf44de0d9bf0f474c5df04b182214d57a196a717aef8868f9948c", "0x27306ffc7a96c8c27c9812d9dfa649ab6897b69125939aabe814e07d105daa32", "0x0c7f0b70aa08158e55bb39471609782656793ac76a03f2b64dcd135e6542592c", "0x03885b9eff8dac38a64779e3aba31f18c74166892cef9c5081ab57f6daf59865", "0x18dd8385333838c514fd11f36469c88e7ea5f6440aee17fa93c0f03c765d4ced", "0x08ad5bc6c05ecc9ae0d8f0b3196f229a53dbe753f41c12c52045c40e7d8220cc", "0x2f308380f90378084075f2bafa73228b17cbdfc2d693f9aaa1e5089557d0f32e", "0x2d3407e6de05e5935a31037c3db88069d0c41ec86cc8dda815048d6ce76f7a5f", "0x108c231f660e75f209201507a2dba6fccf99734ad91db8ecea675275afdf3ce1", "0x0e68df40e8c467a617229ab0f1dc0d4a04254492e709333d623c0963518dd6b4", "0x290650614292eec7c4f26fd402a047298f1a618dc8ff7de615752f737df7d515", "0x0de290891aaf146fd890a3cd5c25025113df2ec4d0a134513a2f397eaf4e3ea9", "0x25521f6f658bd20d9aaa8041164509b7b8d96fc5ef385f6eb6582375d1a86168", "0x0e9ab2f2f06220644c41fb09456d91751c522b015622f30568e66457f647a2bc", "0x28364f88f1e9c7d8e7767a3b954c5daa29223d646279930b34da51351dc01992", "0x0560c214728aacc262eeee0037be142d81aec26a1f5a9cf0606c4236ed344aa8", "0x1faea1662601fa01ad93d160277a1c81f2c60a761b74660f24a596ec8cb783e7", "0x0e703bb7bbf3a8bb8211715d86a1becb7aa3271f51d6001d5d3042faa7465df9", "0x0cc5b499ea9d9cbae4a0e33a5b601a7f7b686d6980dc0dd5bae4382a8ab1c7c7", "0x27fae143a80a37af95a47d5953096eef9b1127b5475480b8a6ecebdb00a65e23", "0x02cdf7c51d9182fbe07e7768ed0fcfe452ef70fc2ac87dc38fc0d4137bdf4aec", "0x14838df5a54d57d0a28b0375107bb7e7e7259c576a08ea39db6af8b0341d2911", "0x1b1fb0b1242e17beebb218c4ec88c830accea9bc93deec6d087d36d4d8de31fd", "0x1a8c0bdf35e674aa37118f5ad7fe6b62c65d8502e9697b3a92dfda8a1923d110", "0x2819aaa537cf012ceb48a8c8036b6fee492eeeef6698dcf8e3bc825d71efa3f8", "0x1ceedf534535a0d2a427b2ceeb3c8878a658b80eaf5210dbc0d32888fe3d05a7", "0x25c96dba803387eb5f3562785bc3bccddb7c9eb019bd4b07dd4563f77965c00c", "0x0353f3ff0f4f3da362b11eac12167dcbc9b3c76fb555f7e5534c14bb4c3f8037", "0x2904e33424ad29d38bda66a50b54a67acdf09be06a068ddc09d5eabdf9c2a9e5", "0x0b28534bf4b58e7f46c4a7514f3b521dd47bbac2a3adf09387baf19ec8df39c5", "0x1628b67c5d7b8c4cb5d8cdd2d0fd1d92bea3bfcf490fba7f16447cb686d7a388", "0x151bde642447aaf993e737329a3b81c6e243eecbe6a7bb43cdb8ffe74b2c0484", "0x07b319f585e9a9a3883deaddd9b0f43c844cbc7477636034f1543ce9f98821bf", "0x2c8738d76925012cc029f5b888be3cae165daa6beb22b5d73f017c918d891c34", "0x118fff7a26b04a6476c21267a3a4e96247640f6eabd05a05f1a94f881c6ee32b", "0x081d82e0808b6d444b03e1d722375adef2659d5914faa3d9ca4cb12c912be257", "0x18426c5ff5a3140f19bdc05e247cc05e1f70e1ea482b2a2b21f4930a494d7a61", "0x296babb7c6a72783d92bc3dee7f90a97302d64a518faeec0f42af4f599ccc0d1", "0x03337dd83835a2e9fe02c97056360eec725d55b01f039663108939f0333dba11", "0x11a796e7e6f1081be5aad42b475dc224f9547769bc6b358af63207fe0d324a4a", "0x2419618a28070cb7af904460207371f5ff9fa0939f6a0148add60ede530b0f14", "0x004d323457b070f3f41a4ce1ad5a867b3dea1a592bccb40c4d69c8521d9682b6", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x2d6ba30a2a23364900cf52019e2d19574813fe4922763a4e281c58c400ffce14", "0x06a0c085375f88283bedf3a1fc76ef35490655f372e2a985842a9375383b69d7", "0x219b78e5cf2ab2e35edfc8e40362062081a24ff4e9c9d15afa254c2a02d6d4e2", "0x182f29b047e6167c338c36d31685a825c66f327336545c623e7a6bd18e4fa97f", "0x1686460e2586e702724b9daf02315a33ddf5cbd275cfadbc3858f9ef3fe97133", "0x2183aaf585ac708b4000a5b88cf5a767356677087133bd90fff1c3e030b91f1e", "0x27dfa9c69d03c7776fecac8e0f56162caa95f44692cdae91f5b52dfc97eb9006", "0x10a9959de8c6d238c6c6dd68274cc9fc5b6d66759938638072d71659a2fe210d", "0x0e179d6215630fdd7d50362ade21893456d4b9a693e96152d9a6bac6518d4605", "0x0175b579d4e3b24eb0a319a6c79756c8a68ce2c1e0d0d8d1593d685125fbfb66", "0x1132bd3d531944f5024f2705d39b13e00ae90c246f6550c745234fd3d080712b", "0x1f2326f3955b431f2a17e937128b890aa366b107b69c61b8b45832fd06ce9e4e", "0x13576e6c03c3f2042c56113991821ec1f9dec46b6b0ff2748e037c94e6656c40", "0x00bb713034ce9d247110149e2a1754dc76f3ad700d420508148060091037477a", "0x25fb93286a48dc64c67ffac9e3f4a96b6c70bb87744e10e44a782117f8f537a0", "0x191227cd5e49d8a6b5aca93888b3286b41069df547e4bd91ffe65e48ab45b2a8", "0x120d4ac764ca4db67357140c8a8dd1523c013f747250a03a6130416669b087e1", "0x131cc1285b242d73eee36b79ccb3024525ae3caf0f91981cb89ec8d81b16a198", "0x0cacfa5aa1bc4624d5d476aced4d4c8026fb881679172dbc482d18772bc28c9f", "0x0e138279e8a4fe06018e9b9e649921500766e7a7afcc971f41732aa51ec31a43", "0x000000000000000000000000000000332f935a88cd2cc8a138d5ff2efe4cdec8", "0x0e1c2af7515e65c7ebced1a37faf4dbeef5c414f5601219d00d3844658b05a61", "0x12aff8e8eed2d2946c91652d448240590690672893b4759cdd31e1ec9ea45138", "0x1e89f396af25e81f9c4b3af2b0a15fd961789f3a8aa60edbdc4e8f2dfb610375", "0x29c05199f808bf38009ee7fa3c82b6aa5e3d65f180f49d4564c4bf6918399461", "0x019ce7ac46f4e5f1d4ce2d3866321506cea78ff5e5fe400d83b0395341cfe5d5", "0x20b40d1a69e62e7eecbf490915e2791975d3bca30859f237c56c4486e1fbb441", "0x243f7e62233a1f80ee17978814d7ab095bcc416d6bcee4583ce1167c7206b7b4", "0x0b6067a921e8d87bc8fd1af67382fbe2a27bcc833effa13fd7d85b5458d71e28", "0x30307a6766be04f3c50378d1b83f2e147e2ceef344d0c60e1abf939d29c26e27", "0x004c0ec19588b920084d00c6bfe0af4dbf83ca101eac5d833cb8191fe1c298b4", "0x00da79a40286bd8d3993b331a72f8195c7ba04bd863d1afd469bb094e29cc7d9", "0x115b70a2c50ee9abc28472ba8e820cfba158113a5a39c8e31817c84182d0503a", "0x09341d5c4b6d85bde38834a418a8ca375592c320c669bdd540c7ccee760f2ea1", "0x09341d5c4b6d85bde38834a418a8ca375592c320c669bdd540c7ccee760f2ea1", "0x0e63e927a9562ce0914fcd8892dff9a94ac722365ce21b8f5c75cc560b364e57", "0x05cf84989894e741a3e1cd815a8f84febfb08e61ee7b424c902fb02ca7d12e95", "0x1f958ad88d5e4a270f35e534154e7a519c5bbfab36d5084202d5b78baf63e09e", "0x21f0a33450db8821c2f8d042aae7e70bf05c9814b063e73c5e95f8ddba515a81", "0x2767a30fa0351c7deb2c8f542ecace4c41c1d136dd460dfad50b372f2a5f4b71", "0x137ee4ebfbc7227bf57ffc35d3368dd4f96c62911db9380aafa220d061c3b59d", "0x111515d3566611192f64e1e0848635ca6d7f73d8039d8b3522da1e2359e6d1b2", "0x2f6284e905c491b8defe4c467b2e664e2fbf144b5ca45e05c4a9d1aa8d41e149", "0x1e688ca09721459cd96d6af042716567a8f5fdb479f08ff9eff248c6013315a4", "0x00000000000000000000000000000015207c89ecabf752a46c0d5b8dbd296d86", "0x0000000000000000000000000000000000286c2b4d49249737816da8fd9f2753", "0x0000000000000000000000000000002492e649af820ca5d83e59823126c03bfb", "0x00000000000000000000000000000000001cdf1b636e33bf02a813687147476e", "0x000000000000000000000000000000b49023689f96212b8166d0c9b105e6df9a", "0x00000000000000000000000000000000000d9d27730e57d86079464ecd8d9edd", "0x0000000000000000000000000000005292b5583bd716a723bae47d344d655528", "0x000000000000000000000000000000000026651dba1a1074382c734163ab3614", "0x0000000000000000000000000000008984f01bc1f237c72fd6d2bb10cc21eb85", "0x00000000000000000000000000000000001029818de60ae9bb21ac2b5d5a4c97", "0x0000000000000000000000000000003aca28da52679f34e33756dfe00f1d8072", "0x0000000000000000000000000000000000124ecac53af720c02d18f54fd29100", "0x000000000000000000000000000000d09ed1c104d0397f046d89b8476f47e641", "0x00000000000000000000000000000000002c5094b27ad41c8a203b16dc74ee54", "0x000000000000000000000000000000bf8609068d29793771eb3f64e7dc3db96d", "0x0000000000000000000000000000000000225e220e16aedaecf2c10de6e41042", "0x0000000000000000000000000000006ae4f0d8baca7866ad4632141f90770cd7", "0x0000000000000000000000000000000000256cb979ab5bbe98be3a413ae8f246", "0x000000000000000000000000000000891f30bd3ac8e7e63e00db4951d518822f", "0x000000000000000000000000000000000014dffca5d842acfcd23fa491a7dae2", "0x000000000000000000000000000000af99905ea5b7a25f2172f044a59b90e67d", "0x00000000000000000000000000000000001e35bb78e382a5b98ad04b846df528", "0x0000000000000000000000000000003cfb75469b791ea188b8dfdff0f269e7b5", "0x00000000000000000000000000000000000e4fb9eb44a3d44d808794066f8811", "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", "0x000000000000000000000000000000c42f38f2993af03e18e76996c49f945c6a", "0x00000000000000000000000000000000002aefe820f0e4700abedd9fb6f046c1", "0x0000000000000000000000000000007a878e53414bf22854877c5066eaf916b8", "0x00000000000000000000000000000000001410a75247434da28c1ba6b64703bb", "0x000000000000000000000000000000bca902c1e2af8b47771e7eb42c3870f46b", "0x0000000000000000000000000000000000276eb602c3c232b51668d229d602b8", "0x000000000000000000000000000000dac1254c0753ee39d49d795bc6b3550ba7", "0x000000000000000000000000000000000007d60be9174146bd83f202aa062b92"] -public_inputs = ["0x0000000000000000000000000000000000000000000000000000000000000003"] -verification_key = ["0x0000000000000000000000000000000000000000000000000000000000000040", "0x0000000000000000000000000000000000000000000000000000000000000011", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000003", "0x0000000000000000000000000000000000000000000000000000000000000004", "0x0000000000000000000000000000000000000000000000000000000000000005", "0x0000000000000000000000000000000000000000000000000000000000000006", "0x0000000000000000000000000000000000000000000000000000000000000007", "0x0000000000000000000000000000000000000000000000000000000000000008", "0x0000000000000000000000000000000000000000000000000000000000000009", "0x000000000000000000000000000000000000000000000000000000000000000a", "0x000000000000000000000000000000000000000000000000000000000000000b", "0x000000000000000000000000000000000000000000000000000000000000000c", "0x000000000000000000000000000000000000000000000000000000000000000d", "0x000000000000000000000000000000000000000000000000000000000000000e", "0x000000000000000000000000000000000000000000000000000000000000000f", "0x0000000000000000000000000000000000000000000000000000000000000010", "0x00000000000000000000000000000060e430ad1c23bfcf3514323aae3f206e84", "0x00000000000000000000000000000000001b5c3ff4c2458d8f481b1c068f27ae", "0x000000000000000000000000000000bb510ab2112def34980e4fc6998ad9dd16", "0x00000000000000000000000000000000000576e7c105b43e061e13cb877fefe1", "0x000000000000000000000000000000ced074785d11857b065d8199e6669a601c", "0x00000000000000000000000000000000000053b48a4098c1c0ae268f273952f7", "0x000000000000000000000000000000d1d4b26e941db8168cee8f6de548ae0fd8", "0x00000000000000000000000000000000001a9adf5a6dadc3d948bb61dfd63f4c", "0x0000000000000000000000000000009ce1faac6f8de6ebb18f1db17372c82ad5", "0x00000000000000000000000000000000002002681bb417184b2df070a16a3858", "0x000000000000000000000000000000161baa651a8092e0e84725594de5aba511", "0x00000000000000000000000000000000000be0064399c2a1efff9eb0cdcb2223", "0x0000000000000000000000000000008673be6fd1bdbe980a29d8c1ded54381e7", "0x000000000000000000000000000000000008a5158a7d9648cf1d234524c9fa0c", "0x0000000000000000000000000000002b4fce6e4b1c72062b296d49bca2aa4130", "0x00000000000000000000000000000000002e45a9eff4b6769e55fb710cded44f", "0x00000000000000000000000000000072b85bf733758b76bcf97333efb85a23e3", "0x000000000000000000000000000000000017da0ea508994fc82862715e4b5592", "0x00000000000000000000000000000094fa74695cf058dba8ff35aec95456c6c3", "0x0000000000000000000000000000000000211acddb851061c24b8f159e832bd1", "0x000000000000000000000000000000303b5e5c531384b9a792e11702ad3bcab0", "0x00000000000000000000000000000000000d336dff51a60b8833d5d7f6d4314c", "0x0000000000000000000000000000009f825dde88092070747180d581c342444a", "0x0000000000000000000000000000000000237fbd6511a03cca8cac01b555fe01", "0x0000000000000000000000000000007c313205159495df6d8de292079a4844ff", "0x000000000000000000000000000000000018facdfc468530dd45e8f7a1d38ce9", "0x0000000000000000000000000000000d1ce33446fc3dc4ab40ca38d92dac74e1", "0x00000000000000000000000000000000000852d8e3e0e8f4435af3e94222688b", "0x0000000000000000000000000000006c04ee19ec1dfec87ed47d6d04aa158de2", "0x000000000000000000000000000000000013240f97a584b45184c8ec31319b5f", "0x000000000000000000000000000000cefb5d240b07ceb4be26ea429b6dc9d9e0", "0x00000000000000000000000000000000002dad22022121d689f57fb38ca21349", "0x000000000000000000000000000000c9f189f2a91aeb664ce376d8b157ba98f8", "0x00000000000000000000000000000000002531a51ad54f124d58094b219818d2", "0x000000000000000000000000000000ef1e6db71809307f677677e62b4163f556", "0x0000000000000000000000000000000000272da4396fb2a7ee0638b9140e523d", "0x0000000000000000000000000000002e54c0244a7732c87bc4712a76dd8c83fb", "0x000000000000000000000000000000000007db77b3e04b7eba9643da57cbbe4d", "0x000000000000000000000000000000e0dfe1ddd7f74ae0d636c910c3e85830d8", "0x00000000000000000000000000000000000466fa9b57ec4664abd1505b490862", "0x0000000000000000000000000000009ee55ae8a32fe5384c79907067cc27192e", "0x00000000000000000000000000000000000799d0e465cec07ecb5238c854e830", "0x0000000000000000000000000000001d5910ad361e76e1c241247a823733c39f", "0x00000000000000000000000000000000002b03f2ccf7507564da2e6678bef8fe", "0x000000000000000000000000000000ee40d90bea71fba7a412dd61fcf34e8ceb", "0x0000000000000000000000000000000000140b0936c323fd2471155617b6af56", "0x0000000000000000000000000000002b90071823185c5ff8e440fd3d73b6fefc", "0x00000000000000000000000000000000002b6c10790a5f6631c87d652e059df4", "0x00000000000000000000000000000029a17181c7934fc3fdbd352eac5cb521b9", "0x00000000000000000000000000000000001f497cbf5284ff29a2d336e5991999", "0x000000000000000000000000000000072bd9c0c6beda1fdee6d4ff0432ba9e1b", "0x000000000000000000000000000000000013ea38a0bd2aa751a490a724fac818", "0x000000000000000000000000000000c599f63dcd3edd49f08ae5c3141c1e3493", "0x00000000000000000000000000000000002bdb36be0bea09950dd32a8ccf6fbc", "0x00000000000000000000000000000047f27f29724e7f19eba0340256a0bd4b7d", "0x00000000000000000000000000000000001c1c5ccf87a962129ca785f8f35120", "0x000000000000000000000000000000c5c71efdae00679bbe4a95096e012b1817", "0x000000000000000000000000000000000017a365de041e317817d0135f2b48e0", "0x0000000000000000000000000000008ae711ac402f7848d719c93a89ba8d39f1", "0x00000000000000000000000000000000002b6fb40ed8a1935226f4f9786a0499", "0x0000000000000000000000000000002f03a71501d83de1da5715a4e9462d6198", "0x00000000000000000000000000000000001644064443b8546f48eae693af47b8", "0x00000000000000000000000000000083763ab1b6e8fe269b2fe4c7b9c448c08d", "0x000000000000000000000000000000000021d7cc18c59676a8eeb47c0111c251", "0x000000000000000000000000000000b5f937153073e03ea7d51a996e0ebc2e6b", "0x000000000000000000000000000000000011ddd0e26457373eb06e0493177672", "0x000000000000000000000000000000c5f6eb9f6fc8fa99811a4a88c74a6d018b", "0x000000000000000000000000000000000025bcd07a0732c123567834f5109558", "0x000000000000000000000000000000aeb08a0b1a4442189448b4e97490568146", "0x000000000000000000000000000000000002a1744e4771705536a88f07e0f90f", "0x000000000000000000000000000000b938568293bd0724b0ea76c2ec34c4a829", "0x0000000000000000000000000000000000053296e8f3b9ad3af877dfa9c7c2a7", "0x000000000000000000000000000000f0ca1db6323996eba26bdc86dafef9d10b", "0x00000000000000000000000000000000001441a46c58af03d5645d52721d956a", "0x0000000000000000000000000000008bbf8f884013c66c28ba09c2fbd573b656", "0x0000000000000000000000000000000000206c391ca06fac27d1908e94570243", "0x0000000000000000000000000000002d4f5aaed88ba4f79612d53b804ca8f194", "0x00000000000000000000000000000000001674011c96392df08970fa6b7b4cb8", "0x0000000000000000000000000000009f88297c1729d76c4d9306853598c91325", "0x0000000000000000000000000000000000256f51adfcacc3c1e340be4d32d3e9", "0x0000000000000000000000000000000ab9955eec0d74eb799afed2a802b24d75", "0x00000000000000000000000000000000001fcbe43ea105b30d36ed0b21b03411", "0x000000000000000000000000000000d66b1d5433f1aa5305cd1edce7c22de466", "0x00000000000000000000000000000000002331546a256b8a3b751956806680d4", "0x000000000000000000000000000000e97954ad6cd6f45fb15c91434121db4304", "0x00000000000000000000000000000000002e20a97e09d50f227ced47e7a98250", "0x0000000000000000000000000000001ebbc27eb9ebededefba79522eb58ae89b", "0x0000000000000000000000000000000000090efa4974e566e81d1177b85a30be", "0x0000000000000000000000000000005eafa070b9c9632404052642e3bc14f9fd", "0x00000000000000000000000000000000001489068864102daca6a6b8bc4d448b", "0x0000000000000000000000000000009ebc91aaaac036a6477cadbe54e8556dfd", "0x00000000000000000000000000000000000ef6d835e2ed3343b95c82c8c54037", "0x00000000000000000000000000000033b28b529dff46e93af4e7422530478e4a", "0x000000000000000000000000000000000020a86c2f8591bf190bcddcc03c42fb", "0x000000000000000000000000000000a9679d0acc088f7dc27bf6d866bcd2dda2", "0x00000000000000000000000000000000002fb9d0d2d4099402bed74f738f64cc", "0x00000000000000000000000000000023b09f876a29a061582848a8b9a5870c12", "0x00000000000000000000000000000000001d5bb906f03f0d49e9c4791bc43af9", "0x00000000000000000000000000000017aac9854ea240d8ec97bf760c4d4ba870", "0x00000000000000000000000000000000000b227a556c414ada0dc75bb303e30e", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000009b624fa65d1a24b7f14a8f25f3789622af", "0x000000000000000000000000000000000013d47bff8c630e847b70e2732fd3f0", "0x00000000000000000000000000000061d21663e93132f32921075f4c936a84df", "0x00000000000000000000000000000000001a74ca4e118fb480b9b999902989a3"] diff --git a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/src/main.nr b/noir/noir-repo/test_programs/execution_success/verify_honk_proof/src/main.nr deleted file mode 100644 index b60a47ccc7f..00000000000 --- a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/src/main.nr +++ /dev/null @@ -1,17 +0,0 @@ - -// This circuit aggregates a single Honk proof from `assert_statement_recursive`. -global SIZE_OF_PROOF_IF_LOGN_IS_28 : u32 = 439; -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(verification_key, proof, public_inputs, key_hash); -} diff --git a/noir/noir-repo/test_programs/noir_test_success/bounded_vec/src/main.nr b/noir/noir-repo/test_programs/noir_test_success/bounded_vec/src/main.nr index 7b3e63df072..cb9879b1c9e 100644 --- a/noir/noir-repo/test_programs/noir_test_success/bounded_vec/src/main.nr +++ b/noir/noir-repo/test_programs/noir_test_success/bounded_vec/src/main.nr @@ -52,7 +52,7 @@ fn test_vec_get_unchecked() { } // docs:start:get_unchecked_example -fn sum_of_first_three(v: BoundedVec) -> u32 { +fn sum_of_first_three(v: BoundedVec) -> u32 { // Always ensure the length is larger than the largest // index passed to get_unchecked assert(v.len() > 2); diff --git a/noir/noir-repo/test_programs/noir_test_success/comptime_expr/src/main.nr b/noir/noir-repo/test_programs/noir_test_success/comptime_expr/src/main.nr index c1f70e7acee..709180879a0 100644 --- a/noir/noir-repo/test_programs/noir_test_success/comptime_expr/src/main.nr +++ b/noir/noir-repo/test_programs/noir_test_success/comptime_expr/src/main.nr @@ -326,6 +326,35 @@ mod tests { } } + #[test] + fn test_expr_as_constructor() { + comptime + { + let expr = quote { Foo { a: 1, b: 2 } }.as_expr().unwrap(); + let (_typ, fields) = expr.as_constructor().unwrap(); + assert_eq(fields.len(), 2); + assert_eq(fields[0].0, quote { a }); + assert_eq(fields[0].1.as_integer().unwrap(), (1, false)); + assert_eq(fields[1].0, quote { b }); + assert_eq(fields[1].1.as_integer().unwrap(), (2, false)); + } + } + + #[test] + fn test_expr_modify_for_constructor() { + comptime + { + let expr = quote { foo::bar::Baz:: { a: 1, b: 2 } }.as_expr().unwrap(); + let expr = expr.modify(times_two); + let (_typ, fields) = expr.as_constructor().unwrap(); + assert_eq(fields.len(), 2); + assert_eq(fields[0].0, quote { a }); + assert_eq(fields[0].1.as_integer().unwrap(), (2, false)); + assert_eq(fields[1].0, quote { b }); + assert_eq(fields[1].1.as_integer().unwrap(), (4, false)); + } + } + // This test can't only be around the comptime block since that will cause // `nargo fmt` to remove the comptime keyword. // docs:start:as_expr_example @@ -606,6 +635,48 @@ mod tests { } } + #[test] + fn test_expr_as_lambda() { + comptime + { + let expr = quote { |x: Field| -> Field { 1 } }.as_expr().unwrap(); + let (params, return_type, body) = expr.as_lambda().unwrap(); + assert_eq(params.len(), 1); + assert(params[0].1.unwrap().is_field()); + assert(return_type.unwrap().is_field()); + assert_eq(body.as_block().unwrap()[0].as_integer().unwrap(), (1, false)); + + let expr = quote { |x| { 1 } }.as_expr().unwrap(); + let (params, return_type, body) = expr.as_lambda().unwrap(); + assert_eq(params.len(), 1); + assert(params[0].1.is_none()); + assert(return_type.is_none()); + assert_eq(body.as_block().unwrap()[0].as_integer().unwrap(), (1, false)); + } + } + + #[test] + fn test_expr_modify_lambda() { + comptime + { + let expr = quote { |x: Field| -> Field { 1 } }.as_expr().unwrap(); + let expr = expr.modify(times_two); + let (params, return_type, body) = expr.as_lambda().unwrap(); + assert_eq(params.len(), 1); + assert(params[0].1.unwrap().is_field()); + assert(return_type.unwrap().is_field()); + assert_eq(body.as_block().unwrap()[0].as_block().unwrap()[0].as_integer().unwrap(), (2, false)); + + let expr = quote { |x| { 1 } }.as_expr().unwrap(); + let expr = expr.modify(times_two); + let (params, return_type, body) = expr.as_lambda().unwrap(); + assert_eq(params.len(), 1); + assert(params[0].1.is_none()); + assert(return_type.is_none()); + assert_eq(body.as_block().unwrap()[0].as_block().unwrap()[0].as_integer().unwrap(), (2, false)); + } + } + #[test] fn test_expr_as_let() { comptime @@ -641,6 +712,58 @@ mod tests { } } + #[test] + fn test_expr_as_for_statement() { + comptime + { + let expr = quote { for x in 2 { 3 } }.as_expr().unwrap(); + let (index, array, body) = expr.as_for().unwrap(); + assert_eq(index, quote { x }); + assert_eq(array.as_integer().unwrap(), (2, false)); + assert_eq(body.as_block().unwrap()[0].as_integer().unwrap(), (3, false)); + } + } + + #[test] + fn test_expr_modify_for_statement() { + comptime + { + let expr = quote { for x in 2 { 3 } }.as_expr().unwrap(); + let expr = expr.modify(times_two); + let (index, array, body) = expr.as_for().unwrap(); + assert_eq(index, quote { x }); + assert_eq(array.as_integer().unwrap(), (4, false)); + assert_eq(body.as_block().unwrap()[0].as_block().unwrap()[0].as_integer().unwrap(), (6, false)); + } + } + + #[test] + fn test_expr_as_for_range_statement() { + comptime + { + let expr = quote { for x in 2..3 { 4 } }.as_expr().unwrap(); + let (index, from, to, body) = expr.as_for_range().unwrap(); + assert_eq(index, quote { x }); + assert_eq(from.as_integer().unwrap(), (2, false)); + assert_eq(to.as_integer().unwrap(), (3, false)); + assert_eq(body.as_block().unwrap()[0].as_integer().unwrap(), (4, false)); + } + } + + #[test] + fn test_expr_modify_for_range_statement() { + comptime + { + let expr = quote { for x in 2..3 { 4 } }.as_expr().unwrap(); + let expr = expr.modify(times_two); + let (index, from, to, body) = expr.as_for_range().unwrap(); + assert_eq(index, quote { x }); + assert_eq(from.as_integer().unwrap(), (4, false)); + assert_eq(to.as_integer().unwrap(), (6, false)); + assert_eq(body.as_block().unwrap()[0].as_block().unwrap()[0].as_integer().unwrap(), (8, false)); + } + } + #[test] fn test_automatically_unwraps_parenthesized_expression() { comptime diff --git a/noir/noir-repo/tooling/debugger/ignored-tests.txt b/noir/noir-repo/tooling/debugger/ignored-tests.txt index 745971d9b28..78e14397938 100644 --- a/noir/noir-repo/tooling/debugger/ignored-tests.txt +++ b/noir/noir-repo/tooling/debugger/ignored-tests.txt @@ -3,4 +3,5 @@ debug_logs is_unconstrained macros references -regression_4709 \ No newline at end of file +regression_4709 +reference_only_used_as_alias \ No newline at end of file diff --git a/noir/noir-repo/tooling/lsp/src/lib.rs b/noir/noir-repo/tooling/lsp/src/lib.rs index 6557975743c..39d4c3faa61 100644 --- a/noir/noir-repo/tooling/lsp/src/lib.rs +++ b/noir/noir-repo/tooling/lsp/src/lib.rs @@ -35,7 +35,7 @@ use nargo::{ use nargo_toml::{find_file_manifest, resolve_workspace_from_toml, PackageSelection}; use noirc_driver::{file_manager_with_stdlib, prepare_crate, NOIR_ARTIFACT_VERSION_STRING}; use noirc_frontend::{ - graph::{CrateId, CrateName}, + graph::{CrateGraph, CrateId, CrateName}, hir::{ def_map::{parse_file, CrateDefMap}, Context, FunctionNameMatch, ParsedFiles, @@ -66,6 +66,7 @@ mod modules; mod notifications; mod requests; mod solver; +mod trait_impl_method_stub_generator; mod types; mod utils; mod visibility; @@ -91,15 +92,26 @@ pub struct LspState { open_documents_count: usize, input_files: HashMap, cached_lenses: HashMap>, - cached_definitions: HashMap, cached_parsed_files: HashMap))>, - cached_def_maps: HashMap>, + workspace_cache: HashMap, + package_cache: HashMap, options: LspInitializationOptions, // Tracks files that currently have errors, by package root. files_with_errors: HashMap>, } +struct WorkspaceCacheData { + file_manager: FileManager, +} + +struct PackageCacheData { + crate_id: CrateId, + crate_graph: CrateGraph, + node_interner: NodeInterner, + def_maps: BTreeMap, +} + impl LspState { fn new( client: &ClientSocket, @@ -111,12 +123,11 @@ impl LspState { solver: WrapperSolver(Box::new(solver)), input_files: HashMap::new(), cached_lenses: HashMap::new(), - cached_definitions: HashMap::new(), - open_documents_count: 0, cached_parsed_files: HashMap::new(), - cached_def_maps: HashMap::new(), + workspace_cache: HashMap::new(), + package_cache: HashMap::new(), + open_documents_count: 0, options: Default::default(), - files_with_errors: HashMap::new(), } } diff --git a/noir/noir-repo/tooling/lsp/src/notifications/mod.rs b/noir/noir-repo/tooling/lsp/src/notifications/mod.rs index 96e339ee212..6cddd278e62 100644 --- a/noir/noir-repo/tooling/lsp/src/notifications/mod.rs +++ b/noir/noir-repo/tooling/lsp/src/notifications/mod.rs @@ -2,7 +2,9 @@ use std::collections::HashSet; use std::ops::ControlFlow; use std::path::PathBuf; -use crate::insert_all_files_for_workspace_into_file_manager; +use crate::{ + insert_all_files_for_workspace_into_file_manager, PackageCacheData, WorkspaceCacheData, +}; use async_lsp::{ErrorCode, LanguageClient, ResponseError}; use fm::{FileManager, FileMap}; use fxhash::FxHashMap as HashMap; @@ -79,7 +81,8 @@ pub(super) fn on_did_close_text_document( state.open_documents_count -= 1; if state.open_documents_count == 0 { - state.cached_definitions.clear(); + state.package_cache.clear(); + state.workspace_cache.clear(); } let document_uri = params.text_document.uri; @@ -155,8 +158,15 @@ pub(crate) fn process_workspace_for_noir_document( Some(&file_path), ); state.cached_lenses.insert(document_uri.to_string(), collected_lenses); - state.cached_definitions.insert(package.root_dir.clone(), context.def_interner); - state.cached_def_maps.insert(package.root_dir.clone(), context.def_maps); + state.package_cache.insert( + package.root_dir.clone(), + PackageCacheData { + crate_id, + crate_graph: context.crate_graph, + node_interner: context.def_interner, + def_maps: context.def_maps, + }, + ); let fm = &context.file_manager; let files = fm.as_file_map(); @@ -166,6 +176,11 @@ pub(crate) fn process_workspace_for_noir_document( } } + state.workspace_cache.insert( + workspace.root_dir.clone(), + WorkspaceCacheData { file_manager: workspace_file_manager }, + ); + Ok(()) } diff --git a/noir/noir-repo/tooling/lsp/src/requests/code_action/fill_struct_fields.rs b/noir/noir-repo/tooling/lsp/src/requests/code_action/fill_struct_fields.rs index f57fbc652ad..be8602d99a9 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/code_action/fill_struct_fields.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/code_action/fill_struct_fields.rs @@ -1,6 +1,9 @@ use lsp_types::TextEdit; use noirc_errors::{Location, Span}; -use noirc_frontend::{ast::ConstructorExpression, node_interner::ReferenceId}; +use noirc_frontend::{ + ast::{ConstructorExpression, UnresolvedTypeData}, + node_interner::ReferenceId, +}; use crate::byte_span_to_range; @@ -12,8 +15,11 @@ impl<'a> CodeActionFinder<'a> { return; } - // Find out which struct this is - let location = Location::new(constructor.type_name.last_ident().span(), self.file); + let UnresolvedTypeData::Named(path, _, _) = &constructor.typ.typ else { + return; + }; + + let location = Location::new(path.span, self.file); let Some(ReferenceId::Struct(struct_id)) = self.interner.find_referenced(location) else { return; }; diff --git a/noir/noir-repo/tooling/lsp/src/requests/code_action/implement_missing_members.rs b/noir/noir-repo/tooling/lsp/src/requests/code_action/implement_missing_members.rs index eb1a8704131..1cd181966a2 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/code_action/implement_missing_members.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/code_action/implement_missing_members.rs @@ -1,21 +1,13 @@ -use std::collections::{BTreeMap, HashMap}; +use std::collections::HashMap; use lsp_types::TextEdit; use noirc_errors::{Location, Span}; use noirc_frontend::{ ast::{NoirTraitImpl, TraitImplItemKind, UnresolvedTypeData}, - graph::CrateId, - hir::{ - def_map::{CrateDefMap, ModuleId}, - type_check::generics::TraitGenerics, - }, - hir_def::{function::FuncMeta, stmt::HirPattern, traits::Trait}, - macros_api::{ModuleDefId, NodeInterner}, node_interner::ReferenceId, - Kind, ResolvedGeneric, Type, TypeVariableKind, }; -use crate::{byte_span_to_range, modules::relative_module_id_path}; +use crate::{byte_span_to_range, trait_impl_method_stub_generator::TraitImplMethodStubGenerator}; use super::CodeActionFinder; @@ -109,10 +101,12 @@ impl<'a> CodeActionFinder<'a> { for (name, func_id) in method_ids { let func_meta = self.interner.function_meta(func_id); + let modifiers = self.interner.function_modifiers(func_id); - let mut generator = MethodStubGenerator::new( + let mut generator = TraitImplMethodStubGenerator::new( name, func_meta, + modifiers, trait_, noir_trait_impl, self.interner, @@ -120,6 +114,8 @@ impl<'a> CodeActionFinder<'a> { self.module_id, indent + 4, ); + generator.set_body(format!("panic(f\"Implement {}\")", name)); + let stub = generator.generate(); stubs.push(stub); } @@ -136,430 +132,6 @@ impl<'a> CodeActionFinder<'a> { } } -struct MethodStubGenerator<'a> { - name: &'a str, - func_meta: &'a FuncMeta, - trait_: &'a Trait, - noir_trait_impl: &'a NoirTraitImpl, - interner: &'a NodeInterner, - def_maps: &'a BTreeMap, - module_id: ModuleId, - indent: usize, - string: String, -} - -impl<'a> MethodStubGenerator<'a> { - #[allow(clippy::too_many_arguments)] - fn new( - name: &'a str, - func_meta: &'a FuncMeta, - trait_: &'a Trait, - noir_trait_impl: &'a NoirTraitImpl, - interner: &'a NodeInterner, - def_maps: &'a BTreeMap, - module_id: ModuleId, - indent: usize, - ) -> Self { - Self { - name, - func_meta, - trait_, - noir_trait_impl, - interner, - def_maps, - module_id, - indent, - string: String::new(), - } - } - - fn generate(&mut self) -> String { - let indent_string = " ".repeat(self.indent); - - self.string.push_str(&indent_string); - self.string.push_str("fn "); - self.string.push_str(self.name); - self.append_resolved_generics(&self.func_meta.direct_generics); - self.string.push('('); - for (index, (pattern, typ, _visibility)) in self.func_meta.parameters.iter().enumerate() { - if index > 0 { - self.string.push_str(", "); - } - if self.append_pattern(pattern) { - self.string.push_str(": "); - self.append_type(typ); - } - } - self.string.push(')'); - - let return_type = self.func_meta.return_type(); - if return_type != &Type::Unit { - self.string.push_str(" -> "); - self.append_type(return_type); - } - - if !self.func_meta.trait_constraints.is_empty() { - self.string.push_str(" where "); - for (index, constraint) in self.func_meta.trait_constraints.iter().enumerate() { - if index > 0 { - self.string.push_str(", "); - } - self.append_type(&constraint.typ); - self.string.push_str(": "); - let trait_ = self.interner.get_trait(constraint.trait_id); - self.string.push_str(&trait_.name.0.contents); - self.append_trait_generics(&constraint.trait_generics); - } - } - - self.string.push_str(" {\n"); - - let body_indent_string = " ".repeat(self.indent + 4); - self.string.push_str(&body_indent_string); - self.string.push_str("panic(f\"Implement "); - self.string.push_str(self.name); - self.string.push_str("\")\n"); - self.string.push_str(&indent_string); - self.string.push_str("}\n"); - std::mem::take(&mut self.string) - } - - /// Appends a pattern and returns true if this was not the self type - fn append_pattern(&mut self, pattern: &HirPattern) -> bool { - match pattern { - HirPattern::Identifier(hir_ident) => { - let definition = self.interner.definition(hir_ident.id); - self.string.push_str(&definition.name); - &definition.name != "self" - } - HirPattern::Mutable(pattern, _) => { - self.string.push_str("mut "); - self.append_pattern(pattern) - } - HirPattern::Tuple(patterns, _) => { - self.string.push('('); - for (index, pattern) in patterns.iter().enumerate() { - if index > 0 { - self.string.push_str(", "); - } - self.append_pattern(pattern); - } - self.string.push(')'); - true - } - HirPattern::Struct(typ, patterns, _) => { - self.append_type(typ); - self.string.push_str(" { "); - for (index, (name, _pattern)) in patterns.iter().enumerate() { - if index > 0 { - self.string.push_str(", "); - } - self.string.push_str(&name.0.contents); - } - self.string.push_str(" }"); - true - } - } - } - - fn append_type(&mut self, typ: &Type) { - match typ { - Type::FieldElement => self.string.push_str("Field"), - Type::Array(n, e) => { - self.string.push('['); - self.append_type(e); - self.string.push_str("; "); - self.append_type(n); - self.string.push(']'); - } - Type::Slice(typ) => { - self.string.push('['); - self.append_type(typ); - self.string.push(']'); - } - Type::Tuple(types) => { - self.string.push('('); - for (index, typ) in types.iter().enumerate() { - if index > 0 { - self.string.push_str(", "); - } - self.append_type(typ); - } - self.string.push(')'); - } - Type::Struct(struct_type, generics) => { - let struct_type = struct_type.borrow(); - - let current_module_data = - &self.def_maps[&self.module_id.krate].modules()[self.module_id.local_id.0]; - - // Check if the struct type is already imported/visible in this module - let per_ns = current_module_data.find_name(&struct_type.name); - if let Some((module_def_id, _, _)) = per_ns.types { - if module_def_id == ModuleDefId::TypeId(struct_type.id) { - self.string.push_str(&struct_type.name.0.contents); - self.append_generics(generics); - return; - } - } - - 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 current_module_parent_id = current_module_data - .parent - .map(|parent| ModuleId { krate: self.module_id.krate, local_id: parent }); - - let relative_path = relative_module_id_path( - parent_module_id, - &self.module_id, - current_module_parent_id, - self.interner, - ); - - if !relative_path.is_empty() { - self.string.push_str(&relative_path); - self.string.push_str("::"); - } - self.string.push_str(&struct_type.name.0.contents); - self.append_generics(generics); - } - Type::Alias(type_alias, generics) => { - let type_alias = type_alias.borrow(); - - let current_module_data = - &self.def_maps[&self.module_id.krate].modules()[self.module_id.local_id.0]; - - // Check if the alias type is already imported/visible in this module - let per_ns = current_module_data.find_name(&type_alias.name); - if let Some((module_def_id, _, _)) = per_ns.types { - if module_def_id == ModuleDefId::TypeAliasId(type_alias.id) { - self.string.push_str(&type_alias.name.0.contents); - self.append_generics(generics); - return; - } - } - - let parent_module_id = - self.interner.reference_module(ReferenceId::Alias(type_alias.id)).unwrap(); - - let current_module_parent_id = current_module_data - .parent - .map(|parent| ModuleId { krate: self.module_id.krate, local_id: parent }); - - let relative_path = relative_module_id_path( - *parent_module_id, - &self.module_id, - current_module_parent_id, - self.interner, - ); - - if !relative_path.is_empty() { - self.string.push_str(&relative_path); - self.string.push_str("::"); - } - self.string.push_str(&type_alias.name.0.contents); - self.append_generics(generics); - } - Type::TraitAsType(trait_id, _, trait_generics) => { - let trait_ = self.interner.get_trait(*trait_id); - - let current_module_data = - &self.def_maps[&self.module_id.krate].modules()[self.module_id.local_id.0]; - - // Check if the trait type is already imported/visible in this module - let per_ns = current_module_data.find_name(&trait_.name); - if let Some((module_def_id, _, _)) = per_ns.types { - if module_def_id == ModuleDefId::TraitId(*trait_id) { - self.string.push_str(&trait_.name.0.contents); - self.append_trait_generics(trait_generics); - return; - } - } - - let parent_module_id = - self.interner.reference_module(ReferenceId::Trait(*trait_id)).unwrap(); - - let current_module_parent_id = current_module_data - .parent - .map(|parent| ModuleId { krate: self.module_id.krate, local_id: parent }); - - let relative_path = relative_module_id_path( - *parent_module_id, - &self.module_id, - current_module_parent_id, - self.interner, - ); - - if !relative_path.is_empty() { - self.string.push_str(&relative_path); - self.string.push_str("::"); - } - self.string.push_str(&trait_.name.0.contents); - self.append_trait_generics(trait_generics); - } - Type::TypeVariable(typevar, _) => { - if typevar.id() == self.trait_.self_type_typevar.id() { - self.string.push_str("Self"); - return; - } - - let generics = &self.trait_.generics; - if let Some(index) = - generics.iter().position(|generic| generic.type_var.id() == typevar.id()) - { - if let Some(typ) = self.noir_trait_impl.trait_generics.ordered_args.get(index) { - self.string.push_str(&typ.to_string()); - return; - } - } - - for associated_type in &self.trait_.associated_types { - if typevar.id() == associated_type.type_var.id() { - self.string.push_str("Self::"); - self.string.push_str(&associated_type.name); - return; - } - } - - for generic in &self.func_meta.direct_generics { - if typevar.id() == generic.type_var.id() { - self.string.push_str(&generic.name); - return; - } - } - - self.string.push_str("error"); - } - Type::NamedGeneric(typevar, _name, _kind) => { - self.append_type(&Type::TypeVariable(typevar.clone(), TypeVariableKind::Normal)); - } - Type::Function(args, ret, env, unconstrained) => { - if *unconstrained { - self.string.push_str("unconstrained "); - } - self.string.push_str("fn"); - - if let Type::Unit = **env { - } else { - self.string.push('['); - self.append_type(env); - self.string.push(']'); - } - - self.string.push('('); - for (index, arg) in args.iter().enumerate() { - if index > 0 { - self.string.push_str(", "); - } - self.append_type(arg); - } - self.string.push(')'); - - if let Type::Unit = **ret { - } else { - self.string.push_str(" -> "); - self.append_type(ret); - } - } - Type::MutableReference(typ) => { - self.string.push_str("&mut "); - self.append_type(typ); - } - Type::Forall(_, _) => { - panic!("Shouldn't get a Type::Forall"); - } - Type::InfixExpr(left, op, right) => { - self.append_type(left); - self.string.push(' '); - self.string.push_str(&op.to_string()); - self.string.push(' '); - self.append_type(right); - } - Type::Constant(_) - | Type::Integer(_, _) - | Type::Bool - | Type::String(_) - | Type::FmtString(_, _) - | Type::Unit - | Type::Quoted(_) - | Type::Error => self.string.push_str(&typ.to_string()), - } - } - - fn append_generics(&mut self, generics: &[Type]) { - if generics.is_empty() { - return; - } - - self.string.push('<'); - for (index, typ) in generics.iter().enumerate() { - if index > 0 { - self.string.push_str(", "); - } - self.append_type(typ); - } - self.string.push('>'); - } - - fn append_trait_generics(&mut self, generics: &TraitGenerics) { - if generics.named.is_empty() && generics.ordered.is_empty() { - return; - } - - let mut index = 0; - - self.string.push('<'); - for generic in &generics.ordered { - if index > 0 { - self.string.push_str(", "); - } - self.append_type(generic); - index += 1; - } - for named_type in &generics.named { - if index > 0 { - self.string.push_str(", "); - } - self.string.push_str(&named_type.name.0.contents); - self.string.push_str(" = "); - self.append_type(&named_type.typ); - index += 1; - } - self.string.push('>'); - } - - fn append_resolved_generics(&mut self, generics: &[ResolvedGeneric]) { - if generics.is_empty() { - return; - } - - self.string.push('<'); - for (index, generic) in self.func_meta.direct_generics.iter().enumerate() { - if index > 0 { - self.string.push_str(", "); - } - self.append_resolved_generic(generic); - } - self.string.push('>'); - } - - fn append_resolved_generic(&mut self, generic: &ResolvedGeneric) { - match &generic.kind { - Kind::Normal => self.string.push_str(&generic.name), - Kind::Numeric(typ) => { - self.string.push_str("let "); - self.string.push_str(&generic.name); - self.string.push_str(": "); - self.append_type(typ); - } - } - } -} - #[cfg(test)] mod tests { use tokio::test; diff --git a/noir/noir-repo/tooling/lsp/src/requests/code_action/import_or_qualify.rs b/noir/noir-repo/tooling/lsp/src/requests/code_action/import_or_qualify.rs index d537144ce7b..03a953bde85 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/code_action/import_or_qualify.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/code_action/import_or_qualify.rs @@ -134,7 +134,7 @@ mod tests { let src = r#" mod foo { mod bar { - struct SomeTypeInBar {} + pub struct SomeTypeInBar {} } } @@ -144,7 +144,7 @@ mod tests { let expected = r#" mod foo { mod bar { - struct SomeTypeInBar {} + pub struct SomeTypeInBar {} } } @@ -160,7 +160,7 @@ mod tests { let src = r#"mod foo { mod bar { - struct SomeTypeInBar {} + pub struct SomeTypeInBar {} } } @@ -170,7 +170,7 @@ fn foo(x: SomeType>| { files: &'a FileMap, file: FileId, + source: &'a str, lines: Vec<&'a str>, byte_index: usize, byte: Option, @@ -105,6 +114,7 @@ struct NodeFinder<'a> { /// The line where an auto_import must be inserted auto_import_line: usize, self_type: Option, + in_comptime: bool, } impl<'a> NodeFinder<'a> { @@ -133,6 +143,7 @@ impl<'a> NodeFinder<'a> { Self { files, file, + source, lines: source.lines().collect(), byte_index, byte, @@ -147,6 +158,7 @@ impl<'a> NodeFinder<'a> { nesting: 0, auto_import_line: 0, self_type: None, + in_comptime: false, } } @@ -170,8 +182,13 @@ impl<'a> NodeFinder<'a> { } fn complete_constructor_field_name(&mut self, constructor_expression: &ConstructorExpression) { - let location = - Location::new(constructor_expression.type_name.last_ident().span(), self.file); + let span = if let UnresolvedTypeData::Named(path, _, _) = &constructor_expression.typ.typ { + path.last_ident().span() + } else { + constructor_expression.typ.span + }; + + let location = Location::new(span, self.file); let Some(ReferenceId::Struct(struct_id)) = self.interner.find_referenced(location) else { return; }; @@ -346,6 +363,8 @@ impl<'a> NodeFinder<'a> { self.local_variables_completion(&prefix); self.builtin_functions_completion(&prefix, function_completion_kind); self.builtin_values_completion(&prefix); + self.builtin_types_completion(&prefix); + self.type_parameters_completion(&prefix); if let Some(self_type) = &self.self_type { let self_prefix = true; self.complete_type_fields_and_methods( @@ -537,6 +556,7 @@ impl<'a> NodeFinder<'a> { function_completion_kind: FunctionCompletionKind, self_prefix: bool, ) { + let typ = &typ; match typ { Type::Struct(struct_type, generics) => { self.complete_struct_fields(&struct_type.borrow(), generics, prefix, self_prefix); @@ -561,6 +581,16 @@ impl<'a> NodeFinder<'a> { Type::Tuple(types) => { self.complete_tuple_fields(types, self_prefix); } + Type::TypeVariable(var, _) | Type::NamedGeneric(var, _, _) => { + if let TypeBinding::Bound(typ) = &*var.borrow() { + return self.complete_type_fields_and_methods( + typ, + prefix, + function_completion_kind, + self_prefix, + ); + } + } Type::FieldElement | Type::Array(_, _) | Type::Slice(_) @@ -569,12 +599,10 @@ impl<'a> NodeFinder<'a> { | Type::String(_) | Type::FmtString(_, _) | Type::Unit - | Type::TypeVariable(_, _) | Type::TraitAsType(_, _, _) - | Type::NamedGeneric(_, _, _) | Type::Function(..) | Type::Forall(_, _) - | Type::Constant(_) + | Type::Constant(..) | Type::Quoted(_) | Type::InfixExpr(_, _, _) | Type::Error => (), @@ -602,17 +630,26 @@ impl<'a> NodeFinder<'a> { }; for (name, methods) in methods_by_name { - for func_id in methods.iter() { + for (func_id, method_type) in methods.iter() { + if function_kind == FunctionKind::Any { + if let Some(method_type) = method_type { + if method_type.unify(typ).is_err() { + continue; + } + } + } + if name_matches(name, prefix) { - if let Some(completion_item) = self.function_completion_item( + let completion_items = self.function_completion_items( name, func_id, function_completion_kind, function_kind, None, // attribute first type self_prefix, - ) { - self.completion_items.push(completion_item); + ); + if !completion_items.is_empty() { + self.completion_items.extend(completion_items); self.suggested_module_def_ids.insert(ModuleDefId::FunctionId(func_id)); } } @@ -631,15 +668,16 @@ impl<'a> NodeFinder<'a> { for (name, func_id) in &trait_.method_ids { if name_matches(name, prefix) { - if let Some(completion_item) = self.function_completion_item( + let completion_items = self.function_completion_items( name, *func_id, function_completion_kind, function_kind, None, // attribute first type self_prefix, - ) { - self.completion_items.push(completion_item); + ); + if !completion_items.is_empty() { + self.completion_items.extend(completion_items); self.suggested_module_def_ids.insert(ModuleDefId::FunctionId(*func_id)); } } @@ -719,14 +757,15 @@ impl<'a> NodeFinder<'a> { let per_ns = module_data.find_name(ident); if let Some((module_def_id, visibility, _)) = per_ns.types { if is_visible(module_id, self.module_id, visibility, self.def_maps) { - if let Some(completion_item) = self.module_def_id_completion_item( + let completion_items = self.module_def_id_completion_items( module_def_id, name.clone(), function_completion_kind, function_kind, requested_items, - ) { - self.completion_items.push(completion_item); + ); + if !completion_items.is_empty() { + self.completion_items.extend(completion_items); self.suggested_module_def_ids.insert(module_def_id); } } @@ -734,14 +773,15 @@ impl<'a> NodeFinder<'a> { if let Some((module_def_id, visibility, _)) = per_ns.values { if is_visible(module_id, self.module_id, visibility, self.def_maps) { - if let Some(completion_item) = self.module_def_id_completion_item( + let completion_items = self.module_def_id_completion_items( module_def_id, name.clone(), function_completion_kind, function_kind, requested_items, - ) { - self.completion_items.push(completion_item); + ); + if !completion_items.is_empty() { + self.completion_items.extend(completion_items); self.suggested_module_def_ids.insert(module_def_id); } } @@ -843,6 +883,75 @@ impl<'a> NodeFinder<'a> { } } + fn suggest_trait_impl_function( + &mut self, + noir_trait_impl: &NoirTraitImpl, + noir_function: &NoirFunction, + ) { + // First find the trait + let location = Location::new(noir_trait_impl.trait_name.span(), self.file); + let Some(ReferenceId::Trait(trait_id)) = self.interner.find_referenced(location) else { + return; + }; + + let trait_ = self.interner.get_trait(trait_id); + + // Get all methods + let mut method_ids = trait_.method_ids.clone(); + + // Remove the ones that already are implemented + for item in &noir_trait_impl.items { + if let TraitImplItemKind::Function(noir_function) = &item.item.kind { + method_ids.remove(noir_function.name()); + } + } + + let indent = 0; + + // Suggest the ones that match the name + let prefix = noir_function.name(); + for (name, func_id) in method_ids { + if !name_matches(&name, prefix) { + continue; + } + + let func_meta = self.interner.function_meta(&func_id); + let modifiers = self.interner.function_modifiers(&func_id); + + let mut generator = TraitImplMethodStubGenerator::new( + &name, + func_meta, + modifiers, + trait_, + noir_trait_impl, + self.interner, + self.def_maps, + self.module_id, + indent, + ); + generator.set_body("${1}".to_string()); + + let stub = generator.generate(); + + // We don't need the initial indent nor the final newlines + let stub = stub.trim(); + // We also don't need the leading "fn " as that's already in the code; + let stub = stub.strip_prefix("fn ").unwrap(); + + let label = if func_meta.parameters.is_empty() { + format!("fn {}()", &name) + } else { + format!("fn {}(..)", &name) + }; + + let completion_item = trait_impl_method_completion_item(label, stub); + let completion_item = self + .completion_item_with_doc_comments(ReferenceId::Function(func_id), completion_item); + + self.completion_items.push(completion_item); + } + } + fn try_set_self_type(&mut self, pattern: &Pattern) { match pattern { Pattern::Identifier(ident) => { @@ -851,7 +960,8 @@ impl<'a> NodeFinder<'a> { if let Some(ReferenceId::Local(definition_id)) = self.interner.find_referenced(location) { - self.self_type = Some(self.interner.definition_type(definition_id)); + self.self_type = + Some(self.interner.definition_type(definition_id).follow_bindings()); } } } @@ -860,6 +970,32 @@ impl<'a> NodeFinder<'a> { } } + fn get_lvalue_type(&self, lvalue: &LValue) -> Option { + match lvalue { + LValue::Ident(ident) => { + let location = Location::new(ident.span(), self.file); + if let Some(ReferenceId::Local(definition_id)) = + self.interner.find_referenced(location) + { + let typ = self.interner.definition_type(definition_id); + Some(typ) + } else { + None + } + } + LValue::MemberAccess { object, field_name, .. } => { + let typ = self.get_lvalue_type(object)?; + get_field_type(&typ, &field_name.0.contents) + } + LValue::Index { array, .. } => { + let typ = self.get_lvalue_type(array)?; + get_array_element_type(typ) + } + LValue::Dereference(lvalue, ..) => self.get_lvalue_type(lvalue), + LValue::Interned(..) => None, + } + } + fn includes_span(&self, span: Span) -> bool { span.start() as usize <= self.byte_index && self.byte_index <= span.end() as usize } @@ -933,8 +1069,12 @@ impl<'a> Visitor for NodeFinder<'a> { self.collect_local_variables(¶m.pattern); } + let old_in_comptime = self.in_comptime; + self.in_comptime = noir_function.def.is_comptime; + noir_function.def.body.accept(Some(span), self); + self.in_comptime = old_in_comptime; self.type_parameters = old_type_parameters; self.self_type = None; @@ -949,6 +1089,24 @@ impl<'a> Visitor for NodeFinder<'a> { self.collect_type_parameters_in_generics(&noir_trait_impl.impl_generics); for item in &noir_trait_impl.items { + if let TraitImplItemKind::Function(noir_function) = &item.item.kind { + // Check if it's `fn foo>|<` and neither `(` nor `<` follow + if noir_function.name_ident().span().end() as usize == self.byte_index + && noir_function.parameters().is_empty() + { + let bytes = self.source.as_bytes(); + let mut cursor = self.byte_index; + while cursor < bytes.len() && bytes[cursor].is_ascii_whitespace() { + cursor += 1; + } + let char = bytes[cursor] as char; + if char != '(' && char != '<' { + self.suggest_trait_impl_function(noir_trait_impl, noir_function); + return false; + } + } + } + item.item.accept(self); } @@ -1054,7 +1212,6 @@ impl<'a> Visitor for NodeFinder<'a> { if after_dot && call_expression.func.span.end() as usize == self.byte_index - 1 { let location = Location::new(call_expression.func.span, self.file); if let Some(typ) = self.interner.type_at_location(location) { - let typ = typ.follow_bindings(); let prefix = ""; let self_prefix = false; self.complete_type_fields_and_methods( @@ -1085,7 +1242,6 @@ impl<'a> Visitor for NodeFinder<'a> { if self.includes_span(method_call_expression.method_name.span()) { let location = Location::new(method_call_expression.object.span, self.file); if let Some(typ) = self.interner.type_at_location(location) { - let typ = typ.follow_bindings(); let prefix = method_call_expression.method_name.to_string(); let offset = self.byte_index - method_call_expression.method_name.span().start() as usize; @@ -1139,8 +1295,12 @@ impl<'a> Visitor for NodeFinder<'a> { let old_local_variables = self.local_variables.clone(); self.local_variables.clear(); + let old_in_comptime = self.in_comptime; + self.in_comptime = true; + statement.accept(self); + self.in_comptime = old_in_comptime; self.local_variables = old_local_variables; false @@ -1159,6 +1319,7 @@ impl<'a> Visitor for NodeFinder<'a> { } fn visit_lvalue_ident(&mut self, ident: &Ident) { + // If we have `foo.>|<` we suggest `foo`'s type fields and methods if self.byte == Some(b'.') && ident.span().end() as usize == self.byte_index - 1 { let location = Location::new(ident.span(), self.file); if let Some(ReferenceId::Local(definition_id)) = self.interner.find_referenced(location) @@ -1176,6 +1337,72 @@ impl<'a> Visitor for NodeFinder<'a> { } } + fn visit_lvalue_member_access( + &mut self, + object: &LValue, + field_name: &Ident, + span: Span, + ) -> bool { + // If we have `foo.bar.>|<` we solve the type of `foo`, get the field `bar`, + // then suggest methods of the resulting type. + if self.byte == Some(b'.') && span.end() as usize == self.byte_index - 1 { + if let Some(typ) = self.get_lvalue_type(object) { + if let Some(typ) = get_field_type(&typ, &field_name.0.contents) { + let prefix = ""; + let self_prefix = false; + self.complete_type_fields_and_methods( + &typ, + prefix, + FunctionCompletionKind::NameAndParameters, + self_prefix, + ); + } + } + + return false; + } + true + } + + fn visit_lvalue_index(&mut self, array: &LValue, _index: &Expression, span: Span) -> bool { + // If we have `foo[index].>|<` we solve the type of `foo`, then get the array/slice element type, + // then suggest methods of that type. + if self.byte == Some(b'.') && span.end() as usize == self.byte_index - 1 { + if let Some(typ) = self.get_lvalue_type(array) { + if let Some(typ) = get_array_element_type(typ) { + let prefix = ""; + let self_prefix = false; + self.complete_type_fields_and_methods( + &typ, + prefix, + FunctionCompletionKind::NameAndParameters, + self_prefix, + ); + } + } + return false; + } + true + } + + fn visit_lvalue_dereference(&mut self, lvalue: &LValue, span: Span) -> bool { + if self.byte == Some(b'.') && span.end() as usize == self.byte_index - 1 { + if let Some(typ) = self.get_lvalue_type(lvalue) { + let prefix = ""; + let self_prefix = false; + self.complete_type_fields_and_methods( + &typ, + prefix, + FunctionCompletionKind::NameAndParameters, + self_prefix, + ); + } + return false; + } + + true + } + fn visit_variable(&mut self, path: &Path, _: Span) -> bool { self.find_in_path(path, RequestedItems::AnyItems); false @@ -1195,7 +1422,6 @@ impl<'a> Visitor for NodeFinder<'a> { { let location = Location::new(expression.span, self.file); if let Some(typ) = self.interner.type_at_location(location) { - let typ = typ.follow_bindings(); let prefix = ""; let self_prefix = false; self.complete_type_fields_and_methods( @@ -1219,8 +1445,12 @@ impl<'a> Visitor for NodeFinder<'a> { let old_local_variables = self.local_variables.clone(); self.local_variables.clear(); + let old_in_comptime = self.in_comptime; + self.in_comptime = true; + block_expression.accept(Some(span), self); + self.in_comptime = old_in_comptime; self.local_variables = old_local_variables; false @@ -1231,7 +1461,11 @@ impl<'a> Visitor for NodeFinder<'a> { constructor_expression: &ConstructorExpression, _: Span, ) -> bool { - self.find_in_path(&constructor_expression.type_name, RequestedItems::OnlyTypes); + let UnresolvedTypeData::Named(path, _, _) = &constructor_expression.typ.typ else { + return true; + }; + + self.find_in_path(path, RequestedItems::OnlyTypes); // Check if we need to autocomplete the field name if constructor_expression @@ -1261,7 +1495,6 @@ impl<'a> Visitor for NodeFinder<'a> { // Assuming member_access_expression is of the form `foo.bar`, we are right after `bar` let location = Location::new(member_access_expression.lhs.span, self.file); if let Some(typ) = self.interner.type_at_location(location) { - let typ = typ.follow_bindings(); let prefix = ident.to_string().to_case(Case::Snake); let self_prefix = false; self.complete_type_fields_and_methods( @@ -1331,13 +1564,126 @@ impl<'a> Visitor for NodeFinder<'a> { false } - fn visit_custom_attribute(&mut self, attribute: &CustomAtrribute, target: AttributeTarget) { + fn visit_type_path(&mut self, type_path: &TypePath, _: Span) -> bool { + if type_path.item.span().end() as usize != self.byte_index { + return true; + } + + let typ = match &type_path.typ.typ { + UnresolvedTypeData::FieldElement => Some(Type::FieldElement), + UnresolvedTypeData::Integer(signedness, integer_bit_size) => { + Some(Type::Integer(*signedness, *integer_bit_size)) + } + UnresolvedTypeData::Bool => Some(Type::Bool), + UnresolvedTypeData::String(UnresolvedTypeExpression::Constant(value, _)) => { + Some(Type::String(Box::new(Type::Constant( + *value, + Kind::Numeric(Box::new(Type::Integer( + Signedness::Unsigned, + IntegerBitSize::ThirtyTwo, + ))), + )))) + } + UnresolvedTypeData::Quoted(quoted_type) => Some(Type::Quoted(*quoted_type)), + _ => None, + }; + + if let Some(typ) = typ { + let prefix = &type_path.item.0.contents; + self.complete_type_methods( + &typ, + prefix, + FunctionKind::Any, + FunctionCompletionKind::NameAndParameters, + false, // self_prefix + ); + } + + false + } + + fn visit_custom_attribute(&mut self, attribute: &CustomAttribute, target: AttributeTarget) { if self.byte_index != attribute.contents_span.end() as usize { return; } self.suggest_attributes(&attribute.contents, target); } + + fn visit_quote(&mut self, tokens: &Tokens) { + let mut last_was_dollar = false; + + for token in &tokens.0 { + let span = token.to_span(); + if span.end() as usize > self.byte_index { + break; + } + + let token = token.token(); + + if let Token::DollarSign = token { + if span.end() as usize == self.byte_index { + self.local_variables_completion(""); + break; + } + + last_was_dollar = true; + continue; + } + + if span.end() as usize == self.byte_index { + let prefix = token.to_string(); + if last_was_dollar { + self.local_variables_completion(&prefix); + } + break; + } + + last_was_dollar = false; + } + } +} + +fn get_field_type(typ: &Type, name: &str) -> Option { + match typ { + Type::Struct(struct_type, generics) => { + Some(struct_type.borrow().get_field(name, generics)?.0) + } + Type::Tuple(types) => { + if let Ok(index) = name.parse::() { + types.get(index as usize).cloned() + } else { + None + } + } + Type::Alias(alias_type, generics) => Some(alias_type.borrow().get_type(generics)), + Type::TypeVariable(var, _) | Type::NamedGeneric(var, _, _) => { + if let TypeBinding::Bound(typ) = &*var.borrow() { + get_field_type(typ, name) + } else { + None + } + } + _ => None, + } +} + +fn get_array_element_type(typ: Type) -> Option { + match typ { + Type::Array(_, typ) | Type::Slice(typ) => Some(*typ), + Type::Alias(alias_type, generics) => { + let typ = alias_type.borrow().get_type(&generics); + get_array_element_type(typ) + } + Type::TypeVariable(var, _) | Type::NamedGeneric(var, _, _) => { + if let TypeBinding::Bound(typ) = &*var.borrow() { + get_array_element_type(typ.clone()) + } else { + None + } + } + _ => None, + } } /// Returns true if name matches a prefix written in code. diff --git a/noir/noir-repo/tooling/lsp/src/requests/completion/auto_import.rs b/noir/noir-repo/tooling/lsp/src/requests/completion/auto_import.rs index f9c5dab0672..2713ae252bf 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/completion/auto_import.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/completion/auto_import.rs @@ -29,73 +29,78 @@ impl<'a> NodeFinder<'a> { continue; } - let Some(mut completion_item) = self.module_def_id_completion_item( + let completion_items = self.module_def_id_completion_items( *module_def_id, name.clone(), function_completion_kind, FunctionKind::Any, requested_items, - ) else { + ); + + if completion_items.is_empty() { continue; }; - let module_full_path = if let Some(defining_module) = defining_module { - relative_module_id_path( - *defining_module, - &self.module_id, - current_module_parent_id, - self.interner, - ) - } else { - let Some(module_full_path) = relative_module_full_path( - *module_def_id, - *visibility, - self.module_id, - current_module_parent_id, - self.interner, - self.def_maps, - ) else { - continue; + self.suggested_module_def_ids.insert(*module_def_id); + + for mut completion_item in completion_items { + let module_full_path = if let Some(defining_module) = defining_module { + relative_module_id_path( + *defining_module, + &self.module_id, + current_module_parent_id, + self.interner, + ) + } else { + let Some(module_full_path) = relative_module_full_path( + *module_def_id, + *visibility, + self.module_id, + current_module_parent_id, + self.interner, + self.def_maps, + ) else { + continue; + }; + module_full_path }; - module_full_path - }; - let full_path = if defining_module.is_some() - || !matches!(module_def_id, ModuleDefId::ModuleId(..)) - { - format!("{}::{}", module_full_path, name) - } else { - module_full_path - }; + let full_path = if defining_module.is_some() + || !matches!(module_def_id, ModuleDefId::ModuleId(..)) + { + format!("{}::{}", module_full_path, name) + } else { + module_full_path + }; - let mut label_details = completion_item.label_details.unwrap(); - label_details.detail = Some(format!("(use {})", full_path)); - completion_item.label_details = Some(label_details); + let mut label_details = completion_item.label_details.unwrap(); + label_details.detail = Some(format!("(use {})", full_path)); + completion_item.label_details = Some(label_details); - let line = self.auto_import_line as u32; - let character = (self.nesting * 4) as u32; - let indent = " ".repeat(self.nesting * 4); - let mut newlines = "\n"; + let line = self.auto_import_line as u32; + let character = (self.nesting * 4) as u32; + let indent = " ".repeat(self.nesting * 4); + let mut newlines = "\n"; - // If the line we are inserting into is not an empty line, insert an extra line to make some room - if let Some(line_text) = self.lines.get(line as usize) { - if !line_text.trim().is_empty() { - newlines = "\n\n"; + // If the line we are inserting into is not an empty line, insert an extra line to make some room + if let Some(line_text) = self.lines.get(line as usize) { + if !line_text.trim().is_empty() { + newlines = "\n\n"; + } } - } - completion_item.additional_text_edits = Some(vec![TextEdit { - range: Range { - start: Position { line, character }, - end: Position { line, character }, - }, - new_text: format!("use {};{}{}", full_path, newlines, indent), - }]); + completion_item.additional_text_edits = Some(vec![TextEdit { + range: Range { + start: Position { line, character }, + end: Position { line, character }, + }, + new_text: format!("use {};{}{}", full_path, newlines, indent), + }]); - completion_item.sort_text = Some(auto_import_sort_text()); + completion_item.sort_text = Some(auto_import_sort_text()); - self.completion_items.push(completion_item); - self.suggested_module_def_ids.insert(*module_def_id); + self.completion_items.push(completion_item); + } } } } diff --git a/noir/noir-repo/tooling/lsp/src/requests/completion/builtins.rs b/noir/noir-repo/tooling/lsp/src/requests/completion/builtins.rs index 520c158d260..6812ebc135b 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/completion/builtins.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/completion/builtins.rs @@ -128,6 +128,7 @@ pub(super) fn builtin_integer_types() -> [&'static str; 8] { pub(super) fn keyword_builtin_type(keyword: &Keyword) -> Option<&'static str> { match keyword { Keyword::Bool => Some("bool"), + Keyword::CtString => Some("CtString"), Keyword::Expr => Some("Expr"), Keyword::Field => Some("Field"), Keyword::FunctionDefinition => Some("FunctionDefinition"), @@ -212,6 +213,7 @@ pub(super) fn keyword_builtin_function(keyword: &Keyword) -> Option NodeFinder<'a> { - pub(super) fn module_def_id_completion_item( + pub(super) fn module_def_id_completion_items( &self, module_def_id: ModuleDefId, name: String, function_completion_kind: FunctionCompletionKind, function_kind: FunctionKind, requested_items: RequestedItems, - ) -> Option { + ) -> Vec { match requested_items { RequestedItems::OnlyTypes => match module_def_id { - ModuleDefId::FunctionId(_) | ModuleDefId::GlobalId(_) => return None, + ModuleDefId::FunctionId(_) | ModuleDefId::GlobalId(_) => return Vec::new(), ModuleDefId::ModuleId(_) | ModuleDefId::TypeId(_) | ModuleDefId::TypeAliasId(_) @@ -38,7 +38,7 @@ impl<'a> NodeFinder<'a> { }, RequestedItems::OnlyAttributeFunctions(..) => { if !matches!(module_def_id, ModuleDefId::FunctionId(..)) { - return None; + return Vec::new(); } } RequestedItems::AnyItems => (), @@ -57,8 +57,8 @@ impl<'a> NodeFinder<'a> { }; match module_def_id { - ModuleDefId::ModuleId(id) => Some(self.module_completion_item(name, id)), - ModuleDefId::FunctionId(func_id) => self.function_completion_item( + ModuleDefId::ModuleId(id) => vec![self.module_completion_item(name, id)], + ModuleDefId::FunctionId(func_id) => self.function_completion_items( &name, func_id, function_completion_kind, @@ -66,10 +66,10 @@ impl<'a> NodeFinder<'a> { attribute_first_type.as_ref(), false, // self_prefix ), - ModuleDefId::TypeId(struct_id) => Some(self.struct_completion_item(name, struct_id)), - ModuleDefId::TypeAliasId(id) => Some(self.type_alias_completion_item(name, id)), - ModuleDefId::TraitId(trait_id) => Some(self.trait_completion_item(name, trait_id)), - ModuleDefId::GlobalId(global_id) => Some(self.global_completion_item(name, global_id)), + ModuleDefId::TypeId(struct_id) => vec![self.struct_completion_item(name, struct_id)], + ModuleDefId::TypeAliasId(id) => vec![self.type_alias_completion_item(name, id)], + ModuleDefId::TraitId(trait_id) => vec![self.trait_completion_item(name, trait_id)], + ModuleDefId::GlobalId(global_id) => vec![self.global_completion_item(name, global_id)], } } @@ -133,7 +133,7 @@ impl<'a> NodeFinder<'a> { self.completion_item_with_doc_comments(ReferenceId::Global(global_id), completion_item) } - pub(super) fn function_completion_item( + pub(super) fn function_completion_items( &self, name: &String, func_id: FuncId, @@ -141,7 +141,7 @@ impl<'a> NodeFinder<'a> { function_kind: FunctionKind, attribute_first_type: Option<&Type>, self_prefix: bool, - ) -> Option { + ) -> Vec { let func_meta = self.interner.function_meta(&func_id); let func_self_type = if let Some((pattern, typ, _)) = func_meta.parameters.0.first() { @@ -161,12 +161,12 @@ impl<'a> NodeFinder<'a> { if let Some(attribute_first_type) = attribute_first_type { if func_meta.parameters.is_empty() { - return None; + return Vec::new(); } let (_, typ, _) = &func_meta.parameters.0[0]; if typ != attribute_first_type { - return None; + return Vec::new(); } } @@ -186,23 +186,77 @@ impl<'a> NodeFinder<'a> { } if self_type != func_self_type { - return None; + return Vec::new(); } } else if let Type::Tuple(self_tuple_types) = self_type { // Tuple types of different lengths seem to also have methods defined on all of them, // so here we reject methods for tuples where the length doesn't match. if let Type::Tuple(func_self_tuple_types) = func_self_type { if self_tuple_types.len() != func_self_tuple_types.len() { - return None; + return Vec::new(); } } } } else { - return None; + return Vec::new(); } } } + let make_completion_item = |is_macro_call| { + self.function_completion_item( + name, + func_id, + func_meta, + func_self_type, + function_completion_kind, + function_kind, + attribute_first_type, + self_prefix, + is_macro_call, + ) + }; + + // When suggesting functions in attributes, never suggest a macro call + if attribute_first_type.is_some() { + return vec![make_completion_item(false)]; + } + + // Special case: the `unquote` macro + // (it's unlikely users will define a function named `unquote` that does something different than std's unquote) + if name == "unquote" { + return vec![make_completion_item(true)]; + } + + let modifiers = self.interner.function_modifiers(&func_id); + if modifiers.is_comptime + && matches!(func_meta.return_type(), Type::Quoted(QuotedType::Quoted)) + { + if self.in_comptime { + vec![make_completion_item(false), make_completion_item(true)] + } else { + // If not in a comptime block we can't operate with comptime values so the only thing + // we can do is call a macro. + vec![make_completion_item(true)] + } + } else { + vec![make_completion_item(false)] + } + } + + #[allow(clippy::too_many_arguments)] + pub(super) fn function_completion_item( + &self, + name: &String, + func_id: FuncId, + func_meta: &FuncMeta, + func_self_type: Option<&Type>, + function_completion_kind: FunctionCompletionKind, + function_kind: FunctionKind, + attribute_first_type: Option<&Type>, + self_prefix: bool, + is_macro_call: bool, + ) -> CompletionItem { let is_operator = if let Some(trait_impl_id) = &func_meta.trait_impl { let trait_impl = self.interner.get_trait_implementation(*trait_impl_id); let trait_impl = trait_impl.borrow(); @@ -211,6 +265,7 @@ impl<'a> NodeFinder<'a> { false }; let name = if self_prefix { format!("self.{}", name) } else { name.clone() }; + let name = if is_macro_call { format!("{}!", name) } else { name }; let name = &name; let description = func_meta_type_to_string(func_meta, func_self_type.is_some()); let mut has_arguments = false; @@ -269,10 +324,8 @@ impl<'a> NodeFinder<'a> { } } }; - let completion_item = - self.completion_item_with_doc_comments(ReferenceId::Function(func_id), completion_item); - Some(completion_item) + self.completion_item_with_doc_comments(ReferenceId::Function(func_id), completion_item) } fn compute_function_insert_text( @@ -320,7 +373,7 @@ impl<'a> NodeFinder<'a> { text } - fn completion_item_with_doc_comments( + pub(super) fn completion_item_with_doc_comments( &self, id: ReferenceId, completion_item: CompletionItem, @@ -368,6 +421,13 @@ pub(super) fn module_completion_item(name: impl Into) -> CompletionItem ) } +pub(super) fn trait_impl_method_completion_item( + label: impl Into, + insert_text: impl Into, +) -> CompletionItem { + snippet_completion_item(label, CompletionItemKind::METHOD, insert_text, None) +} + fn func_meta_type_to_string(func_meta: &FuncMeta, has_self_type: bool) -> String { let mut typ = &func_meta.typ; if let Type::Forall(_, typ_) = typ { diff --git a/noir/noir-repo/tooling/lsp/src/requests/completion/tests.rs b/noir/noir-repo/tooling/lsp/src/requests/completion/tests.rs index 6809e24e645..45eb79bd1c2 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/completion/tests.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/completion/tests.rs @@ -8,6 +8,7 @@ mod completion_tests { completion_item_with_detail, completion_item_with_sort_text, completion_item_with_trigger_parameter_hints_command, module_completion_item, simple_completion_item, snippet_completion_item, + trait_impl_method_completion_item, }, sort_text::{auto_import_sort_text, self_mismatch_sort_text}, }, @@ -175,7 +176,7 @@ mod completion_tests { async fn test_use_struct() { let src = r#" mod foo { - struct Foo {} + pub struct Foo {} } use foo::>|< "#; @@ -430,6 +431,27 @@ mod completion_tests { .await; } + #[test] + async fn test_complete_type_path_with_non_empty_name() { + let src = r#" + trait One { + fn one() -> Self; + } + + impl One for Field { + fn one() -> Self { + 1 + } + } + + fn main() { + Field::o>|< + } + "#; + assert_completion(src, vec![function_completion_item("one()", "one()", "fn() -> Field")]) + .await; + } + #[test] async fn test_complete_function_without_arguments() { let src = r#" @@ -755,6 +777,18 @@ mod completion_tests { ); } + #[test] + async fn test_suggest_builtin_types_in_any_position() { + let src = r#" + fn foo() { + i>|< + } + "#; + + let items = get_completions(src).await; + assert!(items.iter().any(|item| item.label == "i8")); + } + #[test] async fn test_suggest_true() { let src = r#" @@ -762,15 +796,11 @@ mod completion_tests { let x = t>|< } "#; - assert_completion_excluding_auto_import( - src, - vec![simple_completion_item( - "true", - CompletionItemKind::KEYWORD, - Some("bool".to_string()), - )], - ) - .await; + + let items = get_completions(src).await; + assert!(items + .iter() + .any(|item| item.label == "true" && item.kind == Some(CompletionItemKind::KEYWORD))); } #[test] @@ -1918,7 +1948,7 @@ mod completion_tests { #[some>|<] fn foo() {} - fn some_attr(f: FunctionDefinition, x: Field) {} + comptime fn some_attr(f: FunctionDefinition, x: Field) -> Quoted {} fn some_other_function(x: Field) {} "#; @@ -1927,7 +1957,7 @@ mod completion_tests { vec![function_completion_item( "some_attr(…)", "some_attr(${1:x})", - "fn(FunctionDefinition, Field)", + "fn(FunctionDefinition, Field) -> Quoted", )], ) .await; @@ -1968,4 +1998,257 @@ mod completion_tests { ) .await; } + + #[test] + async fn test_suggests_trait_impl_function() { + let src = r#" + trait Trait { + fn foo(x: i32) -> i32; + } + + struct Foo {} + + impl Trait for Foo { + fn f>|< + }"#; + + assert_completion( + src, + vec![trait_impl_method_completion_item( + "fn foo(..)", + "foo(x: i32) -> i32 {\n ${1}\n}", + )], + ) + .await; + } + + #[test] + async fn test_suggests_trait_impl_default_function() { + let src = r#" + trait Trait { + fn foo(x: i32) -> i32 { 1 } + } + + struct Foo {} + + impl Trait for Foo { + fn f>|< + }"#; + + assert_completion( + src, + vec![trait_impl_method_completion_item( + "fn foo(..)", + "foo(x: i32) -> i32 {\n ${1}\n}", + )], + ) + .await; + } + + #[test] + async fn test_suggests_when_assignment_follows_in_chain_1() { + let src = r#" + struct Foo { + bar: Bar + } + + struct Bar { + baz: Field + } + + fn f(foo: Foo) { + let mut x = 1; + + foo.bar.>|< + + x = 2; + }"#; + + assert_completion(src, vec![field_completion_item("baz", "Field")]).await; + } + + #[test] + async fn test_suggests_when_assignment_follows_in_chain_2() { + let src = r#" + struct Foo { + bar: Bar + } + + struct Bar { + baz: Baz + } + + struct Baz { + qux: Field + } + + fn f(foo: Foo) { + let mut x = 1; + + foo.bar.baz.>|< + + x = 2; + }"#; + + assert_completion(src, vec![field_completion_item("qux", "Field")]).await; + } + + #[test] + async fn test_suggests_when_assignment_follows_in_chain_3() { + let src = r#" + struct Foo { + foo: Field + } + + fn execute() { + let a = Foo { foo: 1 }; + a.>|< + + x = 1; + }"#; + + assert_completion(src, vec![field_completion_item("foo", "Field")]).await; + } + + #[test] + async fn test_suggests_when_assignment_follows_in_chain_4() { + let src = r#" + struct Foo { + bar: Bar + } + + struct Bar { + baz: Field + } + + fn execute() { + let foo = Foo { foo: 1 }; + foo.bar.>|< + + x = 1; + }"#; + + assert_completion(src, vec![field_completion_item("baz", "Field")]).await; + } + + #[test] + async fn test_suggests_when_assignment_follows_in_chain_with_index() { + let src = r#" + struct Foo { + bar: Field + } + + fn f(foos: [Foo; 3]) { + let mut x = 1; + + foos[0].>|< + + x = 2; + }"#; + + assert_completion(src, vec![field_completion_item("bar", "Field")]).await; + } + + #[test] + async fn test_suggests_macro_call_if_comptime_function_returns_quoted() { + let src = r#" + comptime fn foobar() -> Quoted {} + + fn main() { + comptime { + fooba>|< + } + } + "#; + + assert_completion_excluding_auto_import( + src, + vec![ + function_completion_item("foobar!()", "foobar!()", "fn() -> Quoted"), + function_completion_item("foobar()", "foobar()", "fn() -> Quoted"), + ], + ) + .await; + } + + #[test] + async fn test_suggests_only_macro_call_if_comptime_function_returns_quoted_and_outside_comptime( + ) { + let src = r#" + comptime fn foobar() -> Quoted {} + + fn main() { + fooba>|< + } + "#; + + assert_completion_excluding_auto_import( + src, + vec![function_completion_item("foobar!()", "foobar!()", "fn() -> Quoted")], + ) + .await; + } + + #[test] + async fn test_only_suggests_macro_call_for_unquote() { + let src = r#" + use std::meta::unquote; + + fn main() { + unquot>|< + } + "#; + + let completions = get_completions(src).await; + assert_eq!(completions.len(), 1); + assert_eq!(completions[0].label, "unquote!(…)"); + } + + #[test] + async fn test_suggests_variable_in_quoted_after_dollar() { + let src = r#" + fn main() { + comptime { + let some_var = 1; + quote { + $>|< + } + } + } + "#; + + assert_completion( + src, + vec![simple_completion_item( + "some_var", + CompletionItemKind::VARIABLE, + Some("Field".to_string()), + )], + ) + .await; + } + + #[test] + async fn test_suggests_variable_in_quoted_after_dollar_and_letters() { + let src = r#" + fn main() { + comptime { + let some_var = 1; + quote { + $s>|< + } + } + } + "#; + + assert_completion( + src, + vec![simple_completion_item( + "some_var", + CompletionItemKind::VARIABLE, + Some("Field".to_string()), + )], + ) + .await; + } } diff --git a/noir/noir-repo/tooling/lsp/src/requests/hover.rs b/noir/noir-repo/tooling/lsp/src/requests/hover.rs index 8e9666a624b..46d2a5cfc8f 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/hover.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/hover.rs @@ -5,11 +5,12 @@ use fm::FileMap; use lsp_types::{Hover, HoverContents, HoverParams, MarkupContent, MarkupKind}; use noirc_frontend::{ ast::Visibility, + elaborator::types::try_eval_array_length_id, hir::def_map::ModuleId, - hir_def::{stmt::HirPattern, traits::Trait}, - macros_api::{NodeInterner, StructId}, + hir_def::{expr::HirArrayLiteral, stmt::HirPattern, traits::Trait}, + macros_api::{HirExpression, HirLiteral, NodeInterner, StructId}, node_interner::{ - DefinitionId, DefinitionKind, FuncId, GlobalId, ReferenceId, TraitId, TypeAliasId, + DefinitionId, DefinitionKind, ExprId, FuncId, GlobalId, ReferenceId, TraitId, TypeAliasId, }, Generics, Shared, StructType, Type, TypeAlias, TypeBinding, TypeVariable, }; @@ -166,17 +167,34 @@ fn format_trait(id: TraitId, args: &ProcessRequestCallbackArgs) -> String { fn format_global(id: GlobalId, args: &ProcessRequestCallbackArgs) -> String { let global_info = args.interner.get_global(id); let definition_id = global_info.definition_id; + let definition = args.interner.definition(definition_id); let typ = args.interner.definition_type(definition_id); let mut string = String::new(); if format_parent_module(ReferenceId::Global(id), args, &mut string) { string.push('\n'); } + string.push_str(" "); + if definition.comptime { + string.push_str("comptime "); + } + if definition.mutable { + string.push_str("mut "); + } string.push_str("global "); string.push_str(&global_info.ident.0.contents); string.push_str(": "); string.push_str(&format!("{}", typ)); + + // See if we can figure out what's the global's value + if let Some(stmt) = args.interner.get_global_let_statement(id) { + if let Some(value) = get_global_value(args.interner, stmt.expression) { + string.push_str(" = "); + string.push_str(&value); + } + } + string.push_str(&go_to_type_links(&typ, args.interner, args.files)); append_doc_comments(args.interner, ReferenceId::Global(id), &mut string); @@ -184,6 +202,72 @@ fn format_global(id: GlobalId, args: &ProcessRequestCallbackArgs) -> String { string } +fn get_global_value(interner: &NodeInterner, expr: ExprId) -> Option { + let span = interner.expr_span(&expr); + + // Globals as array lengths are extremely common, so we try that first. + if let Ok(result) = try_eval_array_length_id(interner, expr, span) { + return Some(result.to_string()); + } + + match interner.expression(&expr) { + HirExpression::Literal(literal) => match literal { + HirLiteral::Array(hir_array_literal) => { + get_global_array_value(interner, hir_array_literal, false) + } + HirLiteral::Slice(hir_array_literal) => { + get_global_array_value(interner, hir_array_literal, true) + } + HirLiteral::Bool(value) => Some(value.to_string()), + HirLiteral::Integer(field_element, _) => Some(field_element.to_string()), + HirLiteral::Str(string) => Some(format!("{:?}", string)), + HirLiteral::FmtStr(..) => None, + HirLiteral::Unit => Some("()".to_string()), + }, + HirExpression::Tuple(values) => { + get_exprs_global_value(interner, &values).map(|value| format!("({})", value)) + } + _ => None, + } +} + +fn get_global_array_value( + interner: &NodeInterner, + literal: HirArrayLiteral, + is_slice: bool, +) -> Option { + match literal { + HirArrayLiteral::Standard(values) => { + get_exprs_global_value(interner, &values).map(|value| { + if is_slice { + format!("&[{}]", value) + } else { + format!("[{}]", value) + } + }) + } + HirArrayLiteral::Repeated { repeated_element, length } => { + get_global_value(interner, repeated_element).map(|value| { + if is_slice { + format!("&[{}; {}]", value, length) + } else { + format!("[{}; {}]", value, length) + } + }) + } + } +} + +fn get_exprs_global_value(interner: &NodeInterner, exprs: &[ExprId]) -> Option { + let strings: Vec = + exprs.iter().filter_map(|value| get_global_value(interner, *value)).collect(); + if strings.len() == exprs.len() { + Some(strings.join(", ")) + } else { + None + } +} + fn format_function(id: FuncId, args: &ProcessRequestCallbackArgs) -> String { let func_meta = args.interner.function_meta(&id); let func_name_definition_id = args.interner.definition(func_meta.name.id); @@ -263,6 +347,10 @@ fn format_alias(id: TypeAliasId, args: &ProcessRequestCallbackArgs) -> String { fn format_local(id: DefinitionId, args: &ProcessRequestCallbackArgs) -> String { let definition_info = args.interner.definition(id); + if let DefinitionKind::Global(global_id) = &definition_info.kind { + return format_global(*global_id, args); + } + let DefinitionKind::Local(expr_id) = definition_info.kind else { panic!("Expected a local reference to reference a local definition") }; @@ -447,7 +535,7 @@ impl<'a> TypeLinksGatherer<'a> { | Type::FmtString(_, _) | Type::Unit | Type::Forall(_, _) - | Type::Constant(_) + | Type::Constant(..) | Type::Quoted(_) | Type::Error => (), } @@ -629,7 +717,7 @@ mod hover_tests { "two/src/lib.nr", Position { line: 15, character: 25 }, r#" one::subone - global some_global: Field"#, + global some_global: Field = 2"#, ) .await; } diff --git a/noir/noir-repo/tooling/lsp/src/requests/inlay_hint.rs b/noir/noir-repo/tooling/lsp/src/requests/inlay_hint.rs index 43e0227fa26..2eef4f6e262 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/inlay_hint.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/inlay_hint.rs @@ -477,14 +477,6 @@ fn push_type_parts(typ: &Type, parts: &mut Vec, files: &File push_type_variable_parts(binding, parts, files); } } - Type::TypeVariable(binding, TypeVariableKind::Constant(n)) => { - if let TypeBinding::Unbound(_) = &*binding.borrow() { - // TypeVariableKind::Constant(n) binds to Type::Constant(n) by default, so just show that. - parts.push(string_part(n.to_string())); - } else { - push_type_variable_parts(binding, parts, files); - } - } Type::FieldElement | Type::Integer(..) @@ -530,6 +522,7 @@ fn get_expression_name(expression: &Expression) -> Option { ExpressionKind::Cast(cast) => get_expression_name(&cast.lhs), ExpressionKind::Parenthesized(expr) => get_expression_name(expr), ExpressionKind::AsTraitPath(path) => Some(path.impl_item.to_string()), + ExpressionKind::TypePath(path) => Some(path.item.to_string()), ExpressionKind::Constructor(..) | ExpressionKind::Infix(..) | ExpressionKind::Index(..) @@ -542,6 +535,7 @@ fn get_expression_name(expression: &Expression) -> Option { | ExpressionKind::Comptime(..) | ExpressionKind::Resolved(..) | ExpressionKind::Interned(..) + | ExpressionKind::InternedStatement(..) | ExpressionKind::Literal(..) | ExpressionKind::Unsafe(..) | ExpressionKind::Error => None, diff --git a/noir/noir-repo/tooling/lsp/src/requests/mod.rs b/noir/noir-repo/tooling/lsp/src/requests/mod.rs index fea758e0e52..576d026081d 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/mod.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/mod.rs @@ -2,9 +2,9 @@ use std::collections::BTreeMap; use std::path::PathBuf; use std::{collections::HashMap, future::Future}; -use crate::insert_all_files_for_workspace_into_file_manager; +use crate::{insert_all_files_for_workspace_into_file_manager, parse_diff, PackageCacheData}; use crate::{ - parse_diff, resolve_workspace_for_source_path, + resolve_workspace_for_source_path, types::{CodeLensOptions, InitializeParams}, }; use async_lsp::{ErrorCode, ResponseError}; @@ -238,7 +238,11 @@ pub(crate) fn on_initialize( )), completion_provider: Some(lsp_types::OneOf::Right(lsp_types::CompletionOptions { resolve_provider: None, - trigger_characters: Some(vec![".".to_string(), ":".to_string()]), + trigger_characters: Some(vec![ + ".".to_string(), // For method calls + ":".to_string(), // For paths + "$".to_string(), // For $var inside `quote { ... }` + ]), all_commit_characters: None, work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None, @@ -407,7 +411,7 @@ pub(crate) struct ProcessRequestCallbackArgs<'a> { location: noirc_errors::Location, files: &'a FileMap, interner: &'a NodeInterner, - interners: &'a HashMap, + package_cache: &'a HashMap, crate_id: CrateId, crate_name: String, dependencies: &'a Vec, @@ -432,6 +436,63 @@ where ResponseError::new(ErrorCode::REQUEST_FAILED, "Could not find package for file") })?; + // In practice when `process_request` is called, a document in the project should already have been + // open so both the workspace and package cache will have data. However, just in case this isn't true + // for some reason, and also for tests (some tests just test a request without going through the full + // LSP workflow), we have a fallback where we type-check the workspace/package, then continue with + // processing the request. + let Some(workspace_cache_data) = state.workspace_cache.get(&workspace.root_dir) else { + return process_request_no_workspace_cache(state, text_document_position_params, callback); + }; + + let Some(package_cache_data) = state.package_cache.get(&package.root_dir) else { + return process_request_no_workspace_cache(state, text_document_position_params, callback); + }; + + let file_manager = &workspace_cache_data.file_manager; + let interner = &package_cache_data.node_interner; + let def_maps = &package_cache_data.def_maps; + let crate_graph = &package_cache_data.crate_graph; + let crate_id = package_cache_data.crate_id; + + let files = file_manager.as_file_map(); + + let location = position_to_location( + files, + &PathString::from(file_path), + &text_document_position_params.position, + )?; + + Ok(callback(ProcessRequestCallbackArgs { + location, + files, + interner, + package_cache: &state.package_cache, + crate_id, + crate_name: package.name.to_string(), + dependencies: &crate_graph[crate_id].dependencies, + def_maps, + })) +} + +pub(crate) fn process_request_no_workspace_cache( + state: &mut LspState, + text_document_position_params: TextDocumentPositionParams, + callback: F, +) -> Result +where + F: FnOnce(ProcessRequestCallbackArgs) -> T, +{ + let file_path = + text_document_position_params.text_document.uri.to_file_path().map_err(|_| { + ResponseError::new(ErrorCode::REQUEST_FAILED, "URI is not a valid file path") + })?; + + let workspace = resolve_workspace_for_source_path(file_path.as_path()).unwrap(); + let package = crate::workspace_package_for_file(&workspace, &file_path).ok_or_else(|| { + ResponseError::new(ErrorCode::REQUEST_FAILED, "Could not find package for file") + })?; + let mut workspace_file_manager = workspace.new_file_manager(); insert_all_files_for_workspace_into_file_manager( state, @@ -445,9 +506,9 @@ where let interner; let def_maps; - if let Some(def_interner) = state.cached_definitions.get(&package.root_dir) { - interner = def_interner; - def_maps = state.cached_def_maps.get(&package.root_dir).unwrap(); + if let Some(package_cache) = state.package_cache.get(&package.root_dir) { + interner = &package_cache.node_interner; + def_maps = &package_cache.def_maps; } else { // We ignore the warnings and errors produced by compilation while resolving the definition let _ = noirc_driver::check_crate(&mut context, crate_id, &Default::default()); @@ -455,7 +516,7 @@ where def_maps = &context.def_maps; } - let files = context.file_manager.as_file_map(); + let files = workspace_file_manager.as_file_map(); let location = position_to_location( files, @@ -467,17 +528,18 @@ where location, files, interner, - interners: &state.cached_definitions, + package_cache: &state.package_cache, crate_id, crate_name: package.name.to_string(), - dependencies: &context.crate_graph[context.root_crate_id()].dependencies, + dependencies: &context.crate_graph[crate_id].dependencies, def_maps, })) } + pub(crate) fn find_all_references_in_workspace( location: noirc_errors::Location, interner: &NodeInterner, - cached_interners: &HashMap, + package_cache: &HashMap, files: &FileMap, include_declaration: bool, include_self_type_name: bool, @@ -499,10 +561,10 @@ pub(crate) fn find_all_references_in_workspace( include_declaration, include_self_type_name, ); - for interner in cached_interners.values() { + for cache_data in package_cache.values() { locations.extend(find_all_references( referenced_location, - interner, + &cache_data.node_interner, files, include_declaration, include_self_type_name, diff --git a/noir/noir-repo/tooling/lsp/src/requests/references.rs b/noir/noir-repo/tooling/lsp/src/requests/references.rs index c720156659d..6d3f92447cb 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/references.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/references.rs @@ -16,7 +16,7 @@ pub(crate) fn on_references_request( find_all_references_in_workspace( args.location, args.interner, - args.interners, + args.package_cache, args.files, include_declaration, true, diff --git a/noir/noir-repo/tooling/lsp/src/requests/rename.rs b/noir/noir-repo/tooling/lsp/src/requests/rename.rs index 84956681167..95dd6b506be 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/rename.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/rename.rs @@ -38,7 +38,7 @@ pub(crate) fn on_rename_request( let rename_changes = find_all_references_in_workspace( args.location, args.interner, - args.interners, + args.package_cache, args.files, true, false, diff --git a/noir/noir-repo/tooling/lsp/src/requests/signature_help.rs b/noir/noir-repo/tooling/lsp/src/requests/signature_help.rs index 8f1bbb1570f..b075fea1d1e 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/signature_help.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/signature_help.rs @@ -8,8 +8,8 @@ use lsp_types::{ use noirc_errors::{Location, Span}; use noirc_frontend::{ ast::{ - CallExpression, ConstrainKind, ConstrainStatement, Expression, ExpressionKind, - FunctionReturnType, MethodCallExpression, Statement, Visitor, + CallExpression, ConstrainKind, ConstrainStatement, Expression, FunctionReturnType, + MethodCallExpression, Statement, Visitor, }, hir_def::{function::FuncMeta, stmt::HirPattern}, macros_api::NodeInterner, @@ -375,39 +375,24 @@ impl<'a> Visitor for SignatureFinder<'a> { return false; } - let arguments_span = if let Some(expr) = &constrain_statement.1 { - Span::from(constrain_statement.0.span.start()..expr.span.end()) - } else { - constrain_statement.0.span - }; + let kind_len = constrain_statement.kind.to_string().len() as u32; + let span = constrain_statement.span; + let arguments_span = Span::from(span.start() + kind_len + 1..span.end() - 1); if !self.includes_span(arguments_span) { return false; } - match constrain_statement.2 { - ConstrainKind::Assert => { - let mut arguments = vec![constrain_statement.0.clone()]; - if let Some(expr) = &constrain_statement.1 { - arguments.push(expr.clone()); - } + let active_parameter = self.compute_active_parameter(&constrain_statement.arguments); - let active_parameter = self.compute_active_parameter(&arguments); + match constrain_statement.kind { + ConstrainKind::Assert => { let signature_information = self.assert_signature_information(active_parameter); self.set_signature_help(signature_information); } ConstrainKind::AssertEq => { - if let ExpressionKind::Infix(infix) = &constrain_statement.0.kind { - let mut arguments = vec![infix.lhs.clone(), infix.rhs.clone()]; - if let Some(expr) = &constrain_statement.1 { - arguments.push(expr.clone()); - } - - let active_parameter = self.compute_active_parameter(&arguments); - let signature_information = - self.assert_eq_signature_information(active_parameter); - self.set_signature_help(signature_information); - } + let signature_information = self.assert_eq_signature_information(active_parameter); + self.set_signature_help(signature_information); } ConstrainKind::Constrain => (), } diff --git a/noir/noir-repo/tooling/lsp/src/requests/test_run.rs b/noir/noir-repo/tooling/lsp/src/requests/test_run.rs index 081eb815c8b..50c699bb6a6 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/test_run.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/test_run.rs @@ -84,7 +84,7 @@ fn on_test_run_request_inner( &state.solver, &mut context, &test_function, - false, + true, None, Some(workspace.root_dir.clone()), Some(package.name.to_string()), diff --git a/noir/noir-repo/tooling/lsp/src/trait_impl_method_stub_generator.rs b/noir/noir-repo/tooling/lsp/src/trait_impl_method_stub_generator.rs new file mode 100644 index 00000000000..ae12bac4c06 --- /dev/null +++ b/noir/noir-repo/tooling/lsp/src/trait_impl_method_stub_generator.rs @@ -0,0 +1,455 @@ +use std::collections::BTreeMap; + +use noirc_frontend::{ + ast::NoirTraitImpl, + graph::CrateId, + hir::{ + def_map::{CrateDefMap, ModuleId}, + type_check::generics::TraitGenerics, + }, + hir_def::{function::FuncMeta, stmt::HirPattern, traits::Trait}, + macros_api::{ModuleDefId, NodeInterner}, + node_interner::{FunctionModifiers, ReferenceId}, + Kind, ResolvedGeneric, Type, TypeVariableKind, +}; + +use crate::modules::relative_module_id_path; + +pub(crate) struct TraitImplMethodStubGenerator<'a> { + name: &'a str, + func_meta: &'a FuncMeta, + modifiers: &'a FunctionModifiers, + trait_: &'a Trait, + noir_trait_impl: &'a NoirTraitImpl, + interner: &'a NodeInterner, + def_maps: &'a BTreeMap, + module_id: ModuleId, + indent: usize, + body: Option, + string: String, +} + +impl<'a> TraitImplMethodStubGenerator<'a> { + #[allow(clippy::too_many_arguments)] + pub(crate) fn new( + name: &'a str, + func_meta: &'a FuncMeta, + modifiers: &'a FunctionModifiers, + trait_: &'a Trait, + noir_trait_impl: &'a NoirTraitImpl, + interner: &'a NodeInterner, + def_maps: &'a BTreeMap, + module_id: ModuleId, + indent: usize, + ) -> Self { + Self { + name, + func_meta, + modifiers, + trait_, + noir_trait_impl, + interner, + def_maps, + module_id, + indent, + body: None, + string: String::new(), + } + } + + /// Sets the body to include in the stub method. By default an empty body will be generated. + pub(crate) fn set_body(&mut self, body: String) { + self.body = Some(body); + } + + pub(crate) fn generate(&mut self) -> String { + let indent_string = " ".repeat(self.indent); + + self.string.push_str(&indent_string); + if self.modifiers.is_unconstrained { + self.string.push_str("unconstrained "); + } + self.string.push_str("fn "); + self.string.push_str(self.name); + self.append_resolved_generics(&self.func_meta.direct_generics); + self.string.push('('); + for (index, (pattern, typ, _visibility)) in self.func_meta.parameters.iter().enumerate() { + if index > 0 { + self.string.push_str(", "); + } + if self.append_pattern(pattern) { + self.string.push_str(": "); + self.append_type(typ); + } + } + self.string.push(')'); + + let return_type = self.func_meta.return_type(); + if return_type != &Type::Unit { + self.string.push_str(" -> "); + self.append_type(return_type); + } + + if !self.func_meta.trait_constraints.is_empty() { + self.string.push_str(" where "); + for (index, constraint) in self.func_meta.trait_constraints.iter().enumerate() { + if index > 0 { + self.string.push_str(", "); + } + self.append_type(&constraint.typ); + self.string.push_str(": "); + let trait_ = self.interner.get_trait(constraint.trait_id); + self.string.push_str(&trait_.name.0.contents); + self.append_trait_generics(&constraint.trait_generics); + } + } + + self.string.push_str(" {\n"); + + if let Some(body) = &self.body { + let body_indent_string = " ".repeat(self.indent + 4); + self.string.push_str(&body_indent_string); + self.string.push_str(body); + self.string.push('\n'); + self.string.push_str(&indent_string); + } + + self.string.push_str("}\n"); + std::mem::take(&mut self.string) + } + + /// Appends a pattern and returns true if this was not the self type + fn append_pattern(&mut self, pattern: &HirPattern) -> bool { + match pattern { + HirPattern::Identifier(hir_ident) => { + let definition = self.interner.definition(hir_ident.id); + self.string.push_str(&definition.name); + &definition.name != "self" + } + HirPattern::Mutable(pattern, _) => { + self.string.push_str("mut "); + self.append_pattern(pattern) + } + HirPattern::Tuple(patterns, _) => { + self.string.push('('); + for (index, pattern) in patterns.iter().enumerate() { + if index > 0 { + self.string.push_str(", "); + } + self.append_pattern(pattern); + } + self.string.push(')'); + true + } + HirPattern::Struct(typ, patterns, _) => { + self.append_type(typ); + self.string.push_str(" { "); + for (index, (name, _pattern)) in patterns.iter().enumerate() { + if index > 0 { + self.string.push_str(", "); + } + self.string.push_str(&name.0.contents); + } + self.string.push_str(" }"); + true + } + } + } + + fn append_type(&mut self, typ: &Type) { + match typ { + Type::FieldElement => self.string.push_str("Field"), + Type::Array(n, e) => { + self.string.push('['); + self.append_type(e); + self.string.push_str("; "); + self.append_type(n); + self.string.push(']'); + } + Type::Slice(typ) => { + self.string.push('['); + self.append_type(typ); + self.string.push(']'); + } + Type::Tuple(types) => { + self.string.push('('); + for (index, typ) in types.iter().enumerate() { + if index > 0 { + self.string.push_str(", "); + } + self.append_type(typ); + } + self.string.push(')'); + } + Type::Struct(struct_type, generics) => { + let struct_type = struct_type.borrow(); + + let current_module_data = + &self.def_maps[&self.module_id.krate].modules()[self.module_id.local_id.0]; + + // Check if the struct type is already imported/visible in this module + let per_ns = current_module_data.find_name(&struct_type.name); + if let Some((module_def_id, _, _)) = per_ns.types { + if module_def_id == ModuleDefId::TypeId(struct_type.id) { + self.string.push_str(&struct_type.name.0.contents); + self.append_generics(generics); + return; + } + } + + 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 current_module_parent_id = current_module_data + .parent + .map(|parent| ModuleId { krate: self.module_id.krate, local_id: parent }); + + let relative_path = relative_module_id_path( + parent_module_id, + &self.module_id, + current_module_parent_id, + self.interner, + ); + + if !relative_path.is_empty() { + self.string.push_str(&relative_path); + self.string.push_str("::"); + } + self.string.push_str(&struct_type.name.0.contents); + self.append_generics(generics); + } + Type::Alias(type_alias, generics) => { + let type_alias = type_alias.borrow(); + + let current_module_data = + &self.def_maps[&self.module_id.krate].modules()[self.module_id.local_id.0]; + + // Check if the alias type is already imported/visible in this module + let per_ns = current_module_data.find_name(&type_alias.name); + if let Some((module_def_id, _, _)) = per_ns.types { + if module_def_id == ModuleDefId::TypeAliasId(type_alias.id) { + self.string.push_str(&type_alias.name.0.contents); + self.append_generics(generics); + return; + } + } + + let parent_module_id = + self.interner.reference_module(ReferenceId::Alias(type_alias.id)).unwrap(); + + let current_module_parent_id = current_module_data + .parent + .map(|parent| ModuleId { krate: self.module_id.krate, local_id: parent }); + + let relative_path = relative_module_id_path( + *parent_module_id, + &self.module_id, + current_module_parent_id, + self.interner, + ); + + if !relative_path.is_empty() { + self.string.push_str(&relative_path); + self.string.push_str("::"); + } + self.string.push_str(&type_alias.name.0.contents); + self.append_generics(generics); + } + Type::TraitAsType(trait_id, _, trait_generics) => { + let trait_ = self.interner.get_trait(*trait_id); + + let current_module_data = + &self.def_maps[&self.module_id.krate].modules()[self.module_id.local_id.0]; + + // Check if the trait type is already imported/visible in this module + let per_ns = current_module_data.find_name(&trait_.name); + if let Some((module_def_id, _, _)) = per_ns.types { + if module_def_id == ModuleDefId::TraitId(*trait_id) { + self.string.push_str(&trait_.name.0.contents); + self.append_trait_generics(trait_generics); + return; + } + } + + let parent_module_id = + self.interner.reference_module(ReferenceId::Trait(*trait_id)).unwrap(); + + let current_module_parent_id = current_module_data + .parent + .map(|parent| ModuleId { krate: self.module_id.krate, local_id: parent }); + + let relative_path = relative_module_id_path( + *parent_module_id, + &self.module_id, + current_module_parent_id, + self.interner, + ); + + if !relative_path.is_empty() { + self.string.push_str(&relative_path); + self.string.push_str("::"); + } + self.string.push_str(&trait_.name.0.contents); + self.append_trait_generics(trait_generics); + } + Type::TypeVariable(typevar, _) => { + if typevar.id() == self.trait_.self_type_typevar.id() { + self.string.push_str("Self"); + return; + } + + let generics = &self.trait_.generics; + if let Some(index) = + generics.iter().position(|generic| generic.type_var.id() == typevar.id()) + { + if let Some(typ) = self.noir_trait_impl.trait_generics.ordered_args.get(index) { + self.string.push_str(&typ.to_string()); + return; + } + } + + for associated_type in &self.trait_.associated_types { + if typevar.id() == associated_type.type_var.id() { + self.string.push_str("Self::"); + self.string.push_str(&associated_type.name); + return; + } + } + + for generic in &self.func_meta.direct_generics { + if typevar.id() == generic.type_var.id() { + self.string.push_str(&generic.name); + return; + } + } + + self.string.push_str("error"); + } + Type::NamedGeneric(typevar, _name, _kind) => { + self.append_type(&Type::TypeVariable(typevar.clone(), TypeVariableKind::Normal)); + } + Type::Function(args, ret, env, unconstrained) => { + if *unconstrained { + self.string.push_str("unconstrained "); + } + self.string.push_str("fn"); + + if let Type::Unit = **env { + } else { + self.string.push('['); + self.append_type(env); + self.string.push(']'); + } + + self.string.push('('); + for (index, arg) in args.iter().enumerate() { + if index > 0 { + self.string.push_str(", "); + } + self.append_type(arg); + } + self.string.push(')'); + + if let Type::Unit = **ret { + } else { + self.string.push_str(" -> "); + self.append_type(ret); + } + } + Type::MutableReference(typ) => { + self.string.push_str("&mut "); + self.append_type(typ); + } + Type::Forall(_, _) => { + panic!("Shouldn't get a Type::Forall"); + } + Type::InfixExpr(left, op, right) => { + self.append_type(left); + self.string.push(' '); + self.string.push_str(&op.to_string()); + self.string.push(' '); + self.append_type(right); + } + Type::Constant(..) + | Type::Integer(_, _) + | Type::Bool + | Type::String(_) + | Type::FmtString(_, _) + | Type::Unit + | Type::Quoted(_) + | Type::Error => self.string.push_str(&typ.to_string()), + } + } + + fn append_generics(&mut self, generics: &[Type]) { + if generics.is_empty() { + return; + } + + self.string.push('<'); + for (index, typ) in generics.iter().enumerate() { + if index > 0 { + self.string.push_str(", "); + } + self.append_type(typ); + } + self.string.push('>'); + } + + fn append_trait_generics(&mut self, generics: &TraitGenerics) { + if generics.named.is_empty() && generics.ordered.is_empty() { + return; + } + + let mut index = 0; + + self.string.push('<'); + for generic in &generics.ordered { + if index > 0 { + self.string.push_str(", "); + } + self.append_type(generic); + index += 1; + } + for named_type in &generics.named { + if index > 0 { + self.string.push_str(", "); + } + self.string.push_str(&named_type.name.0.contents); + self.string.push_str(" = "); + self.append_type(&named_type.typ); + index += 1; + } + self.string.push('>'); + } + + fn append_resolved_generics(&mut self, generics: &[ResolvedGeneric]) { + if generics.is_empty() { + return; + } + + self.string.push('<'); + for (index, generic) in self.func_meta.direct_generics.iter().enumerate() { + if index > 0 { + self.string.push_str(", "); + } + self.append_resolved_generic(generic); + } + self.string.push('>'); + } + + fn append_resolved_generic(&mut self, generic: &ResolvedGeneric) { + match &generic.kind { + Kind::Normal => self.string.push_str(&generic.name), + Kind::Numeric(typ) => { + self.string.push_str("let "); + self.string.push_str(&generic.name); + self.string.push_str(": "); + self.append_type(typ); + } + } + } +} diff --git a/noir/noir-repo/tooling/nargo/src/errors.rs b/noir/noir-repo/tooling/nargo/src/errors.rs index 4a72bb1ec78..313f29517d6 100644 --- a/noir/noir-repo/tooling/nargo/src/errors.rs +++ b/noir/noir-repo/tooling/nargo/src/errors.rs @@ -238,11 +238,8 @@ pub fn try_to_diagnose_runtime_error( }; // The location of the error itself will be the location at the top // of the call stack (the last item in the Vec). - let location = source_locations.last()?; + let location = *source_locations.last()?; let message = extract_message_from_error(&abi.error_types, nargo_err); - Some( - CustomDiagnostic::simple_error(message, String::new(), location.span) - .in_file(location.file) - .with_call_stack(source_locations), - ) + let error = CustomDiagnostic::simple_error(message, String::new(), location.span); + Some(error.with_call_stack(source_locations).in_file(location.file)) } diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs index 0f7773d7ab7..c145ae9dbca 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs @@ -27,6 +27,8 @@ use crate::errors::CliError; #[clap(visible_alias = "e")] pub(crate) struct ExecuteCommand { /// Write the execution witness to named file + /// + /// Defaults to the name of the package being executed. witness_name: Option, /// The name of the toml file which contains the inputs for the prover @@ -83,11 +85,11 @@ pub(crate) fn run(args: ExecuteCommand, config: NargoConfig) -> Result<(), CliEr if let Some(return_value) = return_value { println!("[{}] Circuit output: {return_value:?}", package.name); } - if let Some(witness_name) = &args.witness_name { - let witness_path = save_witness_to_dir(witness_stack, witness_name, target_dir)?; - println!("[{}] Witness saved to {}", package.name, witness_path.display()); - } + let package_name = package.name.clone().into(); + let witness_name = args.witness_name.as_ref().unwrap_or(&package_name); + let witness_path = save_witness_to_dir(witness_stack, witness_name, target_dir)?; + println!("[{}] Witness saved to {}", package.name, witness_path.display()); } Ok(()) } diff --git a/noir/noir-repo/tooling/nargo_fmt/src/rewrite/expr.rs b/noir/noir-repo/tooling/nargo_fmt/src/rewrite/expr.rs index caa60b17cc2..873b5c87056 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/rewrite/expr.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/rewrite/expr.rs @@ -143,9 +143,9 @@ pub(crate) fn rewrite( super::parenthesized(visitor, shape, span, *sub_expr) } ExpressionKind::Constructor(constructor) => { - let type_name = visitor.slice(span.start()..constructor.type_name.span().end()); - let fields_span = visitor - .span_before(constructor.type_name.span().end()..span.end(), Token::LeftBrace); + let type_name = visitor.slice(span.start()..constructor.typ.span.end()); + let fields_span = + visitor.span_before(constructor.typ.span.end()..span.end(), Token::LeftBrace); visitor.format_struct_lit(type_name, fields_span, *constructor) } @@ -178,6 +178,11 @@ pub(crate) fn rewrite( ExpressionKind::Interned(_) => { unreachable!("ExpressionKind::Interned should only emitted by the comptime interpreter") } + ExpressionKind::InternedStatement(_) => { + unreachable!( + "ExpressionKind::InternedStatement should only emitted by the comptime interpreter" + ) + } ExpressionKind::Unquote(expr) => { if matches!(&expr.kind, ExpressionKind::Variable(..)) { format!("${expr}") @@ -187,7 +192,20 @@ pub(crate) fn rewrite( } ExpressionKind::AsTraitPath(path) => { let trait_path = rewrite_path(visitor, shape, path.trait_path); - format!("<{} as {}>::{}", path.typ, trait_path, path.impl_item) + + if path.trait_generics.is_empty() { + format!("<{} as {}>::{}", path.typ, trait_path, path.impl_item) + } else { + let generics = path.trait_generics; + format!("<{} as {}::{}>::{}", path.typ, trait_path, generics, path.impl_item) + } + } + ExpressionKind::TypePath(path) => { + if path.turbofish.is_empty() { + format!("{}::{}", path.typ, path.item) + } else { + format!("{}::{}::{}", path.typ, path.item, path.turbofish) + } } } } diff --git a/noir/noir-repo/tooling/nargo_fmt/src/visitor/stmt.rs b/noir/noir-repo/tooling/nargo_fmt/src/visitor/stmt.rs index b5ac14a33b3..8908aabd87c 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/visitor/stmt.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/visitor/stmt.rs @@ -2,9 +2,7 @@ use std::iter::zip; use noirc_frontend::macros_api::Span; -use noirc_frontend::ast::{ - ConstrainKind, ConstrainStatement, ExpressionKind, ForRange, Statement, StatementKind, -}; +use noirc_frontend::ast::{ConstrainKind, ConstrainStatement, ForRange, Statement, StatementKind}; use crate::{rewrite, visitor::expr::wrap_exprs}; @@ -38,37 +36,21 @@ impl super::FmtVisitor<'_> { self.push_rewrite(format!("{let_str} {expr_str};"), span); } - StatementKind::Constrain(ConstrainStatement(expr, message, kind)) => { + StatementKind::Constrain(ConstrainStatement { kind, arguments, span: _ }) => { let mut nested_shape = self.shape(); let shape = nested_shape; nested_shape.indent.block_indent(self.config); - let message = message.map_or(String::new(), |message| { - let message = rewrite::sub_expr(self, nested_shape, message); - format!(", {message}") - }); - - let (callee, args) = match kind { - ConstrainKind::Assert | ConstrainKind::Constrain => { - let assertion = rewrite::sub_expr(self, nested_shape, expr); - let args = format!("{assertion}{message}"); - - ("assert", args) - } - ConstrainKind::AssertEq => { - if let ExpressionKind::Infix(infix) = expr.kind { - let lhs = rewrite::sub_expr(self, nested_shape, infix.lhs); - let rhs = rewrite::sub_expr(self, nested_shape, infix.rhs); - - let args = format!("{lhs}, {rhs}{message}"); - - ("assert_eq", args) - } else { - unreachable!() - } - } + let callee = match kind { + ConstrainKind::Assert | ConstrainKind::Constrain => "assert", + ConstrainKind::AssertEq => "assert_eq", }; + let args = arguments + .into_iter() + .map(|arg| rewrite::sub_expr(self, nested_shape, arg)) + .collect::>() + .join(", "); let args = wrap_exprs( "(", diff --git a/noir/noir-repo/tooling/noir_codegen/package.json b/noir/noir-repo/tooling/noir_codegen/package.json index e7f03822633..75429cc4281 100644 --- a/noir/noir-repo/tooling/noir_codegen/package.json +++ b/noir/noir-repo/tooling/noir_codegen/package.json @@ -3,7 +3,7 @@ "contributors": [ "The Noir Team " ], - "version": "0.33.0", + "version": "0.34.0", "packageManager": "yarn@3.5.1", "license": "(MIT OR Apache-2.0)", "type": "module", diff --git a/noir/noir-repo/tooling/noir_codegen/test/test_lib/src/lib.nr b/noir/noir-repo/tooling/noir_codegen/test/test_lib/src/lib.nr index 4915b0a2c49..4229de06157 100644 --- a/noir/noir-repo/tooling/noir_codegen/test/test_lib/src/lib.nr +++ b/noir/noir-repo/tooling/noir_codegen/test/test_lib/src/lib.nr @@ -1,10 +1,10 @@ -struct MyStruct { +struct MyStruct { foo: bool, bar: [str; BAR_SIZE], baz: Field } -struct NestedStruct { +struct NestedStruct { foo: MyStruct, bar: [MyStruct; BAR_SIZE], baz: BAZ_TYP diff --git a/noir/noir-repo/tooling/noir_js/package.json b/noir/noir-repo/tooling/noir_js/package.json index 8ae098778d9..55347ec9af5 100644 --- a/noir/noir-repo/tooling/noir_js/package.json +++ b/noir/noir-repo/tooling/noir_js/package.json @@ -3,7 +3,7 @@ "contributors": [ "The Noir Team " ], - "version": "0.33.0", + "version": "0.34.0", "packageManager": "yarn@3.5.1", "license": "(MIT OR Apache-2.0)", "type": "module", diff --git a/noir/noir-repo/tooling/noir_js/scripts/compile_test_programs.sh b/noir/noir-repo/tooling/noir_js/scripts/compile_test_programs.sh index 0642159aa69..c65aea823a4 100755 --- a/noir/noir-repo/tooling/noir_js/scripts/compile_test_programs.sh +++ b/noir/noir-repo/tooling/noir_js/scripts/compile_test_programs.sh @@ -5,3 +5,4 @@ nargo --program-dir ./test/noir_compiled_examples/assert_lt compile --force nargo --program-dir ./test/noir_compiled_examples/assert_msg_runtime compile --force nargo --program-dir ./test/noir_compiled_examples/fold_fibonacci compile --force nargo --program-dir ./test/noir_compiled_examples/assert_raw_payload compile --force +nargo --program-dir ./test/noir_compiled_examples/databus compile --force diff --git a/noir/noir-repo/tooling/noir_js/test/node/execute.test.ts b/noir/noir-repo/tooling/noir_js/test/node/execute.test.ts index 7c93a911042..ceac21b2860 100644 --- a/noir/noir-repo/tooling/noir_js/test/node/execute.test.ts +++ b/noir/noir-repo/tooling/noir_js/test/node/execute.test.ts @@ -2,6 +2,7 @@ import assert_lt_json from '../noir_compiled_examples/assert_lt/target/assert_lt import assert_msg_json from '../noir_compiled_examples/assert_msg_runtime/target/assert_msg_runtime.json' assert { type: 'json' }; import fold_fibonacci_json from '../noir_compiled_examples/fold_fibonacci/target/fold_fibonacci.json' assert { type: 'json' }; import assert_raw_payload_json from '../noir_compiled_examples/assert_raw_payload/target/assert_raw_payload.json' assert { type: 'json' }; +import databus_json from '../noir_compiled_examples/databus/target/databus.json' assert { type: 'json' }; import { Noir, ErrorWithPayload } from '@noir-lang/noir_js'; import { CompiledCircuit } from '@noir-lang/types'; @@ -10,6 +11,7 @@ import { expect } from 'chai'; const assert_lt_program = assert_lt_json as CompiledCircuit; const assert_msg_runtime = assert_msg_json as CompiledCircuit; const fold_fibonacci_program = fold_fibonacci_json as CompiledCircuit; +const databus_program = databus_json as CompiledCircuit; it('executes a single-ACIR program correctly', async () => { const inputs = { @@ -21,43 +23,20 @@ it('executes a single-ACIR program correctly', async () => { expect(returnValue).to.be.eq('0x05'); }); -it('circuit with a fmt string assert message should fail with the resolved assertion message', async () => { +it('successfully executes a program with multiple acir circuits', async () => { const inputs = { x: '10', - y: '5', }; - try { - await new Noir(assert_msg_runtime).execute(inputs); - } catch (error) { - const knownError = error as Error; - expect(knownError.message).to.equal('Circuit execution failed: Expected x < y but got 10 < 5'); - } -}); - -it('circuit with a raw assert payload should fail with the decoded payload', async () => { - const inputs = { - x: '7', - y: '5', - }; - try { - await new Noir(assert_raw_payload_json).execute(inputs); - } catch (error) { - const knownError = error as ErrorWithPayload; - const invalidXYErrorSelector = Object.keys(assert_raw_payload_json.abi.error_types)[0]; - expect(knownError.rawAssertionPayload!.selector).to.equal(invalidXYErrorSelector); - expect(knownError.decodedAssertionPayload).to.deep.equal({ - x: '0x07', - y: '0x05', - }); - } + expect(() => new Noir(fold_fibonacci_program).execute(inputs)).to.not.throw(); }); -it('successfully executes a program with multiple acir circuits', async () => { +it('circuit with a fmt string assert message should fail with the resolved assertion message', async () => { const inputs = { x: '10', + y: '5', }; try { - await new Noir(fold_fibonacci_program).execute(inputs); + await new Noir(assert_msg_runtime).execute(inputs); } catch (error) { const knownError = error as Error; expect(knownError.message).to.equal('Circuit execution failed: Expected x < y but got 10 < 5'); @@ -82,50 +61,12 @@ it('circuit with a raw assert payload should fail with the decoded payload', asy } }); -it('successfully executes a program with multiple acir circuits', async () => { +it('successfully decodes the return values from a program using the databus', async () => { const inputs = { - x: '10', + x: '3', + y: '4', + z: [1, 2, 3, 4], }; - try { - await new Noir(fold_fibonacci_program).execute(inputs); - } catch (error) { - const knownError = error as Error; - expect(knownError.message).to.equal('Circuit execution failed: Error: Cannot satisfy constraint'); - } -}); - -it('successfully executes a program with multiple acir circuits', async () => { - const inputs = { - x: '10', - }; - try { - await new Noir(fold_fibonacci_program).execute(inputs); - } catch (error) { - const knownError = error as Error; - expect(knownError.message).to.equal('Circuit execution failed: Error: Cannot satisfy constraint'); - } -}); - -it('successfully executes a program with multiple acir circuits', async () => { - const inputs = { - x: '10', - }; - try { - await new Noir(fold_fibonacci_program).execute(inputs); - } catch (error) { - const knownError = error as Error; - expect(knownError.message).to.equal('Circuit execution failed: Error: Cannot satisfy constraint'); - } -}); - -it('successfully executes a program with multiple acir circuits', async () => { - const inputs = { - x: '10', - }; - try { - await new Noir(fold_fibonacci_program).execute(inputs); - } catch (error) { - const knownError = error as Error; - expect(knownError.message).to.equal('Circuit execution failed: Error: Cannot satisfy constraint'); - } + const { returnValue } = await new Noir(databus_program).execute(inputs); + expect(returnValue).to.be.eq('0x09'); }); diff --git a/noir/noir-repo/tooling/noir_js/test/noir_compiled_examples/databus/Nargo.toml b/noir/noir-repo/tooling/noir_js/test/noir_compiled_examples/databus/Nargo.toml new file mode 100644 index 00000000000..d484b80325e --- /dev/null +++ b/noir/noir-repo/tooling/noir_js/test/noir_compiled_examples/databus/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "databus" +type = "bin" +authors = [""] +[dependencies] diff --git a/noir/noir-repo/tooling/noir_js/test/noir_compiled_examples/databus/src/main.nr b/noir/noir-repo/tooling/noir_js/test/noir_compiled_examples/databus/src/main.nr new file mode 100644 index 00000000000..ecc7794cf9e --- /dev/null +++ b/noir/noir-repo/tooling/noir_js/test/noir_compiled_examples/databus/src/main.nr @@ -0,0 +1,12 @@ +fn main(mut x: u32, y: call_data(0) u32, z: call_data(0) [u32; 4]) -> return_data u32 { + let a = z[x]; + unsafe { + a + foo(y) + } +} + +// Use an unconstrained function to force the compiler to avoid inlining +unconstrained fn foo(x: u32) -> u32 { + x + 1 +} + diff --git a/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json b/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json index a5593cc284c..14fb5afe5f0 100644 --- a/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json +++ b/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json @@ -3,7 +3,7 @@ "contributors": [ "The Noir Team " ], - "version": "0.33.0", + "version": "0.34.0", "packageManager": "yarn@3.5.1", "license": "(MIT OR Apache-2.0)", "type": "module", @@ -41,7 +41,7 @@ "lint": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ./.eslintignore --max-warnings 0" }, "dependencies": { - "@aztec/bb.js": "portal:../../../../barretenberg/ts", + "@aztec/bb.js": "0.55.0", "@noir-lang/types": "workspace:*", "fflate": "^0.8.0" }, diff --git a/noir/noir-repo/tooling/noir_js_types/package.json b/noir/noir-repo/tooling/noir_js_types/package.json index 55aa85ae907..21dd5beabeb 100644 --- a/noir/noir-repo/tooling/noir_js_types/package.json +++ b/noir/noir-repo/tooling/noir_js_types/package.json @@ -4,7 +4,7 @@ "The Noir Team " ], "packageManager": "yarn@3.5.1", - "version": "0.33.0", + "version": "0.34.0", "license": "(MIT OR Apache-2.0)", "homepage": "https://noir-lang.org/", "repository": { diff --git a/noir/noir-repo/tooling/noirc_abi/src/lib.rs b/noir/noir-repo/tooling/noirc_abi/src/lib.rs index c3e1ade04fa..39f2e935618 100644 --- a/noir/noir-repo/tooling/noirc_abi/src/lib.rs +++ b/noir/noir-repo/tooling/noirc_abi/src/lib.rs @@ -197,7 +197,12 @@ impl Abi { /// Returns whether any values are needed to be made public for verification. pub fn has_public_inputs(&self) -> bool { - self.return_type.is_some() || self.parameters.iter().any(|param| param.is_public()) + let has_public_args = self.parameters.iter().any(|param| param.is_public()); + let has_public_return = self + .return_type + .as_ref() + .map_or(false, |typ| matches!(typ.visibility, AbiVisibility::Public)); + has_public_args || has_public_return } /// Returns `true` if the ABI contains no parameters or return value. @@ -346,15 +351,7 @@ impl Abi { .copied() }) { - // We do not return value for the data bus. - if return_type.visibility == AbiVisibility::DataBus { - None - } else { - Some(decode_value( - &mut return_witness_values.into_iter(), - &return_type.abi_type, - )?) - } + Some(decode_value(&mut return_witness_values.into_iter(), &return_type.abi_type)?) } else { // Unlike for the circuit inputs, we tolerate not being able to find the witness values for the return value. // This is because the user may be decoding a partial witness map for which is hasn't been calculated yet. diff --git a/noir/noir-repo/tooling/noirc_abi_wasm/build.sh b/noir/noir-repo/tooling/noirc_abi_wasm/build.sh index c07d2d8a4c1..16fb26e55db 100755 --- a/noir/noir-repo/tooling/noirc_abi_wasm/build.sh +++ b/noir/noir-repo/tooling/noirc_abi_wasm/build.sh @@ -25,7 +25,7 @@ function run_if_available { require_command jq require_command cargo require_command wasm-bindgen -#require_command wasm-opt +require_command wasm-opt self_path=$(dirname "$(readlink -f "$0")") pname=$(cargo read-manifest | jq -r '.name') diff --git a/noir/noir-repo/tooling/noirc_abi_wasm/package.json b/noir/noir-repo/tooling/noirc_abi_wasm/package.json index f3f4b9dacec..b8d0e74617d 100644 --- a/noir/noir-repo/tooling/noirc_abi_wasm/package.json +++ b/noir/noir-repo/tooling/noirc_abi_wasm/package.json @@ -3,7 +3,7 @@ "contributors": [ "The Noir Team " ], - "version": "0.33.0", + "version": "0.34.0", "license": "(MIT OR Apache-2.0)", "homepage": "https://noir-lang.org/", "repository": { diff --git a/noir/noir-repo/yarn.lock b/noir/noir-repo/yarn.lock index f77e9f7e72e..5d713532c67 100644 --- a/noir/noir-repo/yarn.lock +++ b/noir/noir-repo/yarn.lock @@ -221,18 +221,19 @@ __metadata: languageName: node linkType: hard -"@aztec/bb.js@portal:../../../../barretenberg/ts::locator=%40noir-lang%2Fbackend_barretenberg%40workspace%3Atooling%2Fnoir_js_backend_barretenberg": - version: 0.0.0-use.local - resolution: "@aztec/bb.js@portal:../../../../barretenberg/ts::locator=%40noir-lang%2Fbackend_barretenberg%40workspace%3Atooling%2Fnoir_js_backend_barretenberg" +"@aztec/bb.js@npm:0.55.0": + version: 0.55.0 + resolution: "@aztec/bb.js@npm:0.55.0" dependencies: comlink: ^4.4.1 commander: ^10.0.1 debug: ^4.3.4 tslib: ^2.4.0 bin: - bb.js: ./dest/node/main.js + bb.js: dest/node/main.js + checksum: 18ae18a962e05fd28e15e17796ec08e889ea331ec1790f8c77aa1d9472b4942c8f03c2cb8d8366a2e7a6896ffc135cdfc5b3bb6c9743bdf85e183f771c4f7b88 languageName: node - linkType: soft + linkType: hard "@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.11, @babel/code-frame@npm:^7.16.0, @babel/code-frame@npm:^7.22.13, @babel/code-frame@npm:^7.23.5, @babel/code-frame@npm:^7.8.3": version: 7.23.5 @@ -4160,7 +4161,7 @@ __metadata: version: 0.0.0-use.local resolution: "@noir-lang/backend_barretenberg@workspace:tooling/noir_js_backend_barretenberg" dependencies: - "@aztec/bb.js": "portal:../../../../barretenberg/ts" + "@aztec/bb.js": 0.55.0 "@noir-lang/types": "workspace:*" "@types/node": ^20.6.2 "@types/prettier": ^3